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