layer_shika_composition/
layer_surface.rs

1use layer_shika_adapters::SurfaceState;
2use layer_shika_adapters::platform::slint_interpreter::ComponentInstance;
3use layer_shika_adapters::platform::wayland::{Anchor, WaylandKeyboardInteractivity, WaylandLayer};
4use layer_shika_domain::value_objects::anchor::AnchorEdges;
5use layer_shika_domain::value_objects::keyboard_interactivity::KeyboardInteractivity;
6use layer_shika_domain::value_objects::layer::Layer;
7use layer_shika_domain::value_objects::margins::Margins;
8
9/// Low-level handle for configuring layer-shell surface properties
10///
11/// Always call `commit()` after changes to apply them to the compositor.
12pub struct LayerSurfaceHandle<'a> {
13    window_state: &'a SurfaceState,
14}
15
16impl<'a> LayerSurfaceHandle<'a> {
17    pub(crate) fn from_window_state(window_state: &'a SurfaceState) -> Self {
18        Self { window_state }
19    }
20
21    /// Sets the anchor using Wayland anchor flags
22    pub fn set_anchor(&self, anchor: Anchor) {
23        self.window_state.layer_surface().set_anchor(anchor);
24    }
25
26    /// Sets the anchor edges for positioning
27    pub fn set_anchor_edges(&self, anchor: AnchorEdges) {
28        let wayland_anchor = Self::convert_anchor(anchor);
29        self.window_state.layer_surface().set_anchor(wayland_anchor);
30    }
31
32    fn convert_anchor(anchor: AnchorEdges) -> Anchor {
33        let mut result = Anchor::empty();
34
35        if anchor.has_top() {
36            result = result.union(Anchor::Top);
37        }
38        if anchor.has_bottom() {
39            result = result.union(Anchor::Bottom);
40        }
41        if anchor.has_left() {
42            result = result.union(Anchor::Left);
43        }
44        if anchor.has_right() {
45            result = result.union(Anchor::Right);
46        }
47
48        result
49    }
50
51    /// Sets the surface size in pixels
52    pub fn set_size(&self, width: u32, height: u32) {
53        self.window_state.layer_surface().set_size(width, height);
54    }
55
56    /// Sets the exclusive zone in pixels
57    ///
58    /// Positive values reserve space, `0` means no reservation, `-1` for auto-calculation.
59    pub fn set_exclusive_zone(&self, zone: i32) {
60        self.window_state.layer_surface().set_exclusive_zone(zone);
61    }
62
63    /// Sets the margins around the surface
64    pub fn set_margins(&self, margins: Margins) {
65        self.window_state.layer_surface().set_margin(
66            margins.top,
67            margins.right,
68            margins.bottom,
69            margins.left,
70        );
71    }
72
73    /// Sets the keyboard interactivity mode
74    pub fn set_keyboard_interactivity(&self, mode: KeyboardInteractivity) {
75        let wayland_mode = match mode {
76            KeyboardInteractivity::None => WaylandKeyboardInteractivity::None,
77            KeyboardInteractivity::Exclusive => WaylandKeyboardInteractivity::Exclusive,
78            KeyboardInteractivity::OnDemand => WaylandKeyboardInteractivity::OnDemand,
79        };
80        self.window_state
81            .layer_surface()
82            .set_keyboard_interactivity(wayland_mode);
83    }
84
85    /// Sets the layer (stacking order)
86    ///
87    /// From bottom to top: Background, Bottom, Top, Overlay.
88    pub fn set_layer(&self, layer: Layer) {
89        let wayland_layer = match layer {
90            Layer::Background => WaylandLayer::Background,
91            Layer::Bottom => WaylandLayer::Bottom,
92            Layer::Top => WaylandLayer::Top,
93            Layer::Overlay => WaylandLayer::Overlay,
94        };
95        self.window_state.layer_surface().set_layer(wayland_layer);
96    }
97
98    /// Commits all pending changes to the compositor
99    pub fn commit(&self) {
100        self.window_state.commit_surface();
101    }
102}
103
104pub trait ShellSurfaceConfigHandler {
105    fn configure_surface(&self, instance: &ComponentInstance, surface: LayerSurfaceHandle<'_>);
106}
107
108impl<F> ShellSurfaceConfigHandler for F
109where
110    F: Fn(&ComponentInstance, LayerSurfaceHandle<'_>),
111{
112    fn configure_surface(&self, instance: &ComponentInstance, surface: LayerSurfaceHandle<'_>) {
113        self(instance, surface);
114    }
115}