Skip to main content

wl_proxy/protocols/wayland/
wl_surface.rs

1//! an onscreen surface
2//!
3//! A surface is a rectangular area that may be displayed on zero
4//! or more outputs, and shown any number of times at the compositor's
5//! discretion. They can present wl_buffers, receive user input, and
6//! define a local coordinate system.
7//!
8//! The size of a surface (and relative positions on it) is described
9//! in surface-local coordinates, which may differ from the buffer
10//! coordinates of the pixel content, in case a buffer_transform
11//! or a buffer_scale is used.
12//!
13//! A surface without a "role" is fairly useless: a compositor does
14//! not know where, when or how to present it. The role is the
15//! purpose of a wl_surface. Examples of roles are a cursor for a
16//! pointer (as set by wl_pointer.set_cursor), a drag icon
17//! (wl_data_device.start_drag), a sub-surface
18//! (wl_subcompositor.get_subsurface), and a window as defined by a
19//! shell protocol (e.g. wl_shell.get_shell_surface).
20//!
21//! A surface can have only one role at a time. Initially a
22//! wl_surface does not have a role. Once a wl_surface is given a
23//! role, it is set permanently for the whole lifetime of the
24//! wl_surface object. Giving the current role again is allowed,
25//! unless explicitly forbidden by the relevant interface
26//! specification.
27//!
28//! Surface roles are given by requests in other interfaces such as
29//! wl_pointer.set_cursor. The request should explicitly mention
30//! that this request gives a role to a wl_surface. Often, this
31//! request also creates a new protocol object that represents the
32//! role and adds additional functionality to wl_surface. When a
33//! client wants to destroy a wl_surface, they must destroy this role
34//! object before the wl_surface, otherwise a defunct_role_object error is
35//! sent.
36//!
37//! Destroying the role object does not remove the role from the
38//! wl_surface, but it may stop the wl_surface from "playing the role".
39//! For instance, if a wl_subsurface object is destroyed, the wl_surface
40//! it was created for will be unmapped and forget its position and
41//! z-order. It is allowed to create a wl_subsurface for the same
42//! wl_surface again, but it is not allowed to use the wl_surface as
43//! a cursor (cursor is a different role than sub-surface, and role
44//! switching is not allowed).
45
46use crate::protocol_helpers::prelude::*;
47use super::super::all_types::*;
48
49/// A wl_surface object.
50///
51/// See the documentation of [the module][self] for the interface description.
52pub struct WlSurface {
53    core: ObjectCore,
54    handler: HandlerHolder<dyn WlSurfaceHandler>,
55}
56
57struct DefaultHandler;
58
59impl WlSurfaceHandler for DefaultHandler { }
60
61impl ConcreteObject for WlSurface {
62    const XML_VERSION: u32 = 6;
63    const INTERFACE: ObjectInterface = ObjectInterface::WlSurface;
64    const INTERFACE_NAME: &str = "wl_surface";
65}
66
67impl WlSurface {
68    /// Sets a new handler.
69    pub fn set_handler(&self, handler: impl WlSurfaceHandler) {
70        self.set_boxed_handler(Box::new(handler));
71    }
72
73    /// Sets a new, already boxed handler.
74    pub fn set_boxed_handler(&self, handler: Box<dyn WlSurfaceHandler>) {
75        if self.core.state.destroyed.get() {
76            return;
77        }
78        self.handler.set(Some(handler));
79    }
80}
81
82impl Debug for WlSurface {
83    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84        f.debug_struct("WlSurface")
85            .field("server_obj_id", &self.core.server_obj_id.get())
86            .field("client_id", &self.core.client_id.get())
87            .field("client_obj_id", &self.core.client_obj_id.get())
88            .finish()
89    }
90}
91
92impl WlSurface {
93    /// Since when the destroy message is available.
94    pub const MSG__DESTROY__SINCE: u32 = 1;
95
96    /// delete surface
97    ///
98    /// Deletes the surface and invalidates its object ID.
99    #[inline]
100    pub fn try_send_destroy(
101        &self,
102    ) -> Result<(), ObjectError> {
103        let core = self.core();
104        let Some(id) = core.server_obj_id.get() else {
105            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
106        };
107        #[cfg(feature = "logging")]
108        if self.core.state.log {
109            #[cold]
110            fn log(state: &State, id: u32) {
111                let (millis, micros) = time_since_epoch();
112                let prefix = &state.log_prefix;
113                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.destroy()\n", id);
114                state.log(args);
115            }
116            log(&self.core.state, id);
117        }
118        let Some(endpoint) = &self.core.state.server else {
119            return Ok(());
120        };
121        if !endpoint.flush_queued.replace(true) {
122            self.core.state.add_flushable_endpoint(endpoint, None);
123        }
124        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
125        let outgoing = &mut *outgoing_ref;
126        let mut fmt = outgoing.formatter();
127        fmt.words([
128            id,
129            0,
130        ]);
131        self.core.handle_server_destroy();
132        Ok(())
133    }
134
135    /// delete surface
136    ///
137    /// Deletes the surface and invalidates its object ID.
138    #[inline]
139    pub fn send_destroy(
140        &self,
141    ) {
142        let res = self.try_send_destroy(
143        );
144        if let Err(e) = res {
145            log_send("wl_surface.destroy", &e);
146        }
147    }
148
149    /// Since when the attach message is available.
150    pub const MSG__ATTACH__SINCE: u32 = 1;
151
152    /// set the surface contents
153    ///
154    /// Set a buffer as the content of this surface.
155    ///
156    /// The new size of the surface is calculated based on the buffer
157    /// size transformed by the inverse buffer_transform and the
158    /// inverse buffer_scale. This means that at commit time the supplied
159    /// buffer size must be an integer multiple of the buffer_scale. If
160    /// that's not the case, an invalid_size error is sent.
161    ///
162    /// The x and y arguments specify the location of the new pending
163    /// buffer's upper left corner, relative to the current buffer's upper
164    /// left corner, in surface-local coordinates. In other words, the
165    /// x and y, combined with the new surface size define in which
166    /// directions the surface's size changes. Setting anything other than 0
167    /// as x and y arguments is discouraged, and should instead be replaced
168    /// with using the separate wl_surface.offset request.
169    ///
170    /// When the bound wl_surface version is 5 or higher, passing any
171    /// non-zero x or y is a protocol violation, and will result in an
172    /// 'invalid_offset' error being raised. The x and y arguments are ignored
173    /// and do not change the pending state. To achieve equivalent semantics,
174    /// use wl_surface.offset.
175    ///
176    /// Surface contents are double-buffered state, see wl_surface.commit.
177    ///
178    /// The initial surface contents are void; there is no content.
179    /// wl_surface.attach assigns the given wl_buffer as the pending
180    /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
181    /// surface contents, and the size of the surface becomes the size
182    /// calculated from the wl_buffer, as described above. After commit,
183    /// there is no pending buffer until the next attach.
184    ///
185    /// Committing a pending wl_buffer allows the compositor to read the
186    /// pixels in the wl_buffer. The compositor may access the pixels at
187    /// any time after the wl_surface.commit request. When the compositor
188    /// will not access the pixels anymore, it will send the
189    /// wl_buffer.release event. Only after receiving wl_buffer.release,
190    /// the client may reuse the wl_buffer. A wl_buffer that has been
191    /// attached and then replaced by another attach instead of committed
192    /// will not receive a release event, and is not used by the
193    /// compositor.
194    ///
195    /// If a pending wl_buffer has been committed to more than one wl_surface,
196    /// the delivery of wl_buffer.release events becomes undefined. A well
197    /// behaved client should not rely on wl_buffer.release events in this
198    /// case. Alternatively, a client could create multiple wl_buffer objects
199    /// from the same backing storage or use a protocol extension providing
200    /// per-commit release notifications.
201    ///
202    /// Destroying the wl_buffer after wl_buffer.release does not change
203    /// the surface contents. Destroying the wl_buffer before wl_buffer.release
204    /// is allowed as long as the underlying buffer storage isn't re-used (this
205    /// can happen e.g. on client process termination). However, if the client
206    /// destroys the wl_buffer before receiving the wl_buffer.release event and
207    /// mutates the underlying buffer storage, the surface contents become
208    /// undefined immediately.
209    ///
210    /// If wl_surface.attach is sent with a NULL wl_buffer, the
211    /// following wl_surface.commit will remove the surface content.
212    ///
213    /// If a pending wl_buffer has been destroyed, the result is not specified.
214    /// Many compositors are known to remove the surface content on the following
215    /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
216    /// maximise compatibility should not destroy pending buffers and should
217    /// ensure that they explicitly remove content from surfaces, even after
218    /// destroying buffers.
219    ///
220    /// # Arguments
221    ///
222    /// - `buffer`: buffer of surface contents
223    /// - `x`: surface-local x coordinate
224    /// - `y`: surface-local y coordinate
225    #[inline]
226    pub fn try_send_attach(
227        &self,
228        buffer: Option<&Rc<WlBuffer>>,
229        x: i32,
230        y: i32,
231    ) -> Result<(), ObjectError> {
232        let (
233            arg0,
234            arg1,
235            arg2,
236        ) = (
237            buffer,
238            x,
239            y,
240        );
241        let arg0 = arg0.map(|a| a.core());
242        let core = self.core();
243        let Some(id) = core.server_obj_id.get() else {
244            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
245        };
246        let arg0_id = match arg0 {
247            None => 0,
248            Some(arg0) => match arg0.server_obj_id.get() {
249                None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("buffer"))),
250                Some(id) => id,
251            },
252        };
253        #[cfg(feature = "logging")]
254        if self.core.state.log {
255            #[cold]
256            fn log(state: &State, id: u32, arg0: u32, arg1: i32, arg2: i32) {
257                let (millis, micros) = time_since_epoch();
258                let prefix = &state.log_prefix;
259                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.attach(buffer: wl_buffer#{}, x: {}, y: {})\n", id, arg0, arg1, arg2);
260                state.log(args);
261            }
262            log(&self.core.state, id, arg0_id, arg1, arg2);
263        }
264        let Some(endpoint) = &self.core.state.server else {
265            return Ok(());
266        };
267        if !endpoint.flush_queued.replace(true) {
268            self.core.state.add_flushable_endpoint(endpoint, None);
269        }
270        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
271        let outgoing = &mut *outgoing_ref;
272        let mut fmt = outgoing.formatter();
273        fmt.words([
274            id,
275            1,
276            arg0_id,
277            arg1 as u32,
278            arg2 as u32,
279        ]);
280        Ok(())
281    }
282
283    /// set the surface contents
284    ///
285    /// Set a buffer as the content of this surface.
286    ///
287    /// The new size of the surface is calculated based on the buffer
288    /// size transformed by the inverse buffer_transform and the
289    /// inverse buffer_scale. This means that at commit time the supplied
290    /// buffer size must be an integer multiple of the buffer_scale. If
291    /// that's not the case, an invalid_size error is sent.
292    ///
293    /// The x and y arguments specify the location of the new pending
294    /// buffer's upper left corner, relative to the current buffer's upper
295    /// left corner, in surface-local coordinates. In other words, the
296    /// x and y, combined with the new surface size define in which
297    /// directions the surface's size changes. Setting anything other than 0
298    /// as x and y arguments is discouraged, and should instead be replaced
299    /// with using the separate wl_surface.offset request.
300    ///
301    /// When the bound wl_surface version is 5 or higher, passing any
302    /// non-zero x or y is a protocol violation, and will result in an
303    /// 'invalid_offset' error being raised. The x and y arguments are ignored
304    /// and do not change the pending state. To achieve equivalent semantics,
305    /// use wl_surface.offset.
306    ///
307    /// Surface contents are double-buffered state, see wl_surface.commit.
308    ///
309    /// The initial surface contents are void; there is no content.
310    /// wl_surface.attach assigns the given wl_buffer as the pending
311    /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
312    /// surface contents, and the size of the surface becomes the size
313    /// calculated from the wl_buffer, as described above. After commit,
314    /// there is no pending buffer until the next attach.
315    ///
316    /// Committing a pending wl_buffer allows the compositor to read the
317    /// pixels in the wl_buffer. The compositor may access the pixels at
318    /// any time after the wl_surface.commit request. When the compositor
319    /// will not access the pixels anymore, it will send the
320    /// wl_buffer.release event. Only after receiving wl_buffer.release,
321    /// the client may reuse the wl_buffer. A wl_buffer that has been
322    /// attached and then replaced by another attach instead of committed
323    /// will not receive a release event, and is not used by the
324    /// compositor.
325    ///
326    /// If a pending wl_buffer has been committed to more than one wl_surface,
327    /// the delivery of wl_buffer.release events becomes undefined. A well
328    /// behaved client should not rely on wl_buffer.release events in this
329    /// case. Alternatively, a client could create multiple wl_buffer objects
330    /// from the same backing storage or use a protocol extension providing
331    /// per-commit release notifications.
332    ///
333    /// Destroying the wl_buffer after wl_buffer.release does not change
334    /// the surface contents. Destroying the wl_buffer before wl_buffer.release
335    /// is allowed as long as the underlying buffer storage isn't re-used (this
336    /// can happen e.g. on client process termination). However, if the client
337    /// destroys the wl_buffer before receiving the wl_buffer.release event and
338    /// mutates the underlying buffer storage, the surface contents become
339    /// undefined immediately.
340    ///
341    /// If wl_surface.attach is sent with a NULL wl_buffer, the
342    /// following wl_surface.commit will remove the surface content.
343    ///
344    /// If a pending wl_buffer has been destroyed, the result is not specified.
345    /// Many compositors are known to remove the surface content on the following
346    /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
347    /// maximise compatibility should not destroy pending buffers and should
348    /// ensure that they explicitly remove content from surfaces, even after
349    /// destroying buffers.
350    ///
351    /// # Arguments
352    ///
353    /// - `buffer`: buffer of surface contents
354    /// - `x`: surface-local x coordinate
355    /// - `y`: surface-local y coordinate
356    #[inline]
357    pub fn send_attach(
358        &self,
359        buffer: Option<&Rc<WlBuffer>>,
360        x: i32,
361        y: i32,
362    ) {
363        let res = self.try_send_attach(
364            buffer,
365            x,
366            y,
367        );
368        if let Err(e) = res {
369            log_send("wl_surface.attach", &e);
370        }
371    }
372
373    /// Since when the damage message is available.
374    pub const MSG__DAMAGE__SINCE: u32 = 1;
375
376    /// mark part of the surface damaged
377    ///
378    /// This request is used to describe the regions where the pending
379    /// buffer is different from the current surface contents, and where
380    /// the surface therefore needs to be repainted. The compositor
381    /// ignores the parts of the damage that fall outside of the surface.
382    ///
383    /// Damage is double-buffered state, see wl_surface.commit.
384    ///
385    /// The damage rectangle is specified in surface-local coordinates,
386    /// where x and y specify the upper left corner of the damage rectangle.
387    ///
388    /// The initial value for pending damage is empty: no damage.
389    /// wl_surface.damage adds pending damage: the new pending damage
390    /// is the union of old pending damage and the given rectangle.
391    ///
392    /// wl_surface.commit assigns pending damage as the current damage,
393    /// and clears pending damage. The server will clear the current
394    /// damage as it repaints the surface.
395    ///
396    /// Note! New clients should not use this request. Instead damage can be
397    /// posted with wl_surface.damage_buffer which uses buffer coordinates
398    /// instead of surface coordinates.
399    ///
400    /// # Arguments
401    ///
402    /// - `x`: surface-local x coordinate
403    /// - `y`: surface-local y coordinate
404    /// - `width`: width of damage rectangle
405    /// - `height`: height of damage rectangle
406    #[inline]
407    pub fn try_send_damage(
408        &self,
409        x: i32,
410        y: i32,
411        width: i32,
412        height: i32,
413    ) -> Result<(), ObjectError> {
414        let (
415            arg0,
416            arg1,
417            arg2,
418            arg3,
419        ) = (
420            x,
421            y,
422            width,
423            height,
424        );
425        let core = self.core();
426        let Some(id) = core.server_obj_id.get() else {
427            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
428        };
429        #[cfg(feature = "logging")]
430        if self.core.state.log {
431            #[cold]
432            fn log(state: &State, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
433                let (millis, micros) = time_since_epoch();
434                let prefix = &state.log_prefix;
435                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.damage(x: {}, y: {}, width: {}, height: {})\n", id, arg0, arg1, arg2, arg3);
436                state.log(args);
437            }
438            log(&self.core.state, id, arg0, arg1, arg2, arg3);
439        }
440        let Some(endpoint) = &self.core.state.server else {
441            return Ok(());
442        };
443        if !endpoint.flush_queued.replace(true) {
444            self.core.state.add_flushable_endpoint(endpoint, None);
445        }
446        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
447        let outgoing = &mut *outgoing_ref;
448        let mut fmt = outgoing.formatter();
449        fmt.words([
450            id,
451            2,
452            arg0 as u32,
453            arg1 as u32,
454            arg2 as u32,
455            arg3 as u32,
456        ]);
457        Ok(())
458    }
459
460    /// mark part of the surface damaged
461    ///
462    /// This request is used to describe the regions where the pending
463    /// buffer is different from the current surface contents, and where
464    /// the surface therefore needs to be repainted. The compositor
465    /// ignores the parts of the damage that fall outside of the surface.
466    ///
467    /// Damage is double-buffered state, see wl_surface.commit.
468    ///
469    /// The damage rectangle is specified in surface-local coordinates,
470    /// where x and y specify the upper left corner of the damage rectangle.
471    ///
472    /// The initial value for pending damage is empty: no damage.
473    /// wl_surface.damage adds pending damage: the new pending damage
474    /// is the union of old pending damage and the given rectangle.
475    ///
476    /// wl_surface.commit assigns pending damage as the current damage,
477    /// and clears pending damage. The server will clear the current
478    /// damage as it repaints the surface.
479    ///
480    /// Note! New clients should not use this request. Instead damage can be
481    /// posted with wl_surface.damage_buffer which uses buffer coordinates
482    /// instead of surface coordinates.
483    ///
484    /// # Arguments
485    ///
486    /// - `x`: surface-local x coordinate
487    /// - `y`: surface-local y coordinate
488    /// - `width`: width of damage rectangle
489    /// - `height`: height of damage rectangle
490    #[inline]
491    pub fn send_damage(
492        &self,
493        x: i32,
494        y: i32,
495        width: i32,
496        height: i32,
497    ) {
498        let res = self.try_send_damage(
499            x,
500            y,
501            width,
502            height,
503        );
504        if let Err(e) = res {
505            log_send("wl_surface.damage", &e);
506        }
507    }
508
509    /// Since when the frame message is available.
510    pub const MSG__FRAME__SINCE: u32 = 1;
511
512    /// request a frame throttling hint
513    ///
514    /// Request a notification when it is a good time to start drawing a new
515    /// frame, by creating a frame callback. This is useful for throttling
516    /// redrawing operations, and driving animations.
517    ///
518    /// When a client is animating on a wl_surface, it can use the 'frame'
519    /// request to get notified when it is a good time to draw and commit the
520    /// next frame of animation. If the client commits an update earlier than
521    /// that, it is likely that some updates will not make it to the display,
522    /// and the client is wasting resources by drawing too often.
523    ///
524    /// The frame request will take effect on the next wl_surface.commit.
525    /// The notification will only be posted for one frame unless
526    /// requested again. For a wl_surface, the notifications are posted in
527    /// the order the frame requests were committed.
528    ///
529    /// The server must send the notifications so that a client
530    /// will not send excessive updates, while still allowing
531    /// the highest possible update rate for clients that wait for the reply
532    /// before drawing again. The server should give some time for the client
533    /// to draw and commit after sending the frame callback events to let it
534    /// hit the next output refresh.
535    ///
536    /// A server should avoid signaling the frame callbacks if the
537    /// surface is not visible in any way, e.g. the surface is off-screen,
538    /// or completely obscured by other opaque surfaces.
539    ///
540    /// The object returned by this request will be destroyed by the
541    /// compositor after the callback is fired and as such the client must not
542    /// attempt to use it after that point.
543    ///
544    /// The callback_data passed in the callback is the current time, in
545    /// milliseconds, with an undefined base.
546    ///
547    /// # Arguments
548    ///
549    /// - `callback`: callback object for the frame request
550    #[inline]
551    pub fn try_send_frame(
552        &self,
553        callback: &Rc<WlCallback>,
554    ) -> Result<(), ObjectError> {
555        let (
556            arg0,
557        ) = (
558            callback,
559        );
560        let arg0_obj = arg0;
561        let arg0 = arg0_obj.core();
562        let core = self.core();
563        let Some(id) = core.server_obj_id.get() else {
564            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
565        };
566        arg0.generate_server_id(arg0_obj.clone())
567            .map_err(|e| ObjectError(ObjectErrorKind::GenerateServerId("callback", e)))?;
568        let arg0_id = arg0.server_obj_id.get().unwrap_or(0);
569        #[cfg(feature = "logging")]
570        if self.core.state.log {
571            #[cold]
572            fn log(state: &State, id: u32, arg0: 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_surface#{}.frame(callback: wl_callback#{})\n", id, arg0);
576                state.log(args);
577            }
578            log(&self.core.state, id, arg0_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            3,
592            arg0_id,
593        ]);
594        Ok(())
595    }
596
597    /// request a frame throttling hint
598    ///
599    /// Request a notification when it is a good time to start drawing a new
600    /// frame, by creating a frame callback. This is useful for throttling
601    /// redrawing operations, and driving animations.
602    ///
603    /// When a client is animating on a wl_surface, it can use the 'frame'
604    /// request to get notified when it is a good time to draw and commit the
605    /// next frame of animation. If the client commits an update earlier than
606    /// that, it is likely that some updates will not make it to the display,
607    /// and the client is wasting resources by drawing too often.
608    ///
609    /// The frame request will take effect on the next wl_surface.commit.
610    /// The notification will only be posted for one frame unless
611    /// requested again. For a wl_surface, the notifications are posted in
612    /// the order the frame requests were committed.
613    ///
614    /// The server must send the notifications so that a client
615    /// will not send excessive updates, while still allowing
616    /// the highest possible update rate for clients that wait for the reply
617    /// before drawing again. The server should give some time for the client
618    /// to draw and commit after sending the frame callback events to let it
619    /// hit the next output refresh.
620    ///
621    /// A server should avoid signaling the frame callbacks if the
622    /// surface is not visible in any way, e.g. the surface is off-screen,
623    /// or completely obscured by other opaque surfaces.
624    ///
625    /// The object returned by this request will be destroyed by the
626    /// compositor after the callback is fired and as such the client must not
627    /// attempt to use it after that point.
628    ///
629    /// The callback_data passed in the callback is the current time, in
630    /// milliseconds, with an undefined base.
631    ///
632    /// # Arguments
633    ///
634    /// - `callback`: callback object for the frame request
635    #[inline]
636    pub fn send_frame(
637        &self,
638        callback: &Rc<WlCallback>,
639    ) {
640        let res = self.try_send_frame(
641            callback,
642        );
643        if let Err(e) = res {
644            log_send("wl_surface.frame", &e);
645        }
646    }
647
648    /// request a frame throttling hint
649    ///
650    /// Request a notification when it is a good time to start drawing a new
651    /// frame, by creating a frame callback. This is useful for throttling
652    /// redrawing operations, and driving animations.
653    ///
654    /// When a client is animating on a wl_surface, it can use the 'frame'
655    /// request to get notified when it is a good time to draw and commit the
656    /// next frame of animation. If the client commits an update earlier than
657    /// that, it is likely that some updates will not make it to the display,
658    /// and the client is wasting resources by drawing too often.
659    ///
660    /// The frame request will take effect on the next wl_surface.commit.
661    /// The notification will only be posted for one frame unless
662    /// requested again. For a wl_surface, the notifications are posted in
663    /// the order the frame requests were committed.
664    ///
665    /// The server must send the notifications so that a client
666    /// will not send excessive updates, while still allowing
667    /// the highest possible update rate for clients that wait for the reply
668    /// before drawing again. The server should give some time for the client
669    /// to draw and commit after sending the frame callback events to let it
670    /// hit the next output refresh.
671    ///
672    /// A server should avoid signaling the frame callbacks if the
673    /// surface is not visible in any way, e.g. the surface is off-screen,
674    /// or completely obscured by other opaque surfaces.
675    ///
676    /// The object returned by this request will be destroyed by the
677    /// compositor after the callback is fired and as such the client must not
678    /// attempt to use it after that point.
679    ///
680    /// The callback_data passed in the callback is the current time, in
681    /// milliseconds, with an undefined base.
682    #[inline]
683    pub fn new_try_send_frame(
684        &self,
685    ) -> Result<Rc<WlCallback>, ObjectError> {
686        let callback = self.core.create_child();
687        self.try_send_frame(
688            &callback,
689        )?;
690        Ok(callback)
691    }
692
693    /// request a frame throttling hint
694    ///
695    /// Request a notification when it is a good time to start drawing a new
696    /// frame, by creating a frame callback. This is useful for throttling
697    /// redrawing operations, and driving animations.
698    ///
699    /// When a client is animating on a wl_surface, it can use the 'frame'
700    /// request to get notified when it is a good time to draw and commit the
701    /// next frame of animation. If the client commits an update earlier than
702    /// that, it is likely that some updates will not make it to the display,
703    /// and the client is wasting resources by drawing too often.
704    ///
705    /// The frame request will take effect on the next wl_surface.commit.
706    /// The notification will only be posted for one frame unless
707    /// requested again. For a wl_surface, the notifications are posted in
708    /// the order the frame requests were committed.
709    ///
710    /// The server must send the notifications so that a client
711    /// will not send excessive updates, while still allowing
712    /// the highest possible update rate for clients that wait for the reply
713    /// before drawing again. The server should give some time for the client
714    /// to draw and commit after sending the frame callback events to let it
715    /// hit the next output refresh.
716    ///
717    /// A server should avoid signaling the frame callbacks if the
718    /// surface is not visible in any way, e.g. the surface is off-screen,
719    /// or completely obscured by other opaque surfaces.
720    ///
721    /// The object returned by this request will be destroyed by the
722    /// compositor after the callback is fired and as such the client must not
723    /// attempt to use it after that point.
724    ///
725    /// The callback_data passed in the callback is the current time, in
726    /// milliseconds, with an undefined base.
727    #[inline]
728    pub fn new_send_frame(
729        &self,
730    ) -> Rc<WlCallback> {
731        let callback = self.core.create_child();
732        self.send_frame(
733            &callback,
734        );
735        callback
736    }
737
738    /// Since when the set_opaque_region message is available.
739    pub const MSG__SET_OPAQUE_REGION__SINCE: u32 = 1;
740
741    /// set opaque region
742    ///
743    /// This request sets the region of the surface that contains
744    /// opaque content.
745    ///
746    /// The opaque region is an optimization hint for the compositor
747    /// that lets it optimize the redrawing of content behind opaque
748    /// regions.  Setting an opaque region is not required for correct
749    /// behaviour, but marking transparent content as opaque will result
750    /// in repaint artifacts.
751    ///
752    /// The opaque region is specified in surface-local coordinates.
753    ///
754    /// The compositor ignores the parts of the opaque region that fall
755    /// outside of the surface.
756    ///
757    /// Opaque region is double-buffered state, see wl_surface.commit.
758    ///
759    /// wl_surface.set_opaque_region changes the pending opaque region.
760    /// wl_surface.commit copies the pending region to the current region.
761    /// Otherwise, the pending and current regions are never changed.
762    ///
763    /// The initial value for an opaque region is empty. Setting the pending
764    /// opaque region has copy semantics, and the wl_region object can be
765    /// destroyed immediately. A NULL wl_region causes the pending opaque
766    /// region to be set to empty.
767    ///
768    /// # Arguments
769    ///
770    /// - `region`: opaque region of the surface
771    #[inline]
772    pub fn try_send_set_opaque_region(
773        &self,
774        region: Option<&Rc<WlRegion>>,
775    ) -> Result<(), ObjectError> {
776        let (
777            arg0,
778        ) = (
779            region,
780        );
781        let arg0 = arg0.map(|a| a.core());
782        let core = self.core();
783        let Some(id) = core.server_obj_id.get() else {
784            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
785        };
786        let arg0_id = match arg0 {
787            None => 0,
788            Some(arg0) => match arg0.server_obj_id.get() {
789                None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("region"))),
790                Some(id) => id,
791            },
792        };
793        #[cfg(feature = "logging")]
794        if self.core.state.log {
795            #[cold]
796            fn log(state: &State, id: u32, arg0: u32) {
797                let (millis, micros) = time_since_epoch();
798                let prefix = &state.log_prefix;
799                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.set_opaque_region(region: wl_region#{})\n", id, arg0);
800                state.log(args);
801            }
802            log(&self.core.state, id, arg0_id);
803        }
804        let Some(endpoint) = &self.core.state.server else {
805            return Ok(());
806        };
807        if !endpoint.flush_queued.replace(true) {
808            self.core.state.add_flushable_endpoint(endpoint, None);
809        }
810        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
811        let outgoing = &mut *outgoing_ref;
812        let mut fmt = outgoing.formatter();
813        fmt.words([
814            id,
815            4,
816            arg0_id,
817        ]);
818        Ok(())
819    }
820
821    /// set opaque region
822    ///
823    /// This request sets the region of the surface that contains
824    /// opaque content.
825    ///
826    /// The opaque region is an optimization hint for the compositor
827    /// that lets it optimize the redrawing of content behind opaque
828    /// regions.  Setting an opaque region is not required for correct
829    /// behaviour, but marking transparent content as opaque will result
830    /// in repaint artifacts.
831    ///
832    /// The opaque region is specified in surface-local coordinates.
833    ///
834    /// The compositor ignores the parts of the opaque region that fall
835    /// outside of the surface.
836    ///
837    /// Opaque region is double-buffered state, see wl_surface.commit.
838    ///
839    /// wl_surface.set_opaque_region changes the pending opaque region.
840    /// wl_surface.commit copies the pending region to the current region.
841    /// Otherwise, the pending and current regions are never changed.
842    ///
843    /// The initial value for an opaque region is empty. Setting the pending
844    /// opaque region has copy semantics, and the wl_region object can be
845    /// destroyed immediately. A NULL wl_region causes the pending opaque
846    /// region to be set to empty.
847    ///
848    /// # Arguments
849    ///
850    /// - `region`: opaque region of the surface
851    #[inline]
852    pub fn send_set_opaque_region(
853        &self,
854        region: Option<&Rc<WlRegion>>,
855    ) {
856        let res = self.try_send_set_opaque_region(
857            region,
858        );
859        if let Err(e) = res {
860            log_send("wl_surface.set_opaque_region", &e);
861        }
862    }
863
864    /// Since when the set_input_region message is available.
865    pub const MSG__SET_INPUT_REGION__SINCE: u32 = 1;
866
867    /// set input region
868    ///
869    /// This request sets the region of the surface that can receive
870    /// pointer and touch events.
871    ///
872    /// Input events happening outside of this region will try the next
873    /// surface in the server surface stack. The compositor ignores the
874    /// parts of the input region that fall outside of the surface.
875    ///
876    /// The input region is specified in surface-local coordinates.
877    ///
878    /// Input region is double-buffered state, see wl_surface.commit.
879    ///
880    /// wl_surface.set_input_region changes the pending input region.
881    /// wl_surface.commit copies the pending region to the current region.
882    /// Otherwise the pending and current regions are never changed,
883    /// except cursor and icon surfaces are special cases, see
884    /// wl_pointer.set_cursor and wl_data_device.start_drag.
885    ///
886    /// The initial value for an input region is infinite. That means the
887    /// whole surface will accept input. Setting the pending input region
888    /// has copy semantics, and the wl_region object can be destroyed
889    /// immediately. A NULL wl_region causes the input region to be set
890    /// to infinite.
891    ///
892    /// # Arguments
893    ///
894    /// - `region`: input region of the surface
895    #[inline]
896    pub fn try_send_set_input_region(
897        &self,
898        region: Option<&Rc<WlRegion>>,
899    ) -> Result<(), ObjectError> {
900        let (
901            arg0,
902        ) = (
903            region,
904        );
905        let arg0 = arg0.map(|a| a.core());
906        let core = self.core();
907        let Some(id) = core.server_obj_id.get() else {
908            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
909        };
910        let arg0_id = match arg0 {
911            None => 0,
912            Some(arg0) => match arg0.server_obj_id.get() {
913                None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("region"))),
914                Some(id) => id,
915            },
916        };
917        #[cfg(feature = "logging")]
918        if self.core.state.log {
919            #[cold]
920            fn log(state: &State, id: u32, arg0: u32) {
921                let (millis, micros) = time_since_epoch();
922                let prefix = &state.log_prefix;
923                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.set_input_region(region: wl_region#{})\n", id, arg0);
924                state.log(args);
925            }
926            log(&self.core.state, id, arg0_id);
927        }
928        let Some(endpoint) = &self.core.state.server else {
929            return Ok(());
930        };
931        if !endpoint.flush_queued.replace(true) {
932            self.core.state.add_flushable_endpoint(endpoint, None);
933        }
934        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
935        let outgoing = &mut *outgoing_ref;
936        let mut fmt = outgoing.formatter();
937        fmt.words([
938            id,
939            5,
940            arg0_id,
941        ]);
942        Ok(())
943    }
944
945    /// set input region
946    ///
947    /// This request sets the region of the surface that can receive
948    /// pointer and touch events.
949    ///
950    /// Input events happening outside of this region will try the next
951    /// surface in the server surface stack. The compositor ignores the
952    /// parts of the input region that fall outside of the surface.
953    ///
954    /// The input region is specified in surface-local coordinates.
955    ///
956    /// Input region is double-buffered state, see wl_surface.commit.
957    ///
958    /// wl_surface.set_input_region changes the pending input region.
959    /// wl_surface.commit copies the pending region to the current region.
960    /// Otherwise the pending and current regions are never changed,
961    /// except cursor and icon surfaces are special cases, see
962    /// wl_pointer.set_cursor and wl_data_device.start_drag.
963    ///
964    /// The initial value for an input region is infinite. That means the
965    /// whole surface will accept input. Setting the pending input region
966    /// has copy semantics, and the wl_region object can be destroyed
967    /// immediately. A NULL wl_region causes the input region to be set
968    /// to infinite.
969    ///
970    /// # Arguments
971    ///
972    /// - `region`: input region of the surface
973    #[inline]
974    pub fn send_set_input_region(
975        &self,
976        region: Option<&Rc<WlRegion>>,
977    ) {
978        let res = self.try_send_set_input_region(
979            region,
980        );
981        if let Err(e) = res {
982            log_send("wl_surface.set_input_region", &e);
983        }
984    }
985
986    /// Since when the commit message is available.
987    pub const MSG__COMMIT__SINCE: u32 = 1;
988
989    /// commit pending surface state
990    ///
991    /// Surface state (input, opaque, and damage regions, attached buffers,
992    /// etc.) is double-buffered. Protocol requests modify the pending state,
993    /// as opposed to the active state in use by the compositor.
994    ///
995    /// All requests that need a commit to become effective are documented
996    /// to affect double-buffered state.
997    ///
998    /// Other interfaces may add further double-buffered surface state.
999    ///
1000    /// A commit request atomically creates a Content Update (CU) from the
1001    /// pending state, even if the pending state has not been touched. The
1002    /// content update is placed at the end of a per-surface queue until it
1003    /// becomes active. After commit, the new pending state is as documented for
1004    /// each related request.
1005    ///
1006    /// A CU is either a Desync Content Update (DCU) or a Sync Content Update
1007    /// (SCU). If the surface is effectively synchronized at the commit request,
1008    /// it is a SCU, otherwise a DCU.
1009    ///
1010    /// When a surface transitions from effectively synchronized to effectively
1011    /// desynchronized, all SCUs in its queue which are not reachable by any
1012    /// DCU become DCUs and dependency edges from outside the queue to these CUs
1013    /// are removed.
1014    ///
1015    /// See wl_subsurface for the definition of 'effectively synchronized' and
1016    /// 'effectively desynchronized'.
1017    ///
1018    /// When a CU is placed in the queue, the CU has a dependency on the CU in
1019    /// front of it and to the SCU at end of the queue of every direct child
1020    /// surface if that SCU exists and does not have another dependent. This can
1021    /// form a directed acyclic graph of CUs with dependencies as edges.
1022    ///
1023    /// In addition to surface state, the CU can have constraints that must be
1024    /// satisfied before it can be applied. Other interfaces may add CU
1025    /// constraints.
1026    ///
1027    /// All DCUs which do not have a SCU in front of themselves in their queue,
1028    /// are candidates. If the graph that's reachable by a candidate does not
1029    /// have any unsatisfied constraints, the entire graph must be applied
1030    /// atomically.
1031    ///
1032    /// When a CU is applied, the wl_buffer is applied before all other state.
1033    /// This means that all coordinates in double-buffered state are relative to
1034    /// the newly attached wl_buffers, except for wl_surface.attach itself. If
1035    /// there is no newly attached wl_buffer, the coordinates are relative to
1036    /// the previous content update.
1037    #[inline]
1038    pub fn try_send_commit(
1039        &self,
1040    ) -> Result<(), ObjectError> {
1041        let core = self.core();
1042        let Some(id) = core.server_obj_id.get() else {
1043            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1044        };
1045        #[cfg(feature = "logging")]
1046        if self.core.state.log {
1047            #[cold]
1048            fn log(state: &State, id: u32) {
1049                let (millis, micros) = time_since_epoch();
1050                let prefix = &state.log_prefix;
1051                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.commit()\n", id);
1052                state.log(args);
1053            }
1054            log(&self.core.state, id);
1055        }
1056        let Some(endpoint) = &self.core.state.server else {
1057            return Ok(());
1058        };
1059        if !endpoint.flush_queued.replace(true) {
1060            self.core.state.add_flushable_endpoint(endpoint, None);
1061        }
1062        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1063        let outgoing = &mut *outgoing_ref;
1064        let mut fmt = outgoing.formatter();
1065        fmt.words([
1066            id,
1067            6,
1068        ]);
1069        Ok(())
1070    }
1071
1072    /// commit pending surface state
1073    ///
1074    /// Surface state (input, opaque, and damage regions, attached buffers,
1075    /// etc.) is double-buffered. Protocol requests modify the pending state,
1076    /// as opposed to the active state in use by the compositor.
1077    ///
1078    /// All requests that need a commit to become effective are documented
1079    /// to affect double-buffered state.
1080    ///
1081    /// Other interfaces may add further double-buffered surface state.
1082    ///
1083    /// A commit request atomically creates a Content Update (CU) from the
1084    /// pending state, even if the pending state has not been touched. The
1085    /// content update is placed at the end of a per-surface queue until it
1086    /// becomes active. After commit, the new pending state is as documented for
1087    /// each related request.
1088    ///
1089    /// A CU is either a Desync Content Update (DCU) or a Sync Content Update
1090    /// (SCU). If the surface is effectively synchronized at the commit request,
1091    /// it is a SCU, otherwise a DCU.
1092    ///
1093    /// When a surface transitions from effectively synchronized to effectively
1094    /// desynchronized, all SCUs in its queue which are not reachable by any
1095    /// DCU become DCUs and dependency edges from outside the queue to these CUs
1096    /// are removed.
1097    ///
1098    /// See wl_subsurface for the definition of 'effectively synchronized' and
1099    /// 'effectively desynchronized'.
1100    ///
1101    /// When a CU is placed in the queue, the CU has a dependency on the CU in
1102    /// front of it and to the SCU at end of the queue of every direct child
1103    /// surface if that SCU exists and does not have another dependent. This can
1104    /// form a directed acyclic graph of CUs with dependencies as edges.
1105    ///
1106    /// In addition to surface state, the CU can have constraints that must be
1107    /// satisfied before it can be applied. Other interfaces may add CU
1108    /// constraints.
1109    ///
1110    /// All DCUs which do not have a SCU in front of themselves in their queue,
1111    /// are candidates. If the graph that's reachable by a candidate does not
1112    /// have any unsatisfied constraints, the entire graph must be applied
1113    /// atomically.
1114    ///
1115    /// When a CU is applied, the wl_buffer is applied before all other state.
1116    /// This means that all coordinates in double-buffered state are relative to
1117    /// the newly attached wl_buffers, except for wl_surface.attach itself. If
1118    /// there is no newly attached wl_buffer, the coordinates are relative to
1119    /// the previous content update.
1120    #[inline]
1121    pub fn send_commit(
1122        &self,
1123    ) {
1124        let res = self.try_send_commit(
1125        );
1126        if let Err(e) = res {
1127            log_send("wl_surface.commit", &e);
1128        }
1129    }
1130
1131    /// Since when the enter message is available.
1132    pub const MSG__ENTER__SINCE: u32 = 1;
1133
1134    /// surface enters an output
1135    ///
1136    /// This is emitted whenever a surface's creation, movement, or resizing
1137    /// results in some part of it being within the scanout region of an
1138    /// output.
1139    ///
1140    /// Note that a surface may be overlapping with zero or more outputs.
1141    ///
1142    /// # Arguments
1143    ///
1144    /// - `output`: output entered by the surface
1145    #[inline]
1146    pub fn try_send_enter(
1147        &self,
1148        output: &Rc<WlOutput>,
1149    ) -> Result<(), ObjectError> {
1150        let (
1151            arg0,
1152        ) = (
1153            output,
1154        );
1155        let arg0 = arg0.core();
1156        let core = self.core();
1157        let client_ref = core.client.borrow();
1158        let Some(client) = &*client_ref else {
1159            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1160        };
1161        let id = core.client_obj_id.get().unwrap_or(0);
1162        if arg0.client_id.get() != Some(client.endpoint.id) {
1163            return Err(ObjectError(ObjectErrorKind::ArgNoClientId("output", client.endpoint.id)));
1164        }
1165        let arg0_id = arg0.client_obj_id.get().unwrap_or(0);
1166        #[cfg(feature = "logging")]
1167        if self.core.state.log {
1168            #[cold]
1169            fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
1170                let (millis, micros) = time_since_epoch();
1171                let prefix = &state.log_prefix;
1172                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.enter(output: wl_output#{})\n", client_id, id, arg0);
1173                state.log(args);
1174            }
1175            log(&self.core.state, client.endpoint.id, id, arg0_id);
1176        }
1177        let endpoint = &client.endpoint;
1178        if !endpoint.flush_queued.replace(true) {
1179            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1180        }
1181        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1182        let outgoing = &mut *outgoing_ref;
1183        let mut fmt = outgoing.formatter();
1184        fmt.words([
1185            id,
1186            0,
1187            arg0_id,
1188        ]);
1189        Ok(())
1190    }
1191
1192    /// surface enters an output
1193    ///
1194    /// This is emitted whenever a surface's creation, movement, or resizing
1195    /// results in some part of it being within the scanout region of an
1196    /// output.
1197    ///
1198    /// Note that a surface may be overlapping with zero or more outputs.
1199    ///
1200    /// # Arguments
1201    ///
1202    /// - `output`: output entered by the surface
1203    #[inline]
1204    pub fn send_enter(
1205        &self,
1206        output: &Rc<WlOutput>,
1207    ) {
1208        let res = self.try_send_enter(
1209            output,
1210        );
1211        if let Err(e) = res {
1212            log_send("wl_surface.enter", &e);
1213        }
1214    }
1215
1216    /// Since when the leave message is available.
1217    pub const MSG__LEAVE__SINCE: u32 = 1;
1218
1219    /// surface leaves an output
1220    ///
1221    /// This is emitted whenever a surface's creation, movement, or resizing
1222    /// results in it no longer having any part of it within the scanout region
1223    /// of an output.
1224    ///
1225    /// Clients should not use the number of outputs the surface is on for frame
1226    /// throttling purposes. The surface might be hidden even if no leave event
1227    /// has been sent, and the compositor might expect new surface content
1228    /// updates even if no enter event has been sent. The frame event should be
1229    /// used instead.
1230    ///
1231    /// # Arguments
1232    ///
1233    /// - `output`: output left by the surface
1234    #[inline]
1235    pub fn try_send_leave(
1236        &self,
1237        output: &Rc<WlOutput>,
1238    ) -> Result<(), ObjectError> {
1239        let (
1240            arg0,
1241        ) = (
1242            output,
1243        );
1244        let arg0 = arg0.core();
1245        let core = self.core();
1246        let client_ref = core.client.borrow();
1247        let Some(client) = &*client_ref else {
1248            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1249        };
1250        let id = core.client_obj_id.get().unwrap_or(0);
1251        if arg0.client_id.get() != Some(client.endpoint.id) {
1252            return Err(ObjectError(ObjectErrorKind::ArgNoClientId("output", client.endpoint.id)));
1253        }
1254        let arg0_id = arg0.client_obj_id.get().unwrap_or(0);
1255        #[cfg(feature = "logging")]
1256        if self.core.state.log {
1257            #[cold]
1258            fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
1259                let (millis, micros) = time_since_epoch();
1260                let prefix = &state.log_prefix;
1261                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.leave(output: wl_output#{})\n", client_id, id, arg0);
1262                state.log(args);
1263            }
1264            log(&self.core.state, client.endpoint.id, id, arg0_id);
1265        }
1266        let endpoint = &client.endpoint;
1267        if !endpoint.flush_queued.replace(true) {
1268            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1269        }
1270        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1271        let outgoing = &mut *outgoing_ref;
1272        let mut fmt = outgoing.formatter();
1273        fmt.words([
1274            id,
1275            1,
1276            arg0_id,
1277        ]);
1278        Ok(())
1279    }
1280
1281    /// surface leaves an output
1282    ///
1283    /// This is emitted whenever a surface's creation, movement, or resizing
1284    /// results in it no longer having any part of it within the scanout region
1285    /// of an output.
1286    ///
1287    /// Clients should not use the number of outputs the surface is on for frame
1288    /// throttling purposes. The surface might be hidden even if no leave event
1289    /// has been sent, and the compositor might expect new surface content
1290    /// updates even if no enter event has been sent. The frame event should be
1291    /// used instead.
1292    ///
1293    /// # Arguments
1294    ///
1295    /// - `output`: output left by the surface
1296    #[inline]
1297    pub fn send_leave(
1298        &self,
1299        output: &Rc<WlOutput>,
1300    ) {
1301        let res = self.try_send_leave(
1302            output,
1303        );
1304        if let Err(e) = res {
1305            log_send("wl_surface.leave", &e);
1306        }
1307    }
1308
1309    /// Since when the set_buffer_transform message is available.
1310    pub const MSG__SET_BUFFER_TRANSFORM__SINCE: u32 = 2;
1311
1312    /// sets the buffer transformation
1313    ///
1314    /// This request sets the transformation that the client has already applied
1315    /// to the content of the buffer. The accepted values for the transform
1316    /// parameter are the values for wl_output.transform.
1317    ///
1318    /// The compositor applies the inverse of this transformation whenever it
1319    /// uses the buffer contents.
1320    ///
1321    /// Buffer transform is double-buffered state, see wl_surface.commit.
1322    ///
1323    /// A newly created surface has its buffer transformation set to normal.
1324    ///
1325    /// wl_surface.set_buffer_transform changes the pending buffer
1326    /// transformation. wl_surface.commit copies the pending buffer
1327    /// transformation to the current one. Otherwise, the pending and current
1328    /// values are never changed.
1329    ///
1330    /// The purpose of this request is to allow clients to render content
1331    /// according to the output transform, thus permitting the compositor to
1332    /// use certain optimizations even if the display is rotated. Using
1333    /// hardware overlays and scanning out a client buffer for fullscreen
1334    /// surfaces are examples of such optimizations. Those optimizations are
1335    /// highly dependent on the compositor implementation, so the use of this
1336    /// request should be considered on a case-by-case basis.
1337    ///
1338    /// Note that if the transform value includes 90 or 270 degree rotation,
1339    /// the width of the buffer will become the surface height and the height
1340    /// of the buffer will become the surface width.
1341    ///
1342    /// If transform is not one of the values from the
1343    /// wl_output.transform enum the invalid_transform protocol error
1344    /// is raised.
1345    ///
1346    /// # Arguments
1347    ///
1348    /// - `transform`: transform for interpreting buffer contents
1349    #[inline]
1350    pub fn try_send_set_buffer_transform(
1351        &self,
1352        transform: WlOutputTransform,
1353    ) -> Result<(), ObjectError> {
1354        let (
1355            arg0,
1356        ) = (
1357            transform,
1358        );
1359        let core = self.core();
1360        let Some(id) = core.server_obj_id.get() else {
1361            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1362        };
1363        #[cfg(feature = "logging")]
1364        if self.core.state.log {
1365            #[cold]
1366            fn log(state: &State, id: u32, arg0: WlOutputTransform) {
1367                let (millis, micros) = time_since_epoch();
1368                let prefix = &state.log_prefix;
1369                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.set_buffer_transform(transform: {:?})\n", id, arg0);
1370                state.log(args);
1371            }
1372            log(&self.core.state, id, arg0);
1373        }
1374        let Some(endpoint) = &self.core.state.server else {
1375            return Ok(());
1376        };
1377        if !endpoint.flush_queued.replace(true) {
1378            self.core.state.add_flushable_endpoint(endpoint, None);
1379        }
1380        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1381        let outgoing = &mut *outgoing_ref;
1382        let mut fmt = outgoing.formatter();
1383        fmt.words([
1384            id,
1385            7,
1386            arg0.0,
1387        ]);
1388        Ok(())
1389    }
1390
1391    /// sets the buffer transformation
1392    ///
1393    /// This request sets the transformation that the client has already applied
1394    /// to the content of the buffer. The accepted values for the transform
1395    /// parameter are the values for wl_output.transform.
1396    ///
1397    /// The compositor applies the inverse of this transformation whenever it
1398    /// uses the buffer contents.
1399    ///
1400    /// Buffer transform is double-buffered state, see wl_surface.commit.
1401    ///
1402    /// A newly created surface has its buffer transformation set to normal.
1403    ///
1404    /// wl_surface.set_buffer_transform changes the pending buffer
1405    /// transformation. wl_surface.commit copies the pending buffer
1406    /// transformation to the current one. Otherwise, the pending and current
1407    /// values are never changed.
1408    ///
1409    /// The purpose of this request is to allow clients to render content
1410    /// according to the output transform, thus permitting the compositor to
1411    /// use certain optimizations even if the display is rotated. Using
1412    /// hardware overlays and scanning out a client buffer for fullscreen
1413    /// surfaces are examples of such optimizations. Those optimizations are
1414    /// highly dependent on the compositor implementation, so the use of this
1415    /// request should be considered on a case-by-case basis.
1416    ///
1417    /// Note that if the transform value includes 90 or 270 degree rotation,
1418    /// the width of the buffer will become the surface height and the height
1419    /// of the buffer will become the surface width.
1420    ///
1421    /// If transform is not one of the values from the
1422    /// wl_output.transform enum the invalid_transform protocol error
1423    /// is raised.
1424    ///
1425    /// # Arguments
1426    ///
1427    /// - `transform`: transform for interpreting buffer contents
1428    #[inline]
1429    pub fn send_set_buffer_transform(
1430        &self,
1431        transform: WlOutputTransform,
1432    ) {
1433        let res = self.try_send_set_buffer_transform(
1434            transform,
1435        );
1436        if let Err(e) = res {
1437            log_send("wl_surface.set_buffer_transform", &e);
1438        }
1439    }
1440
1441    /// Since when the set_buffer_scale message is available.
1442    pub const MSG__SET_BUFFER_SCALE__SINCE: u32 = 3;
1443
1444    /// sets the buffer scaling factor
1445    ///
1446    /// This request sets an optional scaling factor on how the compositor
1447    /// interprets the contents of the buffer attached to the window.
1448    ///
1449    /// Buffer scale is double-buffered state, see wl_surface.commit.
1450    ///
1451    /// A newly created surface has its buffer scale set to 1.
1452    ///
1453    /// wl_surface.set_buffer_scale changes the pending buffer scale.
1454    /// wl_surface.commit copies the pending buffer scale to the current one.
1455    /// Otherwise, the pending and current values are never changed.
1456    ///
1457    /// The purpose of this request is to allow clients to supply higher
1458    /// resolution buffer data for use on high resolution outputs. It is
1459    /// intended that you pick the same buffer scale as the scale of the
1460    /// output that the surface is displayed on. This means the compositor
1461    /// can avoid scaling when rendering the surface on that output.
1462    ///
1463    /// Note that if the scale is larger than 1, then you have to attach
1464    /// a buffer that is larger (by a factor of scale in each dimension)
1465    /// than the desired surface size.
1466    ///
1467    /// If scale is not greater than 0 the invalid_scale protocol error is
1468    /// raised.
1469    ///
1470    /// # Arguments
1471    ///
1472    /// - `scale`: scale for interpreting buffer contents
1473    #[inline]
1474    pub fn try_send_set_buffer_scale(
1475        &self,
1476        scale: i32,
1477    ) -> Result<(), ObjectError> {
1478        let (
1479            arg0,
1480        ) = (
1481            scale,
1482        );
1483        let core = self.core();
1484        let Some(id) = core.server_obj_id.get() else {
1485            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1486        };
1487        #[cfg(feature = "logging")]
1488        if self.core.state.log {
1489            #[cold]
1490            fn log(state: &State, id: u32, arg0: i32) {
1491                let (millis, micros) = time_since_epoch();
1492                let prefix = &state.log_prefix;
1493                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.set_buffer_scale(scale: {})\n", id, arg0);
1494                state.log(args);
1495            }
1496            log(&self.core.state, id, arg0);
1497        }
1498        let Some(endpoint) = &self.core.state.server else {
1499            return Ok(());
1500        };
1501        if !endpoint.flush_queued.replace(true) {
1502            self.core.state.add_flushable_endpoint(endpoint, None);
1503        }
1504        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1505        let outgoing = &mut *outgoing_ref;
1506        let mut fmt = outgoing.formatter();
1507        fmt.words([
1508            id,
1509            8,
1510            arg0 as u32,
1511        ]);
1512        Ok(())
1513    }
1514
1515    /// sets the buffer scaling factor
1516    ///
1517    /// This request sets an optional scaling factor on how the compositor
1518    /// interprets the contents of the buffer attached to the window.
1519    ///
1520    /// Buffer scale is double-buffered state, see wl_surface.commit.
1521    ///
1522    /// A newly created surface has its buffer scale set to 1.
1523    ///
1524    /// wl_surface.set_buffer_scale changes the pending buffer scale.
1525    /// wl_surface.commit copies the pending buffer scale to the current one.
1526    /// Otherwise, the pending and current values are never changed.
1527    ///
1528    /// The purpose of this request is to allow clients to supply higher
1529    /// resolution buffer data for use on high resolution outputs. It is
1530    /// intended that you pick the same buffer scale as the scale of the
1531    /// output that the surface is displayed on. This means the compositor
1532    /// can avoid scaling when rendering the surface on that output.
1533    ///
1534    /// Note that if the scale is larger than 1, then you have to attach
1535    /// a buffer that is larger (by a factor of scale in each dimension)
1536    /// than the desired surface size.
1537    ///
1538    /// If scale is not greater than 0 the invalid_scale protocol error is
1539    /// raised.
1540    ///
1541    /// # Arguments
1542    ///
1543    /// - `scale`: scale for interpreting buffer contents
1544    #[inline]
1545    pub fn send_set_buffer_scale(
1546        &self,
1547        scale: i32,
1548    ) {
1549        let res = self.try_send_set_buffer_scale(
1550            scale,
1551        );
1552        if let Err(e) = res {
1553            log_send("wl_surface.set_buffer_scale", &e);
1554        }
1555    }
1556
1557    /// Since when the damage_buffer message is available.
1558    pub const MSG__DAMAGE_BUFFER__SINCE: u32 = 4;
1559
1560    /// mark part of the surface damaged using buffer coordinates
1561    ///
1562    /// This request is used to describe the regions where the pending
1563    /// buffer is different from the current surface contents, and where
1564    /// the surface therefore needs to be repainted. The compositor
1565    /// ignores the parts of the damage that fall outside of the surface.
1566    ///
1567    /// Damage is double-buffered state, see wl_surface.commit.
1568    ///
1569    /// The damage rectangle is specified in buffer coordinates,
1570    /// where x and y specify the upper left corner of the damage rectangle.
1571    ///
1572    /// The initial value for pending damage is empty: no damage.
1573    /// wl_surface.damage_buffer adds pending damage: the new pending
1574    /// damage is the union of old pending damage and the given rectangle.
1575    ///
1576    /// wl_surface.commit assigns pending damage as the current damage,
1577    /// and clears pending damage. The server will clear the current
1578    /// damage as it repaints the surface.
1579    ///
1580    /// This request differs from wl_surface.damage in only one way - it
1581    /// takes damage in buffer coordinates instead of surface-local
1582    /// coordinates. While this generally is more intuitive than surface
1583    /// coordinates, it is especially desirable when using wp_viewport
1584    /// or when a drawing library (like EGL) is unaware of buffer scale
1585    /// and buffer transform.
1586    ///
1587    /// Note: Because buffer transformation changes and damage requests may
1588    /// be interleaved in the protocol stream, it is impossible to determine
1589    /// the actual mapping between surface and buffer damage until
1590    /// wl_surface.commit time. Therefore, compositors wishing to take both
1591    /// kinds of damage into account will have to accumulate damage from the
1592    /// two requests separately and only transform from one to the other
1593    /// after receiving the wl_surface.commit.
1594    ///
1595    /// # Arguments
1596    ///
1597    /// - `x`: buffer-local x coordinate
1598    /// - `y`: buffer-local y coordinate
1599    /// - `width`: width of damage rectangle
1600    /// - `height`: height of damage rectangle
1601    #[inline]
1602    pub fn try_send_damage_buffer(
1603        &self,
1604        x: i32,
1605        y: i32,
1606        width: i32,
1607        height: i32,
1608    ) -> Result<(), ObjectError> {
1609        let (
1610            arg0,
1611            arg1,
1612            arg2,
1613            arg3,
1614        ) = (
1615            x,
1616            y,
1617            width,
1618            height,
1619        );
1620        let core = self.core();
1621        let Some(id) = core.server_obj_id.get() else {
1622            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1623        };
1624        #[cfg(feature = "logging")]
1625        if self.core.state.log {
1626            #[cold]
1627            fn log(state: &State, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
1628                let (millis, micros) = time_since_epoch();
1629                let prefix = &state.log_prefix;
1630                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.damage_buffer(x: {}, y: {}, width: {}, height: {})\n", id, arg0, arg1, arg2, arg3);
1631                state.log(args);
1632            }
1633            log(&self.core.state, id, arg0, arg1, arg2, arg3);
1634        }
1635        let Some(endpoint) = &self.core.state.server else {
1636            return Ok(());
1637        };
1638        if !endpoint.flush_queued.replace(true) {
1639            self.core.state.add_flushable_endpoint(endpoint, None);
1640        }
1641        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1642        let outgoing = &mut *outgoing_ref;
1643        let mut fmt = outgoing.formatter();
1644        fmt.words([
1645            id,
1646            9,
1647            arg0 as u32,
1648            arg1 as u32,
1649            arg2 as u32,
1650            arg3 as u32,
1651        ]);
1652        Ok(())
1653    }
1654
1655    /// mark part of the surface damaged using buffer coordinates
1656    ///
1657    /// This request is used to describe the regions where the pending
1658    /// buffer is different from the current surface contents, and where
1659    /// the surface therefore needs to be repainted. The compositor
1660    /// ignores the parts of the damage that fall outside of the surface.
1661    ///
1662    /// Damage is double-buffered state, see wl_surface.commit.
1663    ///
1664    /// The damage rectangle is specified in buffer coordinates,
1665    /// where x and y specify the upper left corner of the damage rectangle.
1666    ///
1667    /// The initial value for pending damage is empty: no damage.
1668    /// wl_surface.damage_buffer adds pending damage: the new pending
1669    /// damage is the union of old pending damage and the given rectangle.
1670    ///
1671    /// wl_surface.commit assigns pending damage as the current damage,
1672    /// and clears pending damage. The server will clear the current
1673    /// damage as it repaints the surface.
1674    ///
1675    /// This request differs from wl_surface.damage in only one way - it
1676    /// takes damage in buffer coordinates instead of surface-local
1677    /// coordinates. While this generally is more intuitive than surface
1678    /// coordinates, it is especially desirable when using wp_viewport
1679    /// or when a drawing library (like EGL) is unaware of buffer scale
1680    /// and buffer transform.
1681    ///
1682    /// Note: Because buffer transformation changes and damage requests may
1683    /// be interleaved in the protocol stream, it is impossible to determine
1684    /// the actual mapping between surface and buffer damage until
1685    /// wl_surface.commit time. Therefore, compositors wishing to take both
1686    /// kinds of damage into account will have to accumulate damage from the
1687    /// two requests separately and only transform from one to the other
1688    /// after receiving the wl_surface.commit.
1689    ///
1690    /// # Arguments
1691    ///
1692    /// - `x`: buffer-local x coordinate
1693    /// - `y`: buffer-local y coordinate
1694    /// - `width`: width of damage rectangle
1695    /// - `height`: height of damage rectangle
1696    #[inline]
1697    pub fn send_damage_buffer(
1698        &self,
1699        x: i32,
1700        y: i32,
1701        width: i32,
1702        height: i32,
1703    ) {
1704        let res = self.try_send_damage_buffer(
1705            x,
1706            y,
1707            width,
1708            height,
1709        );
1710        if let Err(e) = res {
1711            log_send("wl_surface.damage_buffer", &e);
1712        }
1713    }
1714
1715    /// Since when the offset message is available.
1716    pub const MSG__OFFSET__SINCE: u32 = 5;
1717
1718    /// set the surface contents offset
1719    ///
1720    /// The x and y arguments specify the location of the new pending
1721    /// buffer's upper left corner, relative to the current buffer's upper
1722    /// left corner, in surface-local coordinates. In other words, the
1723    /// x and y, combined with the new surface size define in which
1724    /// directions the surface's size changes.
1725    ///
1726    /// The exact semantics of wl_surface.offset are role-specific. Refer to
1727    /// the documentation of specific roles for more information.
1728    ///
1729    /// Surface location offset is double-buffered state, see
1730    /// wl_surface.commit.
1731    ///
1732    /// This request is semantically equivalent to and the replaces the x and y
1733    /// arguments in the wl_surface.attach request in wl_surface versions prior
1734    /// to 5. See wl_surface.attach for details.
1735    ///
1736    /// # Arguments
1737    ///
1738    /// - `x`: surface-local x coordinate
1739    /// - `y`: surface-local y coordinate
1740    #[inline]
1741    pub fn try_send_offset(
1742        &self,
1743        x: i32,
1744        y: i32,
1745    ) -> Result<(), ObjectError> {
1746        let (
1747            arg0,
1748            arg1,
1749        ) = (
1750            x,
1751            y,
1752        );
1753        let core = self.core();
1754        let Some(id) = core.server_obj_id.get() else {
1755            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1756        };
1757        #[cfg(feature = "logging")]
1758        if self.core.state.log {
1759            #[cold]
1760            fn log(state: &State, id: u32, arg0: i32, arg1: i32) {
1761                let (millis, micros) = time_since_epoch();
1762                let prefix = &state.log_prefix;
1763                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_surface#{}.offset(x: {}, y: {})\n", id, arg0, arg1);
1764                state.log(args);
1765            }
1766            log(&self.core.state, id, arg0, arg1);
1767        }
1768        let Some(endpoint) = &self.core.state.server else {
1769            return Ok(());
1770        };
1771        if !endpoint.flush_queued.replace(true) {
1772            self.core.state.add_flushable_endpoint(endpoint, None);
1773        }
1774        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1775        let outgoing = &mut *outgoing_ref;
1776        let mut fmt = outgoing.formatter();
1777        fmt.words([
1778            id,
1779            10,
1780            arg0 as u32,
1781            arg1 as u32,
1782        ]);
1783        Ok(())
1784    }
1785
1786    /// set the surface contents offset
1787    ///
1788    /// The x and y arguments specify the location of the new pending
1789    /// buffer's upper left corner, relative to the current buffer's upper
1790    /// left corner, in surface-local coordinates. In other words, the
1791    /// x and y, combined with the new surface size define in which
1792    /// directions the surface's size changes.
1793    ///
1794    /// The exact semantics of wl_surface.offset are role-specific. Refer to
1795    /// the documentation of specific roles for more information.
1796    ///
1797    /// Surface location offset is double-buffered state, see
1798    /// wl_surface.commit.
1799    ///
1800    /// This request is semantically equivalent to and the replaces the x and y
1801    /// arguments in the wl_surface.attach request in wl_surface versions prior
1802    /// to 5. See wl_surface.attach for details.
1803    ///
1804    /// # Arguments
1805    ///
1806    /// - `x`: surface-local x coordinate
1807    /// - `y`: surface-local y coordinate
1808    #[inline]
1809    pub fn send_offset(
1810        &self,
1811        x: i32,
1812        y: i32,
1813    ) {
1814        let res = self.try_send_offset(
1815            x,
1816            y,
1817        );
1818        if let Err(e) = res {
1819            log_send("wl_surface.offset", &e);
1820        }
1821    }
1822
1823    /// Since when the preferred_buffer_scale message is available.
1824    pub const MSG__PREFERRED_BUFFER_SCALE__SINCE: u32 = 6;
1825
1826    /// preferred buffer scale for the surface
1827    ///
1828    /// This event indicates the preferred buffer scale for this surface. It is
1829    /// sent whenever the compositor's preference changes.
1830    ///
1831    /// Before receiving this event the preferred buffer scale for this surface
1832    /// is 1.
1833    ///
1834    /// It is intended that scaling aware clients use this event to scale their
1835    /// content and use wl_surface.set_buffer_scale to indicate the scale they
1836    /// have rendered with. This allows clients to supply a higher detail
1837    /// buffer.
1838    ///
1839    /// The compositor shall emit a scale value greater than 0.
1840    ///
1841    /// # Arguments
1842    ///
1843    /// - `factor`: preferred scaling factor
1844    #[inline]
1845    pub fn try_send_preferred_buffer_scale(
1846        &self,
1847        factor: i32,
1848    ) -> Result<(), ObjectError> {
1849        let (
1850            arg0,
1851        ) = (
1852            factor,
1853        );
1854        let core = self.core();
1855        let client_ref = core.client.borrow();
1856        let Some(client) = &*client_ref else {
1857            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1858        };
1859        let id = core.client_obj_id.get().unwrap_or(0);
1860        #[cfg(feature = "logging")]
1861        if self.core.state.log {
1862            #[cold]
1863            fn log(state: &State, client_id: u64, id: u32, arg0: i32) {
1864                let (millis, micros) = time_since_epoch();
1865                let prefix = &state.log_prefix;
1866                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.preferred_buffer_scale(factor: {})\n", client_id, id, arg0);
1867                state.log(args);
1868            }
1869            log(&self.core.state, client.endpoint.id, id, arg0);
1870        }
1871        let endpoint = &client.endpoint;
1872        if !endpoint.flush_queued.replace(true) {
1873            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1874        }
1875        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1876        let outgoing = &mut *outgoing_ref;
1877        let mut fmt = outgoing.formatter();
1878        fmt.words([
1879            id,
1880            2,
1881            arg0 as u32,
1882        ]);
1883        Ok(())
1884    }
1885
1886    /// preferred buffer scale for the surface
1887    ///
1888    /// This event indicates the preferred buffer scale for this surface. It is
1889    /// sent whenever the compositor's preference changes.
1890    ///
1891    /// Before receiving this event the preferred buffer scale for this surface
1892    /// is 1.
1893    ///
1894    /// It is intended that scaling aware clients use this event to scale their
1895    /// content and use wl_surface.set_buffer_scale to indicate the scale they
1896    /// have rendered with. This allows clients to supply a higher detail
1897    /// buffer.
1898    ///
1899    /// The compositor shall emit a scale value greater than 0.
1900    ///
1901    /// # Arguments
1902    ///
1903    /// - `factor`: preferred scaling factor
1904    #[inline]
1905    pub fn send_preferred_buffer_scale(
1906        &self,
1907        factor: i32,
1908    ) {
1909        let res = self.try_send_preferred_buffer_scale(
1910            factor,
1911        );
1912        if let Err(e) = res {
1913            log_send("wl_surface.preferred_buffer_scale", &e);
1914        }
1915    }
1916
1917    /// Since when the preferred_buffer_transform message is available.
1918    pub const MSG__PREFERRED_BUFFER_TRANSFORM__SINCE: u32 = 6;
1919
1920    /// preferred buffer transform for the surface
1921    ///
1922    /// This event indicates the preferred buffer transform for this surface.
1923    /// It is sent whenever the compositor's preference changes.
1924    ///
1925    /// Before receiving this event the preferred buffer transform for this
1926    /// surface is normal.
1927    ///
1928    /// Applying this transformation to the surface buffer contents and using
1929    /// wl_surface.set_buffer_transform might allow the compositor to use the
1930    /// surface buffer more efficiently.
1931    ///
1932    /// # Arguments
1933    ///
1934    /// - `transform`: preferred transform
1935    #[inline]
1936    pub fn try_send_preferred_buffer_transform(
1937        &self,
1938        transform: WlOutputTransform,
1939    ) -> Result<(), ObjectError> {
1940        let (
1941            arg0,
1942        ) = (
1943            transform,
1944        );
1945        let core = self.core();
1946        let client_ref = core.client.borrow();
1947        let Some(client) = &*client_ref else {
1948            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1949        };
1950        let id = core.client_obj_id.get().unwrap_or(0);
1951        #[cfg(feature = "logging")]
1952        if self.core.state.log {
1953            #[cold]
1954            fn log(state: &State, client_id: u64, id: u32, arg0: WlOutputTransform) {
1955                let (millis, micros) = time_since_epoch();
1956                let prefix = &state.log_prefix;
1957                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.preferred_buffer_transform(transform: {:?})\n", client_id, id, arg0);
1958                state.log(args);
1959            }
1960            log(&self.core.state, client.endpoint.id, id, arg0);
1961        }
1962        let endpoint = &client.endpoint;
1963        if !endpoint.flush_queued.replace(true) {
1964            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1965        }
1966        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1967        let outgoing = &mut *outgoing_ref;
1968        let mut fmt = outgoing.formatter();
1969        fmt.words([
1970            id,
1971            3,
1972            arg0.0,
1973        ]);
1974        Ok(())
1975    }
1976
1977    /// preferred buffer transform for the surface
1978    ///
1979    /// This event indicates the preferred buffer transform for this surface.
1980    /// It is sent whenever the compositor's preference changes.
1981    ///
1982    /// Before receiving this event the preferred buffer transform for this
1983    /// surface is normal.
1984    ///
1985    /// Applying this transformation to the surface buffer contents and using
1986    /// wl_surface.set_buffer_transform might allow the compositor to use the
1987    /// surface buffer more efficiently.
1988    ///
1989    /// # Arguments
1990    ///
1991    /// - `transform`: preferred transform
1992    #[inline]
1993    pub fn send_preferred_buffer_transform(
1994        &self,
1995        transform: WlOutputTransform,
1996    ) {
1997        let res = self.try_send_preferred_buffer_transform(
1998            transform,
1999        );
2000        if let Err(e) = res {
2001            log_send("wl_surface.preferred_buffer_transform", &e);
2002        }
2003    }
2004}
2005
2006/// A message handler for [`WlSurface`] proxies.
2007pub trait WlSurfaceHandler: Any {
2008    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
2009    ///
2010    /// The default handler forwards the event to the client, if any.
2011    #[inline]
2012    fn delete_id(&mut self, slf: &Rc<WlSurface>) {
2013        slf.core.delete_id();
2014    }
2015
2016    /// delete surface
2017    ///
2018    /// Deletes the surface and invalidates its object ID.
2019    #[inline]
2020    fn handle_destroy(
2021        &mut self,
2022        slf: &Rc<WlSurface>,
2023    ) {
2024        if !slf.core.forward_to_server.get() {
2025            return;
2026        }
2027        let res = slf.try_send_destroy(
2028        );
2029        if let Err(e) = res {
2030            log_forward("wl_surface.destroy", &e);
2031        }
2032    }
2033
2034    /// set the surface contents
2035    ///
2036    /// Set a buffer as the content of this surface.
2037    ///
2038    /// The new size of the surface is calculated based on the buffer
2039    /// size transformed by the inverse buffer_transform and the
2040    /// inverse buffer_scale. This means that at commit time the supplied
2041    /// buffer size must be an integer multiple of the buffer_scale. If
2042    /// that's not the case, an invalid_size error is sent.
2043    ///
2044    /// The x and y arguments specify the location of the new pending
2045    /// buffer's upper left corner, relative to the current buffer's upper
2046    /// left corner, in surface-local coordinates. In other words, the
2047    /// x and y, combined with the new surface size define in which
2048    /// directions the surface's size changes. Setting anything other than 0
2049    /// as x and y arguments is discouraged, and should instead be replaced
2050    /// with using the separate wl_surface.offset request.
2051    ///
2052    /// When the bound wl_surface version is 5 or higher, passing any
2053    /// non-zero x or y is a protocol violation, and will result in an
2054    /// 'invalid_offset' error being raised. The x and y arguments are ignored
2055    /// and do not change the pending state. To achieve equivalent semantics,
2056    /// use wl_surface.offset.
2057    ///
2058    /// Surface contents are double-buffered state, see wl_surface.commit.
2059    ///
2060    /// The initial surface contents are void; there is no content.
2061    /// wl_surface.attach assigns the given wl_buffer as the pending
2062    /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
2063    /// surface contents, and the size of the surface becomes the size
2064    /// calculated from the wl_buffer, as described above. After commit,
2065    /// there is no pending buffer until the next attach.
2066    ///
2067    /// Committing a pending wl_buffer allows the compositor to read the
2068    /// pixels in the wl_buffer. The compositor may access the pixels at
2069    /// any time after the wl_surface.commit request. When the compositor
2070    /// will not access the pixels anymore, it will send the
2071    /// wl_buffer.release event. Only after receiving wl_buffer.release,
2072    /// the client may reuse the wl_buffer. A wl_buffer that has been
2073    /// attached and then replaced by another attach instead of committed
2074    /// will not receive a release event, and is not used by the
2075    /// compositor.
2076    ///
2077    /// If a pending wl_buffer has been committed to more than one wl_surface,
2078    /// the delivery of wl_buffer.release events becomes undefined. A well
2079    /// behaved client should not rely on wl_buffer.release events in this
2080    /// case. Alternatively, a client could create multiple wl_buffer objects
2081    /// from the same backing storage or use a protocol extension providing
2082    /// per-commit release notifications.
2083    ///
2084    /// Destroying the wl_buffer after wl_buffer.release does not change
2085    /// the surface contents. Destroying the wl_buffer before wl_buffer.release
2086    /// is allowed as long as the underlying buffer storage isn't re-used (this
2087    /// can happen e.g. on client process termination). However, if the client
2088    /// destroys the wl_buffer before receiving the wl_buffer.release event and
2089    /// mutates the underlying buffer storage, the surface contents become
2090    /// undefined immediately.
2091    ///
2092    /// If wl_surface.attach is sent with a NULL wl_buffer, the
2093    /// following wl_surface.commit will remove the surface content.
2094    ///
2095    /// If a pending wl_buffer has been destroyed, the result is not specified.
2096    /// Many compositors are known to remove the surface content on the following
2097    /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
2098    /// maximise compatibility should not destroy pending buffers and should
2099    /// ensure that they explicitly remove content from surfaces, even after
2100    /// destroying buffers.
2101    ///
2102    /// # Arguments
2103    ///
2104    /// - `buffer`: buffer of surface contents
2105    /// - `x`: surface-local x coordinate
2106    /// - `y`: surface-local y coordinate
2107    ///
2108    /// All borrowed proxies passed to this function are guaranteed to be
2109    /// immutable and non-null.
2110    #[inline]
2111    fn handle_attach(
2112        &mut self,
2113        slf: &Rc<WlSurface>,
2114        buffer: Option<&Rc<WlBuffer>>,
2115        x: i32,
2116        y: i32,
2117    ) {
2118        if !slf.core.forward_to_server.get() {
2119            return;
2120        }
2121        let res = slf.try_send_attach(
2122            buffer,
2123            x,
2124            y,
2125        );
2126        if let Err(e) = res {
2127            log_forward("wl_surface.attach", &e);
2128        }
2129    }
2130
2131    /// mark part of the surface damaged
2132    ///
2133    /// This request is used to describe the regions where the pending
2134    /// buffer is different from the current surface contents, and where
2135    /// the surface therefore needs to be repainted. The compositor
2136    /// ignores the parts of the damage that fall outside of the surface.
2137    ///
2138    /// Damage is double-buffered state, see wl_surface.commit.
2139    ///
2140    /// The damage rectangle is specified in surface-local coordinates,
2141    /// where x and y specify the upper left corner of the damage rectangle.
2142    ///
2143    /// The initial value for pending damage is empty: no damage.
2144    /// wl_surface.damage adds pending damage: the new pending damage
2145    /// is the union of old pending damage and the given rectangle.
2146    ///
2147    /// wl_surface.commit assigns pending damage as the current damage,
2148    /// and clears pending damage. The server will clear the current
2149    /// damage as it repaints the surface.
2150    ///
2151    /// Note! New clients should not use this request. Instead damage can be
2152    /// posted with wl_surface.damage_buffer which uses buffer coordinates
2153    /// instead of surface coordinates.
2154    ///
2155    /// # Arguments
2156    ///
2157    /// - `x`: surface-local x coordinate
2158    /// - `y`: surface-local y coordinate
2159    /// - `width`: width of damage rectangle
2160    /// - `height`: height of damage rectangle
2161    #[inline]
2162    fn handle_damage(
2163        &mut self,
2164        slf: &Rc<WlSurface>,
2165        x: i32,
2166        y: i32,
2167        width: i32,
2168        height: i32,
2169    ) {
2170        if !slf.core.forward_to_server.get() {
2171            return;
2172        }
2173        let res = slf.try_send_damage(
2174            x,
2175            y,
2176            width,
2177            height,
2178        );
2179        if let Err(e) = res {
2180            log_forward("wl_surface.damage", &e);
2181        }
2182    }
2183
2184    /// request a frame throttling hint
2185    ///
2186    /// Request a notification when it is a good time to start drawing a new
2187    /// frame, by creating a frame callback. This is useful for throttling
2188    /// redrawing operations, and driving animations.
2189    ///
2190    /// When a client is animating on a wl_surface, it can use the 'frame'
2191    /// request to get notified when it is a good time to draw and commit the
2192    /// next frame of animation. If the client commits an update earlier than
2193    /// that, it is likely that some updates will not make it to the display,
2194    /// and the client is wasting resources by drawing too often.
2195    ///
2196    /// The frame request will take effect on the next wl_surface.commit.
2197    /// The notification will only be posted for one frame unless
2198    /// requested again. For a wl_surface, the notifications are posted in
2199    /// the order the frame requests were committed.
2200    ///
2201    /// The server must send the notifications so that a client
2202    /// will not send excessive updates, while still allowing
2203    /// the highest possible update rate for clients that wait for the reply
2204    /// before drawing again. The server should give some time for the client
2205    /// to draw and commit after sending the frame callback events to let it
2206    /// hit the next output refresh.
2207    ///
2208    /// A server should avoid signaling the frame callbacks if the
2209    /// surface is not visible in any way, e.g. the surface is off-screen,
2210    /// or completely obscured by other opaque surfaces.
2211    ///
2212    /// The object returned by this request will be destroyed by the
2213    /// compositor after the callback is fired and as such the client must not
2214    /// attempt to use it after that point.
2215    ///
2216    /// The callback_data passed in the callback is the current time, in
2217    /// milliseconds, with an undefined base.
2218    ///
2219    /// # Arguments
2220    ///
2221    /// - `callback`: callback object for the frame request
2222    #[inline]
2223    fn handle_frame(
2224        &mut self,
2225        slf: &Rc<WlSurface>,
2226        callback: &Rc<WlCallback>,
2227    ) {
2228        if !slf.core.forward_to_server.get() {
2229            return;
2230        }
2231        let res = slf.try_send_frame(
2232            callback,
2233        );
2234        if let Err(e) = res {
2235            log_forward("wl_surface.frame", &e);
2236        }
2237    }
2238
2239    /// set opaque region
2240    ///
2241    /// This request sets the region of the surface that contains
2242    /// opaque content.
2243    ///
2244    /// The opaque region is an optimization hint for the compositor
2245    /// that lets it optimize the redrawing of content behind opaque
2246    /// regions.  Setting an opaque region is not required for correct
2247    /// behaviour, but marking transparent content as opaque will result
2248    /// in repaint artifacts.
2249    ///
2250    /// The opaque region is specified in surface-local coordinates.
2251    ///
2252    /// The compositor ignores the parts of the opaque region that fall
2253    /// outside of the surface.
2254    ///
2255    /// Opaque region is double-buffered state, see wl_surface.commit.
2256    ///
2257    /// wl_surface.set_opaque_region changes the pending opaque region.
2258    /// wl_surface.commit copies the pending region to the current region.
2259    /// Otherwise, the pending and current regions are never changed.
2260    ///
2261    /// The initial value for an opaque region is empty. Setting the pending
2262    /// opaque region has copy semantics, and the wl_region object can be
2263    /// destroyed immediately. A NULL wl_region causes the pending opaque
2264    /// region to be set to empty.
2265    ///
2266    /// # Arguments
2267    ///
2268    /// - `region`: opaque region of the surface
2269    ///
2270    /// All borrowed proxies passed to this function are guaranteed to be
2271    /// immutable and non-null.
2272    #[inline]
2273    fn handle_set_opaque_region(
2274        &mut self,
2275        slf: &Rc<WlSurface>,
2276        region: Option<&Rc<WlRegion>>,
2277    ) {
2278        if !slf.core.forward_to_server.get() {
2279            return;
2280        }
2281        let res = slf.try_send_set_opaque_region(
2282            region,
2283        );
2284        if let Err(e) = res {
2285            log_forward("wl_surface.set_opaque_region", &e);
2286        }
2287    }
2288
2289    /// set input region
2290    ///
2291    /// This request sets the region of the surface that can receive
2292    /// pointer and touch events.
2293    ///
2294    /// Input events happening outside of this region will try the next
2295    /// surface in the server surface stack. The compositor ignores the
2296    /// parts of the input region that fall outside of the surface.
2297    ///
2298    /// The input region is specified in surface-local coordinates.
2299    ///
2300    /// Input region is double-buffered state, see wl_surface.commit.
2301    ///
2302    /// wl_surface.set_input_region changes the pending input region.
2303    /// wl_surface.commit copies the pending region to the current region.
2304    /// Otherwise the pending and current regions are never changed,
2305    /// except cursor and icon surfaces are special cases, see
2306    /// wl_pointer.set_cursor and wl_data_device.start_drag.
2307    ///
2308    /// The initial value for an input region is infinite. That means the
2309    /// whole surface will accept input. Setting the pending input region
2310    /// has copy semantics, and the wl_region object can be destroyed
2311    /// immediately. A NULL wl_region causes the input region to be set
2312    /// to infinite.
2313    ///
2314    /// # Arguments
2315    ///
2316    /// - `region`: input region of the surface
2317    ///
2318    /// All borrowed proxies passed to this function are guaranteed to be
2319    /// immutable and non-null.
2320    #[inline]
2321    fn handle_set_input_region(
2322        &mut self,
2323        slf: &Rc<WlSurface>,
2324        region: Option<&Rc<WlRegion>>,
2325    ) {
2326        if !slf.core.forward_to_server.get() {
2327            return;
2328        }
2329        let res = slf.try_send_set_input_region(
2330            region,
2331        );
2332        if let Err(e) = res {
2333            log_forward("wl_surface.set_input_region", &e);
2334        }
2335    }
2336
2337    /// commit pending surface state
2338    ///
2339    /// Surface state (input, opaque, and damage regions, attached buffers,
2340    /// etc.) is double-buffered. Protocol requests modify the pending state,
2341    /// as opposed to the active state in use by the compositor.
2342    ///
2343    /// All requests that need a commit to become effective are documented
2344    /// to affect double-buffered state.
2345    ///
2346    /// Other interfaces may add further double-buffered surface state.
2347    ///
2348    /// A commit request atomically creates a Content Update (CU) from the
2349    /// pending state, even if the pending state has not been touched. The
2350    /// content update is placed at the end of a per-surface queue until it
2351    /// becomes active. After commit, the new pending state is as documented for
2352    /// each related request.
2353    ///
2354    /// A CU is either a Desync Content Update (DCU) or a Sync Content Update
2355    /// (SCU). If the surface is effectively synchronized at the commit request,
2356    /// it is a SCU, otherwise a DCU.
2357    ///
2358    /// When a surface transitions from effectively synchronized to effectively
2359    /// desynchronized, all SCUs in its queue which are not reachable by any
2360    /// DCU become DCUs and dependency edges from outside the queue to these CUs
2361    /// are removed.
2362    ///
2363    /// See wl_subsurface for the definition of 'effectively synchronized' and
2364    /// 'effectively desynchronized'.
2365    ///
2366    /// When a CU is placed in the queue, the CU has a dependency on the CU in
2367    /// front of it and to the SCU at end of the queue of every direct child
2368    /// surface if that SCU exists and does not have another dependent. This can
2369    /// form a directed acyclic graph of CUs with dependencies as edges.
2370    ///
2371    /// In addition to surface state, the CU can have constraints that must be
2372    /// satisfied before it can be applied. Other interfaces may add CU
2373    /// constraints.
2374    ///
2375    /// All DCUs which do not have a SCU in front of themselves in their queue,
2376    /// are candidates. If the graph that's reachable by a candidate does not
2377    /// have any unsatisfied constraints, the entire graph must be applied
2378    /// atomically.
2379    ///
2380    /// When a CU is applied, the wl_buffer is applied before all other state.
2381    /// This means that all coordinates in double-buffered state are relative to
2382    /// the newly attached wl_buffers, except for wl_surface.attach itself. If
2383    /// there is no newly attached wl_buffer, the coordinates are relative to
2384    /// the previous content update.
2385    #[inline]
2386    fn handle_commit(
2387        &mut self,
2388        slf: &Rc<WlSurface>,
2389    ) {
2390        if !slf.core.forward_to_server.get() {
2391            return;
2392        }
2393        let res = slf.try_send_commit(
2394        );
2395        if let Err(e) = res {
2396            log_forward("wl_surface.commit", &e);
2397        }
2398    }
2399
2400    /// surface enters an output
2401    ///
2402    /// This is emitted whenever a surface's creation, movement, or resizing
2403    /// results in some part of it being within the scanout region of an
2404    /// output.
2405    ///
2406    /// Note that a surface may be overlapping with zero or more outputs.
2407    ///
2408    /// # Arguments
2409    ///
2410    /// - `output`: output entered by the surface
2411    ///
2412    /// All borrowed proxies passed to this function are guaranteed to be
2413    /// immutable and non-null.
2414    #[inline]
2415    fn handle_enter(
2416        &mut self,
2417        slf: &Rc<WlSurface>,
2418        output: &Rc<WlOutput>,
2419    ) {
2420        if !slf.core.forward_to_client.get() {
2421            return;
2422        }
2423        if let Some(client_id) = slf.core.client_id.get() {
2424            if let Some(client_id_2) = output.core().client_id.get() {
2425                if client_id != client_id_2 {
2426                    return;
2427                }
2428            }
2429        }
2430        let res = slf.try_send_enter(
2431            output,
2432        );
2433        if let Err(e) = res {
2434            log_forward("wl_surface.enter", &e);
2435        }
2436    }
2437
2438    /// surface leaves an output
2439    ///
2440    /// This is emitted whenever a surface's creation, movement, or resizing
2441    /// results in it no longer having any part of it within the scanout region
2442    /// of an output.
2443    ///
2444    /// Clients should not use the number of outputs the surface is on for frame
2445    /// throttling purposes. The surface might be hidden even if no leave event
2446    /// has been sent, and the compositor might expect new surface content
2447    /// updates even if no enter event has been sent. The frame event should be
2448    /// used instead.
2449    ///
2450    /// # Arguments
2451    ///
2452    /// - `output`: output left by the surface
2453    ///
2454    /// All borrowed proxies passed to this function are guaranteed to be
2455    /// immutable and non-null.
2456    #[inline]
2457    fn handle_leave(
2458        &mut self,
2459        slf: &Rc<WlSurface>,
2460        output: &Rc<WlOutput>,
2461    ) {
2462        if !slf.core.forward_to_client.get() {
2463            return;
2464        }
2465        if let Some(client_id) = slf.core.client_id.get() {
2466            if let Some(client_id_2) = output.core().client_id.get() {
2467                if client_id != client_id_2 {
2468                    return;
2469                }
2470            }
2471        }
2472        let res = slf.try_send_leave(
2473            output,
2474        );
2475        if let Err(e) = res {
2476            log_forward("wl_surface.leave", &e);
2477        }
2478    }
2479
2480    /// sets the buffer transformation
2481    ///
2482    /// This request sets the transformation that the client has already applied
2483    /// to the content of the buffer. The accepted values for the transform
2484    /// parameter are the values for wl_output.transform.
2485    ///
2486    /// The compositor applies the inverse of this transformation whenever it
2487    /// uses the buffer contents.
2488    ///
2489    /// Buffer transform is double-buffered state, see wl_surface.commit.
2490    ///
2491    /// A newly created surface has its buffer transformation set to normal.
2492    ///
2493    /// wl_surface.set_buffer_transform changes the pending buffer
2494    /// transformation. wl_surface.commit copies the pending buffer
2495    /// transformation to the current one. Otherwise, the pending and current
2496    /// values are never changed.
2497    ///
2498    /// The purpose of this request is to allow clients to render content
2499    /// according to the output transform, thus permitting the compositor to
2500    /// use certain optimizations even if the display is rotated. Using
2501    /// hardware overlays and scanning out a client buffer for fullscreen
2502    /// surfaces are examples of such optimizations. Those optimizations are
2503    /// highly dependent on the compositor implementation, so the use of this
2504    /// request should be considered on a case-by-case basis.
2505    ///
2506    /// Note that if the transform value includes 90 or 270 degree rotation,
2507    /// the width of the buffer will become the surface height and the height
2508    /// of the buffer will become the surface width.
2509    ///
2510    /// If transform is not one of the values from the
2511    /// wl_output.transform enum the invalid_transform protocol error
2512    /// is raised.
2513    ///
2514    /// # Arguments
2515    ///
2516    /// - `transform`: transform for interpreting buffer contents
2517    #[inline]
2518    fn handle_set_buffer_transform(
2519        &mut self,
2520        slf: &Rc<WlSurface>,
2521        transform: WlOutputTransform,
2522    ) {
2523        if !slf.core.forward_to_server.get() {
2524            return;
2525        }
2526        let res = slf.try_send_set_buffer_transform(
2527            transform,
2528        );
2529        if let Err(e) = res {
2530            log_forward("wl_surface.set_buffer_transform", &e);
2531        }
2532    }
2533
2534    /// sets the buffer scaling factor
2535    ///
2536    /// This request sets an optional scaling factor on how the compositor
2537    /// interprets the contents of the buffer attached to the window.
2538    ///
2539    /// Buffer scale is double-buffered state, see wl_surface.commit.
2540    ///
2541    /// A newly created surface has its buffer scale set to 1.
2542    ///
2543    /// wl_surface.set_buffer_scale changes the pending buffer scale.
2544    /// wl_surface.commit copies the pending buffer scale to the current one.
2545    /// Otherwise, the pending and current values are never changed.
2546    ///
2547    /// The purpose of this request is to allow clients to supply higher
2548    /// resolution buffer data for use on high resolution outputs. It is
2549    /// intended that you pick the same buffer scale as the scale of the
2550    /// output that the surface is displayed on. This means the compositor
2551    /// can avoid scaling when rendering the surface on that output.
2552    ///
2553    /// Note that if the scale is larger than 1, then you have to attach
2554    /// a buffer that is larger (by a factor of scale in each dimension)
2555    /// than the desired surface size.
2556    ///
2557    /// If scale is not greater than 0 the invalid_scale protocol error is
2558    /// raised.
2559    ///
2560    /// # Arguments
2561    ///
2562    /// - `scale`: scale for interpreting buffer contents
2563    #[inline]
2564    fn handle_set_buffer_scale(
2565        &mut self,
2566        slf: &Rc<WlSurface>,
2567        scale: i32,
2568    ) {
2569        if !slf.core.forward_to_server.get() {
2570            return;
2571        }
2572        let res = slf.try_send_set_buffer_scale(
2573            scale,
2574        );
2575        if let Err(e) = res {
2576            log_forward("wl_surface.set_buffer_scale", &e);
2577        }
2578    }
2579
2580    /// mark part of the surface damaged using buffer coordinates
2581    ///
2582    /// This request is used to describe the regions where the pending
2583    /// buffer is different from the current surface contents, and where
2584    /// the surface therefore needs to be repainted. The compositor
2585    /// ignores the parts of the damage that fall outside of the surface.
2586    ///
2587    /// Damage is double-buffered state, see wl_surface.commit.
2588    ///
2589    /// The damage rectangle is specified in buffer coordinates,
2590    /// where x and y specify the upper left corner of the damage rectangle.
2591    ///
2592    /// The initial value for pending damage is empty: no damage.
2593    /// wl_surface.damage_buffer adds pending damage: the new pending
2594    /// damage is the union of old pending damage and the given rectangle.
2595    ///
2596    /// wl_surface.commit assigns pending damage as the current damage,
2597    /// and clears pending damage. The server will clear the current
2598    /// damage as it repaints the surface.
2599    ///
2600    /// This request differs from wl_surface.damage in only one way - it
2601    /// takes damage in buffer coordinates instead of surface-local
2602    /// coordinates. While this generally is more intuitive than surface
2603    /// coordinates, it is especially desirable when using wp_viewport
2604    /// or when a drawing library (like EGL) is unaware of buffer scale
2605    /// and buffer transform.
2606    ///
2607    /// Note: Because buffer transformation changes and damage requests may
2608    /// be interleaved in the protocol stream, it is impossible to determine
2609    /// the actual mapping between surface and buffer damage until
2610    /// wl_surface.commit time. Therefore, compositors wishing to take both
2611    /// kinds of damage into account will have to accumulate damage from the
2612    /// two requests separately and only transform from one to the other
2613    /// after receiving the wl_surface.commit.
2614    ///
2615    /// # Arguments
2616    ///
2617    /// - `x`: buffer-local x coordinate
2618    /// - `y`: buffer-local y coordinate
2619    /// - `width`: width of damage rectangle
2620    /// - `height`: height of damage rectangle
2621    #[inline]
2622    fn handle_damage_buffer(
2623        &mut self,
2624        slf: &Rc<WlSurface>,
2625        x: i32,
2626        y: i32,
2627        width: i32,
2628        height: i32,
2629    ) {
2630        if !slf.core.forward_to_server.get() {
2631            return;
2632        }
2633        let res = slf.try_send_damage_buffer(
2634            x,
2635            y,
2636            width,
2637            height,
2638        );
2639        if let Err(e) = res {
2640            log_forward("wl_surface.damage_buffer", &e);
2641        }
2642    }
2643
2644    /// set the surface contents offset
2645    ///
2646    /// The x and y arguments specify the location of the new pending
2647    /// buffer's upper left corner, relative to the current buffer's upper
2648    /// left corner, in surface-local coordinates. In other words, the
2649    /// x and y, combined with the new surface size define in which
2650    /// directions the surface's size changes.
2651    ///
2652    /// The exact semantics of wl_surface.offset are role-specific. Refer to
2653    /// the documentation of specific roles for more information.
2654    ///
2655    /// Surface location offset is double-buffered state, see
2656    /// wl_surface.commit.
2657    ///
2658    /// This request is semantically equivalent to and the replaces the x and y
2659    /// arguments in the wl_surface.attach request in wl_surface versions prior
2660    /// to 5. See wl_surface.attach for details.
2661    ///
2662    /// # Arguments
2663    ///
2664    /// - `x`: surface-local x coordinate
2665    /// - `y`: surface-local y coordinate
2666    #[inline]
2667    fn handle_offset(
2668        &mut self,
2669        slf: &Rc<WlSurface>,
2670        x: i32,
2671        y: i32,
2672    ) {
2673        if !slf.core.forward_to_server.get() {
2674            return;
2675        }
2676        let res = slf.try_send_offset(
2677            x,
2678            y,
2679        );
2680        if let Err(e) = res {
2681            log_forward("wl_surface.offset", &e);
2682        }
2683    }
2684
2685    /// preferred buffer scale for the surface
2686    ///
2687    /// This event indicates the preferred buffer scale for this surface. It is
2688    /// sent whenever the compositor's preference changes.
2689    ///
2690    /// Before receiving this event the preferred buffer scale for this surface
2691    /// is 1.
2692    ///
2693    /// It is intended that scaling aware clients use this event to scale their
2694    /// content and use wl_surface.set_buffer_scale to indicate the scale they
2695    /// have rendered with. This allows clients to supply a higher detail
2696    /// buffer.
2697    ///
2698    /// The compositor shall emit a scale value greater than 0.
2699    ///
2700    /// # Arguments
2701    ///
2702    /// - `factor`: preferred scaling factor
2703    #[inline]
2704    fn handle_preferred_buffer_scale(
2705        &mut self,
2706        slf: &Rc<WlSurface>,
2707        factor: i32,
2708    ) {
2709        if !slf.core.forward_to_client.get() {
2710            return;
2711        }
2712        let res = slf.try_send_preferred_buffer_scale(
2713            factor,
2714        );
2715        if let Err(e) = res {
2716            log_forward("wl_surface.preferred_buffer_scale", &e);
2717        }
2718    }
2719
2720    /// preferred buffer transform for the surface
2721    ///
2722    /// This event indicates the preferred buffer transform for this surface.
2723    /// It is sent whenever the compositor's preference changes.
2724    ///
2725    /// Before receiving this event the preferred buffer transform for this
2726    /// surface is normal.
2727    ///
2728    /// Applying this transformation to the surface buffer contents and using
2729    /// wl_surface.set_buffer_transform might allow the compositor to use the
2730    /// surface buffer more efficiently.
2731    ///
2732    /// # Arguments
2733    ///
2734    /// - `transform`: preferred transform
2735    #[inline]
2736    fn handle_preferred_buffer_transform(
2737        &mut self,
2738        slf: &Rc<WlSurface>,
2739        transform: WlOutputTransform,
2740    ) {
2741        if !slf.core.forward_to_client.get() {
2742            return;
2743        }
2744        let res = slf.try_send_preferred_buffer_transform(
2745            transform,
2746        );
2747        if let Err(e) = res {
2748            log_forward("wl_surface.preferred_buffer_transform", &e);
2749        }
2750    }
2751}
2752
2753impl ObjectPrivate for WlSurface {
2754    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
2755        Rc::<Self>::new_cyclic(|slf| Self {
2756            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlSurface, version),
2757            handler: Default::default(),
2758        })
2759    }
2760
2761    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
2762        let Some(mut handler) = self.handler.try_borrow_mut() else {
2763            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
2764        };
2765        if let Some(handler) = &mut *handler {
2766            handler.delete_id(&self);
2767        } else {
2768            self.core.delete_id();
2769        }
2770        Ok(())
2771    }
2772
2773    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
2774        let Some(mut handler) = self.handler.try_borrow_mut() else {
2775            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
2776        };
2777        let handler = &mut *handler;
2778        match msg[1] & 0xffff {
2779            0 => {
2780                if msg.len() != 2 {
2781                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
2782                }
2783                #[cfg(feature = "logging")]
2784                if self.core.state.log {
2785                    #[cold]
2786                    fn log(state: &State, client_id: u64, id: u32) {
2787                        let (millis, micros) = time_since_epoch();
2788                        let prefix = &state.log_prefix;
2789                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.destroy()\n", client_id, id);
2790                        state.log(args);
2791                    }
2792                    log(&self.core.state, client.endpoint.id, msg[0]);
2793                }
2794                self.core.handle_client_destroy();
2795                if let Some(handler) = handler {
2796                    (**handler).handle_destroy(&self);
2797                } else {
2798                    DefaultHandler.handle_destroy(&self);
2799                }
2800            }
2801            1 => {
2802                let [
2803                    arg0,
2804                    arg1,
2805                    arg2,
2806                ] = msg[2..] else {
2807                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
2808                };
2809                let arg1 = arg1 as i32;
2810                let arg2 = arg2 as i32;
2811                #[cfg(feature = "logging")]
2812                if self.core.state.log {
2813                    #[cold]
2814                    fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: i32, arg2: i32) {
2815                        let (millis, micros) = time_since_epoch();
2816                        let prefix = &state.log_prefix;
2817                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.attach(buffer: wl_buffer#{}, x: {}, y: {})\n", client_id, id, arg0, arg1, arg2);
2818                        state.log(args);
2819                    }
2820                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2);
2821                }
2822                let arg0 = if arg0 == 0 {
2823                    None
2824                } else {
2825                    let arg0_id = arg0;
2826                    let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2827                        return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2828                    };
2829                    let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlBuffer>() else {
2830                        let o = client.endpoint.lookup(arg0_id).unwrap();
2831                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("buffer", o.core().interface, ObjectInterface::WlBuffer)));
2832                    };
2833                    Some(arg0)
2834                };
2835                let arg0 = arg0.as_ref();
2836                if let Some(handler) = handler {
2837                    (**handler).handle_attach(&self, arg0, arg1, arg2);
2838                } else {
2839                    DefaultHandler.handle_attach(&self, arg0, arg1, arg2);
2840                }
2841            }
2842            2 => {
2843                let [
2844                    arg0,
2845                    arg1,
2846                    arg2,
2847                    arg3,
2848                ] = msg[2..] else {
2849                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
2850                };
2851                let arg0 = arg0 as i32;
2852                let arg1 = arg1 as i32;
2853                let arg2 = arg2 as i32;
2854                let arg3 = arg3 as i32;
2855                #[cfg(feature = "logging")]
2856                if self.core.state.log {
2857                    #[cold]
2858                    fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
2859                        let (millis, micros) = time_since_epoch();
2860                        let prefix = &state.log_prefix;
2861                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.damage(x: {}, y: {}, width: {}, height: {})\n", client_id, id, arg0, arg1, arg2, arg3);
2862                        state.log(args);
2863                    }
2864                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
2865                }
2866                if let Some(handler) = handler {
2867                    (**handler).handle_damage(&self, arg0, arg1, arg2, arg3);
2868                } else {
2869                    DefaultHandler.handle_damage(&self, arg0, arg1, arg2, arg3);
2870                }
2871            }
2872            3 => {
2873                let [
2874                    arg0,
2875                ] = msg[2..] else {
2876                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2877                };
2878                #[cfg(feature = "logging")]
2879                if self.core.state.log {
2880                    #[cold]
2881                    fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2882                        let (millis, micros) = time_since_epoch();
2883                        let prefix = &state.log_prefix;
2884                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.frame(callback: wl_callback#{})\n", client_id, id, arg0);
2885                        state.log(args);
2886                    }
2887                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
2888                }
2889                let arg0_id = arg0;
2890                let arg0 = WlCallback::new(&self.core.state, self.core.version);
2891                arg0.core().set_client_id(client, arg0_id, arg0.clone())
2892                    .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg0_id, "callback", e)))?;
2893                let arg0 = &arg0;
2894                if let Some(handler) = handler {
2895                    (**handler).handle_frame(&self, arg0);
2896                } else {
2897                    DefaultHandler.handle_frame(&self, arg0);
2898                }
2899            }
2900            4 => {
2901                let [
2902                    arg0,
2903                ] = msg[2..] else {
2904                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2905                };
2906                #[cfg(feature = "logging")]
2907                if self.core.state.log {
2908                    #[cold]
2909                    fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2910                        let (millis, micros) = time_since_epoch();
2911                        let prefix = &state.log_prefix;
2912                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_opaque_region(region: wl_region#{})\n", client_id, id, arg0);
2913                        state.log(args);
2914                    }
2915                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
2916                }
2917                let arg0 = if arg0 == 0 {
2918                    None
2919                } else {
2920                    let arg0_id = arg0;
2921                    let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2922                        return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2923                    };
2924                    let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlRegion>() else {
2925                        let o = client.endpoint.lookup(arg0_id).unwrap();
2926                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("region", o.core().interface, ObjectInterface::WlRegion)));
2927                    };
2928                    Some(arg0)
2929                };
2930                let arg0 = arg0.as_ref();
2931                if let Some(handler) = handler {
2932                    (**handler).handle_set_opaque_region(&self, arg0);
2933                } else {
2934                    DefaultHandler.handle_set_opaque_region(&self, arg0);
2935                }
2936            }
2937            5 => {
2938                let [
2939                    arg0,
2940                ] = msg[2..] else {
2941                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2942                };
2943                #[cfg(feature = "logging")]
2944                if self.core.state.log {
2945                    #[cold]
2946                    fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2947                        let (millis, micros) = time_since_epoch();
2948                        let prefix = &state.log_prefix;
2949                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_input_region(region: wl_region#{})\n", client_id, id, arg0);
2950                        state.log(args);
2951                    }
2952                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
2953                }
2954                let arg0 = if arg0 == 0 {
2955                    None
2956                } else {
2957                    let arg0_id = arg0;
2958                    let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2959                        return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2960                    };
2961                    let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlRegion>() else {
2962                        let o = client.endpoint.lookup(arg0_id).unwrap();
2963                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("region", o.core().interface, ObjectInterface::WlRegion)));
2964                    };
2965                    Some(arg0)
2966                };
2967                let arg0 = arg0.as_ref();
2968                if let Some(handler) = handler {
2969                    (**handler).handle_set_input_region(&self, arg0);
2970                } else {
2971                    DefaultHandler.handle_set_input_region(&self, arg0);
2972                }
2973            }
2974            6 => {
2975                if msg.len() != 2 {
2976                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
2977                }
2978                #[cfg(feature = "logging")]
2979                if self.core.state.log {
2980                    #[cold]
2981                    fn log(state: &State, client_id: u64, id: u32) {
2982                        let (millis, micros) = time_since_epoch();
2983                        let prefix = &state.log_prefix;
2984                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.commit()\n", client_id, id);
2985                        state.log(args);
2986                    }
2987                    log(&self.core.state, client.endpoint.id, msg[0]);
2988                }
2989                if let Some(handler) = handler {
2990                    (**handler).handle_commit(&self);
2991                } else {
2992                    DefaultHandler.handle_commit(&self);
2993                }
2994            }
2995            7 => {
2996                let [
2997                    arg0,
2998                ] = msg[2..] else {
2999                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3000                };
3001                let arg0 = WlOutputTransform(arg0);
3002                #[cfg(feature = "logging")]
3003                if self.core.state.log {
3004                    #[cold]
3005                    fn log(state: &State, client_id: u64, id: u32, arg0: WlOutputTransform) {
3006                        let (millis, micros) = time_since_epoch();
3007                        let prefix = &state.log_prefix;
3008                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_buffer_transform(transform: {:?})\n", client_id, id, arg0);
3009                        state.log(args);
3010                    }
3011                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
3012                }
3013                if let Some(handler) = handler {
3014                    (**handler).handle_set_buffer_transform(&self, arg0);
3015                } else {
3016                    DefaultHandler.handle_set_buffer_transform(&self, arg0);
3017                }
3018            }
3019            8 => {
3020                let [
3021                    arg0,
3022                ] = msg[2..] else {
3023                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3024                };
3025                let arg0 = arg0 as i32;
3026                #[cfg(feature = "logging")]
3027                if self.core.state.log {
3028                    #[cold]
3029                    fn log(state: &State, client_id: u64, id: u32, arg0: i32) {
3030                        let (millis, micros) = time_since_epoch();
3031                        let prefix = &state.log_prefix;
3032                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_buffer_scale(scale: {})\n", client_id, id, arg0);
3033                        state.log(args);
3034                    }
3035                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
3036                }
3037                if let Some(handler) = handler {
3038                    (**handler).handle_set_buffer_scale(&self, arg0);
3039                } else {
3040                    DefaultHandler.handle_set_buffer_scale(&self, arg0);
3041                }
3042            }
3043            9 => {
3044                let [
3045                    arg0,
3046                    arg1,
3047                    arg2,
3048                    arg3,
3049                ] = msg[2..] else {
3050                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
3051                };
3052                let arg0 = arg0 as i32;
3053                let arg1 = arg1 as i32;
3054                let arg2 = arg2 as i32;
3055                let arg3 = arg3 as i32;
3056                #[cfg(feature = "logging")]
3057                if self.core.state.log {
3058                    #[cold]
3059                    fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
3060                        let (millis, micros) = time_since_epoch();
3061                        let prefix = &state.log_prefix;
3062                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.damage_buffer(x: {}, y: {}, width: {}, height: {})\n", client_id, id, arg0, arg1, arg2, arg3);
3063                        state.log(args);
3064                    }
3065                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
3066                }
3067                if let Some(handler) = handler {
3068                    (**handler).handle_damage_buffer(&self, arg0, arg1, arg2, arg3);
3069                } else {
3070                    DefaultHandler.handle_damage_buffer(&self, arg0, arg1, arg2, arg3);
3071                }
3072            }
3073            10 => {
3074                let [
3075                    arg0,
3076                    arg1,
3077                ] = msg[2..] else {
3078                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
3079                };
3080                let arg0 = arg0 as i32;
3081                let arg1 = arg1 as i32;
3082                #[cfg(feature = "logging")]
3083                if self.core.state.log {
3084                    #[cold]
3085                    fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32) {
3086                        let (millis, micros) = time_since_epoch();
3087                        let prefix = &state.log_prefix;
3088                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.offset(x: {}, y: {})\n", client_id, id, arg0, arg1);
3089                        state.log(args);
3090                    }
3091                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1);
3092                }
3093                if let Some(handler) = handler {
3094                    (**handler).handle_offset(&self, arg0, arg1);
3095                } else {
3096                    DefaultHandler.handle_offset(&self, arg0, arg1);
3097                }
3098            }
3099            n => {
3100                let _ = client;
3101                let _ = msg;
3102                let _ = fds;
3103                let _ = handler;
3104                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
3105            }
3106        }
3107        Ok(())
3108    }
3109
3110    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
3111        let Some(mut handler) = self.handler.try_borrow_mut() else {
3112            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
3113        };
3114        let handler = &mut *handler;
3115        match msg[1] & 0xffff {
3116            0 => {
3117                let [
3118                    arg0,
3119                ] = msg[2..] else {
3120                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3121                };
3122                #[cfg(feature = "logging")]
3123                if self.core.state.log {
3124                    #[cold]
3125                    fn log(state: &State, id: u32, arg0: u32) {
3126                        let (millis, micros) = time_since_epoch();
3127                        let prefix = &state.log_prefix;
3128                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_surface#{}.enter(output: wl_output#{})\n", id, arg0);
3129                        state.log(args);
3130                    }
3131                    log(&self.core.state, msg[0], arg0);
3132                }
3133                let arg0_id = arg0;
3134                let Some(arg0) = server.lookup(arg0_id) else {
3135                    return Err(ObjectError(ObjectErrorKind::NoServerObject(arg0_id)));
3136                };
3137                let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlOutput>() else {
3138                    let o = server.lookup(arg0_id).unwrap();
3139                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("output", o.core().interface, ObjectInterface::WlOutput)));
3140                };
3141                let arg0 = &arg0;
3142                if let Some(handler) = handler {
3143                    (**handler).handle_enter(&self, arg0);
3144                } else {
3145                    DefaultHandler.handle_enter(&self, arg0);
3146                }
3147            }
3148            1 => {
3149                let [
3150                    arg0,
3151                ] = msg[2..] else {
3152                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3153                };
3154                #[cfg(feature = "logging")]
3155                if self.core.state.log {
3156                    #[cold]
3157                    fn log(state: &State, id: u32, arg0: u32) {
3158                        let (millis, micros) = time_since_epoch();
3159                        let prefix = &state.log_prefix;
3160                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_surface#{}.leave(output: wl_output#{})\n", id, arg0);
3161                        state.log(args);
3162                    }
3163                    log(&self.core.state, msg[0], arg0);
3164                }
3165                let arg0_id = arg0;
3166                let Some(arg0) = server.lookup(arg0_id) else {
3167                    return Err(ObjectError(ObjectErrorKind::NoServerObject(arg0_id)));
3168                };
3169                let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlOutput>() else {
3170                    let o = server.lookup(arg0_id).unwrap();
3171                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("output", o.core().interface, ObjectInterface::WlOutput)));
3172                };
3173                let arg0 = &arg0;
3174                if let Some(handler) = handler {
3175                    (**handler).handle_leave(&self, arg0);
3176                } else {
3177                    DefaultHandler.handle_leave(&self, arg0);
3178                }
3179            }
3180            2 => {
3181                let [
3182                    arg0,
3183                ] = msg[2..] else {
3184                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3185                };
3186                let arg0 = arg0 as i32;
3187                #[cfg(feature = "logging")]
3188                if self.core.state.log {
3189                    #[cold]
3190                    fn log(state: &State, id: u32, arg0: i32) {
3191                        let (millis, micros) = time_since_epoch();
3192                        let prefix = &state.log_prefix;
3193                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_surface#{}.preferred_buffer_scale(factor: {})\n", id, arg0);
3194                        state.log(args);
3195                    }
3196                    log(&self.core.state, msg[0], arg0);
3197                }
3198                if let Some(handler) = handler {
3199                    (**handler).handle_preferred_buffer_scale(&self, arg0);
3200                } else {
3201                    DefaultHandler.handle_preferred_buffer_scale(&self, arg0);
3202                }
3203            }
3204            3 => {
3205                let [
3206                    arg0,
3207                ] = msg[2..] else {
3208                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3209                };
3210                let arg0 = WlOutputTransform(arg0);
3211                #[cfg(feature = "logging")]
3212                if self.core.state.log {
3213                    #[cold]
3214                    fn log(state: &State, id: u32, arg0: WlOutputTransform) {
3215                        let (millis, micros) = time_since_epoch();
3216                        let prefix = &state.log_prefix;
3217                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_surface#{}.preferred_buffer_transform(transform: {:?})\n", id, arg0);
3218                        state.log(args);
3219                    }
3220                    log(&self.core.state, msg[0], arg0);
3221                }
3222                if let Some(handler) = handler {
3223                    (**handler).handle_preferred_buffer_transform(&self, arg0);
3224                } else {
3225                    DefaultHandler.handle_preferred_buffer_transform(&self, arg0);
3226                }
3227            }
3228            n => {
3229                let _ = server;
3230                let _ = msg;
3231                let _ = fds;
3232                let _ = handler;
3233                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
3234            }
3235        }
3236        Ok(())
3237    }
3238
3239    fn get_request_name(&self, id: u32) -> Option<&'static str> {
3240        let name = match id {
3241            0 => "destroy",
3242            1 => "attach",
3243            2 => "damage",
3244            3 => "frame",
3245            4 => "set_opaque_region",
3246            5 => "set_input_region",
3247            6 => "commit",
3248            7 => "set_buffer_transform",
3249            8 => "set_buffer_scale",
3250            9 => "damage_buffer",
3251            10 => "offset",
3252            _ => return None,
3253        };
3254        Some(name)
3255    }
3256
3257    fn get_event_name(&self, id: u32) -> Option<&'static str> {
3258        let name = match id {
3259            0 => "enter",
3260            1 => "leave",
3261            2 => "preferred_buffer_scale",
3262            3 => "preferred_buffer_transform",
3263            _ => return None,
3264        };
3265        Some(name)
3266    }
3267}
3268
3269impl Object for WlSurface {
3270    fn core(&self) -> &ObjectCore {
3271        &self.core
3272    }
3273
3274    fn unset_handler(&self) {
3275        self.handler.set(None);
3276    }
3277
3278    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
3279        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
3280        if borrowed.is_none() {
3281            return Err(HandlerAccessError::NoHandler);
3282        }
3283        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
3284    }
3285
3286    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
3287        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
3288        if borrowed.is_none() {
3289            return Err(HandlerAccessError::NoHandler);
3290        }
3291        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
3292    }
3293}
3294
3295impl WlSurface {
3296    /// Since when the error.invalid_scale enum variant is available.
3297    pub const ENM__ERROR_INVALID_SCALE__SINCE: u32 = 1;
3298    /// Since when the error.invalid_transform enum variant is available.
3299    pub const ENM__ERROR_INVALID_TRANSFORM__SINCE: u32 = 1;
3300    /// Since when the error.invalid_size enum variant is available.
3301    pub const ENM__ERROR_INVALID_SIZE__SINCE: u32 = 1;
3302    /// Since when the error.invalid_offset enum variant is available.
3303    pub const ENM__ERROR_INVALID_OFFSET__SINCE: u32 = 1;
3304    /// Since when the error.defunct_role_object enum variant is available.
3305    pub const ENM__ERROR_DEFUNCT_ROLE_OBJECT__SINCE: u32 = 1;
3306}
3307
3308/// wl_surface error values
3309///
3310/// These errors can be emitted in response to wl_surface requests.
3311#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
3312pub struct WlSurfaceError(pub u32);
3313
3314impl WlSurfaceError {
3315    /// buffer scale value is invalid
3316    pub const INVALID_SCALE: Self = Self(0);
3317
3318    /// buffer transform value is invalid
3319    pub const INVALID_TRANSFORM: Self = Self(1);
3320
3321    /// buffer size is invalid
3322    pub const INVALID_SIZE: Self = Self(2);
3323
3324    /// buffer offset is invalid
3325    pub const INVALID_OFFSET: Self = Self(3);
3326
3327    /// surface was destroyed before its role object
3328    pub const DEFUNCT_ROLE_OBJECT: Self = Self(4);
3329}
3330
3331impl Debug for WlSurfaceError {
3332    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
3333        let name = match *self {
3334            Self::INVALID_SCALE => "INVALID_SCALE",
3335            Self::INVALID_TRANSFORM => "INVALID_TRANSFORM",
3336            Self::INVALID_SIZE => "INVALID_SIZE",
3337            Self::INVALID_OFFSET => "INVALID_OFFSET",
3338            Self::DEFUNCT_ROLE_OBJECT => "DEFUNCT_ROLE_OBJECT",
3339            _ => return Debug::fmt(&self.0, f),
3340        };
3341        f.write_str(name)
3342    }
3343}