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