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}