From b5d09e655b14c0e6d643966575a22b164ccd88ae Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 24 Jul 2024 21:33:46 -0400 Subject: [PATCH] wayland: surface: add show/hide functionality While the keyboard is running, it may want to automatically show or hide itself depending on whether a text input is active. Add functions to show and hide the surface by destroying and re-creating it. Phosh's compositor, phoc, does not emit configure events in reaction to a surface being committed with no buffer attached. The complicated surface creation/destruction process is for compatibility with phoc. --- src/wayland/buffer.rs | 7 ++- src/wayland/dispatcher.rs | 2 +- src/wayland/surface.rs | 122 ++++++++++++++++++++++++++++---------- 3 files changed, 96 insertions(+), 35 deletions(-) diff --git a/src/wayland/buffer.rs b/src/wayland/buffer.rs index d940663..47fab85 100644 --- a/src/wayland/buffer.rs +++ b/src/wayland/buffer.rs @@ -145,14 +145,17 @@ impl ImgRef::new(ptr, self.width as usize, self.height as usize) } - pub fn consume(&mut self, surface: &WlSurface) -> Option>> + pub fn consume(&mut self, surface: Option<&WlSurface>) -> Option>> { if self.used { return None; } self.used = true; - surface.attach(Some(&self.buf), 0, 0); + + if let Some(surface) = surface { + surface.attach(Some(&self.buf), 0, 0); + } // The ARGB format is in little endian. let ptr = self.map.as_mut().as_bgra_mut(); diff --git a/src/wayland/dispatcher.rs b/src/wayland/dispatcher.rs index 9ce87d7..3378e26 100644 --- a/src/wayland/dispatcher.rs +++ b/src/wayland/dispatcher.rs @@ -68,7 +68,7 @@ impl Dispatcher { }; let disp = Surface::new(queue.clone(), - &shm, &compositor, &layer_shell, + &shm, compositor, layer_shell, frac_scale_man, vper, 185)?; let gfx = Graphics::new(disp); let gfx = Mutex::new(gfx); diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index 149acb0..dd8bacd 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -24,13 +24,21 @@ use wayland::viewporter::wp_viewport::WpViewport; pub struct Surface { bufs: [Buffer; 2], - surface: WlSurface, - layer_surf: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, + + queue: QueueHandle, + comp: WlCompositor, + layer_shell: zwlr_layer_shell_v1::ZwlrLayerShellV1, + vper: Option, + fsm: Option, + + surface: Option, + layer_surf: Option, vp: Option, used_buf: usize, configured: bool, scale: u32, + height: i32, } const LAYER_ANCHOR: zwlr_layer_surface_v1::Anchor @@ -46,42 +54,38 @@ impl + Dispatch + Dispatch + 'static> Surface { - pub fn new(queue: QueueHandle, shm: &WlShm, comp: &WlCompositor, - layer_shell: &zwlr_layer_shell_v1::ZwlrLayerShellV1, - frac_scale_man: Option, + pub fn new(queue: QueueHandle, shm: &WlShm, comp: WlCompositor, + layer_shell: zwlr_layer_shell_v1::ZwlrLayerShellV1, + fsm: Option, vper: Option, - size: i32) + height: i32) -> Result, Error> { let buf1 = Buffer::new(queue.clone(), shm, 0)?; let buf2 = Buffer::new(queue.clone(), shm, 1)?; - let surface = comp.create_surface(&queue, ()); - - let layer_surf = layer_shell.get_layer_surface(&surface, None, - zwlr_layer_shell_v1::Layer::Top, - String::from("osk-ufkbd"), - &queue, ()); - - frac_scale_man.map(|fsm| fsm.get_fractional_scale(&surface, &queue, ())); - - let vp = vper.map(|vper| vper.get_viewport(&surface, &queue, ())); - - layer_surf.set_size(0, size as u32); - layer_surf.set_exclusive_zone(size); - layer_surf.set_anchor(LAYER_ANCHOR); - - surface.commit(); - - Ok(Surface { + let mut surf = Surface { bufs: [buf1, buf2], - surface, - layer_surf, - vp, + + queue: queue.clone(), + comp, + layer_shell, + vper, + fsm, + + surface: None, + layer_surf: None, + vp: None, + used_buf: 1, configured: false, scale: 120, - }) + height, + }; + + surf.show(); + + Ok(surf) } pub fn configured(&self) -> bool @@ -92,7 +96,7 @@ impl pub fn ack_configure(&mut self, serial: u32) { self.configured = true; - self.layer_surf.ack_configure(serial); + self.layer_surf.as_ref().unwrap().ack_configure(serial); } pub fn scale(&self) -> u32 @@ -104,6 +108,58 @@ impl { self.scale = scale; } + + pub fn hide(&mut self) + { + self.configured = false; + + if let Some(vp) = &self.vp { + vp.destroy(); + self.vp = None; + } + + if let Some(ls) = &self.layer_surf { + ls.destroy(); + self.layer_surf = None; + } + + if let Some(s) = &self.surface { + s.destroy(); + self.surface = None; + } + } + + pub fn show(&mut self) + { + if self.layer_surf.is_some() || self.surface.is_some() { + return; + } + + let surface = self.comp.create_surface(&self.queue, ()); + + let layer_surf = self.layer_shell.get_layer_surface(&surface, None, + zwlr_layer_shell_v1::Layer::Top, + String::from("osk"), + &self.queue, ()); + + self.fsm.as_ref().map(|fsm| { + fsm.get_fractional_scale(&surface, &self.queue, ()) + }); + + let vp = self.vper.as_ref().map(|vper| { + vper.get_viewport(&surface, &self.queue, ()) + }); + + layer_surf.set_size(0, self.height as u32); + layer_surf.set_exclusive_zone(self.height); + layer_surf.set_anchor(LAYER_ANCHOR); + + surface.commit(); + + self.surface = Some(surface); + self.layer_surf = Some(layer_surf); + self.vp = vp; + } } impl @@ -123,7 +179,7 @@ impl fn begin(&mut self) -> ImgRefMut> { for (id, buf) in self.bufs.iter_mut().enumerate() { - if let Some(img) = buf.consume(&self.surface) { + if let Some(img) = buf.consume(self.surface.as_ref()) { self.used_buf = id; return img; } @@ -149,8 +205,10 @@ impl fn end(&mut self, x: u32, y: u32, width: u32, height: u32) { - self.surface.damage_buffer(x as i32, y as i32, width as i32, height as i32); - self.surface.commit(); + if let Some(surface) = &self.surface { + surface.damage_buffer(x as i32, y as i32, width as i32, height as i32); + surface.commit(); + } for (id, buf) in self.bufs.iter_mut().enumerate() { if id != self.used_buf {