simple_window/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        data: *mut u8,
693        slf: &UntypedBorrowedProxy,
694        opcode: u32,
695        args: *mut wl_argument,
696    ) {
697        // SAFETY: This function requires that slf has the interface INTERFACE
698        let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlShellSurfaceRef>(slf) };
699        match opcode {
700            0 => {
701                // SAFETY: INTERFACE requires that there are 1 arguments
702                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
703                // SAFETY: - INTERFACE requires that args[0] contains a uint
704                let arg0 = unsafe { args[0].u };
705                self.0.ping(slf, arg0);
706            }
707            1 => {
708                // SAFETY: INTERFACE requires that there are 3 arguments
709                let args = unsafe { &*args.cast::<[wl_argument; 3]>() };
710                // SAFETY: - INTERFACE requires that args[0] contains a uint
711                let arg0 = unsafe { WlShellSurfaceResize(args[0].u) };
712                // SAFETY: - INTERFACE requires that args[1] contains an int
713                let arg1 = unsafe { args[1].i };
714                // SAFETY: - INTERFACE requires that args[2] contains an int
715                let arg2 = unsafe { args[2].i };
716                self.0.configure(slf, arg0, arg1, arg2);
717            }
718            2 => {
719                self.0.popup_done(slf);
720            }
721            _ => {
722                invalid_opcode("wl_shell_surface", opcode);
723            }
724        }
725    }
726}
727
728impl<H> CreateEventHandler<H> for private::ProxyApi
729where
730    H: WlShellSurfaceEventHandler,
731{
732    type EventHandler = private::EventHandler<H>;
733
734    #[inline]
735    fn create_event_handler(handler: H) -> Self::EventHandler {
736        private::EventHandler(handler)
737    }
738}
739
740impl WlShellSurface {
741    /// Since when the resize.none enum variant is available.
742    #[allow(dead_code)]
743    pub const ENM__RESIZE_NONE__SINCE: u32 = 1;
744    /// Since when the resize.top enum variant is available.
745    #[allow(dead_code)]
746    pub const ENM__RESIZE_TOP__SINCE: u32 = 1;
747    /// Since when the resize.bottom enum variant is available.
748    #[allow(dead_code)]
749    pub const ENM__RESIZE_BOTTOM__SINCE: u32 = 1;
750    /// Since when the resize.left enum variant is available.
751    #[allow(dead_code)]
752    pub const ENM__RESIZE_LEFT__SINCE: u32 = 1;
753    /// Since when the resize.top_left enum variant is available.
754    #[allow(dead_code)]
755    pub const ENM__RESIZE_TOP_LEFT__SINCE: u32 = 1;
756    /// Since when the resize.bottom_left enum variant is available.
757    #[allow(dead_code)]
758    pub const ENM__RESIZE_BOTTOM_LEFT__SINCE: u32 = 1;
759    /// Since when the resize.right enum variant is available.
760    #[allow(dead_code)]
761    pub const ENM__RESIZE_RIGHT__SINCE: u32 = 1;
762    /// Since when the resize.top_right enum variant is available.
763    #[allow(dead_code)]
764    pub const ENM__RESIZE_TOP_RIGHT__SINCE: u32 = 1;
765    /// Since when the resize.bottom_right enum variant is available.
766    #[allow(dead_code)]
767    pub const ENM__RESIZE_BOTTOM_RIGHT__SINCE: u32 = 1;
768
769    /// Since when the transient.inactive enum variant is available.
770    #[allow(dead_code)]
771    pub const ENM__TRANSIENT_INACTIVE__SINCE: u32 = 1;
772
773    /// Since when the fullscreen_method.default enum variant is available.
774    #[allow(dead_code)]
775    pub const ENM__FULLSCREEN_METHOD_DEFAULT__SINCE: u32 = 1;
776    /// Since when the fullscreen_method.scale enum variant is available.
777    #[allow(dead_code)]
778    pub const ENM__FULLSCREEN_METHOD_SCALE__SINCE: u32 = 1;
779    /// Since when the fullscreen_method.driver enum variant is available.
780    #[allow(dead_code)]
781    pub const ENM__FULLSCREEN_METHOD_DRIVER__SINCE: u32 = 1;
782    /// Since when the fullscreen_method.fill enum variant is available.
783    #[allow(dead_code)]
784    pub const ENM__FULLSCREEN_METHOD_FILL__SINCE: u32 = 1;
785}
786
787/// edge values for resizing
788///
789/// These values are used to indicate which edge of a surface
790/// is being dragged in a resize operation. The server may
791/// use this information to adapt its behavior, e.g. choose
792/// an appropriate cursor image.
793#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
794#[allow(dead_code)]
795pub struct WlShellSurfaceResize(pub u32);
796
797/// An iterator over the set bits in a [WlShellSurfaceResize].
798///
799/// You can construct this with the `IntoIterator` implementation of `WlShellSurfaceResize`.
800#[derive(Clone, Debug)]
801pub struct WlShellSurfaceResizeIter(pub u32);
802
803impl WlShellSurfaceResize {
804    /// no edge
805    #[allow(dead_code)]
806    pub const NONE: Self = Self(0);
807
808    /// top edge
809    #[allow(dead_code)]
810    pub const TOP: Self = Self(1);
811
812    /// bottom edge
813    #[allow(dead_code)]
814    pub const BOTTOM: Self = Self(2);
815
816    /// left edge
817    #[allow(dead_code)]
818    pub const LEFT: Self = Self(4);
819
820    /// top and left edges
821    #[allow(dead_code)]
822    pub const TOP_LEFT: Self = Self(5);
823
824    /// bottom and left edges
825    #[allow(dead_code)]
826    pub const BOTTOM_LEFT: Self = Self(6);
827
828    /// right edge
829    #[allow(dead_code)]
830    pub const RIGHT: Self = Self(8);
831
832    /// top and right edges
833    #[allow(dead_code)]
834    pub const TOP_RIGHT: Self = Self(9);
835
836    /// bottom and right edges
837    #[allow(dead_code)]
838    pub const BOTTOM_RIGHT: Self = Self(10);
839}
840
841#[allow(dead_code)]
842impl WlShellSurfaceResize {
843    #[inline]
844    pub const fn empty() -> Self {
845        Self(0)
846    }
847
848    #[inline]
849    #[must_use]
850    pub const fn is_empty(self) -> bool {
851        self.0 == 0
852    }
853
854    #[inline]
855    #[must_use]
856    pub const fn contains(self, other: Self) -> bool {
857        self.0 & other.0 == other.0
858    }
859
860    #[inline]
861    #[must_use]
862    pub const fn intersects(self, other: Self) -> bool {
863        self.0 & other.0 != 0
864    }
865
866    #[inline]
867    pub const fn insert(&mut self, other: Self) {
868        *self = self.union(other);
869    }
870
871    #[inline]
872    pub const fn remove(&mut self, other: Self) {
873        *self = self.difference(other);
874    }
875
876    #[inline]
877    pub const fn toggle(&mut self, other: Self) {
878        *self = self.symmetric_difference(other);
879    }
880
881    #[inline]
882    pub const fn set(&mut self, other: Self, value: bool) {
883        if value {
884            self.insert(other);
885        } else {
886            self.remove(other);
887        }
888    }
889
890    #[inline]
891    #[must_use]
892    pub const fn intersection(self, other: Self) -> Self {
893        Self(self.0 & other.0)
894    }
895
896    #[inline]
897    #[must_use]
898    pub const fn union(self, other: Self) -> Self {
899        Self(self.0 | other.0)
900    }
901
902    #[inline]
903    #[must_use]
904    pub const fn difference(self, other: Self) -> Self {
905        Self(self.0 & !other.0)
906    }
907
908    #[inline]
909    #[must_use]
910    pub const fn complement(self) -> Self {
911        Self(!self.0)
912    }
913
914    #[inline]
915    #[must_use]
916    pub const fn symmetric_difference(self, other: Self) -> Self {
917        Self(self.0 ^ other.0)
918    }
919
920    #[inline]
921    pub const fn all_known() -> Self {
922        #[allow(clippy::eq_op, clippy::identity_op)]
923        Self(0 | 0 | 1 | 2 | 4 | 5 | 6 | 8 | 9 | 10)
924    }
925}
926
927impl Iterator for WlShellSurfaceResizeIter {
928    type Item = WlShellSurfaceResize;
929
930    fn next(&mut self) -> Option<Self::Item> {
931        if self.0 == 0 {
932            return None;
933        }
934        let bit = 1 << self.0.trailing_zeros();
935        self.0 &= !bit;
936        Some(WlShellSurfaceResize(bit))
937    }
938}
939
940impl IntoIterator for WlShellSurfaceResize {
941    type Item = WlShellSurfaceResize;
942    type IntoIter = WlShellSurfaceResizeIter;
943
944    fn into_iter(self) -> Self::IntoIter {
945        WlShellSurfaceResizeIter(self.0)
946    }
947}
948
949impl BitAnd for WlShellSurfaceResize {
950    type Output = Self;
951
952    fn bitand(self, rhs: Self) -> Self::Output {
953        self.intersection(rhs)
954    }
955}
956
957impl BitAndAssign for WlShellSurfaceResize {
958    fn bitand_assign(&mut self, rhs: Self) {
959        *self = self.intersection(rhs);
960    }
961}
962
963impl BitOr for WlShellSurfaceResize {
964    type Output = Self;
965
966    fn bitor(self, rhs: Self) -> Self::Output {
967        self.union(rhs)
968    }
969}
970
971impl BitOrAssign for WlShellSurfaceResize {
972    fn bitor_assign(&mut self, rhs: Self) {
973        *self = self.union(rhs);
974    }
975}
976
977impl BitXor for WlShellSurfaceResize {
978    type Output = Self;
979
980    fn bitxor(self, rhs: Self) -> Self::Output {
981        self.symmetric_difference(rhs)
982    }
983}
984
985impl BitXorAssign for WlShellSurfaceResize {
986    fn bitxor_assign(&mut self, rhs: Self) {
987        *self = self.symmetric_difference(rhs);
988    }
989}
990
991impl Sub for WlShellSurfaceResize {
992    type Output = Self;
993
994    fn sub(self, rhs: Self) -> Self::Output {
995        self.difference(rhs)
996    }
997}
998
999impl SubAssign for WlShellSurfaceResize {
1000    fn sub_assign(&mut self, rhs: Self) {
1001        *self = self.difference(rhs);
1002    }
1003}
1004
1005impl Not for WlShellSurfaceResize {
1006    type Output = Self;
1007
1008    fn not(self) -> Self::Output {
1009        self.complement()
1010    }
1011}
1012
1013impl Debug for WlShellSurfaceResize {
1014    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1015        let mut v = self.0;
1016        let mut first = true;
1017        if v & 1 == 1 {
1018            v &= !1;
1019            if first {
1020                first = false;
1021            } else {
1022                f.write_str(" | ")?;
1023            }
1024            f.write_str("TOP")?;
1025        }
1026        if v & 2 == 2 {
1027            v &= !2;
1028            if first {
1029                first = false;
1030            } else {
1031                f.write_str(" | ")?;
1032            }
1033            f.write_str("BOTTOM")?;
1034        }
1035        if v & 4 == 4 {
1036            v &= !4;
1037            if first {
1038                first = false;
1039            } else {
1040                f.write_str(" | ")?;
1041            }
1042            f.write_str("LEFT")?;
1043        }
1044        if v & 5 == 5 {
1045            v &= !5;
1046            if first {
1047                first = false;
1048            } else {
1049                f.write_str(" | ")?;
1050            }
1051            f.write_str("TOP_LEFT")?;
1052        }
1053        if v & 6 == 6 {
1054            v &= !6;
1055            if first {
1056                first = false;
1057            } else {
1058                f.write_str(" | ")?;
1059            }
1060            f.write_str("BOTTOM_LEFT")?;
1061        }
1062        if v & 8 == 8 {
1063            v &= !8;
1064            if first {
1065                first = false;
1066            } else {
1067                f.write_str(" | ")?;
1068            }
1069            f.write_str("RIGHT")?;
1070        }
1071        if v & 9 == 9 {
1072            v &= !9;
1073            if first {
1074                first = false;
1075            } else {
1076                f.write_str(" | ")?;
1077            }
1078            f.write_str("TOP_RIGHT")?;
1079        }
1080        if v & 10 == 10 {
1081            v &= !10;
1082            if first {
1083                first = false;
1084            } else {
1085                f.write_str(" | ")?;
1086            }
1087            f.write_str("BOTTOM_RIGHT")?;
1088        }
1089        if v != 0 {
1090            if first {
1091                first = false;
1092            } else {
1093                f.write_str(" | ")?;
1094            }
1095            write!(f, "0x{v:032x}")?;
1096        }
1097        if first {
1098            f.write_str("NONE")?;
1099        }
1100        Ok(())
1101    }
1102}
1103
1104/// details of transient behaviour
1105///
1106/// These flags specify details of the expected behaviour
1107/// of transient surfaces. Used in the set_transient request.
1108#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
1109#[allow(dead_code)]
1110pub struct WlShellSurfaceTransient(pub u32);
1111
1112/// An iterator over the set bits in a [WlShellSurfaceTransient].
1113///
1114/// You can construct this with the `IntoIterator` implementation of `WlShellSurfaceTransient`.
1115#[derive(Clone, Debug)]
1116pub struct WlShellSurfaceTransientIter(pub u32);
1117
1118impl WlShellSurfaceTransient {
1119    /// do not set keyboard focus
1120    #[allow(dead_code)]
1121    pub const INACTIVE: Self = Self(0x1);
1122}
1123
1124#[allow(dead_code)]
1125impl WlShellSurfaceTransient {
1126    #[inline]
1127    pub const fn empty() -> Self {
1128        Self(0)
1129    }
1130
1131    #[inline]
1132    #[must_use]
1133    pub const fn is_empty(self) -> bool {
1134        self.0 == 0
1135    }
1136
1137    #[inline]
1138    #[must_use]
1139    pub const fn contains(self, other: Self) -> bool {
1140        self.0 & other.0 == other.0
1141    }
1142
1143    #[inline]
1144    #[must_use]
1145    pub const fn intersects(self, other: Self) -> bool {
1146        self.0 & other.0 != 0
1147    }
1148
1149    #[inline]
1150    pub const fn insert(&mut self, other: Self) {
1151        *self = self.union(other);
1152    }
1153
1154    #[inline]
1155    pub const fn remove(&mut self, other: Self) {
1156        *self = self.difference(other);
1157    }
1158
1159    #[inline]
1160    pub const fn toggle(&mut self, other: Self) {
1161        *self = self.symmetric_difference(other);
1162    }
1163
1164    #[inline]
1165    pub const fn set(&mut self, other: Self, value: bool) {
1166        if value {
1167            self.insert(other);
1168        } else {
1169            self.remove(other);
1170        }
1171    }
1172
1173    #[inline]
1174    #[must_use]
1175    pub const fn intersection(self, other: Self) -> Self {
1176        Self(self.0 & other.0)
1177    }
1178
1179    #[inline]
1180    #[must_use]
1181    pub const fn union(self, other: Self) -> Self {
1182        Self(self.0 | other.0)
1183    }
1184
1185    #[inline]
1186    #[must_use]
1187    pub const fn difference(self, other: Self) -> Self {
1188        Self(self.0 & !other.0)
1189    }
1190
1191    #[inline]
1192    #[must_use]
1193    pub const fn complement(self) -> Self {
1194        Self(!self.0)
1195    }
1196
1197    #[inline]
1198    #[must_use]
1199    pub const fn symmetric_difference(self, other: Self) -> Self {
1200        Self(self.0 ^ other.0)
1201    }
1202
1203    #[inline]
1204    pub const fn all_known() -> Self {
1205        #[allow(clippy::eq_op, clippy::identity_op)]
1206        Self(0 | 0x1)
1207    }
1208}
1209
1210impl Iterator for WlShellSurfaceTransientIter {
1211    type Item = WlShellSurfaceTransient;
1212
1213    fn next(&mut self) -> Option<Self::Item> {
1214        if self.0 == 0 {
1215            return None;
1216        }
1217        let bit = 1 << self.0.trailing_zeros();
1218        self.0 &= !bit;
1219        Some(WlShellSurfaceTransient(bit))
1220    }
1221}
1222
1223impl IntoIterator for WlShellSurfaceTransient {
1224    type Item = WlShellSurfaceTransient;
1225    type IntoIter = WlShellSurfaceTransientIter;
1226
1227    fn into_iter(self) -> Self::IntoIter {
1228        WlShellSurfaceTransientIter(self.0)
1229    }
1230}
1231
1232impl BitAnd for WlShellSurfaceTransient {
1233    type Output = Self;
1234
1235    fn bitand(self, rhs: Self) -> Self::Output {
1236        self.intersection(rhs)
1237    }
1238}
1239
1240impl BitAndAssign for WlShellSurfaceTransient {
1241    fn bitand_assign(&mut self, rhs: Self) {
1242        *self = self.intersection(rhs);
1243    }
1244}
1245
1246impl BitOr for WlShellSurfaceTransient {
1247    type Output = Self;
1248
1249    fn bitor(self, rhs: Self) -> Self::Output {
1250        self.union(rhs)
1251    }
1252}
1253
1254impl BitOrAssign for WlShellSurfaceTransient {
1255    fn bitor_assign(&mut self, rhs: Self) {
1256        *self = self.union(rhs);
1257    }
1258}
1259
1260impl BitXor for WlShellSurfaceTransient {
1261    type Output = Self;
1262
1263    fn bitxor(self, rhs: Self) -> Self::Output {
1264        self.symmetric_difference(rhs)
1265    }
1266}
1267
1268impl BitXorAssign for WlShellSurfaceTransient {
1269    fn bitxor_assign(&mut self, rhs: Self) {
1270        *self = self.symmetric_difference(rhs);
1271    }
1272}
1273
1274impl Sub for WlShellSurfaceTransient {
1275    type Output = Self;
1276
1277    fn sub(self, rhs: Self) -> Self::Output {
1278        self.difference(rhs)
1279    }
1280}
1281
1282impl SubAssign for WlShellSurfaceTransient {
1283    fn sub_assign(&mut self, rhs: Self) {
1284        *self = self.difference(rhs);
1285    }
1286}
1287
1288impl Not for WlShellSurfaceTransient {
1289    type Output = Self;
1290
1291    fn not(self) -> Self::Output {
1292        self.complement()
1293    }
1294}
1295
1296impl Debug for WlShellSurfaceTransient {
1297    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1298        let mut v = self.0;
1299        let mut first = true;
1300        if v & 0x1 == 0x1 {
1301            v &= !0x1;
1302            if first {
1303                first = false;
1304            } else {
1305                f.write_str(" | ")?;
1306            }
1307            f.write_str("INACTIVE")?;
1308        }
1309        if v != 0 {
1310            if first {
1311                first = false;
1312            } else {
1313                f.write_str(" | ")?;
1314            }
1315            write!(f, "0x{v:032x}")?;
1316        }
1317        if first {
1318            f.write_str("0")?;
1319        }
1320        Ok(())
1321    }
1322}
1323
1324/// different method to set the surface fullscreen
1325///
1326/// Hints to indicate to the compositor how to deal with a conflict
1327/// between the dimensions of the surface and the dimensions of the
1328/// output. The compositor is free to ignore this parameter.
1329#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1330#[allow(dead_code)]
1331pub struct WlShellSurfaceFullscreenMethod(pub u32);
1332
1333impl WlShellSurfaceFullscreenMethod {
1334    /// no preference, apply default policy
1335    #[allow(dead_code)]
1336    pub const DEFAULT: Self = Self(0);
1337
1338    /// scale, preserve the surface's aspect ratio and center on output
1339    #[allow(dead_code)]
1340    pub const SCALE: Self = Self(1);
1341
1342    /// switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch
1343    #[allow(dead_code)]
1344    pub const DRIVER: Self = Self(2);
1345
1346    /// no upscaling, center on output and add black borders to compensate size mismatch
1347    #[allow(dead_code)]
1348    pub const FILL: Self = Self(3);
1349}
1350
1351impl Debug for WlShellSurfaceFullscreenMethod {
1352    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1353        let name = match *self {
1354            Self::DEFAULT => "DEFAULT",
1355            Self::SCALE => "SCALE",
1356            Self::DRIVER => "DRIVER",
1357            Self::FILL => "FILL",
1358            _ => return Debug::fmt(&self.0, f),
1359        };
1360        f.write_str(name)
1361    }
1362}
1363
1364/// Functional event handlers.
1365pub mod event_handlers {
1366    use super::*;
1367
1368    /// Event handler for ping events.
1369    pub struct Ping<F>(F);
1370    impl<F> WlShellSurfaceEventHandler for Ping<F>
1371    where
1372        F: Fn(&WlShellSurfaceRef, u32),
1373    {
1374        #[inline]
1375        fn ping(&self, _slf: &WlShellSurfaceRef, serial: u32) {
1376            self.0(_slf, serial)
1377        }
1378    }
1379
1380    /// Event handler for configure events.
1381    pub struct Configure<F>(F);
1382    impl<F> WlShellSurfaceEventHandler for Configure<F>
1383    where
1384        F: Fn(&WlShellSurfaceRef, WlShellSurfaceResize, i32, i32),
1385    {
1386        #[inline]
1387        fn configure(
1388            &self,
1389            _slf: &WlShellSurfaceRef,
1390            edges: WlShellSurfaceResize,
1391            width: i32,
1392            height: i32,
1393        ) {
1394            self.0(_slf, edges, width, height)
1395        }
1396    }
1397
1398    /// Event handler for popup_done events.
1399    pub struct PopupDone<F>(F);
1400    impl<F> WlShellSurfaceEventHandler for PopupDone<F>
1401    where
1402        F: Fn(&WlShellSurfaceRef),
1403    {
1404        #[inline]
1405        fn popup_done(&self, _slf: &WlShellSurfaceRef) {
1406            self.0(_slf)
1407        }
1408    }
1409
1410    impl WlShellSurface {
1411        /// Creates an event handler for ping events.
1412        ///
1413        /// The event handler ignores all other events.
1414        #[allow(dead_code)]
1415        pub fn on_ping<F>(f: F) -> Ping<F>
1416        where
1417            F: Fn(&WlShellSurfaceRef, u32),
1418        {
1419            Ping(f)
1420        }
1421
1422        /// Creates an event handler for configure events.
1423        ///
1424        /// The event handler ignores all other events.
1425        #[allow(dead_code)]
1426        pub fn on_configure<F>(f: F) -> Configure<F>
1427        where
1428            F: Fn(&WlShellSurfaceRef, WlShellSurfaceResize, i32, i32),
1429        {
1430            Configure(f)
1431        }
1432
1433        /// Creates an event handler for popup_done events.
1434        ///
1435        /// The event handler ignores all other events.
1436        #[allow(dead_code)]
1437        pub fn on_popup_done<F>(f: F) -> PopupDone<F>
1438        where
1439            F: Fn(&WlShellSurfaceRef),
1440        {
1441            PopupDone(f)
1442        }
1443    }
1444}