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}