diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2023-08-15 12:49:26 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2023-08-15 12:49:26 +0400 |
| commit | 37cbed890f86ba148717b2e85a75337a17bd0167 (patch) | |
| tree | 5c779ba500eff97f7362f8ae7ec3eb2c8725b29f /src/handlers | |
| parent | 8cdd37b9932eb4acd8e983af53d0ba7bb04a3e64 (diff) | |
| download | niri-37cbed890f86ba148717b2e85a75337a17bd0167.tar.gz niri-37cbed890f86ba148717b2e85a75337a17bd0167.tar.bz2 niri-37cbed890f86ba148717b2e85a75337a17bd0167.zip | |
Add initial layer-shell implementation
Those surfaces never receive mouse focus and always keyboard focus,
which may not be always good, but it'll do for now.
Diffstat (limited to 'src/handlers')
| -rw-r--r-- | src/handlers/compositor.rs | 3 | ||||
| -rw-r--r-- | src/handlers/layer_shell.rs | 100 | ||||
| -rw-r--r-- | src/handlers/mod.rs | 1 |
3 files changed, 104 insertions, 0 deletions
diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs index 8b0f032b..2feba445 100644 --- a/src/handlers/compositor.rs +++ b/src/handlers/compositor.rs @@ -112,6 +112,9 @@ impl CompositorHandler for Niri { } } } + + // This might be a layer-shell surface. + self.layer_shell_handle_commit(surface); } } diff --git a/src/handlers/layer_shell.rs b/src/handlers/layer_shell.rs new file mode 100644 index 00000000..236ae7ab --- /dev/null +++ b/src/handlers/layer_shell.rs @@ -0,0 +1,100 @@ +use smithay::delegate_layer_shell; +use smithay::desktop::{layer_map_for_output, LayerSurface, WindowSurfaceType}; +use smithay::output::Output; +use smithay::reexports::wayland_server::protocol::wl_output::WlOutput; +use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; +use smithay::wayland::compositor::with_states; +use smithay::wayland::shell::wlr_layer::{ + Layer, LayerSurface as WlrLayerSurface, LayerSurfaceData, WlrLayerShellHandler, + WlrLayerShellState, +}; + +use crate::niri::Niri; + +impl WlrLayerShellHandler for Niri { + fn shell_state(&mut self) -> &mut WlrLayerShellState { + &mut self.layer_shell_state + } + + fn new_layer_surface( + &mut self, + surface: WlrLayerSurface, + wl_output: Option<WlOutput>, + _layer: Layer, + namespace: String, + ) { + let output = wl_output + .as_ref() + .and_then(Output::from_resource) + .or_else(|| self.monitor_set.active_output().cloned()) + .unwrap(); + let mut map = layer_map_for_output(&output); + map.map_layer(&LayerSurface::new(surface, namespace)) + .unwrap(); + } + + fn layer_destroyed(&mut self, surface: WlrLayerSurface) { + let output = if let Some((output, mut map, layer)) = + self.monitor_set.outputs().find_map(|o| { + let map = layer_map_for_output(o); + let layer = map + .layers() + .find(|&layer| layer.layer_surface() == &surface) + .cloned(); + layer.map(|layer| (o.clone(), map, layer)) + }) { + map.unmap_layer(&layer); + Some(output) + } else { + None + }; + if let Some(output) = output { + self.queue_redraw(output); + } + } +} +delegate_layer_shell!(Niri); + +impl Niri { + pub fn layer_shell_handle_commit(&mut self, surface: &WlSurface) { + let Some(output) = self + .monitor_set + .outputs() + .find(|o| { + let map = layer_map_for_output(o); + map.layer_for_surface(surface, WindowSurfaceType::TOPLEVEL) + .is_some() + }) + .cloned() + else { + return; + }; + + let initial_configure_sent = with_states(surface, |states| { + states + .data_map + .get::<LayerSurfaceData>() + .unwrap() + .lock() + .unwrap() + .initial_configure_sent + }); + + let mut map = layer_map_for_output(&output); + + // arrange the layers before sending the initial configure + // to respect any size the client may have sent + map.arrange(); + // send the initial configure if relevant + if !initial_configure_sent { + let layer = map + .layer_for_surface(surface, WindowSurfaceType::TOPLEVEL) + .unwrap(); + + layer.layer_surface().send_configure(); + } + drop(map); + + self.queue_redraw(output); + } +} diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index ab2a1596..4ad355ca 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,4 +1,5 @@ mod compositor; +mod layer_shell; mod xdg_shell; // |
