poll_integration/common/protocols/wayland/
wl_output.rs

1//! compositor output region
2//!
3//! An output describes part of the compositor geometry.  The
4//! compositor works in the 'compositor coordinate system' and an
5//! output corresponds to a rectangular area in that space that is
6//! actually visible.  This typically corresponds to a monitor that
7//! displays part of the compositor space.  This object is published
8//! as global during start up, or when a monitor is hotplugged.
9
10use {super::super::all_types::*, ::wl_client::builder::prelude::*};
11
12static INTERFACE: wl_interface = wl_interface {
13    name: c"wl_output".as_ptr(),
14    version: 4,
15    method_count: 1,
16    methods: {
17        static MESSAGES: [wl_message; 1] = [wl_message {
18            name: c"release".as_ptr(),
19            signature: c"".as_ptr(),
20            types: {
21                static TYPES: [Option<&'static wl_interface>; 0] = [];
22                TYPES.as_ptr().cast()
23            },
24        }];
25        MESSAGES.as_ptr()
26    },
27    event_count: 6,
28    events: {
29        static MESSAGES: [wl_message; 6] = [
30            wl_message {
31                name: c"geometry".as_ptr(),
32                signature: c"iiiiissi".as_ptr(),
33                types: {
34                    static TYPES: [Option<&'static wl_interface>; 8] =
35                        [None, None, None, None, None, None, None, None];
36                    TYPES.as_ptr().cast()
37                },
38            },
39            wl_message {
40                name: c"mode".as_ptr(),
41                signature: c"uiii".as_ptr(),
42                types: {
43                    static TYPES: [Option<&'static wl_interface>; 4] = [None, None, None, None];
44                    TYPES.as_ptr().cast()
45                },
46            },
47            wl_message {
48                name: c"done".as_ptr(),
49                signature: c"".as_ptr(),
50                types: {
51                    static TYPES: [Option<&'static wl_interface>; 0] = [];
52                    TYPES.as_ptr().cast()
53                },
54            },
55            wl_message {
56                name: c"scale".as_ptr(),
57                signature: c"i".as_ptr(),
58                types: {
59                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
60                    TYPES.as_ptr().cast()
61                },
62            },
63            wl_message {
64                name: c"name".as_ptr(),
65                signature: c"s".as_ptr(),
66                types: {
67                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
68                    TYPES.as_ptr().cast()
69                },
70            },
71            wl_message {
72                name: c"description".as_ptr(),
73                signature: c"s".as_ptr(),
74                types: {
75                    static TYPES: [Option<&'static wl_interface>; 1] = [None];
76                    TYPES.as_ptr().cast()
77                },
78            },
79        ];
80        MESSAGES.as_ptr()
81    },
82};
83
84/// An owned wl_output proxy.
85///
86/// See the documentation of [the module][self] for the interface description.
87#[derive(Clone, Eq, PartialEq)]
88#[repr(transparent)]
89pub struct WlOutput {
90    /// This proxy has the interface INTERFACE.
91    proxy: UntypedOwnedProxy,
92}
93
94/// A borrowed wl_output proxy.
95///
96/// See the documentation of [the module][self] for the interface description.
97#[derive(Eq, PartialEq)]
98#[repr(transparent)]
99pub struct WlOutputRef {
100    /// This proxy has the interface INTERFACE.
101    proxy: UntypedBorrowedProxy,
102}
103
104// SAFETY: WlOutput is a transparent wrapper around UntypedOwnedProxy
105unsafe impl UntypedOwnedProxyWrapper for WlOutput {}
106
107// SAFETY: - INTERFACE is a valid wl_interface
108//         - The only invariant is that self.proxy has a compatible interface
109unsafe impl OwnedProxy for WlOutput {
110    const INTERFACE: &'static str = "wl_output";
111    const WL_INTERFACE: &'static wl_interface = &INTERFACE;
112    const NO_OP_EVENT_HANDLER: Self::NoOpEventHandler =
113        private::EventHandler(private::NoOpEventHandler);
114    const MAX_VERSION: u32 = 4;
115
116    type Borrowed = WlOutputRef;
117    type Api = private::ProxyApi;
118    type NoOpEventHandler = private::EventHandler<private::NoOpEventHandler>;
119}
120
121// SAFETY: WlOutputRef is a transparent wrapper around UntypedBorrowedProxy
122unsafe impl UntypedBorrowedProxyWrapper for WlOutputRef {}
123
124// SAFETY: - The only invariant is that self.proxy has a compatible interface
125unsafe impl BorrowedProxy for WlOutputRef {
126    type Owned = WlOutput;
127}
128
129impl Deref for WlOutput {
130    type Target = WlOutputRef;
131
132    fn deref(&self) -> &Self::Target {
133        proxy::low_level::deref(self)
134    }
135}
136
137mod private {
138    pub struct ProxyApi;
139
140    #[allow(dead_code)]
141    pub struct EventHandler<H>(pub(super) H);
142
143    #[allow(dead_code)]
144    pub struct NoOpEventHandler;
145}
146
147impl Debug for WlOutput {
148    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
149        write!(f, "wl_output#{}", self.proxy.id())
150    }
151}
152
153impl Debug for WlOutputRef {
154    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
155        write!(f, "wl_output#{}", self.proxy.id())
156    }
157}
158
159impl PartialEq<WlOutputRef> for WlOutput {
160    fn eq(&self, other: &WlOutputRef) -> bool {
161        self.proxy == other.proxy
162    }
163}
164
165impl PartialEq<WlOutput> for WlOutputRef {
166    fn eq(&self, other: &WlOutput) -> bool {
167        self.proxy == other.proxy
168    }
169}
170
171#[allow(dead_code)]
172impl WlOutput {
173    /// Since when the release request is available.
174    #[allow(dead_code)]
175    pub const REQ__RELEASE__SINCE: u32 = 3;
176
177    /// release the output object
178    ///
179    /// Using this request a client can tell the server that it is not going to
180    /// use the output object anymore.
181    #[inline]
182    pub fn release(&self) {
183        let mut args = [];
184        // SAFETY: - self.proxy has the interface INTERFACE
185        //         - 0 < INTERFACE.method_count = 1
186        //         - the request signature is ``
187        unsafe {
188            self.proxy.send_destructor(0, &mut args);
189        }
190    }
191}
192
193impl WlOutput {
194    /// Since when the geometry event is available.
195    #[allow(dead_code)]
196    pub const EVT__GEOMETRY__SINCE: u32 = 1;
197
198    /// Since when the mode event is available.
199    #[allow(dead_code)]
200    pub const EVT__MODE__SINCE: u32 = 1;
201
202    /// Since when the done event is available.
203    #[allow(dead_code)]
204    pub const EVT__DONE__SINCE: u32 = 2;
205
206    /// Since when the scale event is available.
207    #[allow(dead_code)]
208    pub const EVT__SCALE__SINCE: u32 = 2;
209
210    /// Since when the name event is available.
211    #[allow(dead_code)]
212    pub const EVT__NAME__SINCE: u32 = 4;
213
214    /// Since when the description event is available.
215    #[allow(dead_code)]
216    pub const EVT__DESCRIPTION__SINCE: u32 = 4;
217}
218
219/// An event handler for [WlOutput] proxies.
220#[allow(dead_code)]
221pub trait WlOutputEventHandler {
222    /// properties of the output
223    ///
224    /// The geometry event describes geometric properties of the output.
225    /// The event is sent when binding to the output object and whenever
226    /// any of the properties change.
227    ///
228    /// The physical size can be set to zero if it doesn't make sense for this
229    /// output (e.g. for projectors or virtual outputs).
230    ///
231    /// The geometry event will be followed by a done event (starting from
232    /// version 2).
233    ///
234    /// Clients should use wl_surface.preferred_buffer_transform instead of the
235    /// transform advertised by this event to find the preferred buffer
236    /// transform to use for a surface.
237    ///
238    /// Note: wl_output only advertises partial information about the output
239    /// position and identification. Some compositors, for instance those not
240    /// implementing a desktop-style output layout or those exposing virtual
241    /// outputs, might fake this information. Instead of using x and y, clients
242    /// should use xdg_output.logical_position. Instead of using make and model,
243    /// clients should use name and description.
244    ///
245    /// # Arguments
246    ///
247    /// - `x`: x position within the global compositor space
248    /// - `y`: y position within the global compositor space
249    /// - `physical_width`: width in millimeters of the output
250    /// - `physical_height`: height in millimeters of the output
251    /// - `subpixel`: subpixel orientation of the output
252    /// - `make`: textual description of the manufacturer
253    /// - `model`: textual description of the model
254    /// - `transform`: additional transformation applied to buffer contents during presentation
255    #[inline]
256    fn geometry(
257        &self,
258        _slf: &WlOutputRef,
259        x: i32,
260        y: i32,
261        physical_width: i32,
262        physical_height: i32,
263        subpixel: WlOutputSubpixel,
264        make: &str,
265        model: &str,
266        transform: WlOutputTransform,
267    ) {
268        let _ = x;
269        let _ = y;
270        let _ = physical_width;
271        let _ = physical_height;
272        let _ = subpixel;
273        let _ = make;
274        let _ = model;
275        let _ = transform;
276    }
277
278    /// advertise available modes for the output
279    ///
280    /// The mode event describes an available mode for the output.
281    ///
282    /// The event is sent when binding to the output object and there
283    /// will always be one mode, the current mode.  The event is sent
284    /// again if an output changes mode, for the mode that is now
285    /// current.  In other words, the current mode is always the last
286    /// mode that was received with the current flag set.
287    ///
288    /// Non-current modes are deprecated. A compositor can decide to only
289    /// advertise the current mode and never send other modes. Clients
290    /// should not rely on non-current modes.
291    ///
292    /// The size of a mode is given in physical hardware units of
293    /// the output device. This is not necessarily the same as
294    /// the output size in the global compositor space. For instance,
295    /// the output may be scaled, as described in wl_output.scale,
296    /// or transformed, as described in wl_output.transform. Clients
297    /// willing to retrieve the output size in the global compositor
298    /// space should use xdg_output.logical_size instead.
299    ///
300    /// The vertical refresh rate can be set to zero if it doesn't make
301    /// sense for this output (e.g. for virtual outputs).
302    ///
303    /// The mode event will be followed by a done event (starting from
304    /// version 2).
305    ///
306    /// Clients should not use the refresh rate to schedule frames. Instead,
307    /// they should use the wl_surface.frame event or the presentation-time
308    /// protocol.
309    ///
310    /// Note: this information is not always meaningful for all outputs. Some
311    /// compositors, such as those exposing virtual outputs, might fake the
312    /// refresh rate or the size.
313    ///
314    /// # Arguments
315    ///
316    /// - `flags`: bitfield of mode flags
317    /// - `width`: width of the mode in hardware units
318    /// - `height`: height of the mode in hardware units
319    /// - `refresh`: vertical refresh rate in mHz
320    #[inline]
321    fn mode(&self, _slf: &WlOutputRef, flags: WlOutputMode, width: i32, height: i32, refresh: i32) {
322        let _ = flags;
323        let _ = width;
324        let _ = height;
325        let _ = refresh;
326    }
327
328    /// sent all information about output
329    ///
330    /// This event is sent after all other properties have been
331    /// sent after binding to the output object and after any
332    /// other property changes done after that. This allows
333    /// changes to the output properties to be seen as
334    /// atomic, even if they happen via multiple events.
335    #[inline]
336    fn done(&self, _slf: &WlOutputRef) {}
337
338    /// output scaling properties
339    ///
340    /// This event contains scaling geometry information
341    /// that is not in the geometry event. It may be sent after
342    /// binding the output object or if the output scale changes
343    /// later. The compositor will emit a non-zero, positive
344    /// value for scale. If it is not sent, the client should
345    /// assume a scale of 1.
346    ///
347    /// A scale larger than 1 means that the compositor will
348    /// automatically scale surface buffers by this amount
349    /// when rendering. This is used for very high resolution
350    /// displays where applications rendering at the native
351    /// resolution would be too small to be legible.
352    ///
353    /// Clients should use wl_surface.preferred_buffer_scale
354    /// instead of this event to find the preferred buffer
355    /// scale to use for a surface.
356    ///
357    /// The scale event will be followed by a done event.
358    ///
359    /// # Arguments
360    ///
361    /// - `factor`: scaling factor of output
362    #[inline]
363    fn scale(&self, _slf: &WlOutputRef, factor: i32) {
364        let _ = factor;
365    }
366
367    /// name of this output
368    ///
369    /// Many compositors will assign user-friendly names to their outputs, show
370    /// them to the user, allow the user to refer to an output, etc. The client
371    /// may wish to know this name as well to offer the user similar behaviors.
372    ///
373    /// The name is a UTF-8 string with no convention defined for its contents.
374    /// Each name is unique among all wl_output globals. The name is only
375    /// guaranteed to be unique for the compositor instance.
376    ///
377    /// The same output name is used for all clients for a given wl_output
378    /// global. Thus, the name can be shared across processes to refer to a
379    /// specific wl_output global.
380    ///
381    /// The name is not guaranteed to be persistent across sessions, thus cannot
382    /// be used to reliably identify an output in e.g. configuration files.
383    ///
384    /// Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
385    /// not assume that the name is a reflection of an underlying DRM connector,
386    /// X11 connection, etc.
387    ///
388    /// The name event is sent after binding the output object. This event is
389    /// only sent once per output object, and the name does not change over the
390    /// lifetime of the wl_output global.
391    ///
392    /// Compositors may re-use the same output name if the wl_output global is
393    /// destroyed and re-created later. Compositors should avoid re-using the
394    /// same name if possible.
395    ///
396    /// The name event will be followed by a done event.
397    ///
398    /// # Arguments
399    ///
400    /// - `name`: output name
401    #[inline]
402    fn name(&self, _slf: &WlOutputRef, name: &str) {
403        let _ = name;
404    }
405
406    /// human-readable description of this output
407    ///
408    /// Many compositors can produce human-readable descriptions of their
409    /// outputs. The client may wish to know this description as well, e.g. for
410    /// output selection purposes.
411    ///
412    /// The description is a UTF-8 string with no convention defined for its
413    /// contents. The description is not guaranteed to be unique among all
414    /// wl_output globals. Examples might include 'Foocorp 11" Display' or
415    /// 'Virtual X11 output via :1'.
416    ///
417    /// The description event is sent after binding the output object and
418    /// whenever the description changes. The description is optional, and may
419    /// not be sent at all.
420    ///
421    /// The description event will be followed by a done event.
422    ///
423    /// # Arguments
424    ///
425    /// - `description`: output description
426    #[inline]
427    fn description(&self, _slf: &WlOutputRef, description: &str) {
428        let _ = description;
429    }
430}
431
432impl WlOutputEventHandler for private::NoOpEventHandler {}
433
434// SAFETY: INTERFACE is a valid wl_interface
435unsafe impl<H> EventHandler for private::EventHandler<H>
436where
437    H: WlOutputEventHandler,
438{
439    const WL_INTERFACE: &'static wl_interface = &INTERFACE;
440
441    #[allow(unused_variables)]
442    unsafe fn handle_event(
443        &self,
444        queue: &Queue,
445        slf: &UntypedBorrowedProxy,
446        opcode: u32,
447        args: *mut wl_argument,
448    ) {
449        // SAFETY: This function required that slf has the interface INTERFACE
450        let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlOutputRef>(slf) };
451        match opcode {
452            0 => {
453                // SAFETY: INTERFACE requires that there are 8 arguments
454                let args = unsafe { &*args.cast::<[wl_argument; 8]>() };
455                // SAFETY: - INTERFACE requires that args[0] contains an int
456                let arg0 = unsafe { args[0].i };
457                // SAFETY: - INTERFACE requires that args[1] contains an int
458                let arg1 = unsafe { args[1].i };
459                // SAFETY: - INTERFACE requires that args[2] contains an int
460                let arg2 = unsafe { args[2].i };
461                // SAFETY: - INTERFACE requires that args[3] contains an int
462                let arg3 = unsafe { args[3].i };
463                // SAFETY: - INTERFACE requires that args[4] contains an int
464                let arg4 = unsafe { WlOutputSubpixel(args[4].u) };
465                // SAFETY: - INTERFACE requires that args[5] contains a string
466                //         - if the pointer is not null, then it is a c string
467                let arg5 = unsafe { convert_string_arg("wl_output", "make", args[5].s) };
468                // SAFETY: - INTERFACE requires that args[6] contains a string
469                //         - if the pointer is not null, then it is a c string
470                let arg6 = unsafe { convert_string_arg("wl_output", "model", args[6].s) };
471                // SAFETY: - INTERFACE requires that args[7] contains an int
472                let arg7 = unsafe { WlOutputTransform(args[7].u) };
473                self.0
474                    .geometry(slf, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
475            }
476            1 => {
477                // SAFETY: INTERFACE requires that there are 4 arguments
478                let args = unsafe { &*args.cast::<[wl_argument; 4]>() };
479                // SAFETY: - INTERFACE requires that args[0] contains a uint
480                let arg0 = unsafe { WlOutputMode(args[0].u) };
481                // SAFETY: - INTERFACE requires that args[1] contains an int
482                let arg1 = unsafe { args[1].i };
483                // SAFETY: - INTERFACE requires that args[2] contains an int
484                let arg2 = unsafe { args[2].i };
485                // SAFETY: - INTERFACE requires that args[3] contains an int
486                let arg3 = unsafe { args[3].i };
487                self.0.mode(slf, arg0, arg1, arg2, arg3);
488            }
489            2 => {
490                self.0.done(slf);
491            }
492            3 => {
493                // SAFETY: INTERFACE requires that there are 1 arguments
494                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
495                // SAFETY: - INTERFACE requires that args[0] contains an int
496                let arg0 = unsafe { args[0].i };
497                self.0.scale(slf, arg0);
498            }
499            4 => {
500                // SAFETY: INTERFACE requires that there are 1 arguments
501                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
502                // SAFETY: - INTERFACE requires that args[0] contains a string
503                //         - if the pointer is not null, then it is a c string
504                let arg0 = unsafe { convert_string_arg("wl_output", "name", args[0].s) };
505                self.0.name(slf, arg0);
506            }
507            5 => {
508                // SAFETY: INTERFACE requires that there are 1 arguments
509                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
510                // SAFETY: - INTERFACE requires that args[0] contains a string
511                //         - if the pointer is not null, then it is a c string
512                let arg0 = unsafe { convert_string_arg("wl_output", "description", args[0].s) };
513                self.0.description(slf, arg0);
514            }
515            _ => {
516                invalid_opcode("wl_output", opcode);
517            }
518        }
519    }
520}
521
522impl<H> CreateEventHandler<H> for private::ProxyApi
523where
524    H: WlOutputEventHandler,
525{
526    type EventHandler = private::EventHandler<H>;
527
528    #[inline]
529    fn create_event_handler(handler: H) -> Self::EventHandler {
530        private::EventHandler(handler)
531    }
532}
533
534impl WlOutput {
535    /// Since when the subpixel.unknown enum variant is available.
536    #[allow(dead_code)]
537    pub const ENM__SUBPIXEL_UNKNOWN__SINCE: u32 = 1;
538    /// Since when the subpixel.none enum variant is available.
539    #[allow(dead_code)]
540    pub const ENM__SUBPIXEL_NONE__SINCE: u32 = 1;
541    /// Since when the subpixel.horizontal_rgb enum variant is available.
542    #[allow(dead_code)]
543    pub const ENM__SUBPIXEL_HORIZONTAL_RGB__SINCE: u32 = 1;
544    /// Since when the subpixel.horizontal_bgr enum variant is available.
545    #[allow(dead_code)]
546    pub const ENM__SUBPIXEL_HORIZONTAL_BGR__SINCE: u32 = 1;
547    /// Since when the subpixel.vertical_rgb enum variant is available.
548    #[allow(dead_code)]
549    pub const ENM__SUBPIXEL_VERTICAL_RGB__SINCE: u32 = 1;
550    /// Since when the subpixel.vertical_bgr enum variant is available.
551    #[allow(dead_code)]
552    pub const ENM__SUBPIXEL_VERTICAL_BGR__SINCE: u32 = 1;
553
554    /// Since when the transform.normal enum variant is available.
555    #[allow(dead_code)]
556    pub const ENM__TRANSFORM_NORMAL__SINCE: u32 = 1;
557    /// Since when the transform.90 enum variant is available.
558    #[allow(dead_code)]
559    pub const ENM__TRANSFORM_90__SINCE: u32 = 1;
560    /// Since when the transform.180 enum variant is available.
561    #[allow(dead_code)]
562    pub const ENM__TRANSFORM_180__SINCE: u32 = 1;
563    /// Since when the transform.270 enum variant is available.
564    #[allow(dead_code)]
565    pub const ENM__TRANSFORM_270__SINCE: u32 = 1;
566    /// Since when the transform.flipped enum variant is available.
567    #[allow(dead_code)]
568    pub const ENM__TRANSFORM_FLIPPED__SINCE: u32 = 1;
569    /// Since when the transform.flipped_90 enum variant is available.
570    #[allow(dead_code)]
571    pub const ENM__TRANSFORM_FLIPPED_90__SINCE: u32 = 1;
572    /// Since when the transform.flipped_180 enum variant is available.
573    #[allow(dead_code)]
574    pub const ENM__TRANSFORM_FLIPPED_180__SINCE: u32 = 1;
575    /// Since when the transform.flipped_270 enum variant is available.
576    #[allow(dead_code)]
577    pub const ENM__TRANSFORM_FLIPPED_270__SINCE: u32 = 1;
578
579    /// Since when the mode.current enum variant is available.
580    #[allow(dead_code)]
581    pub const ENM__MODE_CURRENT__SINCE: u32 = 1;
582    /// Since when the mode.preferred enum variant is available.
583    #[allow(dead_code)]
584    pub const ENM__MODE_PREFERRED__SINCE: u32 = 1;
585}
586
587/// subpixel geometry information
588///
589/// This enumeration describes how the physical
590/// pixels on an output are laid out.
591#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
592#[allow(dead_code)]
593pub struct WlOutputSubpixel(pub u32);
594
595impl WlOutputSubpixel {
596    /// unknown geometry
597    #[allow(dead_code)]
598    pub const UNKNOWN: Self = Self(0);
599
600    /// no geometry
601    #[allow(dead_code)]
602    pub const NONE: Self = Self(1);
603
604    /// horizontal RGB
605    #[allow(dead_code)]
606    pub const HORIZONTAL_RGB: Self = Self(2);
607
608    /// horizontal BGR
609    #[allow(dead_code)]
610    pub const HORIZONTAL_BGR: Self = Self(3);
611
612    /// vertical RGB
613    #[allow(dead_code)]
614    pub const VERTICAL_RGB: Self = Self(4);
615
616    /// vertical BGR
617    #[allow(dead_code)]
618    pub const VERTICAL_BGR: Self = Self(5);
619}
620
621impl Debug for WlOutputSubpixel {
622    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
623        let name = match *self {
624            Self::UNKNOWN => "UNKNOWN",
625            Self::NONE => "NONE",
626            Self::HORIZONTAL_RGB => "HORIZONTAL_RGB",
627            Self::HORIZONTAL_BGR => "HORIZONTAL_BGR",
628            Self::VERTICAL_RGB => "VERTICAL_RGB",
629            Self::VERTICAL_BGR => "VERTICAL_BGR",
630            _ => return Debug::fmt(&self.0, f),
631        };
632        f.write_str(name)
633    }
634}
635
636/// transformation applied to buffer contents
637///
638/// This describes transformations that clients and compositors apply to
639/// buffer contents.
640///
641/// The flipped values correspond to an initial flip around a
642/// vertical axis followed by rotation.
643///
644/// The purpose is mainly to allow clients to render accordingly and
645/// tell the compositor, so that for fullscreen surfaces, the
646/// compositor will still be able to scan out directly from client
647/// surfaces.
648#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
649#[allow(dead_code)]
650pub struct WlOutputTransform(pub u32);
651
652impl WlOutputTransform {
653    /// no transform
654    #[allow(dead_code)]
655    pub const NORMAL: Self = Self(0);
656
657    /// 90 degrees counter-clockwise
658    #[allow(dead_code)]
659    pub const _90: Self = Self(1);
660
661    /// 180 degrees counter-clockwise
662    #[allow(dead_code)]
663    pub const _180: Self = Self(2);
664
665    /// 270 degrees counter-clockwise
666    #[allow(dead_code)]
667    pub const _270: Self = Self(3);
668
669    /// 180 degree flip around a vertical axis
670    #[allow(dead_code)]
671    pub const FLIPPED: Self = Self(4);
672
673    /// flip and rotate 90 degrees counter-clockwise
674    #[allow(dead_code)]
675    pub const FLIPPED_90: Self = Self(5);
676
677    /// flip and rotate 180 degrees counter-clockwise
678    #[allow(dead_code)]
679    pub const FLIPPED_180: Self = Self(6);
680
681    /// flip and rotate 270 degrees counter-clockwise
682    #[allow(dead_code)]
683    pub const FLIPPED_270: Self = Self(7);
684}
685
686impl Debug for WlOutputTransform {
687    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
688        let name = match *self {
689            Self::NORMAL => "NORMAL",
690            Self::_90 => "_90",
691            Self::_180 => "_180",
692            Self::_270 => "_270",
693            Self::FLIPPED => "FLIPPED",
694            Self::FLIPPED_90 => "FLIPPED_90",
695            Self::FLIPPED_180 => "FLIPPED_180",
696            Self::FLIPPED_270 => "FLIPPED_270",
697            _ => return Debug::fmt(&self.0, f),
698        };
699        f.write_str(name)
700    }
701}
702
703/// mode information
704///
705/// These flags describe properties of an output mode.
706/// They are used in the flags bitfield of the mode event.
707#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
708#[allow(dead_code)]
709pub struct WlOutputMode(pub u32);
710
711/// An iterator over the set bits in a [WlOutputMode].
712///
713/// You can construct this with the `IntoIterator` implementation of `WlOutputMode`.
714#[derive(Clone, Debug)]
715pub struct WlOutputModeIter(pub u32);
716
717impl WlOutputMode {
718    /// indicates this is the current mode
719    #[allow(dead_code)]
720    pub const CURRENT: Self = Self(0x1);
721
722    /// indicates this is the preferred mode
723    #[allow(dead_code)]
724    pub const PREFERRED: Self = Self(0x2);
725}
726
727#[allow(dead_code)]
728impl WlOutputMode {
729    #[inline]
730    pub const fn empty() -> Self {
731        Self(0)
732    }
733
734    #[inline]
735    #[must_use]
736    pub const fn is_empty(self) -> bool {
737        self.0 == 0
738    }
739
740    #[inline]
741    #[must_use]
742    pub const fn contains(self, other: Self) -> bool {
743        self.0 & other.0 == other.0
744    }
745
746    #[inline]
747    #[must_use]
748    pub const fn intersects(self, other: Self) -> bool {
749        self.0 & other.0 != 0
750    }
751
752    #[inline]
753    pub const fn insert(&mut self, other: Self) {
754        *self = self.union(other);
755    }
756
757    #[inline]
758    pub const fn remove(&mut self, other: Self) {
759        *self = self.difference(other);
760    }
761
762    #[inline]
763    pub const fn toggle(&mut self, other: Self) {
764        *self = self.symmetric_difference(other);
765    }
766
767    #[inline]
768    pub const fn set(&mut self, other: Self, value: bool) {
769        if value {
770            self.insert(other);
771        } else {
772            self.remove(other);
773        }
774    }
775
776    #[inline]
777    #[must_use]
778    pub const fn intersection(self, other: Self) -> Self {
779        Self(self.0 & other.0)
780    }
781
782    #[inline]
783    #[must_use]
784    pub const fn union(self, other: Self) -> Self {
785        Self(self.0 | other.0)
786    }
787
788    #[inline]
789    #[must_use]
790    pub const fn difference(self, other: Self) -> Self {
791        Self(self.0 & !other.0)
792    }
793
794    #[inline]
795    #[must_use]
796    pub const fn complement(self) -> Self {
797        Self(!self.0)
798    }
799
800    #[inline]
801    #[must_use]
802    pub const fn symmetric_difference(self, other: Self) -> Self {
803        Self(self.0 ^ other.0)
804    }
805
806    #[inline]
807    pub const fn all_known() -> Self {
808        #[allow(clippy::eq_op, clippy::identity_op)]
809        Self(0 | 0x1 | 0x2)
810    }
811}
812
813impl Iterator for WlOutputModeIter {
814    type Item = WlOutputMode;
815
816    fn next(&mut self) -> Option<Self::Item> {
817        if self.0 == 0 {
818            return None;
819        }
820        let bit = 1 << self.0.trailing_zeros();
821        self.0 &= !bit;
822        Some(WlOutputMode(bit))
823    }
824}
825
826impl IntoIterator for WlOutputMode {
827    type Item = WlOutputMode;
828    type IntoIter = WlOutputModeIter;
829
830    fn into_iter(self) -> Self::IntoIter {
831        WlOutputModeIter(self.0)
832    }
833}
834
835impl BitAnd for WlOutputMode {
836    type Output = Self;
837
838    fn bitand(self, rhs: Self) -> Self::Output {
839        self.intersection(rhs)
840    }
841}
842
843impl BitAndAssign for WlOutputMode {
844    fn bitand_assign(&mut self, rhs: Self) {
845        *self = self.intersection(rhs);
846    }
847}
848
849impl BitOr for WlOutputMode {
850    type Output = Self;
851
852    fn bitor(self, rhs: Self) -> Self::Output {
853        self.union(rhs)
854    }
855}
856
857impl BitOrAssign for WlOutputMode {
858    fn bitor_assign(&mut self, rhs: Self) {
859        *self = self.union(rhs);
860    }
861}
862
863impl BitXor for WlOutputMode {
864    type Output = Self;
865
866    fn bitxor(self, rhs: Self) -> Self::Output {
867        self.symmetric_difference(rhs)
868    }
869}
870
871impl BitXorAssign for WlOutputMode {
872    fn bitxor_assign(&mut self, rhs: Self) {
873        *self = self.symmetric_difference(rhs);
874    }
875}
876
877impl Sub for WlOutputMode {
878    type Output = Self;
879
880    fn sub(self, rhs: Self) -> Self::Output {
881        self.difference(rhs)
882    }
883}
884
885impl SubAssign for WlOutputMode {
886    fn sub_assign(&mut self, rhs: Self) {
887        *self = self.difference(rhs);
888    }
889}
890
891impl Not for WlOutputMode {
892    type Output = Self;
893
894    fn not(self) -> Self::Output {
895        self.complement()
896    }
897}
898
899impl Debug for WlOutputMode {
900    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
901        let mut v = self.0;
902        let mut first = true;
903        if v & 0x1 == 0x1 {
904            v &= !0x1;
905            if first {
906                first = false;
907            } else {
908                f.write_str(" | ")?;
909            }
910            f.write_str("CURRENT")?;
911        }
912        if v & 0x2 == 0x2 {
913            v &= !0x2;
914            if first {
915                first = false;
916            } else {
917                f.write_str(" | ")?;
918            }
919            f.write_str("PREFERRED")?;
920        }
921        if v != 0 {
922            if first {
923                first = false;
924            } else {
925                f.write_str(" | ")?;
926            }
927            write!(f, "0x{v:032x}")?;
928        }
929        if first {
930            f.write_str("0")?;
931        }
932        Ok(())
933    }
934}
935
936/// Functional event handlers.
937pub mod event_handlers {
938    use super::*;
939
940    /// Event handler for geometry events.
941    pub struct Geometry<F>(F);
942    impl<F> WlOutputEventHandler for Geometry<F>
943    where
944        F: Fn(&WlOutputRef, i32, i32, i32, i32, WlOutputSubpixel, &str, &str, WlOutputTransform),
945    {
946        #[inline]
947        fn geometry(
948            &self,
949            _slf: &WlOutputRef,
950            x: i32,
951            y: i32,
952            physical_width: i32,
953            physical_height: i32,
954            subpixel: WlOutputSubpixel,
955            make: &str,
956            model: &str,
957            transform: WlOutputTransform,
958        ) {
959            self.0(
960                _slf,
961                x,
962                y,
963                physical_width,
964                physical_height,
965                subpixel,
966                make,
967                model,
968                transform,
969            )
970        }
971    }
972
973    /// Event handler for mode events.
974    pub struct Mode<F>(F);
975    impl<F> WlOutputEventHandler for Mode<F>
976    where
977        F: Fn(&WlOutputRef, WlOutputMode, i32, i32, i32),
978    {
979        #[inline]
980        fn mode(
981            &self,
982            _slf: &WlOutputRef,
983            flags: WlOutputMode,
984            width: i32,
985            height: i32,
986            refresh: i32,
987        ) {
988            self.0(_slf, flags, width, height, refresh)
989        }
990    }
991
992    /// Event handler for done events.
993    pub struct Done<F>(F);
994    impl<F> WlOutputEventHandler for Done<F>
995    where
996        F: Fn(&WlOutputRef),
997    {
998        #[inline]
999        fn done(&self, _slf: &WlOutputRef) {
1000            self.0(_slf)
1001        }
1002    }
1003
1004    /// Event handler for scale events.
1005    pub struct Scale<F>(F);
1006    impl<F> WlOutputEventHandler for Scale<F>
1007    where
1008        F: Fn(&WlOutputRef, i32),
1009    {
1010        #[inline]
1011        fn scale(&self, _slf: &WlOutputRef, factor: i32) {
1012            self.0(_slf, factor)
1013        }
1014    }
1015
1016    /// Event handler for name events.
1017    pub struct Name<F>(F);
1018    impl<F> WlOutputEventHandler for Name<F>
1019    where
1020        F: Fn(&WlOutputRef, &str),
1021    {
1022        #[inline]
1023        fn name(&self, _slf: &WlOutputRef, name: &str) {
1024            self.0(_slf, name)
1025        }
1026    }
1027
1028    /// Event handler for description events.
1029    pub struct Description<F>(F);
1030    impl<F> WlOutputEventHandler for Description<F>
1031    where
1032        F: Fn(&WlOutputRef, &str),
1033    {
1034        #[inline]
1035        fn description(&self, _slf: &WlOutputRef, description: &str) {
1036            self.0(_slf, description)
1037        }
1038    }
1039
1040    impl WlOutput {
1041        /// Creates an event handler for geometry events.
1042        ///
1043        /// The event handler ignores all other events.
1044        #[allow(dead_code)]
1045        pub fn on_geometry<F>(f: F) -> Geometry<F>
1046        where
1047            F: Fn(
1048                &WlOutputRef,
1049                i32,
1050                i32,
1051                i32,
1052                i32,
1053                WlOutputSubpixel,
1054                &str,
1055                &str,
1056                WlOutputTransform,
1057            ),
1058        {
1059            Geometry(f)
1060        }
1061
1062        /// Creates an event handler for mode events.
1063        ///
1064        /// The event handler ignores all other events.
1065        #[allow(dead_code)]
1066        pub fn on_mode<F>(f: F) -> Mode<F>
1067        where
1068            F: Fn(&WlOutputRef, WlOutputMode, i32, i32, i32),
1069        {
1070            Mode(f)
1071        }
1072
1073        /// Creates an event handler for done events.
1074        ///
1075        /// The event handler ignores all other events.
1076        #[allow(dead_code)]
1077        pub fn on_done<F>(f: F) -> Done<F>
1078        where
1079            F: Fn(&WlOutputRef),
1080        {
1081            Done(f)
1082        }
1083
1084        /// Creates an event handler for scale events.
1085        ///
1086        /// The event handler ignores all other events.
1087        #[allow(dead_code)]
1088        pub fn on_scale<F>(f: F) -> Scale<F>
1089        where
1090            F: Fn(&WlOutputRef, i32),
1091        {
1092            Scale(f)
1093        }
1094
1095        /// Creates an event handler for name events.
1096        ///
1097        /// The event handler ignores all other events.
1098        #[allow(dead_code)]
1099        pub fn on_name<F>(f: F) -> Name<F>
1100        where
1101            F: Fn(&WlOutputRef, &str),
1102        {
1103            Name(f)
1104        }
1105
1106        /// Creates an event handler for description events.
1107        ///
1108        /// The event handler ignores all other events.
1109        #[allow(dead_code)]
1110        pub fn on_description<F>(f: F) -> Description<F>
1111        where
1112            F: Fn(&WlOutputRef, &str),
1113        {
1114            Description(f)
1115        }
1116    }
1117}