Files
niri/src/handlers/layer_shell.rs
T

120 lines
3.7 KiB
Rust
Raw Normal View History

2023-08-15 12:49:26 +04:00
use smithay::delegate_layer_shell;
2024-04-19 16:04:41 +04:00
use smithay::desktop::{layer_map_for_output, LayerSurface, PopupKind, WindowSurfaceType};
2023-08-15 12:49:26 +04:00
use smithay::output::Output;
use smithay::reexports::wayland_server::protocol::wl_output::WlOutput;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
2024-05-29 13:32:11 +03:00
use smithay::wayland::compositor::with_states;
2023-08-15 12:49:26 +04:00
use smithay::wayland::shell::wlr_layer::{
Layer, LayerSurface as WlrLayerSurface, LayerSurfaceData, WlrLayerShellHandler,
WlrLayerShellState,
};
2023-12-19 20:56:00 +04:00
use smithay::wayland::shell::xdg::PopupSurface;
2023-08-15 12:49:26 +04:00
2023-09-03 14:10:02 +04:00
use crate::niri::State;
2024-05-29 13:32:11 +03:00
use crate::utils::send_scale_transform;
2023-08-15 12:49:26 +04:00
2023-09-03 14:10:02 +04:00
impl WlrLayerShellHandler for State {
2023-08-15 12:49:26 +04:00
fn shell_state(&mut self) -> &mut WlrLayerShellState {
2023-09-03 14:10:02 +04:00
&mut self.niri.layer_shell_state
2023-08-15 12:49:26 +04:00
}
fn new_layer_surface(
&mut self,
surface: WlrLayerSurface,
wl_output: Option<WlOutput>,
_layer: Layer,
namespace: String,
) {
let output = if let Some(wl_output) = &wl_output {
Output::from_resource(wl_output)
} else {
self.niri.layout.active_output().cloned()
};
let Some(output) = output else {
warn!("no output for new layer surface, closing");
surface.send_close();
return;
};
2023-08-15 12:49:26 +04:00
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| {
2023-08-15 12:49:26 +04:00
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 {
2024-03-23 14:16:36 +04:00
self.niri.output_resized(&output);
2023-08-15 12:49:26 +04:00
}
}
2023-12-19 20:56:00 +04:00
fn new_popup(&mut self, _parent: WlrLayerSurface, popup: PopupSurface) {
2024-04-19 16:04:41 +04:00
self.unconstrain_popup(&PopupKind::Xdg(popup));
2023-12-19 20:56:00 +04:00
}
2023-08-15 12:49:26 +04:00
}
2023-09-03 14:10:02 +04:00
delegate_layer_shell!(State);
2023-08-15 12:49:26 +04:00
2023-09-03 14:10:02 +04:00
impl State {
2023-08-15 12:49:26 +04:00
pub fn layer_shell_handle_commit(&mut self, surface: &WlSurface) {
let Some(output) = self
2023-09-03 14:10:02 +04:00
.niri
.layout
2023-08-15 12:49:26 +04:00
.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();
2024-05-29 13:32:11 +03:00
let scale = output.current_scale();
2023-10-26 00:15:46 +04:00
let transform = output.current_transform();
with_states(surface, |data| {
2024-05-29 13:32:11 +03:00
send_scale_transform(surface, data, scale, transform);
2023-10-26 00:15:46 +04:00
});
2023-08-15 12:49:26 +04:00
layer.layer_surface().send_configure();
}
drop(map);
2024-03-23 14:16:36 +04:00
self.niri.output_resized(&output);
2023-08-15 12:49:26 +04:00
}
}