1mod dispatch;
2
3use std::{
4 convert::TryFrom,
5 sync::{Arc, Weak},
6};
7
8use bitflags::bitflags;
9use wayland_client::{
10 globals::{BindError, GlobalList},
11 protocol::{wl_output, wl_surface},
12 Connection, Dispatch, Proxy, QueueHandle,
13};
14use wayland_protocols::xdg::shell::client::xdg_popup::XdgPopup;
15use wayland_protocols_wlr::layer_shell::v1::client::{zwlr_layer_shell_v1, zwlr_layer_surface_v1};
16
17use crate::{compositor::Surface, globals::GlobalData};
18
19use super::WaylandSurface;
20
21#[derive(Debug)]
22pub struct LayerShell {
23 wlr_layer_shell: zwlr_layer_shell_v1::ZwlrLayerShellV1,
24}
25
26impl LayerShell {
27 /// Binds the wlr layer shell global, `zwlr_layer_shell_v1`.
28 ///
29 /// # Errors
30 ///
31 /// This function will return [`Err`] if the `zwlr_layer_shell_v1` global is not available.
32 pub fn bind<State>(
33 globals: &GlobalList,
34 qh: &QueueHandle<State>,
35 ) -> Result<LayerShell, BindError>
36 where
37 State: Dispatch<zwlr_layer_shell_v1::ZwlrLayerShellV1, GlobalData, State>
38 + LayerShellHandler
39 + 'static,
40 {
41 let wlr_layer_shell = globals.bind(qh, 1..=4, GlobalData)?;
42 Ok(LayerShell { wlr_layer_shell })
43 }
44
45 #[must_use]
46 pub fn create_layer_surface<State>(
47 &self,
48 qh: &QueueHandle<State>,
49 surface: impl Into<Surface>,
50 layer: Layer,
51 namespace: Option<impl Into<String>>,
52 output: Option<&wl_output::WlOutput>,
53 ) -> LayerSurface
54 where
55 State: Dispatch<zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, LayerSurfaceData> + 'static,
56 {
57 // Freeze the queue during the creation of the Arc to avoid a race between events on the
58 // new objects being processed and the Weak in the LayerSurfaceData becoming usable.
59 let freeze = qh.freeze();
60 let surface = surface.into();
61
62 let inner = Arc::new_cyclic(|weak| {
63 let layer_surface = self.wlr_layer_shell.get_layer_surface(
64 surface.wl_surface(),
65 output,
66 layer.into(),
67 namespace.map(Into::into).unwrap_or_default(),
68 qh,
69 LayerSurfaceData { inner: weak.clone() },
70 );
71
72 LayerSurfaceInner { wl_surface: surface, kind: SurfaceKind::Wlr(layer_surface) }
73 });
74 drop(freeze);
75
76 LayerSurface(inner)
77 }
78}
79
80/// Handler for operations on a [`LayerSurface`]
81pub trait LayerShellHandler: Sized {
82 /// The layer surface has been closed.
83 ///
84 /// When this requested is called, the layer surface is no longer shown and all handles of the [`LayerSurface`]
85 /// should be dropped.
86 fn closed(&mut self, conn: &Connection, qh: &QueueHandle<Self>, layer: &LayerSurface);
87
88 /// Apply a suggested surface change.
89 ///
90 /// When this function is called, the compositor is requesting the layer surfaces's size or state to change.
91 fn configure(
92 &mut self,
93 conn: &Connection,
94 qh: &QueueHandle<Self>,
95 layer: &LayerSurface,
96 configure: LayerSurfaceConfigure,
97 serial: u32,
98 );
99}
100
101#[derive(Debug, Clone)]
102pub struct LayerSurface(Arc<LayerSurfaceInner>);
103
104impl PartialEq for LayerSurface {
105 fn eq(&self, other: &Self) -> bool {
106 Arc::ptr_eq(&self.0, &other.0)
107 }
108}
109
110impl LayerSurface {
111 pub fn from_wlr_surface(
112 surface: &zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
113 ) -> Option<LayerSurface> {
114 surface.data::<LayerSurfaceData>().and_then(|data| data.inner.upgrade()).map(LayerSurface)
115 }
116
117 pub fn get_popup(&self, popup: &XdgPopup) {
118 match self.0.kind {
119 SurfaceKind::Wlr(ref s) => s.get_popup(popup),
120 }
121 }
122
123 // Double buffered state
124
125 pub fn set_size(&self, width: u32, height: u32) {
126 match self.0.kind {
127 SurfaceKind::Wlr(ref wlr) => wlr.set_size(width, height),
128 }
129 }
130
131 pub fn set_anchor(&self, anchor: Anchor) {
132 match self.0.kind {
133 // We currently rely on the bitsets being the same
134 SurfaceKind::Wlr(ref wlr) => {
135 wlr.set_anchor(zwlr_layer_surface_v1::Anchor::from_bits_truncate(anchor.bits()))
136 }
137 }
138 }
139
140 pub fn set_exclusive_zone(&self, zone: i32) {
141 match self.0.kind {
142 SurfaceKind::Wlr(ref wlr) => wlr.set_exclusive_zone(zone),
143 }
144 }
145
146 pub fn set_margin(&self, top: i32, right: i32, bottom: i32, left: i32) {
147 match self.0.kind {
148 SurfaceKind::Wlr(ref wlr) => wlr.set_margin(top, right, bottom, left),
149 }
150 }
151
152 pub fn set_keyboard_interactivity(&self, value: KeyboardInteractivity) {
153 match self.0.kind {
154 SurfaceKind::Wlr(ref wlr) => wlr.set_keyboard_interactivity(value.into()),
155 }
156 }
157
158 pub fn set_layer(&self, layer: Layer) {
159 match self.0.kind {
160 SurfaceKind::Wlr(ref wlr) => wlr.set_layer(layer.into()),
161 }
162 }
163
164 pub fn kind(&self) -> &SurfaceKind {
165 &self.0.kind
166 }
167}
168
169impl WaylandSurface for LayerSurface {
170 fn wl_surface(&self) -> &wl_surface::WlSurface {
171 self.0.wl_surface.wl_surface()
172 }
173}
174
175#[non_exhaustive]
176#[derive(Debug, Clone, PartialEq, Eq)]
177pub enum SurfaceKind {
178 Wlr(zwlr_layer_surface_v1::ZwlrLayerSurfaceV1),
179}
180
181#[non_exhaustive]
182#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
183pub enum KeyboardInteractivity {
184 /// No keyboard focus is possible.
185 ///
186 /// This is the default value for all newly created layer shells.
187 None,
188
189 /// Request exclusive keyboard focus if the layer is above shell surfaces.
190 ///
191 /// For [`Layer::Top`] and [`Layer::Overlay`], the seat will always give exclusive access to the layer
192 /// which has this interactivity mode set.
193 ///
194 /// This setting is intended for applications that need to ensure they receive all keyboard events, such
195 /// as a lock screen or a password prompt.
196 Exclusive,
197
198 /// The compositor should focus and unfocus this surface by the user in an implementation specific manner.
199 ///
200 /// Compositors may use their normal mechanisms to manage keyboard focus between layers and regular
201 /// desktop surfaces.
202 ///
203 /// This setting is intended for applications which allow keyboard interaction.
204 OnDemand,
205}
206
207impl Default for KeyboardInteractivity {
208 fn default() -> Self {
209 Self::None
210 }
211}
212
213/// The z-depth of a layer.
214///
215/// These values indicate which order in which layer surfaces are rendered.
216#[non_exhaustive]
217#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
218pub enum Layer {
219 Background,
220
221 Bottom,
222
223 Top,
224
225 Overlay,
226}
227
228/// Error when converting a [`zwlr_layer_shell_v1::Layer`] to a [`Layer`]
229#[derive(Debug, thiserror::Error)]
230#[error("unknown layer")]
231pub struct UnknownLayer;
232
233bitflags! {
234 /// Specifies which edges and corners a layer should be placed at in the anchor rectangle.
235 ///
236 /// A combination of two orthogonal edges will cause the layer's anchor point to be the intersection of
237 /// the edges. For example [`Anchor::TOP`] and [`Anchor::LEFT`] will result in an anchor point in the top
238 /// left of the anchor rectangle.
239 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
240 pub struct Anchor: u32 {
241 /// Top edge of the anchor rectangle.
242 const TOP = 1;
243
244 /// The bottom edge of the anchor rectangle.
245 const BOTTOM = 2;
246
247 /// The left edge of the anchor rectangle.
248 const LEFT = 4;
249
250 /// The right edge of the anchor rectangle.
251 const RIGHT = 8;
252 }
253}
254
255/// A layer surface configure.
256///
257/// A configure describes a compositor request to resize the layer surface or change it's state.
258#[non_exhaustive]
259#[derive(Debug, Clone)]
260pub struct LayerSurfaceConfigure {
261 /// The compositor suggested new size of the layer in surface-local coordinates.
262 ///
263 /// The size is a hint, meaning the new size can be ignored. A smaller size could be picked to satisfy
264 /// some aspect ratio or resize in steps. If the size is smaller than suggested and the layer surface is
265 /// anchored to two opposite anchors then the layer surface will be centered on that axis.
266 ///
267 /// If the width is zero, you may choose any width you want. If the height is zero, you may choose any
268 /// height you want.
269 pub new_size: (u32, u32),
270}
271
272#[derive(Debug)]
273pub struct LayerSurfaceData {
274 inner: Weak<LayerSurfaceInner>,
275}
276
277impl LayerSurfaceData {
278 pub fn layer_surface(&self) -> Option<LayerSurface> {
279 self.inner.upgrade().map(LayerSurface)
280 }
281}
282
283#[macro_export]
284macro_rules! delegate_layer {
285 ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
286 $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
287 $crate::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_shell_v1::ZwlrLayerShellV1: $crate::globals::GlobalData
288 ] => $crate::shell::wlr_layer::LayerShell);
289 $crate::reexports::client::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
290 $crate::reexports::protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1: $crate::shell::wlr_layer::LayerSurfaceData
291 ] => $crate::shell::wlr_layer::LayerShell);
292 };
293}
294
295#[derive(Debug)]
296struct LayerSurfaceInner {
297 wl_surface: Surface,
298 kind: SurfaceKind,
299}
300
301impl TryFrom<zwlr_layer_shell_v1::Layer> for Layer {
302 type Error = UnknownLayer;
303
304 fn try_from(layer: zwlr_layer_shell_v1::Layer) -> Result<Self, Self::Error> {
305 match layer {
306 zwlr_layer_shell_v1::Layer::Background => Ok(Self::Background),
307 zwlr_layer_shell_v1::Layer::Bottom => Ok(Self::Bottom),
308 zwlr_layer_shell_v1::Layer::Top => Ok(Self::Top),
309 zwlr_layer_shell_v1::Layer::Overlay => Ok(Self::Overlay),
310 _ => Err(UnknownLayer),
311 }
312 }
313}
314
315impl From<Layer> for zwlr_layer_shell_v1::Layer {
316 fn from(depth: Layer) -> Self {
317 match depth {
318 Layer::Background => Self::Background,
319 Layer::Bottom => Self::Bottom,
320 Layer::Top => Self::Top,
321 Layer::Overlay => Self::Overlay,
322 }
323 }
324}
325
326impl From<KeyboardInteractivity> for zwlr_layer_surface_v1::KeyboardInteractivity {
327 fn from(interactivity: KeyboardInteractivity) -> Self {
328 match interactivity {
329 KeyboardInteractivity::None => zwlr_layer_surface_v1::KeyboardInteractivity::None,
330 KeyboardInteractivity::Exclusive => {
331 zwlr_layer_surface_v1::KeyboardInteractivity::Exclusive
332 }
333 KeyboardInteractivity::OnDemand => {
334 zwlr_layer_surface_v1::KeyboardInteractivity::OnDemand
335 }
336 }
337 }
338}
339
340impl Drop for LayerSurfaceInner {
341 fn drop(&mut self) {
342 // Layer shell protocol dictates we must destroy the role object before the surface.
343 match self.kind {
344 SurfaceKind::Wlr(ref wlr: &{unknown}) => wlr.destroy(),
345 }
346
347 // Surface will destroy the wl_surface
348 // self.wl_surface.destroy();
349 }
350}
351