simple_window/common/protocols/xdg_shell/xdg_wm_base.rs
1//! create desktop-style surfaces
2//!
3//! The xdg_wm_base interface is exposed as a global object enabling clients
4//! to turn their wl_surfaces into windows in a desktop environment. It
5//! defines the basic functionality needed for clients and the compositor to
6//! create windows that can be dragged, resized, maximized, etc, as well as
7//! creating transient windows such as popup menus.
8
9use {super::super::all_types::*, ::wl_client::builder::prelude::*};
10
11static INTERFACE: wl_interface = wl_interface {
12 name: c"xdg_wm_base".as_ptr(),
13 version: 6,
14 method_count: 4,
15 methods: {
16 static MESSAGES: [wl_message; 4] = [
17 wl_message {
18 name: c"destroy".as_ptr(),
19 signature: c"".as_ptr(),
20 types: {
21 static TYPES: [Option<&'static wl_interface>; 0] = [];
22 TYPES.as_ptr().cast()
23 },
24 },
25 wl_message {
26 name: c"create_positioner".as_ptr(),
27 signature: c"n".as_ptr(),
28 types: {
29 static TYPES: [Option<&'static wl_interface>; 1] =
30 [Some(XdgPositioner::WL_INTERFACE)];
31 TYPES.as_ptr().cast()
32 },
33 },
34 wl_message {
35 name: c"get_xdg_surface".as_ptr(),
36 signature: c"no".as_ptr(),
37 types: {
38 static TYPES: [Option<&'static wl_interface>; 2] = [
39 Some(XdgSurface::WL_INTERFACE),
40 Some(WlSurface::WL_INTERFACE),
41 ];
42 TYPES.as_ptr().cast()
43 },
44 },
45 wl_message {
46 name: c"pong".as_ptr(),
47 signature: c"u".as_ptr(),
48 types: {
49 static TYPES: [Option<&'static wl_interface>; 1] = [None];
50 TYPES.as_ptr().cast()
51 },
52 },
53 ];
54 MESSAGES.as_ptr()
55 },
56 event_count: 1,
57 events: {
58 static MESSAGES: [wl_message; 1] = [wl_message {
59 name: c"ping".as_ptr(),
60 signature: c"u".as_ptr(),
61 types: {
62 static TYPES: [Option<&'static wl_interface>; 1] = [None];
63 TYPES.as_ptr().cast()
64 },
65 }];
66 MESSAGES.as_ptr()
67 },
68};
69
70/// An owned xdg_wm_base proxy.
71///
72/// See the documentation of [the module][self] for the interface description.
73#[derive(Clone, Eq, PartialEq)]
74#[repr(transparent)]
75pub struct XdgWmBase {
76 /// This proxy has the interface INTERFACE.
77 proxy: UntypedOwnedProxy,
78}
79
80/// A borrowed xdg_wm_base proxy.
81///
82/// See the documentation of [the module][self] for the interface description.
83#[derive(Eq, PartialEq)]
84#[repr(transparent)]
85pub struct XdgWmBaseRef {
86 /// This proxy has the interface INTERFACE.
87 proxy: UntypedBorrowedProxy,
88}
89
90// SAFETY: XdgWmBase is a transparent wrapper around UntypedOwnedProxy
91unsafe impl UntypedOwnedProxyWrapper for XdgWmBase {}
92
93// SAFETY: - INTERFACE is a valid wl_interface
94// - The only invariant is that self.proxy has a compatible interface
95unsafe impl OwnedProxy for XdgWmBase {
96 const INTERFACE: &'static str = "xdg_wm_base";
97 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
98 const NO_OP_EVENT_HANDLER: Self::NoOpEventHandler =
99 private::EventHandler(private::NoOpEventHandler);
100 const MAX_VERSION: u32 = 6;
101
102 type Borrowed = XdgWmBaseRef;
103 type Api = private::ProxyApi;
104 type NoOpEventHandler = private::EventHandler<private::NoOpEventHandler>;
105}
106
107// SAFETY: XdgWmBaseRef is a transparent wrapper around UntypedBorrowedProxy
108unsafe impl UntypedBorrowedProxyWrapper for XdgWmBaseRef {}
109
110// SAFETY: - The only invariant is that self.proxy has a compatible interface
111unsafe impl BorrowedProxy for XdgWmBaseRef {
112 type Owned = XdgWmBase;
113}
114
115impl Deref for XdgWmBase {
116 type Target = XdgWmBaseRef;
117
118 fn deref(&self) -> &Self::Target {
119 proxy::low_level::deref(self)
120 }
121}
122
123mod private {
124 pub struct ProxyApi;
125
126 #[allow(dead_code)]
127 pub struct EventHandler<H>(pub(super) H);
128
129 #[allow(dead_code)]
130 pub struct NoOpEventHandler;
131}
132
133impl Debug for XdgWmBase {
134 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
135 write!(f, "xdg_wm_base#{}", self.proxy.id())
136 }
137}
138
139impl Debug for XdgWmBaseRef {
140 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
141 write!(f, "xdg_wm_base#{}", self.proxy.id())
142 }
143}
144
145impl PartialEq<XdgWmBaseRef> for XdgWmBase {
146 fn eq(&self, other: &XdgWmBaseRef) -> bool {
147 self.proxy == other.proxy
148 }
149}
150
151impl PartialEq<XdgWmBase> for XdgWmBaseRef {
152 fn eq(&self, other: &XdgWmBase) -> bool {
153 self.proxy == other.proxy
154 }
155}
156
157#[allow(dead_code)]
158impl XdgWmBase {
159 /// Since when the destroy request is available.
160 #[allow(dead_code)]
161 pub const REQ__DESTROY__SINCE: u32 = 1;
162
163 /// destroy xdg_wm_base
164 ///
165 /// Destroy this xdg_wm_base object.
166 ///
167 /// Destroying a bound xdg_wm_base object while there are surfaces
168 /// still alive created by this xdg_wm_base object instance is illegal
169 /// and will result in a defunct_surfaces error.
170 #[inline]
171 pub fn destroy(&self) {
172 let mut args = [];
173 // SAFETY: - self.proxy has the interface INTERFACE
174 // - 0 < INTERFACE.method_count = 4
175 // - the request signature is ``
176 unsafe {
177 self.proxy.send_destructor(0, &mut args);
178 }
179 }
180
181 /// Since when the create_positioner request is available.
182 #[allow(dead_code)]
183 pub const REQ__CREATE_POSITIONER__SINCE: u32 = 1;
184
185 /// create a positioner object
186 ///
187 /// Create a positioner object. A positioner object is used to position
188 /// surfaces relative to some parent surface. See the interface description
189 /// and xdg_surface.get_popup for details.
190 #[inline]
191 pub fn create_positioner(&self) -> XdgPositioner {
192 let mut args = [wl_argument { n: 0 }];
193 // SAFETY: - self.proxy has the interface INTERFACE
194 // - 1 < INTERFACE.method_count = 4
195 // - the request signature is `n`
196 // - OwnedProxy::WL_INTERFACE is always a valid interface
197 let data = unsafe {
198 self.proxy
199 .send_constructor::<false>(1, &mut args, XdgPositioner::WL_INTERFACE, None)
200 };
201 // SAFETY: data has the interface XdgPositioner::WL_INTERFACE
202 unsafe { proxy::low_level::from_untyped_owned(data) }
203 }
204
205 /// Since when the get_xdg_surface request is available.
206 #[allow(dead_code)]
207 pub const REQ__GET_XDG_SURFACE__SINCE: u32 = 1;
208
209 /// create a shell surface from a surface
210 ///
211 /// This creates an xdg_surface for the given surface. While xdg_surface
212 /// itself is not a role, the corresponding surface may only be assigned
213 /// a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
214 /// illegal to create an xdg_surface for a wl_surface which already has an
215 /// assigned role and this will result in a role error.
216 ///
217 /// This creates an xdg_surface for the given surface. An xdg_surface is
218 /// used as basis to define a role to a given surface, such as xdg_toplevel
219 /// or xdg_popup. It also manages functionality shared between xdg_surface
220 /// based surface roles.
221 ///
222 /// See the documentation of xdg_surface for more details about what an
223 /// xdg_surface is and how it is used.
224 ///
225 /// # Arguments
226 ///
227 /// - `surface`:
228 #[inline]
229 pub fn get_xdg_surface(&self, surface: &WlSurfaceRef) -> XdgSurface {
230 let (arg1,) = (surface,);
231 let obj1_lock = proxy::lock(arg1);
232 let obj1 = check_argument_proxy("surface", obj1_lock.wl_proxy());
233 let mut args = [wl_argument { n: 0 }, wl_argument { o: obj1 }];
234 // SAFETY: - self.proxy has the interface INTERFACE
235 // - 2 < INTERFACE.method_count = 4
236 // - the request signature is `no`
237 // - OwnedProxy::WL_INTERFACE is always a valid interface
238 let data = unsafe {
239 self.proxy
240 .send_constructor::<false>(2, &mut args, XdgSurface::WL_INTERFACE, None)
241 };
242 // SAFETY: data has the interface XdgSurface::WL_INTERFACE
243 unsafe { proxy::low_level::from_untyped_owned(data) }
244 }
245}
246
247#[allow(dead_code)]
248impl XdgWmBaseRef {
249 /// create a positioner object
250 ///
251 /// Create a positioner object. A positioner object is used to position
252 /// surfaces relative to some parent surface. See the interface description
253 /// and xdg_surface.get_popup for details.
254 ///
255 /// # Arguments
256 ///
257 /// - `_queue`: The queue that the returned proxy is assigned to.
258 #[inline]
259 pub fn create_positioner(&self, _queue: &Queue) -> XdgPositioner {
260 let mut args = [wl_argument { n: 0 }];
261 // SAFETY: - self.proxy has the interface INTERFACE
262 // - 1 < INTERFACE.method_count = 4
263 // - the request signature is `n`
264 // - OwnedProxy::WL_INTERFACE is always a valid interface
265 let data = unsafe {
266 self.proxy
267 .send_constructor(_queue, 1, &mut args, XdgPositioner::WL_INTERFACE, None)
268 };
269 // SAFETY: data has the interface XdgPositioner::WL_INTERFACE
270 unsafe { proxy::low_level::from_untyped_owned(data) }
271 }
272
273 /// create a shell surface from a surface
274 ///
275 /// This creates an xdg_surface for the given surface. While xdg_surface
276 /// itself is not a role, the corresponding surface may only be assigned
277 /// a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
278 /// illegal to create an xdg_surface for a wl_surface which already has an
279 /// assigned role and this will result in a role error.
280 ///
281 /// This creates an xdg_surface for the given surface. An xdg_surface is
282 /// used as basis to define a role to a given surface, such as xdg_toplevel
283 /// or xdg_popup. It also manages functionality shared between xdg_surface
284 /// based surface roles.
285 ///
286 /// See the documentation of xdg_surface for more details about what an
287 /// xdg_surface is and how it is used.
288 ///
289 /// # Arguments
290 ///
291 /// - `_queue`: The queue that the returned proxy is assigned to.
292 /// - `surface`:
293 #[inline]
294 pub fn get_xdg_surface(&self, _queue: &Queue, surface: &WlSurfaceRef) -> XdgSurface {
295 let (arg1,) = (surface,);
296 let obj1_lock = proxy::lock(arg1);
297 let obj1 = check_argument_proxy("surface", obj1_lock.wl_proxy());
298 let mut args = [wl_argument { n: 0 }, wl_argument { o: obj1 }];
299 // SAFETY: - self.proxy has the interface INTERFACE
300 // - 2 < INTERFACE.method_count = 4
301 // - the request signature is `no`
302 // - OwnedProxy::WL_INTERFACE is always a valid interface
303 let data = unsafe {
304 self.proxy
305 .send_constructor(_queue, 2, &mut args, XdgSurface::WL_INTERFACE, None)
306 };
307 // SAFETY: data has the interface XdgSurface::WL_INTERFACE
308 unsafe { proxy::low_level::from_untyped_owned(data) }
309 }
310
311 /// respond to a ping event
312 ///
313 /// A client must respond to a ping event with a pong request or
314 /// the client may be deemed unresponsive. See xdg_wm_base.ping
315 /// and xdg_wm_base.error.unresponsive.
316 ///
317 /// # Arguments
318 ///
319 /// - `serial`: serial of the ping event
320 #[inline]
321 pub fn pong(&self, serial: u32) {
322 let (arg0,) = (serial,);
323 let mut args = [wl_argument { u: arg0 }];
324 // SAFETY: - self.proxy has the interface INTERFACE
325 // - 3 < INTERFACE.method_count = 4
326 // - the request signature is `u`
327 unsafe {
328 self.proxy.send_request(3, &mut args);
329 }
330 }
331}
332
333impl XdgWmBase {
334 /// Since when the ping event is available.
335 #[allow(dead_code)]
336 pub const EVT__PING__SINCE: u32 = 1;
337}
338
339/// An event handler for [XdgWmBase] proxies.
340#[allow(dead_code)]
341pub trait XdgWmBaseEventHandler {
342 /// check if the client is alive
343 ///
344 /// The ping event asks the client if it's still alive. Pass the
345 /// serial specified in the event back to the compositor by sending
346 /// a "pong" request back with the specified serial. See xdg_wm_base.pong.
347 ///
348 /// Compositors can use this to determine if the client is still
349 /// alive. It's unspecified what will happen if the client doesn't
350 /// respond to the ping request, or in what timeframe. Clients should
351 /// try to respond in a reasonable amount of time. The “unresponsive”
352 /// error is provided for compositors that wish to disconnect unresponsive
353 /// clients.
354 ///
355 /// A compositor is free to ping in any way it wants, but a client must
356 /// always respond to any xdg_wm_base object it created.
357 ///
358 /// # Arguments
359 ///
360 /// - `serial`: pass this to the pong request
361 #[inline]
362 fn ping(&self, _slf: &XdgWmBaseRef, serial: u32) {
363 let _ = serial;
364 }
365}
366
367impl XdgWmBaseEventHandler for private::NoOpEventHandler {}
368
369// SAFETY: - INTERFACE is a valid wl_interface
370unsafe impl<H> EventHandler for private::EventHandler<H>
371where
372 H: XdgWmBaseEventHandler,
373{
374 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
375
376 #[allow(unused_variables)]
377 unsafe fn handle_event(
378 &self,
379 queue: &Queue,
380 data: *mut u8,
381 slf: &UntypedBorrowedProxy,
382 opcode: u32,
383 args: *mut wl_argument,
384 ) {
385 // SAFETY: This function requires that slf has the interface INTERFACE
386 let slf = unsafe { proxy::low_level::from_untyped_borrowed::<XdgWmBaseRef>(slf) };
387 match opcode {
388 0 => {
389 // SAFETY: INTERFACE requires that there are 1 arguments
390 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
391 // SAFETY: - INTERFACE requires that args[0] contains a uint
392 let arg0 = unsafe { args[0].u };
393 self.0.ping(slf, arg0);
394 }
395 _ => {
396 invalid_opcode("xdg_wm_base", opcode);
397 }
398 }
399 }
400}
401
402impl<H> CreateEventHandler<H> for private::ProxyApi
403where
404 H: XdgWmBaseEventHandler,
405{
406 type EventHandler = private::EventHandler<H>;
407
408 #[inline]
409 fn create_event_handler(handler: H) -> Self::EventHandler {
410 private::EventHandler(handler)
411 }
412}
413
414impl XdgWmBase {
415 /// Since when the error.role enum variant is available.
416 #[allow(dead_code)]
417 pub const ENM__ERROR_ROLE__SINCE: u32 = 1;
418 /// Since when the error.defunct_surfaces enum variant is available.
419 #[allow(dead_code)]
420 pub const ENM__ERROR_DEFUNCT_SURFACES__SINCE: u32 = 1;
421 /// Since when the error.not_the_topmost_popup enum variant is available.
422 #[allow(dead_code)]
423 pub const ENM__ERROR_NOT_THE_TOPMOST_POPUP__SINCE: u32 = 1;
424 /// Since when the error.invalid_popup_parent enum variant is available.
425 #[allow(dead_code)]
426 pub const ENM__ERROR_INVALID_POPUP_PARENT__SINCE: u32 = 1;
427 /// Since when the error.invalid_surface_state enum variant is available.
428 #[allow(dead_code)]
429 pub const ENM__ERROR_INVALID_SURFACE_STATE__SINCE: u32 = 1;
430 /// Since when the error.invalid_positioner enum variant is available.
431 #[allow(dead_code)]
432 pub const ENM__ERROR_INVALID_POSITIONER__SINCE: u32 = 1;
433 /// Since when the error.unresponsive enum variant is available.
434 #[allow(dead_code)]
435 pub const ENM__ERROR_UNRESPONSIVE__SINCE: u32 = 1;
436}
437
438#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
439#[allow(dead_code)]
440pub struct XdgWmBaseError(pub u32);
441
442impl XdgWmBaseError {
443 /// given wl_surface has another role
444 #[allow(dead_code)]
445 pub const ROLE: Self = Self(0);
446
447 /// xdg_wm_base was destroyed before children
448 #[allow(dead_code)]
449 pub const DEFUNCT_SURFACES: Self = Self(1);
450
451 /// the client tried to map or destroy a non-topmost popup
452 #[allow(dead_code)]
453 pub const NOT_THE_TOPMOST_POPUP: Self = Self(2);
454
455 /// the client specified an invalid popup parent surface
456 #[allow(dead_code)]
457 pub const INVALID_POPUP_PARENT: Self = Self(3);
458
459 /// the client provided an invalid surface state
460 #[allow(dead_code)]
461 pub const INVALID_SURFACE_STATE: Self = Self(4);
462
463 /// the client provided an invalid positioner
464 #[allow(dead_code)]
465 pub const INVALID_POSITIONER: Self = Self(5);
466
467 /// the client didn’t respond to a ping event in time
468 #[allow(dead_code)]
469 pub const UNRESPONSIVE: Self = Self(6);
470}
471
472impl Debug for XdgWmBaseError {
473 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
474 let name = match *self {
475 Self::ROLE => "ROLE",
476 Self::DEFUNCT_SURFACES => "DEFUNCT_SURFACES",
477 Self::NOT_THE_TOPMOST_POPUP => "NOT_THE_TOPMOST_POPUP",
478 Self::INVALID_POPUP_PARENT => "INVALID_POPUP_PARENT",
479 Self::INVALID_SURFACE_STATE => "INVALID_SURFACE_STATE",
480 Self::INVALID_POSITIONER => "INVALID_POSITIONER",
481 Self::UNRESPONSIVE => "UNRESPONSIVE",
482 _ => return Debug::fmt(&self.0, f),
483 };
484 f.write_str(name)
485 }
486}
487
488/// Functional event handlers.
489pub mod event_handlers {
490 use super::*;
491
492 /// Event handler for ping events.
493 pub struct Ping<F>(F);
494 impl<F> XdgWmBaseEventHandler for Ping<F>
495 where
496 F: Fn(&XdgWmBaseRef, u32),
497 {
498 #[inline]
499 fn ping(&self, _slf: &XdgWmBaseRef, serial: u32) {
500 self.0(_slf, serial)
501 }
502 }
503
504 impl XdgWmBase {
505 /// Creates an event handler for ping events.
506 ///
507 /// The event handler ignores all other events.
508 #[allow(dead_code)]
509 pub fn on_ping<F>(f: F) -> Ping<F>
510 where
511 F: Fn(&XdgWmBaseRef, u32),
512 {
513 Ping(f)
514 }
515 }
516}