mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-22 02:01:55 +07:00
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.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user