aboutsummaryrefslogtreecommitdiff
path: root/src/handlers
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-08-15 12:49:26 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-08-15 12:49:26 +0400
commit37cbed890f86ba148717b2e85a75337a17bd0167 (patch)
tree5c779ba500eff97f7362f8ae7ec3eb2c8725b29f /src/handlers
parent8cdd37b9932eb4acd8e983af53d0ba7bb04a3e64 (diff)
downloadniri-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.rs3
-rw-r--r--src/handlers/layer_shell.rs100
-rw-r--r--src/handlers/mod.rs1
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;
//