simple_window/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        data: *mut u8,
446        slf: &UntypedBorrowedProxy,
447        opcode: u32,
448        args: *mut wl_argument,
449    ) {
450        // SAFETY: This function requires that slf has the interface INTERFACE
451        let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlOutputRef>(slf) };
452        match opcode {
453            0 => {
454                // SAFETY: INTERFACE requires that there are 8 arguments
455                let args = unsafe { &*args.cast::<[wl_argument; 8]>() };
456                // SAFETY: - INTERFACE requires that args[0] contains an int
457                let arg0 = unsafe { args[0].i };
458                // SAFETY: - INTERFACE requires that args[1] contains an int
459                let arg1 = unsafe { args[1].i };
460                // SAFETY: - INTERFACE requires that args[2] contains an int
461                let arg2 = unsafe { args[2].i };
462                // SAFETY: - INTERFACE requires that args[3] contains an int
463                let arg3 = unsafe { args[3].i };
464                // SAFETY: - INTERFACE requires that args[4] contains an int
465                let arg4 = unsafe { WlOutputSubpixel(args[4].u) };
466                // SAFETY: - INTERFACE requires that args[5] contains a string
467                //         - if the pointer is not null, then it is a c string
468                let arg5 = unsafe { convert_string_arg("wl_output", "make", args[5].s) };
469                // SAFETY: - INTERFACE requires that args[6] contains a string
470                //         - if the pointer is not null, then it is a c string
471                let arg6 = unsafe { convert_string_arg("wl_output", "model", args[6].s) };
472                // SAFETY: - INTERFACE requires that args[7] contains an int
473                let arg7 = unsafe { WlOutputTransform(args[7].u) };
474                self.0
475                    .geometry(slf, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
476            }
477            1 => {
478                // SAFETY: INTERFACE requires that there are 4 arguments
479                let args = unsafe { &*args.cast::<[wl_argument; 4]>() };
480                // SAFETY: - INTERFACE requires that args[0] contains a uint
481                let arg0 = unsafe { WlOutputMode(args[0].u) };
482                // SAFETY: - INTERFACE requires that args[1] contains an int
483                let arg1 = unsafe { args[1].i };
484                // SAFETY: - INTERFACE requires that args[2] contains an int
485                let arg2 = unsafe { args[2].i };
486                // SAFETY: - INTERFACE requires that args[3] contains an int
487                let arg3 = unsafe { args[3].i };
488                self.0.mode(slf, arg0, arg1, arg2, arg3);
489            }
490            2 => {
491                self.0.done(slf);
492            }
493            3 => {
494                // SAFETY: INTERFACE requires that there are 1 arguments
495                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
496                // SAFETY: - INTERFACE requires that args[0] contains an int
497                let arg0 = unsafe { args[0].i };
498                self.0.scale(slf, arg0);
499            }
500            4 => {
501                // SAFETY: INTERFACE requires that there are 1 arguments
502                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
503                // SAFETY: - INTERFACE requires that args[0] contains a string
504                //         - if the pointer is not null, then it is a c string
505                let arg0 = unsafe { convert_string_arg("wl_output", "name", args[0].s) };
506                self.0.name(slf, arg0);
507            }
508            5 => {
509                // SAFETY: INTERFACE requires that there are 1 arguments
510                let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
511                // SAFETY: - INTERFACE requires that args[0] contains a string
512                //         - if the pointer is not null, then it is a c string
513                let arg0 = unsafe { convert_string_arg("wl_output", "description", args[0].s) };
514                self.0.description(slf, arg0);
515            }
516            _ => {
517                invalid_opcode("wl_output", opcode);
518            }
519        }
520    }
521}
522
523impl<H> CreateEventHandler<H> for private::ProxyApi
524where
525    H: WlOutputEventHandler,
526{
527    type EventHandler = private::EventHandler<H>;
528
529    #[inline]
530    fn create_event_handler(handler: H) -> Self::EventHandler {
531        private::EventHandler(handler)
532    }
533}
534
535impl WlOutput {
536    /// Since when the subpixel.unknown enum variant is available.
537    #[allow(dead_code)]
538    pub const ENM__SUBPIXEL_UNKNOWN__SINCE: u32 = 1;
539    /// Since when the subpixel.none enum variant is available.
540    #[allow(dead_code)]
541    pub const ENM__SUBPIXEL_NONE__SINCE: u32 = 1;
542    /// Since when the subpixel.horizontal_rgb enum variant is available.
543    #[allow(dead_code)]
544    pub const ENM__SUBPIXEL_HORIZONTAL_RGB__SINCE: u32 = 1;
545    /// Since when the subpixel.horizontal_bgr enum variant is available.
546    #[allow(dead_code)]
547    pub const ENM__SUBPIXEL_HORIZONTAL_BGR__SINCE: u32 = 1;
548    /// Since when the subpixel.vertical_rgb enum variant is available.
549    #[allow(dead_code)]
550    pub const ENM__SUBPIXEL_VERTICAL_RGB__SINCE: u32 = 1;
551    /// Since when the subpixel.vertical_bgr enum variant is available.
552    #[allow(dead_code)]
553    pub const ENM__SUBPIXEL_VERTICAL_BGR__SINCE: u32 = 1;
554
555    /// Since when the transform.normal enum variant is available.
556    #[allow(dead_code)]
557    pub const ENM__TRANSFORM_NORMAL__SINCE: u32 = 1;
558    /// Since when the transform.90 enum variant is available.
559    #[allow(dead_code)]
560    pub const ENM__TRANSFORM_90__SINCE: u32 = 1;
561    /// Since when the transform.180 enum variant is available.
562    #[allow(dead_code)]
563    pub const ENM__TRANSFORM_180__SINCE: u32 = 1;
564    /// Since when the transform.270 enum variant is available.
565    #[allow(dead_code)]
566    pub const ENM__TRANSFORM_270__SINCE: u32 = 1;
567    /// Since when the transform.flipped enum variant is available.
568    #[allow(dead_code)]
569    pub const ENM__TRANSFORM_FLIPPED__SINCE: u32 = 1;
570    /// Since when the transform.flipped_90 enum variant is available.
571    #[allow(dead_code)]
572    pub const ENM__TRANSFORM_FLIPPED_90__SINCE: u32 = 1;
573    /// Since when the transform.flipped_180 enum variant is available.
574    #[allow(dead_code)]
575    pub const ENM__TRANSFORM_FLIPPED_180__SINCE: u32 = 1;
576    /// Since when the transform.flipped_270 enum variant is available.
577    #[allow(dead_code)]
578    pub const ENM__TRANSFORM_FLIPPED_270__SINCE: u32 = 1;
579
580    /// Since when the mode.current enum variant is available.
581    #[allow(dead_code)]
582    pub const ENM__MODE_CURRENT__SINCE: u32 = 1;
583    /// Since when the mode.preferred enum variant is available.
584    #[allow(dead_code)]
585    pub const ENM__MODE_PREFERRED__SINCE: u32 = 1;
586}
587
588/// subpixel geometry information
589///
590/// This enumeration describes how the physical
591/// pixels on an output are laid out.
592#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
593#[allow(dead_code)]
594pub struct WlOutputSubpixel(pub u32);
595
596impl WlOutputSubpixel {
597    /// unknown geometry
598    #[allow(dead_code)]
599    pub const UNKNOWN: Self = Self(0);
600
601    /// no geometry
602    #[allow(dead_code)]
603    pub const NONE: Self = Self(1);
604
605    /// horizontal RGB
606    #[allow(dead_code)]
607    pub const HORIZONTAL_RGB: Self = Self(2);
608
609    /// horizontal BGR
610    #[allow(dead_code)]
611    pub const HORIZONTAL_BGR: Self = Self(3);
612
613    /// vertical RGB
614    #[allow(dead_code)]
615    pub const VERTICAL_RGB: Self = Self(4);
616
617    /// vertical BGR
618    #[allow(dead_code)]
619    pub const VERTICAL_BGR: Self = Self(5);
620}
621
622impl Debug for WlOutputSubpixel {
623    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
624        let name = match *self {
625            Self::UNKNOWN => "UNKNOWN",
626            Self::NONE => "NONE",
627            Self::HORIZONTAL_RGB => "HORIZONTAL_RGB",
628            Self::HORIZONTAL_BGR => "HORIZONTAL_BGR",
629            Self::VERTICAL_RGB => "VERTICAL_RGB",
630            Self::VERTICAL_BGR => "VERTICAL_BGR",
631            _ => return Debug::fmt(&self.0, f),
632        };
633        f.write_str(name)
634    }
635}
636
637/// transformation applied to buffer contents
638///
639/// This describes transformations that clients and compositors apply to
640/// buffer contents.
641///
642/// The flipped values correspond to an initial flip around a
643/// vertical axis followed by rotation.
644///
645/// The purpose is mainly to allow clients to render accordingly and
646/// tell the compositor, so that for fullscreen surfaces, the
647/// compositor will still be able to scan out directly from client
648/// surfaces.
649#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
650#[allow(dead_code)]
651pub struct WlOutputTransform(pub u32);
652
653impl WlOutputTransform {
654    /// no transform
655    #[allow(dead_code)]
656    pub const NORMAL: Self = Self(0);
657
658    /// 90 degrees counter-clockwise
659    #[allow(dead_code)]
660    pub const _90: Self = Self(1);
661
662    /// 180 degrees counter-clockwise
663    #[allow(dead_code)]
664    pub const _180: Self = Self(2);
665
666    /// 270 degrees counter-clockwise
667    #[allow(dead_code)]
668    pub const _270: Self = Self(3);
669
670    /// 180 degree flip around a vertical axis
671    #[allow(dead_code)]
672    pub const FLIPPED: Self = Self(4);
673
674    /// flip and rotate 90 degrees counter-clockwise
675    #[allow(dead_code)]
676    pub const FLIPPED_90: Self = Self(5);
677
678    /// flip and rotate 180 degrees counter-clockwise
679    #[allow(dead_code)]
680    pub const FLIPPED_180: Self = Self(6);
681
682    /// flip and rotate 270 degrees counter-clockwise
683    #[allow(dead_code)]
684    pub const FLIPPED_270: Self = Self(7);
685}
686
687impl Debug for WlOutputTransform {
688    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
689        let name = match *self {
690            Self::NORMAL => "NORMAL",
691            Self::_90 => "_90",
692            Self::_180 => "_180",
693            Self::_270 => "_270",
694            Self::FLIPPED => "FLIPPED",
695            Self::FLIPPED_90 => "FLIPPED_90",
696            Self::FLIPPED_180 => "FLIPPED_180",
697            Self::FLIPPED_270 => "FLIPPED_270",
698            _ => return Debug::fmt(&self.0, f),
699        };
700        f.write_str(name)
701    }
702}
703
704/// mode information
705///
706/// These flags describe properties of an output mode.
707/// They are used in the flags bitfield of the mode event.
708#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)]
709#[allow(dead_code)]
710pub struct WlOutputMode(pub u32);
711
712/// An iterator over the set bits in a [WlOutputMode].
713///
714/// You can construct this with the `IntoIterator` implementation of `WlOutputMode`.
715#[derive(Clone, Debug)]
716pub struct WlOutputModeIter(pub u32);
717
718impl WlOutputMode {
719    /// indicates this is the current mode
720    #[allow(dead_code)]
721    pub const CURRENT: Self = Self(0x1);
722
723    /// indicates this is the preferred mode
724    #[allow(dead_code)]
725    pub const PREFERRED: Self = Self(0x2);
726}
727
728#[allow(dead_code)]
729impl WlOutputMode {
730    #[inline]
731    pub const fn empty() -> Self {
732        Self(0)
733    }
734
735    #[inline]
736    #[must_use]
737    pub const fn is_empty(self) -> bool {
738        self.0 == 0
739    }
740
741    #[inline]
742    #[must_use]
743    pub const fn contains(self, other: Self) -> bool {
744        self.0 & other.0 == other.0
745    }
746
747    #[inline]
748    #[must_use]
749    pub const fn intersects(self, other: Self) -> bool {
750        self.0 & other.0 != 0
751    }
752
753    #[inline]
754    pub const fn insert(&mut self, other: Self) {
755        *self = self.union(other);
756    }
757
758    #[inline]
759    pub const fn remove(&mut self, other: Self) {
760        *self = self.difference(other);
761    }
762
763    #[inline]
764    pub const fn toggle(&mut self, other: Self) {
765        *self = self.symmetric_difference(other);
766    }
767
768    #[inline]
769    pub const fn set(&mut self, other: Self, value: bool) {
770        if value {
771            self.insert(other);
772        } else {
773            self.remove(other);
774        }
775    }
776
777    #[inline]
778    #[must_use]
779    pub const fn intersection(self, other: Self) -> Self {
780        Self(self.0 & other.0)
781    }
782
783    #[inline]
784    #[must_use]
785    pub const fn union(self, other: Self) -> Self {
786        Self(self.0 | other.0)
787    }
788
789    #[inline]
790    #[must_use]
791    pub const fn difference(self, other: Self) -> Self {
792        Self(self.0 & !other.0)
793    }
794
795    #[inline]
796    #[must_use]
797    pub const fn complement(self) -> Self {
798        Self(!self.0)
799    }
800
801    #[inline]
802    #[must_use]
803    pub const fn symmetric_difference(self, other: Self) -> Self {
804        Self(self.0 ^ other.0)
805    }
806
807    #[inline]
808    pub const fn all_known() -> Self {
809        #[allow(clippy::eq_op, clippy::identity_op)]
810        Self(0 | 0x1 | 0x2)
811    }
812}
813
814impl Iterator for WlOutputModeIter {
815    type Item = WlOutputMode;
816
817    fn next(&mut self) -> Option<Self::Item> {
818        if self.0 == 0 {
819            return None;
820        }
821        let bit = 1 << self.0.trailing_zeros();
822        self.0 &= !bit;
823        Some(WlOutputMode(bit))
824    }
825}
826
827impl IntoIterator for WlOutputMode {
828    type Item = WlOutputMode;
829    type IntoIter = WlOutputModeIter;
830
831    fn into_iter(self) -> Self::IntoIter {
832        WlOutputModeIter(self.0)
833    }
834}
835
836impl BitAnd for WlOutputMode {
837    type Output = Self;
838
839    fn bitand(self, rhs: Self) -> Self::Output {
840        self.intersection(rhs)
841    }
842}
843
844impl BitAndAssign for WlOutputMode {
845    fn bitand_assign(&mut self, rhs: Self) {
846        *self = self.intersection(rhs);
847    }
848}
849
850impl BitOr for WlOutputMode {
851    type Output = Self;
852
853    fn bitor(self, rhs: Self) -> Self::Output {
854        self.union(rhs)
855    }
856}
857
858impl BitOrAssign for WlOutputMode {
859    fn bitor_assign(&mut self, rhs: Self) {
860        *self = self.union(rhs);
861    }
862}
863
864impl BitXor for WlOutputMode {
865    type Output = Self;
866
867    fn bitxor(self, rhs: Self) -> Self::Output {
868        self.symmetric_difference(rhs)
869    }
870}
871
872impl BitXorAssign for WlOutputMode {
873    fn bitxor_assign(&mut self, rhs: Self) {
874        *self = self.symmetric_difference(rhs);
875    }
876}
877
878impl Sub for WlOutputMode {
879    type Output = Self;
880
881    fn sub(self, rhs: Self) -> Self::Output {
882        self.difference(rhs)
883    }
884}
885
886impl SubAssign for WlOutputMode {
887    fn sub_assign(&mut self, rhs: Self) {
888        *self = self.difference(rhs);
889    }
890}
891
892impl Not for WlOutputMode {
893    type Output = Self;
894
895    fn not(self) -> Self::Output {
896        self.complement()
897    }
898}
899
900impl Debug for WlOutputMode {
901    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
902        let mut v = self.0;
903        let mut first = true;
904        if v & 0x1 == 0x1 {
905            v &= !0x1;
906            if first {
907                first = false;
908            } else {
909                f.write_str(" | ")?;
910            }
911            f.write_str("CURRENT")?;
912        }
913        if v & 0x2 == 0x2 {
914            v &= !0x2;
915            if first {
916                first = false;
917            } else {
918                f.write_str(" | ")?;
919            }
920            f.write_str("PREFERRED")?;
921        }
922        if v != 0 {
923            if first {
924                first = false;
925            } else {
926                f.write_str(" | ")?;
927            }
928            write!(f, "0x{v:032x}")?;
929        }
930        if first {
931            f.write_str("0")?;
932        }
933        Ok(())
934    }
935}
936
937/// Functional event handlers.
938pub mod event_handlers {
939    use super::*;
940
941    /// Event handler for geometry events.
942    pub struct Geometry<F>(F);
943    impl<F> WlOutputEventHandler for Geometry<F>
944    where
945        F: Fn(&WlOutputRef, i32, i32, i32, i32, WlOutputSubpixel, &str, &str, WlOutputTransform),
946    {
947        #[inline]
948        fn geometry(
949            &self,
950            _slf: &WlOutputRef,
951            x: i32,
952            y: i32,
953            physical_width: i32,
954            physical_height: i32,
955            subpixel: WlOutputSubpixel,
956            make: &str,
957            model: &str,
958            transform: WlOutputTransform,
959        ) {
960            self.0(
961                _slf,
962                x,
963                y,
964                physical_width,
965                physical_height,
966                subpixel,
967                make,
968                model,
969                transform,
970            )
971        }
972    }
973
974    /// Event handler for mode events.
975    pub struct Mode<F>(F);
976    impl<F> WlOutputEventHandler for Mode<F>
977    where
978        F: Fn(&WlOutputRef, WlOutputMode, i32, i32, i32),
979    {
980        #[inline]
981        fn mode(
982            &self,
983            _slf: &WlOutputRef,
984            flags: WlOutputMode,
985            width: i32,
986            height: i32,
987            refresh: i32,
988        ) {
989            self.0(_slf, flags, width, height, refresh)
990        }
991    }
992
993    /// Event handler for done events.
994    pub struct Done<F>(F);
995    impl<F> WlOutputEventHandler for Done<F>
996    where
997        F: Fn(&WlOutputRef),
998    {
999        #[inline]
1000        fn done(&self, _slf: &WlOutputRef) {
1001            self.0(_slf)
1002        }
1003    }
1004
1005    /// Event handler for scale events.
1006    pub struct Scale<F>(F);
1007    impl<F> WlOutputEventHandler for Scale<F>
1008    where
1009        F: Fn(&WlOutputRef, i32),
1010    {
1011        #[inline]
1012        fn scale(&self, _slf: &WlOutputRef, factor: i32) {
1013            self.0(_slf, factor)
1014        }
1015    }
1016
1017    /// Event handler for name events.
1018    pub struct Name<F>(F);
1019    impl<F> WlOutputEventHandler for Name<F>
1020    where
1021        F: Fn(&WlOutputRef, &str),
1022    {
1023        #[inline]
1024        fn name(&self, _slf: &WlOutputRef, name: &str) {
1025            self.0(_slf, name)
1026        }
1027    }
1028
1029    /// Event handler for description events.
1030    pub struct Description<F>(F);
1031    impl<F> WlOutputEventHandler for Description<F>
1032    where
1033        F: Fn(&WlOutputRef, &str),
1034    {
1035        #[inline]
1036        fn description(&self, _slf: &WlOutputRef, description: &str) {
1037            self.0(_slf, description)
1038        }
1039    }
1040
1041    impl WlOutput {
1042        /// Creates an event handler for geometry events.
1043        ///
1044        /// The event handler ignores all other events.
1045        #[allow(dead_code)]
1046        pub fn on_geometry<F>(f: F) -> Geometry<F>
1047        where
1048            F: Fn(
1049                &WlOutputRef,
1050                i32,
1051                i32,
1052                i32,
1053                i32,
1054                WlOutputSubpixel,
1055                &str,
1056                &str,
1057                WlOutputTransform,
1058            ),
1059        {
1060            Geometry(f)
1061        }
1062
1063        /// Creates an event handler for mode events.
1064        ///
1065        /// The event handler ignores all other events.
1066        #[allow(dead_code)]
1067        pub fn on_mode<F>(f: F) -> Mode<F>
1068        where
1069            F: Fn(&WlOutputRef, WlOutputMode, i32, i32, i32),
1070        {
1071            Mode(f)
1072        }
1073
1074        /// Creates an event handler for done events.
1075        ///
1076        /// The event handler ignores all other events.
1077        #[allow(dead_code)]
1078        pub fn on_done<F>(f: F) -> Done<F>
1079        where
1080            F: Fn(&WlOutputRef),
1081        {
1082            Done(f)
1083        }
1084
1085        /// Creates an event handler for scale events.
1086        ///
1087        /// The event handler ignores all other events.
1088        #[allow(dead_code)]
1089        pub fn on_scale<F>(f: F) -> Scale<F>
1090        where
1091            F: Fn(&WlOutputRef, i32),
1092        {
1093            Scale(f)
1094        }
1095
1096        /// Creates an event handler for name events.
1097        ///
1098        /// The event handler ignores all other events.
1099        #[allow(dead_code)]
1100        pub fn on_name<F>(f: F) -> Name<F>
1101        where
1102            F: Fn(&WlOutputRef, &str),
1103        {
1104            Name(f)
1105        }
1106
1107        /// Creates an event handler for description events.
1108        ///
1109        /// The event handler ignores all other events.
1110        #[allow(dead_code)]
1111        pub fn on_description<F>(f: F) -> Description<F>
1112        where
1113            F: Fn(&WlOutputRef, &str),
1114        {
1115            Description(f)
1116        }
1117    }
1118}