diff options
Diffstat (limited to 'src/handlers/layer_shell.rs')
| -rw-r--r-- | src/handlers/layer_shell.rs | 100 |
1 files changed, 100 insertions, 0 deletions
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); + } +} |
