smithay_client_toolkit/shell/wlr_layer/
mod.rs1mod 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 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 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
80pub trait LayerShellHandler: Sized {
82 fn closed(&mut self, conn: &Connection, qh: &QueueHandle<Self>, layer: &LayerSurface);
87
88 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 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 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, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
183pub enum KeyboardInteractivity {
184 #[default]
188 None,
189
190 Exclusive,
198
199 OnDemand,
206}
207
208#[non_exhaustive]
212#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
213pub enum Layer {
214 Background,
215
216 Bottom,
217
218 Top,
219
220 Overlay,
221}
222
223#[derive(Debug, thiserror::Error)]
225#[error("unknown layer")]
226pub struct UnknownLayer;
227
228bitflags! {
229 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
235 pub struct Anchor: u32 {
236 const TOP = 1;
238
239 const BOTTOM = 2;
241
242 const LEFT = 4;
244
245 const RIGHT = 8;
247 }
248}
249
250#[non_exhaustive]
254#[derive(Debug, Clone)]
255pub struct LayerSurfaceConfigure {
256 pub new_size: (u32, u32),
265}
266
267#[derive(Debug)]
268pub struct LayerSurfaceData {
269 inner: Weak<LayerSurfaceInner>,
270}
271
272impl LayerSurfaceData {
273 pub fn layer_surface(&self) -> Option<LayerSurface> {
274 self.inner.upgrade().map(LayerSurface)
275 }
276}
277
278#[derive(Debug)]
279struct LayerSurfaceInner {
280 wl_surface: Surface,
281 kind: SurfaceKind,
282}
283
284impl TryFrom<zwlr_layer_shell_v1::Layer> for Layer {
285 type Error = UnknownLayer;
286
287 fn try_from(layer: zwlr_layer_shell_v1::Layer) -> Result<Self, Self::Error> {
288 match layer {
289 zwlr_layer_shell_v1::Layer::Background => Ok(Self::Background),
290 zwlr_layer_shell_v1::Layer::Bottom => Ok(Self::Bottom),
291 zwlr_layer_shell_v1::Layer::Top => Ok(Self::Top),
292 zwlr_layer_shell_v1::Layer::Overlay => Ok(Self::Overlay),
293 _ => Err(UnknownLayer),
294 }
295 }
296}
297
298impl From<Layer> for zwlr_layer_shell_v1::Layer {
299 fn from(depth: Layer) -> Self {
300 match depth {
301 Layer::Background => Self::Background,
302 Layer::Bottom => Self::Bottom,
303 Layer::Top => Self::Top,
304 Layer::Overlay => Self::Overlay,
305 }
306 }
307}
308
309impl From<KeyboardInteractivity> for zwlr_layer_surface_v1::KeyboardInteractivity {
310 fn from(interactivity: KeyboardInteractivity) -> Self {
311 match interactivity {
312 KeyboardInteractivity::None => zwlr_layer_surface_v1::KeyboardInteractivity::None,
313 KeyboardInteractivity::Exclusive => {
314 zwlr_layer_surface_v1::KeyboardInteractivity::Exclusive
315 }
316 KeyboardInteractivity::OnDemand => {
317 zwlr_layer_surface_v1::KeyboardInteractivity::OnDemand
318 }
319 }
320 }
321}
322
323impl Drop for LayerSurfaceInner {
324 fn drop(&mut self) {
325 match self.kind {
327 SurfaceKind::Wlr(ref wlr) => wlr.destroy(),
328 }
329
330 }
333}