get_registry/common/protocols/wayland/
wl_shell_surface.rs

1//! desktop-style metadata interface
2//!
3//! An interface that may be implemented by a wl_surface, for
4//! implementations that provide a desktop-style user interface.
5//!
6//! It provides requests to treat surfaces like toplevel, fullscreen
7//! or popup windows, move, resize or maximize them, associate
8//! metadata like title and class, etc.
9//!
10//! On the server side the object is automatically destroyed when
11//! the related wl_surface is destroyed. On the client side,
12//! wl_shell_surface_destroy() must be called before destroying
13//! the wl_surface object.
14
15use {super::super::all_types::*, ::wl_client::builder::prelude::*};
16
17static INTERFACE: wl_interface = wl_interface {
18    name: c"wl_shell_surface".as_ptr(),
19    version: 1,
20    method_count: 10,
21    methods: {
22        static MESSAGES: [wl_message; 10] = [
23            wl_message {
24                name: c"pong".as_ptr(),
25                signature: c"u".as_ptr(),
26                types: {
27                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
28                    TYPES.as_ptr().cast()
29                },
30            },
31            wl_message {
32                name: c"move".as_ptr(),
33                signature: c"ou".as_ptr(),
34                types: {
35                    static TYPES: [Option<&'static wl_interface>; 2] =
36                        [Some(WlSeat::WL_INTERFACE), None];
37                    TYPES.as_ptr().cast()
38                },
39            },
40            wl_message {
41                name: c"resize".as_ptr(),
42                signature: c"ouu".as_ptr(),
43                types: {
44                    static TYPES: [Option<&'static wl_interface>; 3] =
45                        [Some(WlSeat::WL_INTERFACE), None, None];
46                    TYPES.as_ptr().cast()
47                },
48            },
49            wl_message {
50                name: c"set_toplevel".as_ptr(),
51                signature: c"".as_ptr(),
52                types: {
53                    static TYPES: [Option<&'static wl_interface>; 0] = [];
54                    TYPES.as_ptr().cast()
55                },
56            },
57            wl_message {
58                name: c"set_transient".as_ptr(),
59                signature: c"oiiu".as_ptr(),
60                types: {
61                    static TYPES: [Option<&'static wl_interface>; 4] =
62                        [Some(WlSurface::WL_INTERFACE), None, None, None];
63                    TYPES.as_ptr().cast()
64                },
65            },
66            wl_message {
67                name: c"set_fullscreen".as_ptr(),
68                signature: c"uu?o".as_ptr(),
69                types: {
70                    static TYPES: [Option<&'static wl_interface>; 3] =
71                        [None, None, Some(WlOutput::WL_INTERFACE)];
72                    TYPES.as_ptr().cast()
73                },
74            },
75            wl_message {
76                name: c"set_popup".as_ptr(),
77                signature: c"ouoiiu".as_ptr(),
78                types: {
79                    static TYPES: [Option<&'static wl_interface>; 6] = [
80                        Some(WlSeat::WL_INTERFACE),
81                        None,
82                        Some(WlSurface::WL_INTERFACE),
83                        None,
84                        None,
85                        None,
86                    ];
87                    TYPES.as_ptr().cast()
88                },
89            },
90            wl_message {
91                name: c"set_maximized".as_ptr(),
92                signature: c"?o".as_ptr(),
93                types: {
94                    static TYPES: [Option<&'static wl_interface>; 1] =
95                        [Some(WlOutput::WL_INTERFACE)];
96                    TYPES.as_ptr().cast()
97                },
98            },
99            wl_message {
100                name: c"set_title".as_ptr(),
101                signature: c"s".as_ptr(),
102                types: {
103                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
104                    TYPES.as_ptr().cast()
105                },
106            },
107            wl_message {
108                name: c"set_class".as_ptr(),
109                signature: c"s".as_ptr(),
110                types: {
111                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
112                    TYPES.as_ptr().cast()
113                },
114            },
115        ];
116        MESSAGES.as_ptr()
117    },
118    event_count: 3,
119    events: {
120        static MESSAGES: [wl_message; 3] = [
121            wl_message {
122                name: c"ping".as_ptr(),
123                signature: c"u".as_ptr(),
124                types: {
125                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
126                    TYPES.as_ptr().cast()
127                },
128            },
129            wl_message {
130                name: c"configure".as_ptr(),
131                signature: c"uii".as_ptr(),
132                types: {
133                    static TYPES: [Option<&'static wl_interface>; 3] = [None, None, None];
134                    TYPES.as_ptr().cast()
135                },
136            },
137            wl_message {
138                name: c"popup_done".as_ptr(),
139                signature: c"".as_ptr(),
140                types: {
141                    static TYPES: [Option<&'static wl_interface>; 0] = [];
142                    TYPES.as_ptr().cast()
143                },
144            },
145        ];
146        MESSAGES.as_ptr()
147    },
148};
149
150/// An owned wl_shell_surface proxy.
151///
152/// See the documentation of [the module][self] for the interface description.
153#[derive(Clone, Eq, PartialEq)]
154#[repr(transparent)]
155pub struct WlShellSurface {
156    /// This proxy has the interface INTERFACE.
157    proxy: UntypedOwnedProxy,
158}
159
160/// A borrowed wl_shell_surface proxy.
161///
162/// See the documentation of [the module][self] for the interface description.
163#[derive(Eq, PartialEq)]
164#[repr(transparent)]
165pub struct WlShellSurfaceRef {
166    /// This proxy has the interface INTERFACE.
167    proxy: UntypedBorrowedProxy,
168}
169
170// SAFETY: WlShellSurface is a transparent wrapper around UntypedOwnedProxy
171unsafe impl UntypedOwnedProxyWrapper for WlShellSurface {}
172
173// SAFETY: - INTERFACE is a valid wl_interface
174//         - The only invariant is that self.proxy has a compatible interface
175unsafe impl OwnedProxy for WlShellSurface {
176    const INTERFACE: &'static str = "wl_shell_surface";
177    const WL_INTERFACE: &'static wl_interface = &INTERFACE;
178    const NO_OP_EVENT_HANDLER: Self::NoOpEventHandler =
179        private::EventHandler(private::NoOpEventHandler);
180    const MAX_VERSION: u32 = 1;
181
182    type Borrowed = WlShellSurfaceRef;
183    type Api = private::ProxyApi;
184    type NoOpEventHandler = private::EventHandler<private::NoOpEventHandler>;
185}
186
187// SAFETY: WlShellSurfaceRef is a transparent wrapper around UntypedBorrowedProxy
188unsafe impl UntypedBorrowedProxyWrapper for WlShellSurfaceRef {}
189
190// SAFETY: - The only invariant is that self.proxy has a compatible interface
191unsafe impl BorrowedProxy for WlShellSurfaceRef {
192    type Owned = WlShellSurface;
193}
194
195impl Deref for WlShellSurface {
196    type Target = WlShellSurfaceRef;
197
198    fn deref(&self) -> &Self::Target {
199        proxy::low_level::deref(self)
200    }
201}
202
203mod private {
204    pub struct ProxyApi;
205
206    #[allow(dead_code)]
207    pub struct EventHandler<H>(pub(super) H);
208
209    #[allow(dead_code)]
210    pub struct NoOpEventHandler;
211}
212
213impl Debug for WlShellSurface {
214    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
215        write!(f, "wl_shell_surface#{}", self.proxy.id())
216    }
217}
218
219impl Debug for WlShellSurfaceRef {
220    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
221        write!(f, "wl_shell_surface#{}", self.proxy.id())
222    }
223}
224
225impl PartialEq<WlShellSurfaceRef> for WlShellSurface {
226    fn eq(&self, other: &WlShellSurfaceRef) -> bool {
227        self.proxy == other.proxy
228    }
229}
230
231impl PartialEq<WlShellSurface> for WlShellSurfaceRef {
232    fn eq(&self, other: &WlShellSurface) -> bool {
233        self.proxy == other.proxy
234    }
235}
236
237#[allow(dead_code)]
238impl WlShellSurfaceRef {
239    /// respond to a ping event
240    ///
241    /// A client must respond to a ping event with a pong request or
242    /// the client may be deemed unresponsive.
243    ///
244    /// # Arguments
245    ///
246    /// - `serial`: serial number of the ping event
247    #[inline]
248    pub fn pong(&self, serial: u32) {
249        let (arg0,) = (serial,);
250        let mut args = [wl_argument { u: arg0 }];
251        // SAFETY: - self.proxy has the interface INTERFACE
252        //         - 0 < INTERFACE.method_count = 10
253        //         - the request signature is `u`
254        unsafe {
255            self.proxy.send_request(0, &mut args);
256        }
257    }
258
259    /// start an interactive move
260    ///
261    /// Start a pointer-driven move of the surface.
262    ///
263    /// This request must be used in response to a button press event.
264    /// The server may ignore move requests depending on the state of
265    /// the surface (e.g. fullscreen or maximized).
266    ///
267    /// # Arguments
268    ///
269    /// - `seat`: seat whose pointer is used
270    /// - `serial`: serial number of the implicit grab on the pointer
271    #[inline]
272    pub fn r#move(&self, seat: &WlSeatRef, serial: u32) {
273        let (arg0, arg1) = (seat, serial);
274        let obj0_lock = proxy::lock(arg0);
275        let obj0 = check_argument_proxy("seat", obj0_lock.wl_proxy());
276        let mut args = [wl_argument { o: obj0 }, wl_argument { u: arg1 }];
277        // SAFETY: - self.proxy has the interface INTERFACE
278        //         - 1 < INTERFACE.method_count = 10
279        //         - the request signature is `ou`
280        unsafe {
281            self.proxy.send_request(1, &mut args);
282        }
283    }
284
285    /// start an interactive resize
286    ///
287    /// Start a pointer-driven resizing of the surface.
288    ///
289    /// This request must be used in response to a button press event.
290    /// The server may ignore resize requests depending on the state of
291    /// the surface (e.g. fullscreen or maximized).
292    ///
293    /// # Arguments
294    ///
295    /// - `seat`: seat whose pointer is used
296    /// - `serial`: serial number of the implicit grab on the pointer
297    /// - `edges`: which edge or corner is being dragged
298    #[inline]
299    pub fn resize(&self, seat: &WlSeatRef, serial: u32, edges: WlShellSurfaceResize) {
300        let (arg0, arg1, arg2) = (seat, serial, edges);
301        let obj0_lock = proxy::lock(arg0);
302        let obj0 = check_argument_proxy("seat", obj0_lock.wl_proxy());
303        let mut args = [
304            wl_argument { o: obj0 },
305            wl_argument { u: arg1 },
306            wl_argument { u: arg2.0 },
307        ];
308        // SAFETY: - self.proxy has the interface INTERFACE
309        //         - 2 < INTERFACE.method_count = 10
310        //         - the request signature is `ouu`
311        unsafe {
312            self.proxy.send_request(2, &mut args);
313        }
314    }
315
316    /// make the surface a toplevel surface
317    ///
318    /// Map the surface as a toplevel surface.
319    ///
320    /// A toplevel surface is not fullscreen, maximized or transient.
321    #[inline]
322    pub fn set_toplevel(&self) {
323        let mut args = [];
324        // SAFETY: - self.proxy has the interface INTERFACE
325        //         - 3 < INTERFACE.method_count = 10
326        //         - the request signature is ``
327        unsafe {
328            self.proxy.send_request(3, &mut args);
329        }
330    }
331
332    /// make the surface a transient surface
333    ///
334    /// Map the surface relative to an existing surface.
335    ///
336    /// The x and y arguments specify the location of the upper left
337    /// corner of the surface relative to the upper left corner of the
338    /// parent surface, in surface-local coordinates.
339    ///
340    /// The flags argument controls details of the transient behaviour.
341    ///
342    /// # Arguments
343    ///
344    /// - `parent`: parent surface
345    /// - `x`: surface-local x coordinate
346    /// - `y`: surface-local y coordinate
347    /// - `flags`: transient surface behavior
348    #[inline]
349    pub fn set_transient(
350        &self,
351        parent: &WlSurfaceRef,
352        x: i32,
353        y: i32,
354        flags: WlShellSurfaceTransient,
355    ) {
356        let (arg0, arg1, arg2, arg3) = (parent, x, y, flags);
357        let obj0_lock = proxy::lock(arg0);
358        let obj0 = check_argument_proxy("parent", obj0_lock.wl_proxy());
359        let mut args = [
360            wl_argument { o: obj0 },
361            wl_argument { i: arg1 },
362            wl_argument { i: arg2 },
363            wl_argument { u: arg3.0 },
364        ];
365        // SAFETY: - self.proxy has the interface INTERFACE
366        //         - 4 < INTERFACE.method_count = 10
367        //         - the request signature is `oiiu`
368        unsafe {
369            self.proxy.send_request(4, &mut args);
370        }
371    }
372
373    /// make the surface a fullscreen surface
374    ///
375    /// Map the surface as a fullscreen surface.
376    ///
377    /// If an output parameter is given then the surface will be made
378    /// fullscreen on that output. If the client does not specify the
379    /// output then the compositor will apply its policy - usually
380    /// choosing the output on which the surface has the biggest surface
381    /// area.
382    ///
383    /// The client may specify a method to resolve a size conflict
384    /// between the output size and the surface size - this is provided
385    /// through the method parameter.
386    ///
387    /// The framerate parameter is used only when the method is set
388    /// to "driver", to indicate the preferred framerate. A value of 0
389    /// indicates that the client does not care about framerate.  The
390    /// framerate is specified in mHz, that is framerate of 60000 is 60Hz.
391    ///
392    /// A method of "scale" or "driver" implies a scaling operation of
393    /// the surface, either via a direct scaling operation or a change of
394    /// the output mode. This will override any kind of output scaling, so
395    /// that mapping a surface with a buffer size equal to the mode can
396    /// fill the screen independent of buffer_scale.
397    ///
398    /// A method of "fill" means we don't scale up the buffer, however
399    /// any output scale is applied. This means that you may run into
400    /// an edge case where the application maps a buffer with the same
401    /// size of the output mode but buffer_scale 1 (thus making a
402    /// surface larger than the output). In this case it is allowed to
403    /// downscale the results to fit the screen.
404    ///
405    /// The compositor must reply to this request with a configure event
406    /// with the dimensions for the output on which the surface will
407    /// be made fullscreen.
408    ///
409    /// # Arguments
410    ///
411    /// - `method`: method for resolving size conflict
412    /// - `framerate`: framerate in mHz
413    /// - `output`: output on which the surface is to be fullscreen
414    #[inline]
415    pub fn set_fullscreen(
416        &self,
417        method: WlShellSurfaceFullscreenMethod,
418        framerate: u32,
419        output: Option<&WlOutputRef>,
420    ) {
421        let (arg0, arg1, arg2) = (method, framerate, output);
422        let obj2_lock = arg2.map(|arg2| proxy::lock(arg2));
423        let obj2 = obj2_lock
424            .map(|obj2_lock| check_argument_proxy("output", obj2_lock.wl_proxy()))
425            .unwrap_or(ptr::null_mut());
426        let mut args = [
427            wl_argument { u: arg0.0 },
428            wl_argument { u: arg1 },
429            wl_argument { o: obj2 },
430        ];
431        // SAFETY: - self.proxy has the interface INTERFACE
432        //         - 5 < INTERFACE.method_count = 10
433        //         - the request signature is `uu?o`
434        unsafe {
435            self.proxy.send_request(5, &mut args);
436        }
437    }
438
439    /// make the surface a popup surface
440    ///
441    /// Map the surface as a popup.
442    ///
443    /// A popup surface is a transient surface with an added pointer
444    /// grab.
445    ///
446    /// An existing implicit grab will be changed to owner-events mode,
447    /// and the popup grab will continue after the implicit grab ends
448    /// (i.e. releasing the mouse button does not cause the popup to
449    /// be unmapped).
450    ///
451    /// The popup grab continues until the window is destroyed or a
452    /// mouse button is pressed in any other client's window. A click
453    /// in any of the client's surfaces is reported as normal, however,
454    /// clicks in other clients' surfaces will be discarded and trigger
455    /// the callback.
456    ///
457    /// The x and y arguments specify the location of the upper left
458    /// corner of the surface relative to the upper left corner of the
459    /// parent surface, in surface-local coordinates.
460    ///
461    /// # Arguments
462    ///
463    /// - `seat`: seat whose pointer is used
464    /// - `serial`: serial number of the implicit grab on the pointer
465    /// - `parent`: parent surface
466    /// - `x`: surface-local x coordinate
467    /// - `y`: surface-local y coordinate
468    /// - `flags`: transient surface behavior
469    #[inline]
470    pub fn set_popup(
471        &self,
472        seat: &WlSeatRef,
473        serial: u32,
474        parent: &WlSurfaceRef,
475        x: i32,
476        y: i32,
477        flags: WlShellSurfaceTransient,
478    ) {
479        let (arg0, arg1, arg2, arg3, arg4, arg5) = (seat, serial, parent, x, y, flags);
480        let obj0_lock = proxy::lock(arg0);
481        let obj0 = check_argument_proxy("seat", obj0_lock.wl_proxy());
482        let obj2_lock = proxy::lock(arg2);
483        let obj2 = check_argument_proxy("parent", obj2_lock.wl_proxy());
484        let mut args = [
485            wl_argument { o: obj0 },
486            wl_argument { u: arg1 },
487            wl_argument { o: obj2 },
488            wl_argument { i: arg3 },
489            wl_argument { i: arg4 },
490            wl_argument { u: arg5.0 },
491        ];
492        // SAFETY: - self.proxy has the interface INTERFACE
493        //         - 6 < INTERFACE.method_count = 10
494        //         - the request signature is `ouoiiu`
495        unsafe {
496            self.proxy.send_request(6, &mut args);
497        }
498    }
499
500    /// make the surface a maximized surface
501    ///
502    /// Map the surface as a maximized surface.
503    ///
504    /// If an output parameter is given then the surface will be
505    /// maximized on that output. If the client does not specify the
506    /// output then the compositor will apply its policy - usually
507    /// choosing the output on which the surface has the biggest surface
508    /// area.
509    ///
510    /// The compositor will reply with a configure event telling
511    /// the expected new surface size. The operation is completed
512    /// on the next buffer attach to this surface.
513    ///
514    /// A maximized surface typically fills the entire output it is
515    /// bound to, except for desktop elements such as panels. This is
516    /// the main difference between a maximized shell surface and a
517    /// fullscreen shell surface.
518    ///
519    /// The details depend on the compositor implementation.
520    ///
521    /// # Arguments
522    ///
523    /// - `output`: output on which the surface is to be maximized
524    #[inline]
525    pub fn set_maximized(&self, output: Option<&WlOutputRef>) {
526        let (arg0,) = (output,);
527        let obj0_lock = arg0.map(|arg0| proxy::lock(arg0));
528        let obj0 = obj0_lock
529            .map(|obj0_lock| check_argument_proxy("output", obj0_lock.wl_proxy()))
530            .unwrap_or(ptr::null_mut());
531        let mut args = [wl_argument { o: obj0 }];
532        // SAFETY: - self.proxy has the interface INTERFACE
533        //         - 7 < INTERFACE.method_count = 10
534        //         - the request signature is `?o`
535        unsafe {
536            self.proxy.send_request(7, &mut args);
537        }
538    }
539
540    /// set surface title
541    ///
542    /// Set a short title for the surface.
543    ///
544    /// This string may be used to identify the surface in a task bar,
545    /// window list, or other user interface elements provided by the
546    /// compositor.
547    ///
548    /// The string must be encoded in UTF-8.
549    ///
550    /// # Arguments
551    ///
552    /// - `title`: surface title
553    #[inline]
554    pub fn set_title(&self, title: &str) {
555        let (arg0,) = (title,);
556        with_cstr_cache(|cache| {
557            let str0_offset = cache.len();
558            cache.extend_from_slice(arg0.as_bytes());
559            cache.push(0);
560            let str0 = cache[str0_offset..].as_ptr().cast();
561            let mut args = [wl_argument { s: str0 }];
562            // SAFETY: - self.proxy has the interface INTERFACE
563            //         - 8 < INTERFACE.method_count = 10
564            //         - the request signature is `s`
565            unsafe {
566                self.proxy.send_request(8, &mut args);
567            }
568        })
569    }
570
571    /// set surface class
572    ///
573    /// Set a class for the surface.
574    ///
575    /// The surface class identifies the general class of applications
576    /// to which the surface belongs. A common convention is to use the
577    /// file name (or the full path if it is a non-standard location) of
578    /// the application's .desktop file as the class.
579    ///
580    /// # Arguments
581    ///
582    /// - `class_`: surface class
583    #[inline]
584    pub fn set_class(&self, class_: &str) {
585        let (arg0,) = (class_,);
586        with_cstr_cache(|cache| {
587            let str0_offset = cache.len();
588            cache.extend_from_slice(arg0.as_bytes());
589            cache.push(0);
590            let str0 = cache[str0_offset..].as_ptr().cast();
591            let mut args = [wl_argument { s: str0 }];
592            // SAFETY: - self.proxy has the interface INTERFACE
593            //         - 9 < INTERFACE.method_count = 10
594            //         - the request signature is `s`
595            unsafe {
596                self.proxy.send_request(9, &mut args);
597            }
598        })
599    }
600}
601
602impl WlShellSurface {
603    /// Since when the ping event is available.
604    #[allow(dead_code)]
605    pub const EVT__PING__SINCE: u32 = 1;
606
607    /// Since when the configure event is available.
608    #[allow(dead_code)]
609    pub const EVT__CONFIGURE__SINCE: u32 = 1;
610
611    /// Since when the popup_done event is available.
612    #[allow(dead_code)]
613    pub const EVT__POPUP_DONE__SINCE: u32 = 1;
614}
615
616/// An event handler for [WlShellSurface] proxies.
617#[allow(dead_code)]
618pub trait WlShellSurfaceEventHandler {
619    /// ping client
620    ///
621    /// Ping a client to check if it is receiving events and sending
622    /// requests. A client is expected to reply with a pong request.
623    ///
624    /// # Arguments
625    ///
626    /// - `serial`: serial number of the ping
627    #[inline]
628    fn ping(&self, _slf: &WlShellSurfaceRef, serial: u32) {
629        let _ = serial;
630    }
631
632    /// suggest resize
633    ///
634    /// The configure event asks the client to resize its surface.
635    ///
636    /// The size is a hint, in the sense that the client is free to
637    /// ignore it if it doesn't resize, pick a smaller size (to
638    /// satisfy aspect ratio or resize in steps of NxM pixels).
639    ///
640    /// The edges parameter provides a hint about how the surface
641    /// was resized. The client may use this information to decide
642    /// how to adjust its content to the new size (e.g. a scrolling
643    /// area might adjust its content position to leave the viewable
644    /// content unmoved).
645    ///
646    /// The client is free to dismiss all but the last configure
647    /// event it received.
648    ///
649    /// The width and height arguments specify the size of the window
650    /// in surface-local coordinates.
651    ///
652    /// # Arguments
653    ///
654    /// - `edges`: how the surface was resized
655    /// - `width`: new width of the surface
656    /// - `height`: new height of the surface
657    #[inline]
658    fn configure(
659        &self,
660        _slf: &WlShellSurfaceRef,
661        edges: WlShellSurfaceResize,
662        width: i32,
663        height: i32,
664    ) {
665        let _ = edges;
666        let _ = width;
667        let _ = height;
668    }
669
670    /// popup interaction is done
671    ///
672    /// The popup_done event is sent out when a popup grab is broken,
673    /// that is, when the user clicks a surface that doesn't belong
674    /// to the client owning the popup surface.
675    #[inline]
676    fn popup_done(&self, _slf: &WlShellSurfaceRef) {}
677}
678
679impl WlShellSurfaceEventHandler for private::NoOpEventHandler {}
680
681// SAFETY: INTERFACE is a valid wl_interface
682unsafe impl<H> EventHandler for private::EventHandler<H>
683where
684    H: WlShellSurfaceEventHandler,
685{
686    const WL_INTERFACE: &'static wl_interface = &INTERFACE;
687
688    #[allow(unused_variables)]
689    unsafe fn handle_event(
690        &self,
691        queue: &Queue,
692        slf: &UntypedBorrowedProxy,
693        opcode: u32,
694        args: *mut wl_argument,
695    ) {
696        // SAFETY: This function required that slf has the interface INTERFACE
697        let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlShellSurfaceRef>(slf) };
698        match opcode {
699            0 => {
700                // SAFETY: INTERFACE requires that there are 1 arguments
701                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
702                // SAFETY: - INTERFACE requires that args[0] contains a uint
703                let arg0 = unsafe { args[0].u };
704                self.0.ping(slf, arg0);
705            }
706            1 => {
707                // SAFETY: INTERFACE requires that there are 3 arguments
708                let args = unsafe { &*args.cast::<[wl_argument; 3]>() };
709                // SAFETY: - INTERFACE requires that args[0] contains a uint
710                let arg0 = unsafe { WlShellSurfaceResize(args[0].u) };
711                // SAFETY: - INTERFACE requires that args[1] contains an int
712                let arg1 = unsafe { args[1].i };
713                // SAFETY: - INTERFACE requires that args[2] contains an int
714                let arg2 = unsafe { args[2].i };
715                self.0.configure(slf, arg0, arg1, arg2);
716            }
717            2 => {
718                self.0.popup_done(slf);
719            }
720            _ => {
721                invalid_opcode("wl_shell_surface", opcode);
722            }
723        }
724    }
725}
726
727impl<H> CreateEventHandler<H> for private::ProxyApi
728where
729    H: WlShellSurfaceEventHandler,
730{
731    type EventHandler = private::EventHandler<H>;
732
733    #[inline]
734    fn create_event_handler(handler: H) -> Self::EventHandler {
735        private::EventHandler(handler)
736    }
737}
738
739impl WlShellSurface {
740    /// Since when the resize.none enum variant is available.
741    #[allow(dead_code)]
742    pub const ENM__RESIZE_NONE__SINCE: u32 = 1;
743    /// Since when the resize.top enum variant is available.
744    #[allow(dead_code)]
745    pub const ENM__RESIZE_TOP__SINCE: u32 = 1;
746    /// Since when the resize.bottom enum variant is available.
747    #[allow(dead_code)]
748    pub const ENM__RESIZE_BOTTOM__SINCE: u32 = 1;
749    /// Since when the resize.left enum variant is available.
750    #[allow(dead_code)]
751    pub const ENM__RESIZE_LEFT__SINCE: u32 = 1;
752    /// Since when the resize.top_left enum variant is available.
753    #[allow(dead_code)]
754    pub const ENM__RESIZE_TOP_LEFT__SINCE: u32 = 1;
755    /// Since when the resize.bottom_left enum variant is available.
756    #[allow(dead_code)]
757    pub const ENM__RESIZE_BOTTOM_LEFT__SINCE: u32 = 1;
758    /// Since when the resize.right enum variant is available.
759    #[allow(dead_code)]
760    pub const ENM__RESIZE_RIGHT__SINCE: u32 = 1;
761    /// Since when the resize.top_right enum variant is available.
762    #[allow(dead_code)]
763    pub const ENM__RESIZE_TOP_RIGHT__SINCE: u32 = 1;
764    /// Since when the resize.bottom_right enum variant is available.
765    #[allow(dead_code)]
766    pub const ENM__RESIZE_BOTTOM_RIGHT__SINCE: u32 = 1;
767
768    /// Since when the transient.inactive enum variant is available.
769    #[allow(dead_code)]
770    pub const ENM__TRANSIENT_INACTIVE__SINCE: u32 = 1;
771
772    /// Since when the fullscreen_method.default enum variant is available.
773    #[allow(dead_code)]
774    pub const ENM__FULLSCREEN_METHOD_DEFAULT__SINCE: u32 = 1;
775    /// Since when the fullscreen_method.scale enum variant is available.
776    #[allow(dead_code)]
777    pub const ENM__FULLSCREEN_METHOD_SCALE__SINCE: u32 = 1;
778    /// Since when the fullscreen_method.driver enum variant is available.
779    #[allow(dead_code)]
780    pub const ENM__FULLSCREEN_METHOD_DRIVER__SINCE: u32 = 1;
781    /// Since when the fullscreen_method.fill enum variant is available.
782    #[allow(dead_code)]
783    pub const ENM__FULLSCREEN_METHOD_FILL__SINCE: u32 = 1;
784}
785
786/// edge values for resizing
787///
788/// These values are used to indicate which edge of a surface
789/// is being dragged in a resize operation. The server may
790/// use this information to adapt its behavior, e.g. choose
791/// an appropriate cursor image.
792#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
793#[allow(dead_code)]
794pub struct WlShellSurfaceResize(pub u32);
795
796/// An iterator over the set bits in a [WlShellSurfaceResize].
797///
798/// You can construct this with the `IntoIterator` implementation of `WlShellSurfaceResize`.
799#[derive(Clone, Debug)]
800pub struct WlShellSurfaceResizeIter(pub u32);
801
802impl WlShellSurfaceResize {
803    /// no edge
804    #[allow(dead_code)]
805    pub const NONE: Self = Self(0);
806
807    /// top edge
808    #[allow(dead_code)]
809    pub const TOP: Self = Self(1);
810
811    /// bottom edge
812    #[allow(dead_code)]
813    pub const BOTTOM: Self = Self(2);
814
815    /// left edge
816    #[allow(dead_code)]
817    pub const LEFT: Self = Self(4);
818
819    /// top and left edges
820    #[allow(dead_code)]
821    pub const TOP_LEFT: Self = Self(5);
822
823    /// bottom and left edges
824    #[allow(dead_code)]
825    pub const BOTTOM_LEFT: Self = Self(6);
826
827    /// right edge
828    #[allow(dead_code)]
829    pub const RIGHT: Self = Self(8);
830
831    /// top and right edges
832    #[allow(dead_code)]
833    pub const TOP_RIGHT: Self = Self(9);
834
835    /// bottom and right edges
836    #[allow(dead_code)]
837    pub const BOTTOM_RIGHT: Self = Self(10);
838}
839
840#[allow(dead_code)]
841impl WlShellSurfaceResize {
842    #[inline]
843    pub const fn empty() -> Self {
844        Self(0)
845    }
846
847    #[inline]
848    #[must_use]
849    pub const fn is_empty(self) -> bool {
850        self.0 == 0
851    }
852
853    #[inline]
854    #[must_use]
855    pub const fn contains(self, other: Self) -> bool {
856        self.0 & other.0 == other.0
857    }
858
859    #[inline]
860    #[must_use]
861    pub const fn intersects(self, other: Self) -> bool {
862        self.0 & other.0 != 0
863    }
864
865    #[inline]
866    pub const fn insert(&mut self, other: Self) {
867        *self = self.union(other);
868    }
869
870    #[inline]
871    pub const fn remove(&mut self, other: Self) {
872        *self = self.difference(other);
873    }
874
875    #[inline]
876    pub const fn toggle(&mut self, other: Self) {
877        *self = self.symmetric_difference(other);
878    }
879
880    #[inline]
881    pub const fn set(&mut self, other: Self, value: bool) {
882        if value {
883            self.insert(other);
884        } else {
885            self.remove(other);
886        }
887    }
888
889    #[inline]
890    #[must_use]
891    pub const fn intersection(self, other: Self) -> Self {
892        Self(self.0 & other.0)
893    }
894
895    #[inline]
896    #[must_use]
897    pub const fn union(self, other: Self) -> Self {
898        Self(self.0 | other.0)
899    }
900
901    #[inline]
902    #[must_use]
903    pub const fn difference(self, other: Self) -> Self {
904        Self(self.0 & !other.0)
905    }
906
907    #[inline]
908    #[must_use]
909    pub const fn complement(self) -> Self {
910        Self(!self.0)
911    }
912
913    #[inline]
914    #[must_use]
915    pub const fn symmetric_difference(self, other: Self) -> Self {
916        Self(self.0 ^ other.0)
917    }
918
919    #[inline]
920    pub const fn all_known() -> Self {
921        #[allow(clippy::eq_op, clippy::identity_op)]
922        Self(0 | 0 | 1 | 2 | 4 | 5 | 6 | 8 | 9 | 10)
923    }
924}
925
926impl Iterator for WlShellSurfaceResizeIter {
927    type Item = WlShellSurfaceResize;
928
929    fn next(&mut self) -> Option<Self::Item> {
930        if self.0 == 0 {
931            return None;
932        }
933        let bit = 1 << self.0.trailing_zeros();
934        self.0 &= !bit;
935        Some(WlShellSurfaceResize(bit))
936    }
937}
938
939impl IntoIterator for WlShellSurfaceResize {
940    type Item = WlShellSurfaceResize;
941    type IntoIter = WlShellSurfaceResizeIter;
942
943    fn into_iter(self) -> Self::IntoIter {
944        WlShellSurfaceResizeIter(self.0)
945    }
946}
947
948impl BitAnd for WlShellSurfaceResize {
949    type Output = Self;
950
951    fn bitand(self, rhs: Self) -> Self::Output {
952        self.intersection(rhs)
953    }
954}
955
956impl BitAndAssign for WlShellSurfaceResize {
957    fn bitand_assign(&mut self, rhs: Self) {
958        *self = self.intersection(rhs);
959    }
960}
961
962impl BitOr for WlShellSurfaceResize {
963    type Output = Self;
964
965    fn bitor(self, rhs: Self) -> Self::Output {
966        self.union(rhs)
967    }
968}
969
970impl BitOrAssign for WlShellSurfaceResize {
971    fn bitor_assign(&mut self, rhs: Self) {
972        *self = self.union(rhs);
973    }
974}
975
976impl BitXor for WlShellSurfaceResize {
977    type Output = Self;
978
979    fn bitxor(self, rhs: Self) -> Self::Output {
980        self.symmetric_difference(rhs)
981    }
982}
983
984impl BitXorAssign for WlShellSurfaceResize {
985    fn bitxor_assign(&mut self, rhs: Self) {
986        *self = self.symmetric_difference(rhs);
987    }
988}
989
990impl Sub for WlShellSurfaceResize {
991    type Output = Self;
992
993    fn sub(self, rhs: Self) -> Self::Output {
994        self.difference(rhs)
995    }
996}
997
998impl SubAssign for WlShellSurfaceResize {
999    fn sub_assign(&mut self, rhs: Self) {
1000        *self = self.difference(rhs);
1001    }
1002}
1003
1004impl Not for WlShellSurfaceResize {
1005    type Output = Self;
1006
1007    fn not(self) -> Self::Output {
1008        self.complement()
1009    }
1010}
1011
1012impl Debug for WlShellSurfaceResize {
1013    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1014        let mut v = self.0;
1015        let mut first = true;
1016        if v & 1 == 1 {
1017            v &= !1;
1018            if first {
1019                first = false;
1020            } else {
1021                f.write_str(" | ")?;
1022            }
1023            f.write_str("TOP")?;
1024        }
1025        if v & 2 == 2 {
1026            v &= !2;
1027            if first {
1028                first = false;
1029            } else {
1030                f.write_str(" | ")?;
1031            }
1032            f.write_str("BOTTOM")?;
1033        }
1034        if v & 4 == 4 {
1035            v &= !4;
1036            if first {
1037                first = false;
1038            } else {
1039                f.write_str(" | ")?;
1040            }
1041            f.write_str("LEFT")?;
1042        }
1043        if v & 5 == 5 {
1044            v &= !5;
1045            if first {
1046                first = false;
1047            } else {
1048                f.write_str(" | ")?;
1049            }
1050            f.write_str("TOP_LEFT")?;
1051        }
1052        if v & 6 == 6 {
1053            v &= !6;
1054            if first {
1055                first = false;
1056            } else {
1057                f.write_str(" | ")?;
1058            }
1059            f.write_str("BOTTOM_LEFT")?;
1060        }
1061        if v & 8 == 8 {
1062            v &= !8;
1063            if first {
1064                first = false;
1065            } else {
1066                f.write_str(" | ")?;
1067            }
1068            f.write_str("RIGHT")?;
1069        }
1070        if v & 9 == 9 {
1071            v &= !9;
1072            if first {
1073                first = false;
1074            } else {
1075                f.write_str(" | ")?;
1076            }
1077            f.write_str("TOP_RIGHT")?;
1078        }
1079        if v & 10 == 10 {
1080            v &= !10;
1081            if first {
1082                first = false;
1083            } else {
1084                f.write_str(" | ")?;
1085            }
1086            f.write_str("BOTTOM_RIGHT")?;
1087        }
1088        if v != 0 {
1089            if first {
1090                first = false;
1091            } else {
1092                f.write_str(" | ")?;
1093            }
1094            write!(f, "0x{v:032x}")?;
1095        }
1096        if first {
1097            f.write_str("NONE")?;
1098        }
1099        Ok(())
1100    }
1101}
1102
1103/// details of transient behaviour
1104///
1105/// These flags specify details of the expected behaviour
1106/// of transient surfaces. Used in the set_transient request.
1107#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
1108#[allow(dead_code)]
1109pub struct WlShellSurfaceTransient(pub u32);
1110
1111/// An iterator over the set bits in a [WlShellSurfaceTransient].
1112///
1113/// You can construct this with the `IntoIterator` implementation of `WlShellSurfaceTransient`.
1114#[derive(Clone, Debug)]
1115pub struct WlShellSurfaceTransientIter(pub u32);
1116
1117impl WlShellSurfaceTransient {
1118    /// do not set keyboard focus
1119    #[allow(dead_code)]
1120    pub const INACTIVE: Self = Self(0x1);
1121}
1122
1123#[allow(dead_code)]
1124impl WlShellSurfaceTransient {
1125    #[inline]
1126    pub const fn empty() -> Self {
1127        Self(0)
1128    }
1129
1130    #[inline]
1131    #[must_use]
1132    pub const fn is_empty(self) -> bool {
1133        self.0 == 0
1134    }
1135
1136    #[inline]
1137    #[must_use]
1138    pub const fn contains(self, other: Self) -> bool {
1139        self.0 & other.0 == other.0
1140    }
1141
1142    #[inline]
1143    #[must_use]
1144    pub const fn intersects(self, other: Self) -> bool {
1145        self.0 & other.0 != 0
1146    }
1147
1148    #[inline]
1149    pub const fn insert(&mut self, other: Self) {
1150        *self = self.union(other);
1151    }
1152
1153    #[inline]
1154    pub const fn remove(&mut self, other: Self) {
1155        *self = self.difference(other);
1156    }
1157
1158    #[inline]
1159    pub const fn toggle(&mut self, other: Self) {
1160        *self = self.symmetric_difference(other);
1161    }
1162
1163    #[inline]
1164    pub const fn set(&mut self, other: Self, value: bool) {
1165        if value {
1166            self.insert(other);
1167        } else {
1168            self.remove(other);
1169        }
1170    }
1171
1172    #[inline]
1173    #[must_use]
1174    pub const fn intersection(self, other: Self) -> Self {
1175        Self(self.0 & other.0)
1176    }
1177
1178    #[inline]
1179    #[must_use]
1180    pub const fn union(self, other: Self) -> Self {
1181        Self(self.0 | other.0)
1182    }
1183
1184    #[inline]
1185    #[must_use]
1186    pub const fn difference(self, other: Self) -> Self {
1187        Self(self.0 & !other.0)
1188    }
1189
1190    #[inline]
1191    #[must_use]
1192    pub const fn complement(self) -> Self {
1193        Self(!self.0)
1194    }
1195
1196    #[inline]
1197    #[must_use]
1198    pub const fn symmetric_difference(self, other: Self) -> Self {
1199        Self(self.0 ^ other.0)
1200    }
1201
1202    #[inline]
1203    pub const fn all_known() -> Self {
1204        #[allow(clippy::eq_op, clippy::identity_op)]
1205        Self(0 | 0x1)
1206    }
1207}
1208
1209impl Iterator for WlShellSurfaceTransientIter {
1210    type Item = WlShellSurfaceTransient;
1211
1212    fn next(&mut self) -> Option<Self::Item> {
1213        if self.0 == 0 {
1214            return None;
1215        }
1216        let bit = 1 << self.0.trailing_zeros();
1217        self.0 &= !bit;
1218        Some(WlShellSurfaceTransient(bit))
1219    }
1220}
1221
1222impl IntoIterator for WlShellSurfaceTransient {
1223    type Item = WlShellSurfaceTransient;
1224    type IntoIter = WlShellSurfaceTransientIter;
1225
1226    fn into_iter(self) -> Self::IntoIter {
1227        WlShellSurfaceTransientIter(self.0)
1228    }
1229}
1230
1231impl BitAnd for WlShellSurfaceTransient {
1232    type Output = Self;
1233
1234    fn bitand(self, rhs: Self) -> Self::Output {
1235        self.intersection(rhs)
1236    }
1237}
1238
1239impl BitAndAssign for WlShellSurfaceTransient {
1240    fn bitand_assign(&mut self, rhs: Self) {
1241        *self = self.intersection(rhs);
1242    }
1243}
1244
1245impl BitOr for WlShellSurfaceTransient {
1246    type Output = Self;
1247
1248    fn bitor(self, rhs: Self) -> Self::Output {
1249        self.union(rhs)
1250    }
1251}
1252
1253impl BitOrAssign for WlShellSurfaceTransient {
1254    fn bitor_assign(&mut self, rhs: Self) {
1255        *self = self.union(rhs);
1256    }
1257}
1258
1259impl BitXor for WlShellSurfaceTransient {
1260    type Output = Self;
1261
1262    fn bitxor(self, rhs: Self) -> Self::Output {
1263        self.symmetric_difference(rhs)
1264    }
1265}
1266
1267impl BitXorAssign for WlShellSurfaceTransient {
1268    fn bitxor_assign(&mut self, rhs: Self) {
1269        *self = self.symmetric_difference(rhs);
1270    }
1271}
1272
1273impl Sub for WlShellSurfaceTransient {
1274    type Output = Self;
1275
1276    fn sub(self, rhs: Self) -> Self::Output {
1277        self.difference(rhs)
1278    }
1279}
1280
1281impl SubAssign for WlShellSurfaceTransient {
1282    fn sub_assign(&mut self, rhs: Self) {
1283        *self = self.difference(rhs);
1284    }
1285}
1286
1287impl Not for WlShellSurfaceTransient {
1288    type Output = Self;
1289
1290    fn not(self) -> Self::Output {
1291        self.complement()
1292    }
1293}
1294
1295impl Debug for WlShellSurfaceTransient {
1296    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1297        let mut v = self.0;
1298        let mut first = true;
1299        if v & 0x1 == 0x1 {
1300            v &= !0x1;
1301            if first {
1302                first = false;
1303            } else {
1304                f.write_str(" | ")?;
1305            }
1306            f.write_str("INACTIVE")?;
1307        }
1308        if v != 0 {
1309            if first {
1310                first = false;
1311            } else {
1312                f.write_str(" | ")?;
1313            }
1314            write!(f, "0x{v:032x}")?;
1315        }
1316        if first {
1317            f.write_str("0")?;
1318        }
1319        Ok(())
1320    }
1321}
1322
1323/// different method to set the surface fullscreen
1324///
1325/// Hints to indicate to the compositor how to deal with a conflict
1326/// between the dimensions of the surface and the dimensions of the
1327/// output. The compositor is free to ignore this parameter.
1328#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1329#[allow(dead_code)]
1330pub struct WlShellSurfaceFullscreenMethod(pub u32);
1331
1332impl WlShellSurfaceFullscreenMethod {
1333    /// no preference, apply default policy
1334    #[allow(dead_code)]
1335    pub const DEFAULT: Self = Self(0);
1336
1337    /// scale, preserve the surface's aspect ratio and center on output
1338    #[allow(dead_code)]
1339    pub const SCALE: Self = Self(1);
1340
1341    /// switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch
1342    #[allow(dead_code)]
1343    pub const DRIVER: Self = Self(2);
1344
1345    /// no upscaling, center on output and add black borders to compensate size mismatch
1346    #[allow(dead_code)]
1347    pub const FILL: Self = Self(3);
1348}
1349
1350impl Debug for WlShellSurfaceFullscreenMethod {
1351    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1352        let name = match *self {
1353            Self::DEFAULT => "DEFAULT",
1354            Self::SCALE => "SCALE",
1355            Self::DRIVER => "DRIVER",
1356            Self::FILL => "FILL",
1357            _ => return Debug::fmt(&self.0, f),
1358        };
1359        f.write_str(name)
1360    }
1361}
1362
1363/// Functional event handlers.
1364pub mod event_handlers {
1365    use super::*;
1366
1367    /// Event handler for ping events.
1368    pub struct Ping<F>(F);
1369    impl<F> WlShellSurfaceEventHandler for Ping<F>
1370    where
1371        F: Fn(&WlShellSurfaceRef, u32),
1372    {
1373        #[inline]
1374        fn ping(&self, _slf: &WlShellSurfaceRef, serial: u32) {
1375            self.0(_slf, serial)
1376        }
1377    }
1378
1379    /// Event handler for configure events.
1380    pub struct Configure<F>(F);
1381    impl<F> WlShellSurfaceEventHandler for Configure<F>
1382    where
1383        F: Fn(&WlShellSurfaceRef, WlShellSurfaceResize, i32, i32),
1384    {
1385        #[inline]
1386        fn configure(
1387            &self,
1388            _slf: &WlShellSurfaceRef,
1389            edges: WlShellSurfaceResize,
1390            width: i32,
1391            height: i32,
1392        ) {
1393            self.0(_slf, edges, width, height)
1394        }
1395    }
1396
1397    /// Event handler for popup_done events.
1398    pub struct PopupDone<F>(F);
1399    impl<F> WlShellSurfaceEventHandler for PopupDone<F>
1400    where
1401        F: Fn(&WlShellSurfaceRef),
1402    {
1403        #[inline]
1404        fn popup_done(&self, _slf: &WlShellSurfaceRef) {
1405            self.0(_slf)
1406        }
1407    }
1408
1409    impl WlShellSurface {
1410        /// Creates an event handler for ping events.
1411        ///
1412        /// The event handler ignores all other events.
1413        #[allow(dead_code)]
1414        pub fn on_ping<F>(f: F) -> Ping<F>
1415        where
1416            F: Fn(&WlShellSurfaceRef, u32),
1417        {
1418            Ping(f)
1419        }
1420
1421        /// Creates an event handler for configure events.
1422        ///
1423        /// The event handler ignores all other events.
1424        #[allow(dead_code)]
1425        pub fn on_configure<F>(f: F) -> Configure<F>
1426        where
1427            F: Fn(&WlShellSurfaceRef, WlShellSurfaceResize, i32, i32),
1428        {
1429            Configure(f)
1430        }
1431
1432        /// Creates an event handler for popup_done events.
1433        ///
1434        /// The event handler ignores all other events.
1435        #[allow(dead_code)]
1436        pub fn on_popup_done<F>(f: F) -> PopupDone<F>
1437        where
1438            F: Fn(&WlShellSurfaceRef),
1439        {
1440            PopupDone(f)
1441        }
1442    }
1443}