simple_window/common/protocols_data/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 type Data: 'static;
343
344 /// check if the client is alive
345 ///
346 /// The ping event asks the client if it's still alive. Pass the
347 /// serial specified in the event back to the compositor by sending
348 /// a "pong" request back with the specified serial. See xdg_wm_base.pong.
349 ///
350 /// Compositors can use this to determine if the client is still
351 /// alive. It's unspecified what will happen if the client doesn't
352 /// respond to the ping request, or in what timeframe. Clients should
353 /// try to respond in a reasonable amount of time. The “unresponsive”
354 /// error is provided for compositors that wish to disconnect unresponsive
355 /// clients.
356 ///
357 /// A compositor is free to ping in any way it wants, but a client must
358 /// always respond to any xdg_wm_base object it created.
359 ///
360 /// # Arguments
361 ///
362 /// - `serial`: pass this to the pong request
363 #[inline]
364 fn ping(&self, _data: &mut Self::Data, _slf: &XdgWmBaseRef, serial: u32) {
365 let _ = serial;
366 }
367}
368
369impl XdgWmBaseEventHandler for private::NoOpEventHandler {
370 type Data = ();
371}
372
373// SAFETY: - INTERFACE is a valid wl_interface
374// - mutable_type always returns the same value
375unsafe impl<H> EventHandler for private::EventHandler<H>
376where
377 H: XdgWmBaseEventHandler,
378{
379 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
380
381 #[inline]
382 fn mutable_type() -> Option<(TypeId, &'static str)> {
383 let id = TypeId::of::<H::Data>();
384 let name = std::any::type_name::<H::Data>();
385 Some((id, name))
386 }
387
388 #[allow(unused_variables)]
389 unsafe fn handle_event(
390 &self,
391 queue: &Queue,
392 data: *mut u8,
393 slf: &UntypedBorrowedProxy,
394 opcode: u32,
395 args: *mut wl_argument,
396 ) {
397 // SAFETY: This function requires that slf has the interface INTERFACE
398 let slf = unsafe { proxy::low_level::from_untyped_borrowed::<XdgWmBaseRef>(slf) };
399 // SAFETY: This function requires that data is `&mut T` where `T`
400 // has the type id returned by `Self::mutable_type`, i.e.,
401 // `T = H::Data`.
402 let data: &mut H::Data = unsafe { &mut *data.cast() };
403 match opcode {
404 0 => {
405 // SAFETY: INTERFACE requires that there are 1 arguments
406 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
407 // SAFETY: - INTERFACE requires that args[0] contains a uint
408 let arg0 = unsafe { args[0].u };
409 self.0.ping(data, slf, arg0);
410 }
411 _ => {
412 invalid_opcode("xdg_wm_base", opcode);
413 }
414 }
415 }
416}
417
418impl<H> CreateEventHandler<H> for private::ProxyApi
419where
420 H: XdgWmBaseEventHandler,
421{
422 type EventHandler = private::EventHandler<H>;
423
424 #[inline]
425 fn create_event_handler(handler: H) -> Self::EventHandler {
426 private::EventHandler(handler)
427 }
428}
429
430impl XdgWmBase {
431 /// Since when the error.role enum variant is available.
432 #[allow(dead_code)]
433 pub const ENM__ERROR_ROLE__SINCE: u32 = 1;
434 /// Since when the error.defunct_surfaces enum variant is available.
435 #[allow(dead_code)]
436 pub const ENM__ERROR_DEFUNCT_SURFACES__SINCE: u32 = 1;
437 /// Since when the error.not_the_topmost_popup enum variant is available.
438 #[allow(dead_code)]
439 pub const ENM__ERROR_NOT_THE_TOPMOST_POPUP__SINCE: u32 = 1;
440 /// Since when the error.invalid_popup_parent enum variant is available.
441 #[allow(dead_code)]
442 pub const ENM__ERROR_INVALID_POPUP_PARENT__SINCE: u32 = 1;
443 /// Since when the error.invalid_surface_state enum variant is available.
444 #[allow(dead_code)]
445 pub const ENM__ERROR_INVALID_SURFACE_STATE__SINCE: u32 = 1;
446 /// Since when the error.invalid_positioner enum variant is available.
447 #[allow(dead_code)]
448 pub const ENM__ERROR_INVALID_POSITIONER__SINCE: u32 = 1;
449 /// Since when the error.unresponsive enum variant is available.
450 #[allow(dead_code)]
451 pub const ENM__ERROR_UNRESPONSIVE__SINCE: u32 = 1;
452}
453
454#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
455#[allow(dead_code)]
456pub struct XdgWmBaseError(pub u32);
457
458impl XdgWmBaseError {
459 /// given wl_surface has another role
460 #[allow(dead_code)]
461 pub const ROLE: Self = Self(0);
462
463 /// xdg_wm_base was destroyed before children
464 #[allow(dead_code)]
465 pub const DEFUNCT_SURFACES: Self = Self(1);
466
467 /// the client tried to map or destroy a non-topmost popup
468 #[allow(dead_code)]
469 pub const NOT_THE_TOPMOST_POPUP: Self = Self(2);
470
471 /// the client specified an invalid popup parent surface
472 #[allow(dead_code)]
473 pub const INVALID_POPUP_PARENT: Self = Self(3);
474
475 /// the client provided an invalid surface state
476 #[allow(dead_code)]
477 pub const INVALID_SURFACE_STATE: Self = Self(4);
478
479 /// the client provided an invalid positioner
480 #[allow(dead_code)]
481 pub const INVALID_POSITIONER: Self = Self(5);
482
483 /// the client didn’t respond to a ping event in time
484 #[allow(dead_code)]
485 pub const UNRESPONSIVE: Self = Self(6);
486}
487
488impl Debug for XdgWmBaseError {
489 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
490 let name = match *self {
491 Self::ROLE => "ROLE",
492 Self::DEFUNCT_SURFACES => "DEFUNCT_SURFACES",
493 Self::NOT_THE_TOPMOST_POPUP => "NOT_THE_TOPMOST_POPUP",
494 Self::INVALID_POPUP_PARENT => "INVALID_POPUP_PARENT",
495 Self::INVALID_SURFACE_STATE => "INVALID_SURFACE_STATE",
496 Self::INVALID_POSITIONER => "INVALID_POSITIONER",
497 Self::UNRESPONSIVE => "UNRESPONSIVE",
498 _ => return Debug::fmt(&self.0, f),
499 };
500 f.write_str(name)
501 }
502}
503
504/// Functional event handlers.
505pub mod event_handlers {
506 use super::*;
507
508 /// Event handler for ping events.
509 pub struct Ping<T, F>(F, PhantomData<fn(&mut T)>);
510 impl<T, F> XdgWmBaseEventHandler for Ping<T, F>
511 where
512 T: 'static,
513 F: Fn(&mut T, &XdgWmBaseRef, u32),
514 {
515 type Data = T;
516
517 #[inline]
518 fn ping(&self, _data: &mut T, _slf: &XdgWmBaseRef, serial: u32) {
519 self.0(_data, _slf, serial)
520 }
521 }
522
523 impl XdgWmBase {
524 /// Creates an event handler for ping events.
525 ///
526 /// The event handler ignores all other events.
527 #[allow(dead_code)]
528 pub fn on_ping<T, F>(f: F) -> Ping<T, F>
529 where
530 T: 'static,
531 F: Fn(&mut T, &XdgWmBaseRef, u32),
532 {
533 Ping(f, PhantomData)
534 }
535 }
536}