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.
This commit is contained in:
Richard Acayan 2024-07-24 21:33:46 -04:00
parent 53f4daedc0
commit b5d09e655b
3 changed files with 96 additions and 35 deletions

View file

@ -145,14 +145,17 @@ impl<T: Dispatch<WlShmPool, u32>
ImgRef::new(ptr, self.width as usize, self.height as usize)
}
pub fn consume(&mut self, surface: &WlSurface) -> Option<ImgRefMut<BGRA<u8>>>
pub fn consume(&mut self, surface: Option<&WlSurface>) -> Option<ImgRefMut<BGRA<u8>>>
{
if self.used {
return None;
}
self.used = true;
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();

View file

@ -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);

View file

@ -24,13 +24,21 @@ use wayland::viewporter::wp_viewport::WpViewport;
pub struct Surface<T> {
bufs: [Buffer<T>; 2],
surface: WlSurface,
layer_surf: zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
queue: QueueHandle<T>,
comp: WlCompositor,
layer_shell: zwlr_layer_shell_v1::ZwlrLayerShellV1,
vper: Option<WpViewporter>,
fsm: Option<WpFractionalScaleManagerV1>,
surface: Option<WlSurface>,
layer_surf: Option<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1>,
vp: Option<WpViewport>,
used_buf: usize,
configured: bool,
scale: u32,
height: i32,
}
const LAYER_ANCHOR: zwlr_layer_surface_v1::Anchor
@ -46,42 +54,38 @@ impl<T: Dispatch<WlBuffer, u32>
+ Dispatch<WpFractionalScaleV1, ()>
+ Dispatch<WpViewport, ()>
+ 'static> Surface<T> {
pub fn new(queue: QueueHandle<T>, shm: &WlShm, comp: &WlCompositor,
layer_shell: &zwlr_layer_shell_v1::ZwlrLayerShellV1,
frac_scale_man: Option<WpFractionalScaleManagerV1>,
pub fn new(queue: QueueHandle<T>, shm: &WlShm, comp: WlCompositor,
layer_shell: zwlr_layer_shell_v1::ZwlrLayerShellV1,
fsm: Option<WpFractionalScaleManagerV1>,
vper: Option<WpViewporter>,
size: i32)
height: i32)
-> Result<Surface<T>, 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<T: Dispatch<WlBuffer, u32>
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<T: Dispatch<WlBuffer, u32>
{
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<T: Dispatch<WlBuffer, u32>
@ -123,7 +179,7 @@ impl<T: Dispatch<WlBuffer, u32>
fn begin(&mut self) -> ImgRefMut<BGRA<u8>>
{
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<T: Dispatch<WlBuffer, u32>
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 {