smithay/wayland/shell/wlr_layer/
types.rs

1use std::cmp::Ordering;
2
3use wayland_protocols_wlr::layer_shell::v1::server::{zwlr_layer_shell_v1, zwlr_layer_surface_v1};
4use wayland_server::WEnum;
5
6/// Available layers for surfaces
7///
8/// These values indicate which layers a surface can be rendered in.
9/// They are ordered by z depth, bottom-most first.
10/// Traditional shell surfaces will typically be rendered between the bottom and top layers.
11/// Fullscreen shell surfaces are typically rendered at the top layer.
12/// Multiple surfaces can share a single layer, and ordering within a single layer is undefined.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum Layer {
15    /// The lowest layer, used usualy for wallpapers
16    Background,
17    /// The layer bellow the windows and above the wallpaper
18    Bottom,
19    /// The layer above the windows and bellow overlay
20    Top,
21    /// The top layer above all other layers
22    Overlay,
23}
24
25impl TryFrom<WEnum<zwlr_layer_shell_v1::Layer>> for Layer {
26    type Error = (zwlr_layer_shell_v1::Error, String);
27
28    #[inline]
29    fn try_from(layer: WEnum<zwlr_layer_shell_v1::Layer>) -> Result<Self, Self::Error> {
30        use zwlr_layer_shell_v1::Layer;
31
32        match layer {
33            WEnum::Value(Layer::Background) => Ok(Self::Background),
34            WEnum::Value(Layer::Bottom) => Ok(Self::Bottom),
35            WEnum::Value(Layer::Top) => Ok(Self::Top),
36            WEnum::Value(Layer::Overlay) => Ok(Self::Overlay),
37            layer => Err((
38                zwlr_layer_shell_v1::Error::InvalidLayer,
39                format!("invalid layer: {:?}", layer),
40            )),
41        }
42    }
43}
44
45impl Default for Layer {
46    #[inline]
47    fn default() -> Self {
48        Self::Background
49    }
50}
51
52/// Types of keyboard interaction possible for a layer shell surface
53///
54/// The rationale for this is twofold:
55/// - some applications are not interested in keyboard events
56///   and not allowing them to be focused can improve the desktop experience
57/// - some applications will want to take exclusive keyboard focus.
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum KeyboardInteractivity {
60    /// This value indicates that this surface is not interested in keyboard events
61    /// and the compositor should never assign it the keyboard focus.
62    ///
63    /// This is the default value, set for newly created layer shell surfaces.
64    ///
65    /// This is useful for e.g. desktop widgets that display information
66    /// or only have interaction with non-keyboard input devices.
67    None,
68    /// Request exclusive keyboard focus if this surface is above the shell surface layer.
69    ///
70    /// For the top and overlay layers, the seat will always give exclusive keyboard focus
71    /// to the top-most layer which has keyboard interactivity set to exclusive.
72    /// If this layer contains multiple surfaces with keyboard interactivity set to exclusive,
73    /// the compositor determines the one receiving keyboard events in an implementation- defined manner.
74    /// In this case, no guarantee is made when this surface will receive keyboard focus (if ever).
75    ///
76    /// For the bottom and background layers, the compositor is allowed to use normal focus semantics.
77    ///
78    /// This setting is mainly intended for applications that need to
79    /// ensure they receive all keyboard events, such as a lock screen or a password prompt.
80    Exclusive,
81    /// This requests the compositor to allow this surface
82    /// to be focused and unfocused by the user in an implementation-defined manner.
83    /// The user should be able to unfocus this surface even regardless of the layer it is on.
84    ///
85    /// Typically, the compositor will want to use its normal mechanism
86    /// to manage keyboard focus between layer shell surfaces
87    /// with this setting and regular toplevels on the desktop layer (e.g. click to focus).
88    /// Nevertheless, it is possible for a compositor to require a special interaction
89    /// to focus or unfocus layer shell surfaces
90    ///
91    /// This setting is mainly intended for desktop shell components that allow keyboard interaction.
92    /// Using this option can allow implementing a desktop shell that can be fully usable without the mouse.
93    OnDemand,
94}
95
96impl Default for KeyboardInteractivity {
97    #[inline]
98    fn default() -> Self {
99        Self::None
100    }
101}
102
103impl TryFrom<WEnum<zwlr_layer_surface_v1::KeyboardInteractivity>> for KeyboardInteractivity {
104    type Error = (zwlr_layer_surface_v1::Error, String);
105
106    #[inline]
107    fn try_from(ki: WEnum<zwlr_layer_surface_v1::KeyboardInteractivity>) -> Result<Self, Self::Error> {
108        use zwlr_layer_surface_v1::KeyboardInteractivity;
109
110        match ki {
111            WEnum::Value(KeyboardInteractivity::None) => Ok(Self::None),
112            WEnum::Value(KeyboardInteractivity::Exclusive) => Ok(Self::Exclusive),
113            WEnum::Value(KeyboardInteractivity::OnDemand) => Ok(Self::OnDemand),
114            ki => Err((
115                zwlr_layer_surface_v1::Error::InvalidKeyboardInteractivity,
116                format!("wrong keyboard interactivity value: {:?}", ki),
117            )),
118        }
119    }
120}
121
122bitflags::bitflags! {
123    /// Anchor bitflags, describing how the layers surface should be positioned and sized
124    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
125    pub struct Anchor: u32 {
126        /// The top edge of the anchor rectangle
127        const TOP = 1;
128        /// The bottom edge of the anchor rectangle
129        const BOTTOM = 2;
130        /// The left edge of the anchor rectangle
131        const LEFT = 4;
132        /// The right edge of the anchor rectangle
133        const RIGHT = 8;
134    }
135}
136
137impl Anchor {
138    /// Check if anchored horizontally
139    ///
140    /// If it is anchored to `left` and `right` anchor at the same time
141    /// it returns `true`
142    pub fn anchored_horizontally(&self) -> bool {
143        self.contains(Self::LEFT) && self.contains(Self::RIGHT)
144    }
145    /// Check if anchored vertically
146    ///
147    /// If it is anchored to `top` and `bottom` anchor at the same time
148    /// it returns `true`
149    pub fn anchored_vertically(&self) -> bool {
150        self.contains(Self::TOP) && self.contains(Self::BOTTOM)
151    }
152}
153
154impl Default for Anchor {
155    #[inline]
156    fn default() -> Self {
157        Self::empty()
158    }
159}
160
161impl TryFrom<WEnum<zwlr_layer_surface_v1::Anchor>> for Anchor {
162    type Error = (zwlr_layer_surface_v1::Error, String);
163
164    #[inline]
165    fn try_from(anchor: WEnum<zwlr_layer_surface_v1::Anchor>) -> Result<Self, Self::Error> {
166        let a = if let WEnum::Value(anchor) = anchor {
167            Anchor::from_bits(anchor.bits())
168        } else {
169            None
170        };
171
172        a.ok_or((
173            zwlr_layer_surface_v1::Error::InvalidAnchor,
174            format!("invalid anchor {:?}", anchor),
175        ))
176    }
177}
178
179/// Exclusive zone descriptor
180#[derive(Debug, Clone, Copy, PartialEq, Eq)]
181pub enum ExclusiveZone {
182    /// Requests that the compositor avoids occluding an area with other surfaces.
183    ///
184    /// A exclusive zone value is the distance from the edge in surface-local coordinates to consider exclusive.
185    ///
186    /// A exclusive value is only meaningful if the surface is
187    /// anchored to one edge or an edge and both perpendicular edges.
188    ///
189    /// If the surface is:
190    /// - not anchored
191    /// - anchored to only two perpendicular edges (a corner),
192    /// - anchored to only two parallel edges or anchored to all edges,
193    ///
194    /// The exclusive value should be treated the same as [`ExclusiveZone::Neutral`].
195    Exclusive(u32),
196    /// If set to Neutral,
197    /// the surface indicates that it would like to be moved to avoid occluding surfaces with a exclusive zone.
198    Neutral,
199    /// If set to DontCare,
200    /// the surface indicates that it would not like to be moved to accommodate for other surfaces,
201    /// and the compositor should extend it all the way to the edges it is anchored to.
202    DontCare,
203}
204
205impl Default for ExclusiveZone {
206    #[inline]
207    fn default() -> Self {
208        Self::Neutral
209    }
210}
211
212impl From<i32> for ExclusiveZone {
213    #[inline]
214    fn from(v: i32) -> Self {
215        match v.cmp(&0) {
216            Ordering::Greater => Self::Exclusive(v as u32),
217            Ordering::Equal => Self::Neutral,
218            Ordering::Less => Self::DontCare,
219        }
220    }
221}
222
223impl From<ExclusiveZone> for i32 {
224    #[inline]
225    fn from(z: ExclusiveZone) -> i32 {
226        match z {
227            ExclusiveZone::Exclusive(v) => v as i32,
228            ExclusiveZone::Neutral => 0,
229            ExclusiveZone::DontCare => -1,
230        }
231    }
232}
233
234/// Describes distance from the anchor point of the output, in surface-local coordinates.
235///
236/// If surface did not anchor curtain edge, margin for that edge should be ignored.
237///
238/// The exclusive zone should includes the margins.
239#[derive(Debug, Default, Clone, Copy)]
240pub struct Margins {
241    /// Distance from [`Anchor::TOP`]
242    pub top: i32,
243    /// Distance from [`Anchor::TOP`]
244    pub right: i32,
245    /// Distance from [`Anchor::BOTTOM`]
246    pub bottom: i32,
247    /// Distance from [`Anchor::LEFT`]
248    pub left: i32,
249}