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}