wl_proxy/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 crate::protocol_helpers::prelude::*;
11use super::super::all_types::*;
12
13/// A wl_output object.
14///
15/// See the documentation of [the module][self] for the interface description.
16pub struct WlOutput {
17    core: ObjectCore,
18    handler: HandlerHolder<dyn WlOutputHandler>,
19}
20
21struct DefaultHandler;
22
23impl WlOutputHandler for DefaultHandler { }
24
25impl ConcreteObject for WlOutput {
26    const XML_VERSION: u32 = 4;
27    const INTERFACE: ObjectInterface = ObjectInterface::WlOutput;
28    const INTERFACE_NAME: &str = "wl_output";
29}
30
31impl WlOutput {
32    /// Sets a new handler.
33    pub fn set_handler(&self, handler: impl WlOutputHandler) {
34        self.set_boxed_handler(Box::new(handler));
35    }
36
37    /// Sets a new, already boxed handler.
38    pub fn set_boxed_handler(&self, handler: Box<dyn WlOutputHandler>) {
39        if self.core.state.destroyed.get() {
40            return;
41        }
42        self.handler.set(Some(handler));
43    }
44}
45
46impl Debug for WlOutput {
47    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48        f.debug_struct("WlOutput")
49            .field("server_obj_id", &self.core.server_obj_id.get())
50            .field("client_id", &self.core.client_id.get())
51            .field("client_obj_id", &self.core.client_obj_id.get())
52            .finish()
53    }
54}
55
56impl WlOutput {
57    /// Since when the geometry message is available.
58    pub const MSG__GEOMETRY__SINCE: u32 = 1;
59
60    /// properties of the output
61    ///
62    /// The geometry event describes geometric properties of the output.
63    /// The event is sent when binding to the output object and whenever
64    /// any of the properties change.
65    ///
66    /// The physical size can be set to zero if it doesn't make sense for this
67    /// output (e.g. for projectors or virtual outputs).
68    ///
69    /// The geometry event will be followed by a done event (starting from
70    /// version 2).
71    ///
72    /// Clients should use wl_surface.preferred_buffer_transform instead of the
73    /// transform advertised by this event to find the preferred buffer
74    /// transform to use for a surface.
75    ///
76    /// Note: wl_output only advertises partial information about the output
77    /// position and identification. Some compositors, for instance those not
78    /// implementing a desktop-style output layout or those exposing virtual
79    /// outputs, might fake this information. Instead of using x and y, clients
80    /// should use xdg_output.logical_position. Instead of using make and model,
81    /// clients should use name and description.
82    ///
83    /// # Arguments
84    ///
85    /// - `x`: x position within the global compositor space
86    /// - `y`: y position within the global compositor space
87    /// - `physical_width`: width in millimeters of the output
88    /// - `physical_height`: height in millimeters of the output
89    /// - `subpixel`: subpixel orientation of the output
90    /// - `make`: textual description of the manufacturer
91    /// - `model`: textual description of the model
92    /// - `transform`: additional transformation applied to buffer contents during presentation
93    #[inline]
94    pub fn try_send_geometry(
95        &self,
96        x: i32,
97        y: i32,
98        physical_width: i32,
99        physical_height: i32,
100        subpixel: WlOutputSubpixel,
101        make: &str,
102        model: &str,
103        transform: WlOutputTransform,
104    ) -> Result<(), ObjectError> {
105        let (
106            arg0,
107            arg1,
108            arg2,
109            arg3,
110            arg4,
111            arg5,
112            arg6,
113            arg7,
114        ) = (
115            x,
116            y,
117            physical_width,
118            physical_height,
119            subpixel,
120            make,
121            model,
122            transform,
123        );
124        let core = self.core();
125        let client_ref = core.client.borrow();
126        let Some(client) = &*client_ref else {
127            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
128        };
129        let id = core.client_obj_id.get().unwrap_or(0);
130        #[cfg(feature = "logging")]
131        if self.core.state.log {
132            #[cold]
133            fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32, arg4: WlOutputSubpixel, arg5: &str, arg6: &str, arg7: WlOutputTransform) {
134                let (millis, micros) = time_since_epoch();
135                let prefix = &state.log_prefix;
136                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_output#{}.geometry(x: {}, y: {}, physical_width: {}, physical_height: {}, subpixel: {:?}, make: {:?}, model: {:?}, transform: {:?})\n", client_id, id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
137                state.log(args);
138            }
139            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
140        }
141        let endpoint = &client.endpoint;
142        if !endpoint.flush_queued.replace(true) {
143            self.core.state.add_flushable_endpoint(endpoint, Some(client));
144        }
145        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
146        let outgoing = &mut *outgoing_ref;
147        let mut fmt = outgoing.formatter();
148        fmt.words([
149            id,
150            0,
151            arg0 as u32,
152            arg1 as u32,
153            arg2 as u32,
154            arg3 as u32,
155            arg4.0,
156        ]);
157        fmt.string(arg5);
158        fmt.string(arg6);
159        fmt.words([
160            arg7.0,
161        ]);
162        Ok(())
163    }
164
165    /// properties of the output
166    ///
167    /// The geometry event describes geometric properties of the output.
168    /// The event is sent when binding to the output object and whenever
169    /// any of the properties change.
170    ///
171    /// The physical size can be set to zero if it doesn't make sense for this
172    /// output (e.g. for projectors or virtual outputs).
173    ///
174    /// The geometry event will be followed by a done event (starting from
175    /// version 2).
176    ///
177    /// Clients should use wl_surface.preferred_buffer_transform instead of the
178    /// transform advertised by this event to find the preferred buffer
179    /// transform to use for a surface.
180    ///
181    /// Note: wl_output only advertises partial information about the output
182    /// position and identification. Some compositors, for instance those not
183    /// implementing a desktop-style output layout or those exposing virtual
184    /// outputs, might fake this information. Instead of using x and y, clients
185    /// should use xdg_output.logical_position. Instead of using make and model,
186    /// clients should use name and description.
187    ///
188    /// # Arguments
189    ///
190    /// - `x`: x position within the global compositor space
191    /// - `y`: y position within the global compositor space
192    /// - `physical_width`: width in millimeters of the output
193    /// - `physical_height`: height in millimeters of the output
194    /// - `subpixel`: subpixel orientation of the output
195    /// - `make`: textual description of the manufacturer
196    /// - `model`: textual description of the model
197    /// - `transform`: additional transformation applied to buffer contents during presentation
198    #[inline]
199    pub fn send_geometry(
200        &self,
201        x: i32,
202        y: i32,
203        physical_width: i32,
204        physical_height: i32,
205        subpixel: WlOutputSubpixel,
206        make: &str,
207        model: &str,
208        transform: WlOutputTransform,
209    ) {
210        let res = self.try_send_geometry(
211            x,
212            y,
213            physical_width,
214            physical_height,
215            subpixel,
216            make,
217            model,
218            transform,
219        );
220        if let Err(e) = res {
221            log_send("wl_output.geometry", &e);
222        }
223    }
224
225    /// Since when the mode message is available.
226    pub const MSG__MODE__SINCE: u32 = 1;
227
228    /// advertise available modes for the output
229    ///
230    /// The mode event describes an available mode for the output.
231    ///
232    /// The event is sent when binding to the output object and there
233    /// will always be one mode, the current mode.  The event is sent
234    /// again if an output changes mode, for the mode that is now
235    /// current.  In other words, the current mode is always the last
236    /// mode that was received with the current flag set.
237    ///
238    /// Non-current modes are deprecated. A compositor can decide to only
239    /// advertise the current mode and never send other modes. Clients
240    /// should not rely on non-current modes.
241    ///
242    /// The size of a mode is given in physical hardware units of
243    /// the output device. This is not necessarily the same as
244    /// the output size in the global compositor space. For instance,
245    /// the output may be scaled, as described in wl_output.scale,
246    /// or transformed, as described in wl_output.transform. Clients
247    /// willing to retrieve the output size in the global compositor
248    /// space should use xdg_output.logical_size instead.
249    ///
250    /// The vertical refresh rate can be set to zero if it doesn't make
251    /// sense for this output (e.g. for virtual outputs).
252    ///
253    /// The mode event will be followed by a done event (starting from
254    /// version 2).
255    ///
256    /// Clients should not use the refresh rate to schedule frames. Instead,
257    /// they should use the wl_surface.frame event or the presentation-time
258    /// protocol.
259    ///
260    /// Note: this information is not always meaningful for all outputs. Some
261    /// compositors, such as those exposing virtual outputs, might fake the
262    /// refresh rate or the size.
263    ///
264    /// # Arguments
265    ///
266    /// - `flags`: bitfield of mode flags
267    /// - `width`: width of the mode in hardware units
268    /// - `height`: height of the mode in hardware units
269    /// - `refresh`: vertical refresh rate in mHz
270    #[inline]
271    pub fn try_send_mode(
272        &self,
273        flags: WlOutputMode,
274        width: i32,
275        height: i32,
276        refresh: i32,
277    ) -> Result<(), ObjectError> {
278        let (
279            arg0,
280            arg1,
281            arg2,
282            arg3,
283        ) = (
284            flags,
285            width,
286            height,
287            refresh,
288        );
289        let core = self.core();
290        let client_ref = core.client.borrow();
291        let Some(client) = &*client_ref else {
292            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
293        };
294        let id = core.client_obj_id.get().unwrap_or(0);
295        #[cfg(feature = "logging")]
296        if self.core.state.log {
297            #[cold]
298            fn log(state: &State, client_id: u64, id: u32, arg0: WlOutputMode, arg1: i32, arg2: i32, arg3: i32) {
299                let (millis, micros) = time_since_epoch();
300                let prefix = &state.log_prefix;
301                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_output#{}.mode(flags: {:?}, width: {}, height: {}, refresh: {})\n", client_id, id, arg0, arg1, arg2, arg3);
302                state.log(args);
303            }
304            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2, arg3);
305        }
306        let endpoint = &client.endpoint;
307        if !endpoint.flush_queued.replace(true) {
308            self.core.state.add_flushable_endpoint(endpoint, Some(client));
309        }
310        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
311        let outgoing = &mut *outgoing_ref;
312        let mut fmt = outgoing.formatter();
313        fmt.words([
314            id,
315            1,
316            arg0.0,
317            arg1 as u32,
318            arg2 as u32,
319            arg3 as u32,
320        ]);
321        Ok(())
322    }
323
324    /// advertise available modes for the output
325    ///
326    /// The mode event describes an available mode for the output.
327    ///
328    /// The event is sent when binding to the output object and there
329    /// will always be one mode, the current mode.  The event is sent
330    /// again if an output changes mode, for the mode that is now
331    /// current.  In other words, the current mode is always the last
332    /// mode that was received with the current flag set.
333    ///
334    /// Non-current modes are deprecated. A compositor can decide to only
335    /// advertise the current mode and never send other modes. Clients
336    /// should not rely on non-current modes.
337    ///
338    /// The size of a mode is given in physical hardware units of
339    /// the output device. This is not necessarily the same as
340    /// the output size in the global compositor space. For instance,
341    /// the output may be scaled, as described in wl_output.scale,
342    /// or transformed, as described in wl_output.transform. Clients
343    /// willing to retrieve the output size in the global compositor
344    /// space should use xdg_output.logical_size instead.
345    ///
346    /// The vertical refresh rate can be set to zero if it doesn't make
347    /// sense for this output (e.g. for virtual outputs).
348    ///
349    /// The mode event will be followed by a done event (starting from
350    /// version 2).
351    ///
352    /// Clients should not use the refresh rate to schedule frames. Instead,
353    /// they should use the wl_surface.frame event or the presentation-time
354    /// protocol.
355    ///
356    /// Note: this information is not always meaningful for all outputs. Some
357    /// compositors, such as those exposing virtual outputs, might fake the
358    /// refresh rate or the size.
359    ///
360    /// # Arguments
361    ///
362    /// - `flags`: bitfield of mode flags
363    /// - `width`: width of the mode in hardware units
364    /// - `height`: height of the mode in hardware units
365    /// - `refresh`: vertical refresh rate in mHz
366    #[inline]
367    pub fn send_mode(
368        &self,
369        flags: WlOutputMode,
370        width: i32,
371        height: i32,
372        refresh: i32,
373    ) {
374        let res = self.try_send_mode(
375            flags,
376            width,
377            height,
378            refresh,
379        );
380        if let Err(e) = res {
381            log_send("wl_output.mode", &e);
382        }
383    }
384
385    /// Since when the done message is available.
386    pub const MSG__DONE__SINCE: u32 = 2;
387
388    /// sent all information about output
389    ///
390    /// This event is sent after all other properties have been
391    /// sent after binding to the output object and after any
392    /// other property changes done after that. This allows
393    /// changes to the output properties to be seen as
394    /// atomic, even if they happen via multiple events.
395    #[inline]
396    pub fn try_send_done(
397        &self,
398    ) -> Result<(), ObjectError> {
399        let core = self.core();
400        let client_ref = core.client.borrow();
401        let Some(client) = &*client_ref else {
402            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
403        };
404        let id = core.client_obj_id.get().unwrap_or(0);
405        #[cfg(feature = "logging")]
406        if self.core.state.log {
407            #[cold]
408            fn log(state: &State, client_id: u64, id: u32) {
409                let (millis, micros) = time_since_epoch();
410                let prefix = &state.log_prefix;
411                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_output#{}.done()\n", client_id, id);
412                state.log(args);
413            }
414            log(&self.core.state, client.endpoint.id, id);
415        }
416        let endpoint = &client.endpoint;
417        if !endpoint.flush_queued.replace(true) {
418            self.core.state.add_flushable_endpoint(endpoint, Some(client));
419        }
420        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
421        let outgoing = &mut *outgoing_ref;
422        let mut fmt = outgoing.formatter();
423        fmt.words([
424            id,
425            2,
426        ]);
427        Ok(())
428    }
429
430    /// sent all information about output
431    ///
432    /// This event is sent after all other properties have been
433    /// sent after binding to the output object and after any
434    /// other property changes done after that. This allows
435    /// changes to the output properties to be seen as
436    /// atomic, even if they happen via multiple events.
437    #[inline]
438    pub fn send_done(
439        &self,
440    ) {
441        let res = self.try_send_done(
442        );
443        if let Err(e) = res {
444            log_send("wl_output.done", &e);
445        }
446    }
447
448    /// Since when the scale message is available.
449    pub const MSG__SCALE__SINCE: u32 = 2;
450
451    /// output scaling properties
452    ///
453    /// This event contains scaling geometry information
454    /// that is not in the geometry event. It may be sent after
455    /// binding the output object or if the output scale changes
456    /// later. The compositor will emit a non-zero, positive
457    /// value for scale. If it is not sent, the client should
458    /// assume a scale of 1.
459    ///
460    /// A scale larger than 1 means that the compositor will
461    /// automatically scale surface buffers by this amount
462    /// when rendering. This is used for very high resolution
463    /// displays where applications rendering at the native
464    /// resolution would be too small to be legible.
465    ///
466    /// Clients should use wl_surface.preferred_buffer_scale
467    /// instead of this event to find the preferred buffer
468    /// scale to use for a surface.
469    ///
470    /// The scale event will be followed by a done event.
471    ///
472    /// # Arguments
473    ///
474    /// - `factor`: scaling factor of output
475    #[inline]
476    pub fn try_send_scale(
477        &self,
478        factor: i32,
479    ) -> Result<(), ObjectError> {
480        let (
481            arg0,
482        ) = (
483            factor,
484        );
485        let core = self.core();
486        let client_ref = core.client.borrow();
487        let Some(client) = &*client_ref else {
488            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
489        };
490        let id = core.client_obj_id.get().unwrap_or(0);
491        #[cfg(feature = "logging")]
492        if self.core.state.log {
493            #[cold]
494            fn log(state: &State, client_id: u64, id: u32, arg0: i32) {
495                let (millis, micros) = time_since_epoch();
496                let prefix = &state.log_prefix;
497                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_output#{}.scale(factor: {})\n", client_id, id, arg0);
498                state.log(args);
499            }
500            log(&self.core.state, client.endpoint.id, id, arg0);
501        }
502        let endpoint = &client.endpoint;
503        if !endpoint.flush_queued.replace(true) {
504            self.core.state.add_flushable_endpoint(endpoint, Some(client));
505        }
506        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
507        let outgoing = &mut *outgoing_ref;
508        let mut fmt = outgoing.formatter();
509        fmt.words([
510            id,
511            3,
512            arg0 as u32,
513        ]);
514        Ok(())
515    }
516
517    /// output scaling properties
518    ///
519    /// This event contains scaling geometry information
520    /// that is not in the geometry event. It may be sent after
521    /// binding the output object or if the output scale changes
522    /// later. The compositor will emit a non-zero, positive
523    /// value for scale. If it is not sent, the client should
524    /// assume a scale of 1.
525    ///
526    /// A scale larger than 1 means that the compositor will
527    /// automatically scale surface buffers by this amount
528    /// when rendering. This is used for very high resolution
529    /// displays where applications rendering at the native
530    /// resolution would be too small to be legible.
531    ///
532    /// Clients should use wl_surface.preferred_buffer_scale
533    /// instead of this event to find the preferred buffer
534    /// scale to use for a surface.
535    ///
536    /// The scale event will be followed by a done event.
537    ///
538    /// # Arguments
539    ///
540    /// - `factor`: scaling factor of output
541    #[inline]
542    pub fn send_scale(
543        &self,
544        factor: i32,
545    ) {
546        let res = self.try_send_scale(
547            factor,
548        );
549        if let Err(e) = res {
550            log_send("wl_output.scale", &e);
551        }
552    }
553
554    /// Since when the release message is available.
555    pub const MSG__RELEASE__SINCE: u32 = 3;
556
557    /// release the output object
558    ///
559    /// Using this request a client can tell the server that it is not going to
560    /// use the output object anymore.
561    #[inline]
562    pub fn try_send_release(
563        &self,
564    ) -> Result<(), ObjectError> {
565        let core = self.core();
566        let Some(id) = core.server_obj_id.get() else {
567            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
568        };
569        #[cfg(feature = "logging")]
570        if self.core.state.log {
571            #[cold]
572            fn log(state: &State, id: u32) {
573                let (millis, micros) = time_since_epoch();
574                let prefix = &state.log_prefix;
575                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_output#{}.release()\n", id);
576                state.log(args);
577            }
578            log(&self.core.state, id);
579        }
580        let Some(endpoint) = &self.core.state.server else {
581            return Ok(());
582        };
583        if !endpoint.flush_queued.replace(true) {
584            self.core.state.add_flushable_endpoint(endpoint, None);
585        }
586        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
587        let outgoing = &mut *outgoing_ref;
588        let mut fmt = outgoing.formatter();
589        fmt.words([
590            id,
591            0,
592        ]);
593        self.core.handle_server_destroy();
594        Ok(())
595    }
596
597    /// release the output object
598    ///
599    /// Using this request a client can tell the server that it is not going to
600    /// use the output object anymore.
601    #[inline]
602    pub fn send_release(
603        &self,
604    ) {
605        let res = self.try_send_release(
606        );
607        if let Err(e) = res {
608            log_send("wl_output.release", &e);
609        }
610    }
611
612    /// Since when the name message is available.
613    pub const MSG__NAME__SINCE: u32 = 4;
614
615    /// name of this output
616    ///
617    /// Many compositors will assign user-friendly names to their outputs, show
618    /// them to the user, allow the user to refer to an output, etc. The client
619    /// may wish to know this name as well to offer the user similar behaviors.
620    ///
621    /// The name is a UTF-8 string with no convention defined for its contents.
622    /// Each name is unique among all wl_output globals. The name is only
623    /// guaranteed to be unique for the compositor instance.
624    ///
625    /// The same output name is used for all clients for a given wl_output
626    /// global. Thus, the name can be shared across processes to refer to a
627    /// specific wl_output global.
628    ///
629    /// The name is not guaranteed to be persistent across sessions, thus cannot
630    /// be used to reliably identify an output in e.g. configuration files.
631    ///
632    /// Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
633    /// not assume that the name is a reflection of an underlying DRM connector,
634    /// X11 connection, etc.
635    ///
636    /// The name event is sent after binding the output object. This event is
637    /// only sent once per output object, and the name does not change over the
638    /// lifetime of the wl_output global.
639    ///
640    /// Compositors may re-use the same output name if the wl_output global is
641    /// destroyed and re-created later. Compositors should avoid re-using the
642    /// same name if possible.
643    ///
644    /// The name event will be followed by a done event.
645    ///
646    /// # Arguments
647    ///
648    /// - `name`: output name
649    #[inline]
650    pub fn try_send_name(
651        &self,
652        name: &str,
653    ) -> Result<(), ObjectError> {
654        let (
655            arg0,
656        ) = (
657            name,
658        );
659        let core = self.core();
660        let client_ref = core.client.borrow();
661        let Some(client) = &*client_ref else {
662            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
663        };
664        let id = core.client_obj_id.get().unwrap_or(0);
665        #[cfg(feature = "logging")]
666        if self.core.state.log {
667            #[cold]
668            fn log(state: &State, client_id: u64, id: u32, arg0: &str) {
669                let (millis, micros) = time_since_epoch();
670                let prefix = &state.log_prefix;
671                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_output#{}.name(name: {:?})\n", client_id, id, arg0);
672                state.log(args);
673            }
674            log(&self.core.state, client.endpoint.id, id, arg0);
675        }
676        let endpoint = &client.endpoint;
677        if !endpoint.flush_queued.replace(true) {
678            self.core.state.add_flushable_endpoint(endpoint, Some(client));
679        }
680        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
681        let outgoing = &mut *outgoing_ref;
682        let mut fmt = outgoing.formatter();
683        fmt.words([
684            id,
685            4,
686        ]);
687        fmt.string(arg0);
688        Ok(())
689    }
690
691    /// name of this output
692    ///
693    /// Many compositors will assign user-friendly names to their outputs, show
694    /// them to the user, allow the user to refer to an output, etc. The client
695    /// may wish to know this name as well to offer the user similar behaviors.
696    ///
697    /// The name is a UTF-8 string with no convention defined for its contents.
698    /// Each name is unique among all wl_output globals. The name is only
699    /// guaranteed to be unique for the compositor instance.
700    ///
701    /// The same output name is used for all clients for a given wl_output
702    /// global. Thus, the name can be shared across processes to refer to a
703    /// specific wl_output global.
704    ///
705    /// The name is not guaranteed to be persistent across sessions, thus cannot
706    /// be used to reliably identify an output in e.g. configuration files.
707    ///
708    /// Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
709    /// not assume that the name is a reflection of an underlying DRM connector,
710    /// X11 connection, etc.
711    ///
712    /// The name event is sent after binding the output object. This event is
713    /// only sent once per output object, and the name does not change over the
714    /// lifetime of the wl_output global.
715    ///
716    /// Compositors may re-use the same output name if the wl_output global is
717    /// destroyed and re-created later. Compositors should avoid re-using the
718    /// same name if possible.
719    ///
720    /// The name event will be followed by a done event.
721    ///
722    /// # Arguments
723    ///
724    /// - `name`: output name
725    #[inline]
726    pub fn send_name(
727        &self,
728        name: &str,
729    ) {
730        let res = self.try_send_name(
731            name,
732        );
733        if let Err(e) = res {
734            log_send("wl_output.name", &e);
735        }
736    }
737
738    /// Since when the description message is available.
739    pub const MSG__DESCRIPTION__SINCE: u32 = 4;
740
741    /// human-readable description of this output
742    ///
743    /// Many compositors can produce human-readable descriptions of their
744    /// outputs. The client may wish to know this description as well, e.g. for
745    /// output selection purposes.
746    ///
747    /// The description is a UTF-8 string with no convention defined for its
748    /// contents. The description is not guaranteed to be unique among all
749    /// wl_output globals. Examples might include 'Foocorp 11" Display' or
750    /// 'Virtual X11 output via :1'.
751    ///
752    /// The description event is sent after binding the output object and
753    /// whenever the description changes. The description is optional, and may
754    /// not be sent at all.
755    ///
756    /// The description event will be followed by a done event.
757    ///
758    /// # Arguments
759    ///
760    /// - `description`: output description
761    #[inline]
762    pub fn try_send_description(
763        &self,
764        description: &str,
765    ) -> Result<(), ObjectError> {
766        let (
767            arg0,
768        ) = (
769            description,
770        );
771        let core = self.core();
772        let client_ref = core.client.borrow();
773        let Some(client) = &*client_ref else {
774            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
775        };
776        let id = core.client_obj_id.get().unwrap_or(0);
777        #[cfg(feature = "logging")]
778        if self.core.state.log {
779            #[cold]
780            fn log(state: &State, client_id: u64, id: u32, arg0: &str) {
781                let (millis, micros) = time_since_epoch();
782                let prefix = &state.log_prefix;
783                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_output#{}.description(description: {:?})\n", client_id, id, arg0);
784                state.log(args);
785            }
786            log(&self.core.state, client.endpoint.id, id, arg0);
787        }
788        let endpoint = &client.endpoint;
789        if !endpoint.flush_queued.replace(true) {
790            self.core.state.add_flushable_endpoint(endpoint, Some(client));
791        }
792        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
793        let outgoing = &mut *outgoing_ref;
794        let mut fmt = outgoing.formatter();
795        fmt.words([
796            id,
797            5,
798        ]);
799        fmt.string(arg0);
800        Ok(())
801    }
802
803    /// human-readable description of this output
804    ///
805    /// Many compositors can produce human-readable descriptions of their
806    /// outputs. The client may wish to know this description as well, e.g. for
807    /// output selection purposes.
808    ///
809    /// The description is a UTF-8 string with no convention defined for its
810    /// contents. The description is not guaranteed to be unique among all
811    /// wl_output globals. Examples might include 'Foocorp 11" Display' or
812    /// 'Virtual X11 output via :1'.
813    ///
814    /// The description event is sent after binding the output object and
815    /// whenever the description changes. The description is optional, and may
816    /// not be sent at all.
817    ///
818    /// The description event will be followed by a done event.
819    ///
820    /// # Arguments
821    ///
822    /// - `description`: output description
823    #[inline]
824    pub fn send_description(
825        &self,
826        description: &str,
827    ) {
828        let res = self.try_send_description(
829            description,
830        );
831        if let Err(e) = res {
832            log_send("wl_output.description", &e);
833        }
834    }
835}
836
837/// A message handler for [`WlOutput`] proxies.
838pub trait WlOutputHandler: Any {
839    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
840    ///
841    /// The default handler forwards the event to the client, if any.
842    #[inline]
843    fn delete_id(&mut self, slf: &Rc<WlOutput>) {
844        slf.core.delete_id();
845    }
846
847    /// properties of the output
848    ///
849    /// The geometry event describes geometric properties of the output.
850    /// The event is sent when binding to the output object and whenever
851    /// any of the properties change.
852    ///
853    /// The physical size can be set to zero if it doesn't make sense for this
854    /// output (e.g. for projectors or virtual outputs).
855    ///
856    /// The geometry event will be followed by a done event (starting from
857    /// version 2).
858    ///
859    /// Clients should use wl_surface.preferred_buffer_transform instead of the
860    /// transform advertised by this event to find the preferred buffer
861    /// transform to use for a surface.
862    ///
863    /// Note: wl_output only advertises partial information about the output
864    /// position and identification. Some compositors, for instance those not
865    /// implementing a desktop-style output layout or those exposing virtual
866    /// outputs, might fake this information. Instead of using x and y, clients
867    /// should use xdg_output.logical_position. Instead of using make and model,
868    /// clients should use name and description.
869    ///
870    /// # Arguments
871    ///
872    /// - `x`: x position within the global compositor space
873    /// - `y`: y position within the global compositor space
874    /// - `physical_width`: width in millimeters of the output
875    /// - `physical_height`: height in millimeters of the output
876    /// - `subpixel`: subpixel orientation of the output
877    /// - `make`: textual description of the manufacturer
878    /// - `model`: textual description of the model
879    /// - `transform`: additional transformation applied to buffer contents during presentation
880    #[inline]
881    fn handle_geometry(
882        &mut self,
883        slf: &Rc<WlOutput>,
884        x: i32,
885        y: i32,
886        physical_width: i32,
887        physical_height: i32,
888        subpixel: WlOutputSubpixel,
889        make: &str,
890        model: &str,
891        transform: WlOutputTransform,
892    ) {
893        if !slf.core.forward_to_client.get() {
894            return;
895        }
896        let res = slf.try_send_geometry(
897            x,
898            y,
899            physical_width,
900            physical_height,
901            subpixel,
902            make,
903            model,
904            transform,
905        );
906        if let Err(e) = res {
907            log_forward("wl_output.geometry", &e);
908        }
909    }
910
911    /// advertise available modes for the output
912    ///
913    /// The mode event describes an available mode for the output.
914    ///
915    /// The event is sent when binding to the output object and there
916    /// will always be one mode, the current mode.  The event is sent
917    /// again if an output changes mode, for the mode that is now
918    /// current.  In other words, the current mode is always the last
919    /// mode that was received with the current flag set.
920    ///
921    /// Non-current modes are deprecated. A compositor can decide to only
922    /// advertise the current mode and never send other modes. Clients
923    /// should not rely on non-current modes.
924    ///
925    /// The size of a mode is given in physical hardware units of
926    /// the output device. This is not necessarily the same as
927    /// the output size in the global compositor space. For instance,
928    /// the output may be scaled, as described in wl_output.scale,
929    /// or transformed, as described in wl_output.transform. Clients
930    /// willing to retrieve the output size in the global compositor
931    /// space should use xdg_output.logical_size instead.
932    ///
933    /// The vertical refresh rate can be set to zero if it doesn't make
934    /// sense for this output (e.g. for virtual outputs).
935    ///
936    /// The mode event will be followed by a done event (starting from
937    /// version 2).
938    ///
939    /// Clients should not use the refresh rate to schedule frames. Instead,
940    /// they should use the wl_surface.frame event or the presentation-time
941    /// protocol.
942    ///
943    /// Note: this information is not always meaningful for all outputs. Some
944    /// compositors, such as those exposing virtual outputs, might fake the
945    /// refresh rate or the size.
946    ///
947    /// # Arguments
948    ///
949    /// - `flags`: bitfield of mode flags
950    /// - `width`: width of the mode in hardware units
951    /// - `height`: height of the mode in hardware units
952    /// - `refresh`: vertical refresh rate in mHz
953    #[inline]
954    fn handle_mode(
955        &mut self,
956        slf: &Rc<WlOutput>,
957        flags: WlOutputMode,
958        width: i32,
959        height: i32,
960        refresh: i32,
961    ) {
962        if !slf.core.forward_to_client.get() {
963            return;
964        }
965        let res = slf.try_send_mode(
966            flags,
967            width,
968            height,
969            refresh,
970        );
971        if let Err(e) = res {
972            log_forward("wl_output.mode", &e);
973        }
974    }
975
976    /// sent all information about output
977    ///
978    /// This event is sent after all other properties have been
979    /// sent after binding to the output object and after any
980    /// other property changes done after that. This allows
981    /// changes to the output properties to be seen as
982    /// atomic, even if they happen via multiple events.
983    #[inline]
984    fn handle_done(
985        &mut self,
986        slf: &Rc<WlOutput>,
987    ) {
988        if !slf.core.forward_to_client.get() {
989            return;
990        }
991        let res = slf.try_send_done(
992        );
993        if let Err(e) = res {
994            log_forward("wl_output.done", &e);
995        }
996    }
997
998    /// output scaling properties
999    ///
1000    /// This event contains scaling geometry information
1001    /// that is not in the geometry event. It may be sent after
1002    /// binding the output object or if the output scale changes
1003    /// later. The compositor will emit a non-zero, positive
1004    /// value for scale. If it is not sent, the client should
1005    /// assume a scale of 1.
1006    ///
1007    /// A scale larger than 1 means that the compositor will
1008    /// automatically scale surface buffers by this amount
1009    /// when rendering. This is used for very high resolution
1010    /// displays where applications rendering at the native
1011    /// resolution would be too small to be legible.
1012    ///
1013    /// Clients should use wl_surface.preferred_buffer_scale
1014    /// instead of this event to find the preferred buffer
1015    /// scale to use for a surface.
1016    ///
1017    /// The scale event will be followed by a done event.
1018    ///
1019    /// # Arguments
1020    ///
1021    /// - `factor`: scaling factor of output
1022    #[inline]
1023    fn handle_scale(
1024        &mut self,
1025        slf: &Rc<WlOutput>,
1026        factor: i32,
1027    ) {
1028        if !slf.core.forward_to_client.get() {
1029            return;
1030        }
1031        let res = slf.try_send_scale(
1032            factor,
1033        );
1034        if let Err(e) = res {
1035            log_forward("wl_output.scale", &e);
1036        }
1037    }
1038
1039    /// release the output object
1040    ///
1041    /// Using this request a client can tell the server that it is not going to
1042    /// use the output object anymore.
1043    #[inline]
1044    fn handle_release(
1045        &mut self,
1046        slf: &Rc<WlOutput>,
1047    ) {
1048        if !slf.core.forward_to_server.get() {
1049            return;
1050        }
1051        let res = slf.try_send_release(
1052        );
1053        if let Err(e) = res {
1054            log_forward("wl_output.release", &e);
1055        }
1056    }
1057
1058    /// name of this output
1059    ///
1060    /// Many compositors will assign user-friendly names to their outputs, show
1061    /// them to the user, allow the user to refer to an output, etc. The client
1062    /// may wish to know this name as well to offer the user similar behaviors.
1063    ///
1064    /// The name is a UTF-8 string with no convention defined for its contents.
1065    /// Each name is unique among all wl_output globals. The name is only
1066    /// guaranteed to be unique for the compositor instance.
1067    ///
1068    /// The same output name is used for all clients for a given wl_output
1069    /// global. Thus, the name can be shared across processes to refer to a
1070    /// specific wl_output global.
1071    ///
1072    /// The name is not guaranteed to be persistent across sessions, thus cannot
1073    /// be used to reliably identify an output in e.g. configuration files.
1074    ///
1075    /// Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
1076    /// not assume that the name is a reflection of an underlying DRM connector,
1077    /// X11 connection, etc.
1078    ///
1079    /// The name event is sent after binding the output object. This event is
1080    /// only sent once per output object, and the name does not change over the
1081    /// lifetime of the wl_output global.
1082    ///
1083    /// Compositors may re-use the same output name if the wl_output global is
1084    /// destroyed and re-created later. Compositors should avoid re-using the
1085    /// same name if possible.
1086    ///
1087    /// The name event will be followed by a done event.
1088    ///
1089    /// # Arguments
1090    ///
1091    /// - `name`: output name
1092    #[inline]
1093    fn handle_name(
1094        &mut self,
1095        slf: &Rc<WlOutput>,
1096        name: &str,
1097    ) {
1098        if !slf.core.forward_to_client.get() {
1099            return;
1100        }
1101        let res = slf.try_send_name(
1102            name,
1103        );
1104        if let Err(e) = res {
1105            log_forward("wl_output.name", &e);
1106        }
1107    }
1108
1109    /// human-readable description of this output
1110    ///
1111    /// Many compositors can produce human-readable descriptions of their
1112    /// outputs. The client may wish to know this description as well, e.g. for
1113    /// output selection purposes.
1114    ///
1115    /// The description is a UTF-8 string with no convention defined for its
1116    /// contents. The description is not guaranteed to be unique among all
1117    /// wl_output globals. Examples might include 'Foocorp 11" Display' or
1118    /// 'Virtual X11 output via :1'.
1119    ///
1120    /// The description event is sent after binding the output object and
1121    /// whenever the description changes. The description is optional, and may
1122    /// not be sent at all.
1123    ///
1124    /// The description event will be followed by a done event.
1125    ///
1126    /// # Arguments
1127    ///
1128    /// - `description`: output description
1129    #[inline]
1130    fn handle_description(
1131        &mut self,
1132        slf: &Rc<WlOutput>,
1133        description: &str,
1134    ) {
1135        if !slf.core.forward_to_client.get() {
1136            return;
1137        }
1138        let res = slf.try_send_description(
1139            description,
1140        );
1141        if let Err(e) = res {
1142            log_forward("wl_output.description", &e);
1143        }
1144    }
1145}
1146
1147impl ObjectPrivate for WlOutput {
1148    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
1149        Rc::<Self>::new_cyclic(|slf| Self {
1150            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlOutput, version),
1151            handler: Default::default(),
1152        })
1153    }
1154
1155    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
1156        let Some(mut handler) = self.handler.try_borrow_mut() else {
1157            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
1158        };
1159        if let Some(handler) = &mut *handler {
1160            handler.delete_id(&self);
1161        } else {
1162            self.core.delete_id();
1163        }
1164        Ok(())
1165    }
1166
1167    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1168        let Some(mut handler) = self.handler.try_borrow_mut() else {
1169            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1170        };
1171        let handler = &mut *handler;
1172        match msg[1] & 0xffff {
1173            0 => {
1174                if msg.len() != 2 {
1175                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1176                }
1177                #[cfg(feature = "logging")]
1178                if self.core.state.log {
1179                    #[cold]
1180                    fn log(state: &State, client_id: u64, id: u32) {
1181                        let (millis, micros) = time_since_epoch();
1182                        let prefix = &state.log_prefix;
1183                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_output#{}.release()\n", client_id, id);
1184                        state.log(args);
1185                    }
1186                    log(&self.core.state, client.endpoint.id, msg[0]);
1187                }
1188                self.core.handle_client_destroy();
1189                if let Some(handler) = handler {
1190                    (**handler).handle_release(&self);
1191                } else {
1192                    DefaultHandler.handle_release(&self);
1193                }
1194            }
1195            n => {
1196                let _ = client;
1197                let _ = msg;
1198                let _ = fds;
1199                let _ = handler;
1200                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1201            }
1202        }
1203        Ok(())
1204    }
1205
1206    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1207        let Some(mut handler) = self.handler.try_borrow_mut() else {
1208            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1209        };
1210        let handler = &mut *handler;
1211        match msg[1] & 0xffff {
1212            0 => {
1213                let mut offset = 2;
1214                let Some(&arg0) = msg.get(offset) else {
1215                    return Err(ObjectError(ObjectErrorKind::MissingArgument("x")));
1216                };
1217                offset += 1;
1218                let Some(&arg1) = msg.get(offset) else {
1219                    return Err(ObjectError(ObjectErrorKind::MissingArgument("y")));
1220                };
1221                offset += 1;
1222                let Some(&arg2) = msg.get(offset) else {
1223                    return Err(ObjectError(ObjectErrorKind::MissingArgument("physical_width")));
1224                };
1225                offset += 1;
1226                let Some(&arg3) = msg.get(offset) else {
1227                    return Err(ObjectError(ObjectErrorKind::MissingArgument("physical_height")));
1228                };
1229                offset += 1;
1230                let Some(&arg4) = msg.get(offset) else {
1231                    return Err(ObjectError(ObjectErrorKind::MissingArgument("subpixel")));
1232                };
1233                offset += 1;
1234                let arg5;
1235                (arg5, offset) = parse_string::<NonNullString>(msg, offset, "make")?;
1236                let arg6;
1237                (arg6, offset) = parse_string::<NonNullString>(msg, offset, "model")?;
1238                let Some(&arg7) = msg.get(offset) else {
1239                    return Err(ObjectError(ObjectErrorKind::MissingArgument("transform")));
1240                };
1241                offset += 1;
1242                if offset != msg.len() {
1243                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
1244                }
1245                let arg0 = arg0 as i32;
1246                let arg1 = arg1 as i32;
1247                let arg2 = arg2 as i32;
1248                let arg3 = arg3 as i32;
1249                let arg4 = WlOutputSubpixel(arg4);
1250                let arg7 = WlOutputTransform(arg7);
1251                #[cfg(feature = "logging")]
1252                if self.core.state.log {
1253                    #[cold]
1254                    fn log(state: &State, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32, arg4: WlOutputSubpixel, arg5: &str, arg6: &str, arg7: WlOutputTransform) {
1255                        let (millis, micros) = time_since_epoch();
1256                        let prefix = &state.log_prefix;
1257                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_output#{}.geometry(x: {}, y: {}, physical_width: {}, physical_height: {}, subpixel: {:?}, make: {:?}, model: {:?}, transform: {:?})\n", id, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1258                        state.log(args);
1259                    }
1260                    log(&self.core.state, msg[0], arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1261                }
1262                if let Some(handler) = handler {
1263                    (**handler).handle_geometry(&self, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1264                } else {
1265                    DefaultHandler.handle_geometry(&self, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
1266                }
1267            }
1268            1 => {
1269                let [
1270                    arg0,
1271                    arg1,
1272                    arg2,
1273                    arg3,
1274                ] = msg[2..] else {
1275                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
1276                };
1277                let arg0 = WlOutputMode(arg0);
1278                let arg1 = arg1 as i32;
1279                let arg2 = arg2 as i32;
1280                let arg3 = arg3 as i32;
1281                #[cfg(feature = "logging")]
1282                if self.core.state.log {
1283                    #[cold]
1284                    fn log(state: &State, id: u32, arg0: WlOutputMode, arg1: i32, arg2: i32, arg3: i32) {
1285                        let (millis, micros) = time_since_epoch();
1286                        let prefix = &state.log_prefix;
1287                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_output#{}.mode(flags: {:?}, width: {}, height: {}, refresh: {})\n", id, arg0, arg1, arg2, arg3);
1288                        state.log(args);
1289                    }
1290                    log(&self.core.state, msg[0], arg0, arg1, arg2, arg3);
1291                }
1292                if let Some(handler) = handler {
1293                    (**handler).handle_mode(&self, arg0, arg1, arg2, arg3);
1294                } else {
1295                    DefaultHandler.handle_mode(&self, arg0, arg1, arg2, arg3);
1296                }
1297            }
1298            2 => {
1299                if msg.len() != 2 {
1300                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1301                }
1302                #[cfg(feature = "logging")]
1303                if self.core.state.log {
1304                    #[cold]
1305                    fn log(state: &State, id: u32) {
1306                        let (millis, micros) = time_since_epoch();
1307                        let prefix = &state.log_prefix;
1308                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_output#{}.done()\n", id);
1309                        state.log(args);
1310                    }
1311                    log(&self.core.state, msg[0]);
1312                }
1313                if let Some(handler) = handler {
1314                    (**handler).handle_done(&self);
1315                } else {
1316                    DefaultHandler.handle_done(&self);
1317                }
1318            }
1319            3 => {
1320                let [
1321                    arg0,
1322                ] = msg[2..] else {
1323                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
1324                };
1325                let arg0 = arg0 as i32;
1326                #[cfg(feature = "logging")]
1327                if self.core.state.log {
1328                    #[cold]
1329                    fn log(state: &State, id: u32, arg0: i32) {
1330                        let (millis, micros) = time_since_epoch();
1331                        let prefix = &state.log_prefix;
1332                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_output#{}.scale(factor: {})\n", id, arg0);
1333                        state.log(args);
1334                    }
1335                    log(&self.core.state, msg[0], arg0);
1336                }
1337                if let Some(handler) = handler {
1338                    (**handler).handle_scale(&self, arg0);
1339                } else {
1340                    DefaultHandler.handle_scale(&self, arg0);
1341                }
1342            }
1343            4 => {
1344                let mut offset = 2;
1345                let arg0;
1346                (arg0, offset) = parse_string::<NonNullString>(msg, offset, "name")?;
1347                if offset != msg.len() {
1348                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
1349                }
1350                #[cfg(feature = "logging")]
1351                if self.core.state.log {
1352                    #[cold]
1353                    fn log(state: &State, id: u32, arg0: &str) {
1354                        let (millis, micros) = time_since_epoch();
1355                        let prefix = &state.log_prefix;
1356                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_output#{}.name(name: {:?})\n", id, arg0);
1357                        state.log(args);
1358                    }
1359                    log(&self.core.state, msg[0], arg0);
1360                }
1361                if let Some(handler) = handler {
1362                    (**handler).handle_name(&self, arg0);
1363                } else {
1364                    DefaultHandler.handle_name(&self, arg0);
1365                }
1366            }
1367            5 => {
1368                let mut offset = 2;
1369                let arg0;
1370                (arg0, offset) = parse_string::<NonNullString>(msg, offset, "description")?;
1371                if offset != msg.len() {
1372                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
1373                }
1374                #[cfg(feature = "logging")]
1375                if self.core.state.log {
1376                    #[cold]
1377                    fn log(state: &State, id: u32, arg0: &str) {
1378                        let (millis, micros) = time_since_epoch();
1379                        let prefix = &state.log_prefix;
1380                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_output#{}.description(description: {:?})\n", id, arg0);
1381                        state.log(args);
1382                    }
1383                    log(&self.core.state, msg[0], arg0);
1384                }
1385                if let Some(handler) = handler {
1386                    (**handler).handle_description(&self, arg0);
1387                } else {
1388                    DefaultHandler.handle_description(&self, arg0);
1389                }
1390            }
1391            n => {
1392                let _ = server;
1393                let _ = msg;
1394                let _ = fds;
1395                let _ = handler;
1396                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1397            }
1398        }
1399        Ok(())
1400    }
1401
1402    fn get_request_name(&self, id: u32) -> Option<&'static str> {
1403        let name = match id {
1404            0 => "release",
1405            _ => return None,
1406        };
1407        Some(name)
1408    }
1409
1410    fn get_event_name(&self, id: u32) -> Option<&'static str> {
1411        let name = match id {
1412            0 => "geometry",
1413            1 => "mode",
1414            2 => "done",
1415            3 => "scale",
1416            4 => "name",
1417            5 => "description",
1418            _ => return None,
1419        };
1420        Some(name)
1421    }
1422}
1423
1424impl Object for WlOutput {
1425    fn core(&self) -> &ObjectCore {
1426        &self.core
1427    }
1428
1429    fn unset_handler(&self) {
1430        self.handler.set(None);
1431    }
1432
1433    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
1434        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1435        if borrowed.is_none() {
1436            return Err(HandlerAccessError::NoHandler);
1437        }
1438        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
1439    }
1440
1441    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
1442        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1443        if borrowed.is_none() {
1444            return Err(HandlerAccessError::NoHandler);
1445        }
1446        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
1447    }
1448}
1449
1450impl WlOutput {
1451    /// Since when the subpixel.unknown enum variant is available.
1452    pub const ENM__SUBPIXEL_UNKNOWN__SINCE: u32 = 1;
1453    /// Since when the subpixel.none enum variant is available.
1454    pub const ENM__SUBPIXEL_NONE__SINCE: u32 = 1;
1455    /// Since when the subpixel.horizontal_rgb enum variant is available.
1456    pub const ENM__SUBPIXEL_HORIZONTAL_RGB__SINCE: u32 = 1;
1457    /// Since when the subpixel.horizontal_bgr enum variant is available.
1458    pub const ENM__SUBPIXEL_HORIZONTAL_BGR__SINCE: u32 = 1;
1459    /// Since when the subpixel.vertical_rgb enum variant is available.
1460    pub const ENM__SUBPIXEL_VERTICAL_RGB__SINCE: u32 = 1;
1461    /// Since when the subpixel.vertical_bgr enum variant is available.
1462    pub const ENM__SUBPIXEL_VERTICAL_BGR__SINCE: u32 = 1;
1463
1464    /// Since when the transform.normal enum variant is available.
1465    pub const ENM__TRANSFORM_NORMAL__SINCE: u32 = 1;
1466    /// Since when the transform.90 enum variant is available.
1467    pub const ENM__TRANSFORM_90__SINCE: u32 = 1;
1468    /// Since when the transform.180 enum variant is available.
1469    pub const ENM__TRANSFORM_180__SINCE: u32 = 1;
1470    /// Since when the transform.270 enum variant is available.
1471    pub const ENM__TRANSFORM_270__SINCE: u32 = 1;
1472    /// Since when the transform.flipped enum variant is available.
1473    pub const ENM__TRANSFORM_FLIPPED__SINCE: u32 = 1;
1474    /// Since when the transform.flipped_90 enum variant is available.
1475    pub const ENM__TRANSFORM_FLIPPED_90__SINCE: u32 = 1;
1476    /// Since when the transform.flipped_180 enum variant is available.
1477    pub const ENM__TRANSFORM_FLIPPED_180__SINCE: u32 = 1;
1478    /// Since when the transform.flipped_270 enum variant is available.
1479    pub const ENM__TRANSFORM_FLIPPED_270__SINCE: u32 = 1;
1480
1481    /// Since when the mode.current enum variant is available.
1482    pub const ENM__MODE_CURRENT__SINCE: u32 = 1;
1483    /// Since when the mode.preferred enum variant is available.
1484    pub const ENM__MODE_PREFERRED__SINCE: u32 = 1;
1485}
1486
1487/// subpixel geometry information
1488///
1489/// This enumeration describes how the physical
1490/// pixels on an output are laid out.
1491#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1492pub struct WlOutputSubpixel(pub u32);
1493
1494impl WlOutputSubpixel {
1495    /// unknown geometry
1496    pub const UNKNOWN: Self = Self(0);
1497
1498    /// no geometry
1499    pub const NONE: Self = Self(1);
1500
1501    /// horizontal RGB
1502    pub const HORIZONTAL_RGB: Self = Self(2);
1503
1504    /// horizontal BGR
1505    pub const HORIZONTAL_BGR: Self = Self(3);
1506
1507    /// vertical RGB
1508    pub const VERTICAL_RGB: Self = Self(4);
1509
1510    /// vertical BGR
1511    pub const VERTICAL_BGR: Self = Self(5);
1512}
1513
1514impl Debug for WlOutputSubpixel {
1515    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1516        let name = match *self {
1517            Self::UNKNOWN => "UNKNOWN",
1518            Self::NONE => "NONE",
1519            Self::HORIZONTAL_RGB => "HORIZONTAL_RGB",
1520            Self::HORIZONTAL_BGR => "HORIZONTAL_BGR",
1521            Self::VERTICAL_RGB => "VERTICAL_RGB",
1522            Self::VERTICAL_BGR => "VERTICAL_BGR",
1523            _ => return Debug::fmt(&self.0, f),
1524        };
1525        f.write_str(name)
1526    }
1527}
1528
1529/// transformation applied to buffer contents
1530///
1531/// This describes transformations that clients and compositors apply to
1532/// buffer contents.
1533///
1534/// The flipped values correspond to an initial flip around a
1535/// vertical axis followed by rotation.
1536///
1537/// The purpose is mainly to allow clients to render accordingly and
1538/// tell the compositor, so that for fullscreen surfaces, the
1539/// compositor will still be able to scan out directly from client
1540/// surfaces.
1541#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1542pub struct WlOutputTransform(pub u32);
1543
1544impl WlOutputTransform {
1545    /// no transform
1546    pub const NORMAL: Self = Self(0);
1547
1548    /// 90 degrees counter-clockwise
1549    pub const _90: Self = Self(1);
1550
1551    /// 180 degrees counter-clockwise
1552    pub const _180: Self = Self(2);
1553
1554    /// 270 degrees counter-clockwise
1555    pub const _270: Self = Self(3);
1556
1557    /// 180 degree flip around a vertical axis
1558    pub const FLIPPED: Self = Self(4);
1559
1560    /// flip and rotate 90 degrees counter-clockwise
1561    pub const FLIPPED_90: Self = Self(5);
1562
1563    /// flip and rotate 180 degrees counter-clockwise
1564    pub const FLIPPED_180: Self = Self(6);
1565
1566    /// flip and rotate 270 degrees counter-clockwise
1567    pub const FLIPPED_270: Self = Self(7);
1568}
1569
1570impl Debug for WlOutputTransform {
1571    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1572        let name = match *self {
1573            Self::NORMAL => "NORMAL",
1574            Self::_90 => "_90",
1575            Self::_180 => "_180",
1576            Self::_270 => "_270",
1577            Self::FLIPPED => "FLIPPED",
1578            Self::FLIPPED_90 => "FLIPPED_90",
1579            Self::FLIPPED_180 => "FLIPPED_180",
1580            Self::FLIPPED_270 => "FLIPPED_270",
1581            _ => return Debug::fmt(&self.0, f),
1582        };
1583        f.write_str(name)
1584    }
1585}
1586
1587/// mode information
1588///
1589/// These flags describe properties of an output mode.
1590/// They are used in the flags bitfield of the mode event.
1591#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1592#[derive(Default)]
1593pub struct WlOutputMode(pub u32);
1594
1595/// An iterator over the set bits in a [`WlOutputMode`].
1596///
1597/// You can construct this with the `IntoIterator` implementation of `WlOutputMode`.
1598#[derive(Clone, Debug)]
1599pub struct WlOutputModeIter(pub u32);
1600
1601impl WlOutputMode {
1602    /// indicates this is the current mode
1603    pub const CURRENT: Self = Self(0x1);
1604
1605    /// indicates this is the preferred mode
1606    pub const PREFERRED: Self = Self(0x2);
1607}
1608
1609impl WlOutputMode {
1610    #[inline]
1611    pub const fn empty() -> Self {
1612        Self(0)
1613    }
1614
1615    #[inline]
1616    #[must_use]
1617    pub const fn is_empty(self) -> bool {
1618        self.0 == 0
1619    }
1620
1621    #[inline]
1622    #[must_use]
1623    pub const fn contains(self, other: Self) -> bool {
1624        self.0 & other.0 == other.0
1625    }
1626
1627    #[inline]
1628    #[must_use]
1629    pub const fn intersects(self, other: Self) -> bool {
1630        self.0 & other.0 != 0
1631    }
1632
1633    #[inline]
1634    pub const fn insert(&mut self, other: Self) {
1635        *self = self.union(other);
1636    }
1637
1638    #[inline]
1639    pub const fn remove(&mut self, other: Self) {
1640        *self = self.difference(other);
1641    }
1642
1643    #[inline]
1644    pub const fn toggle(&mut self, other: Self) {
1645        *self = self.symmetric_difference(other);
1646    }
1647
1648    #[inline]
1649    pub const fn set(&mut self, other: Self, value: bool) {
1650        if value {
1651            self.insert(other);
1652        } else {
1653            self.remove(other);
1654        }
1655    }
1656
1657    #[inline]
1658    #[must_use]
1659    pub const fn intersection(self, other: Self) -> Self {
1660        Self(self.0 & other.0)
1661    }
1662
1663    #[inline]
1664    #[must_use]
1665    pub const fn union(self, other: Self) -> Self {
1666        Self(self.0 | other.0)
1667    }
1668
1669    #[inline]
1670    #[must_use]
1671    pub const fn difference(self, other: Self) -> Self {
1672        Self(self.0 & !other.0)
1673    }
1674
1675    #[inline]
1676    #[must_use]
1677    pub const fn complement(self) -> Self {
1678        Self(!self.0)
1679    }
1680
1681    #[inline]
1682    #[must_use]
1683    pub const fn symmetric_difference(self, other: Self) -> Self {
1684        Self(self.0 ^ other.0)
1685    }
1686
1687    #[inline]
1688    pub const fn all_known() -> Self {
1689        #[allow(clippy::eq_op, clippy::identity_op)]
1690        Self(0 | 0x1 | 0x2)
1691    }
1692}
1693
1694impl Iterator for WlOutputModeIter {
1695    type Item = WlOutputMode;
1696
1697    fn next(&mut self) -> Option<Self::Item> {
1698        if self.0 == 0 {
1699            return None;
1700        }
1701        let bit = 1 << self.0.trailing_zeros();
1702        self.0 &= !bit;
1703        Some(WlOutputMode(bit))
1704    }
1705}
1706
1707impl IntoIterator for WlOutputMode {
1708    type Item = WlOutputMode;
1709    type IntoIter = WlOutputModeIter;
1710
1711    fn into_iter(self) -> Self::IntoIter {
1712        WlOutputModeIter(self.0)
1713    }
1714}
1715
1716impl BitAnd for WlOutputMode {
1717    type Output = Self;
1718
1719    fn bitand(self, rhs: Self) -> Self::Output {
1720        self.intersection(rhs)
1721    }
1722}
1723
1724impl BitAndAssign for WlOutputMode {
1725    fn bitand_assign(&mut self, rhs: Self) {
1726        *self = self.intersection(rhs);
1727    }
1728}
1729
1730impl BitOr for WlOutputMode {
1731    type Output = Self;
1732
1733    fn bitor(self, rhs: Self) -> Self::Output {
1734        self.union(rhs)
1735    }
1736}
1737
1738impl BitOrAssign for WlOutputMode {
1739    fn bitor_assign(&mut self, rhs: Self) {
1740        *self = self.union(rhs);
1741    }
1742}
1743
1744impl BitXor for WlOutputMode {
1745    type Output = Self;
1746
1747    fn bitxor(self, rhs: Self) -> Self::Output {
1748        self.symmetric_difference(rhs)
1749    }
1750}
1751
1752impl BitXorAssign for WlOutputMode {
1753    fn bitxor_assign(&mut self, rhs: Self) {
1754        *self = self.symmetric_difference(rhs);
1755    }
1756}
1757
1758impl Sub for WlOutputMode {
1759    type Output = Self;
1760
1761    fn sub(self, rhs: Self) -> Self::Output {
1762        self.difference(rhs)
1763    }
1764}
1765
1766impl SubAssign for WlOutputMode {
1767    fn sub_assign(&mut self, rhs: Self) {
1768        *self = self.difference(rhs);
1769    }
1770}
1771
1772impl Not for WlOutputMode {
1773    type Output = Self;
1774
1775    fn not(self) -> Self::Output {
1776        self.complement()
1777    }
1778}
1779
1780impl Debug for WlOutputMode {
1781    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1782        let mut v = self.0;
1783        let mut first = true;
1784        if v & 0x1 == 0x1 {
1785            v &= !0x1;
1786            if first {
1787                first = false;
1788            } else {
1789                f.write_str(" | ")?;
1790            }
1791            f.write_str("CURRENT")?;
1792        }
1793        if v & 0x2 == 0x2 {
1794            v &= !0x2;
1795            if first {
1796                first = false;
1797            } else {
1798                f.write_str(" | ")?;
1799            }
1800            f.write_str("PREFERRED")?;
1801        }
1802        if v != 0 {
1803            if first {
1804                first = false;
1805            } else {
1806                f.write_str(" | ")?;
1807            }
1808            write!(f, "0x{v:032x}")?;
1809        }
1810        if first {
1811            f.write_str("0")?;
1812        }
1813        Ok(())
1814    }
1815}