mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
113 lines
3.5 KiB
Rust
113 lines
3.5 KiB
Rust
use smithay::delegate_layer_shell;
|
|
use smithay::desktop::{layer_map_for_output, LayerSurface, PopupKind, 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::{send_surface_state, with_states};
|
|
use smithay::wayland::shell::wlr_layer::{
|
|
Layer, LayerSurface as WlrLayerSurface, LayerSurfaceData, WlrLayerShellHandler,
|
|
WlrLayerShellState,
|
|
};
|
|
use smithay::wayland::shell::xdg::PopupSurface;
|
|
|
|
use crate::niri::State;
|
|
|
|
impl WlrLayerShellHandler for State {
|
|
fn shell_state(&mut self) -> &mut WlrLayerShellState {
|
|
&mut self.niri.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.niri.layout.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.niri.layout.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.niri.output_resized(&output);
|
|
}
|
|
}
|
|
|
|
fn new_popup(&mut self, _parent: WlrLayerSurface, popup: PopupSurface) {
|
|
self.unconstrain_popup(&PopupKind::Xdg(popup));
|
|
}
|
|
}
|
|
delegate_layer_shell!(State);
|
|
|
|
impl State {
|
|
pub fn layer_shell_handle_commit(&mut self, surface: &WlSurface) {
|
|
let Some(output) = self
|
|
.niri
|
|
.layout
|
|
.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();
|
|
|
|
let scale = output.current_scale().integer_scale();
|
|
let transform = output.current_transform();
|
|
with_states(surface, |data| {
|
|
send_surface_state(surface, data, scale, transform);
|
|
});
|
|
|
|
layer.layer_surface().send_configure();
|
|
}
|
|
drop(map);
|
|
|
|
self.niri.output_resized(&output);
|
|
}
|
|
}
|