Skip to main content

wl_proxy/protocols/wayland/
wl_subsurface.rs

1//! sub-surface interface to a wl_surface
2//!
3//! An additional interface to a wl_surface object, which has been
4//! made a sub-surface. A sub-surface has one parent surface. A
5//! sub-surface's size and position are not limited to that of the parent.
6//! Particularly, a sub-surface is not automatically clipped to its
7//! parent's area.
8//!
9//! A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
10//! and the parent surface is mapped. The order of which one happens
11//! first is irrelevant. A sub-surface is hidden if the parent becomes
12//! hidden, or if a NULL wl_buffer is applied. These rules apply
13//! recursively through the tree of surfaces.
14//!
15//! A sub-surface can be in one of two modes. The possible modes are
16//! synchronized and desynchronized, see methods wl_subsurface.set_sync and
17//! wl_subsurface.set_desync.
18//!
19//! The main surface can be thought to be always in desynchronized mode,
20//! since it does not have a parent in the sub-surfaces sense.
21//!
22//! Even if a sub-surface is in desynchronized mode, it will behave as
23//! in synchronized mode, if its parent surface behaves as in
24//! synchronized mode. This rule is applied recursively throughout the
25//! tree of surfaces. This means, that one can set a sub-surface into
26//! synchronized mode, and then assume that all its child and grand-child
27//! sub-surfaces are synchronized, too, without explicitly setting them.
28//!
29//! If a surface behaves as in synchronized mode, it is effectively
30//! synchronized, otherwise it is effectively desynchronized.
31//!
32//! A sub-surface is initially in the synchronized mode.
33//!
34//! The wl_subsurface interface has requests which modify double-buffered
35//! state of the parent surface (wl_subsurface.set_position, .place_above and
36//! .place_below).
37//!
38//! Destroying a sub-surface takes effect immediately. If you need to
39//! synchronize the removal of a sub-surface to the parent surface update,
40//! unmap the sub-surface first by attaching a NULL wl_buffer, update parent,
41//! and then destroy the sub-surface.
42//!
43//! If the parent wl_surface object is destroyed, the sub-surface is
44//! unmapped.
45//!
46//! A sub-surface never has the keyboard focus of any seat.
47//!
48//! The wl_surface.offset request is ignored: clients must use set_position
49//! instead to move the sub-surface.
50
51use crate::protocol_helpers::prelude::*;
52use super::super::all_types::*;
53
54/// A wl_subsurface object.
55///
56/// See the documentation of [the module][self] for the interface description.
57pub struct WlSubsurface {
58    core: ObjectCore,
59    handler: HandlerHolder<dyn WlSubsurfaceHandler>,
60}
61
62struct DefaultHandler;
63
64impl WlSubsurfaceHandler for DefaultHandler { }
65
66impl ConcreteObject for WlSubsurface {
67    const XML_VERSION: u32 = 1;
68    const INTERFACE: ObjectInterface = ObjectInterface::WlSubsurface;
69    const INTERFACE_NAME: &str = "wl_subsurface";
70}
71
72impl WlSubsurface {
73    /// Sets a new handler.
74    pub fn set_handler(&self, handler: impl WlSubsurfaceHandler) {
75        self.set_boxed_handler(Box::new(handler));
76    }
77
78    /// Sets a new, already boxed handler.
79    pub fn set_boxed_handler(&self, handler: Box<dyn WlSubsurfaceHandler>) {
80        if self.core.state.destroyed.get() {
81            return;
82        }
83        self.handler.set(Some(handler));
84    }
85}
86
87impl Debug for WlSubsurface {
88    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
89        f.debug_struct("WlSubsurface")
90            .field("server_obj_id", &self.core.server_obj_id.get())
91            .field("client_id", &self.core.client_id.get())
92            .field("client_obj_id", &self.core.client_obj_id.get())
93            .finish()
94    }
95}
96
97impl WlSubsurface {
98    /// Since when the destroy message is available.
99    pub const MSG__DESTROY__SINCE: u32 = 1;
100
101    /// remove sub-surface interface
102    ///
103    /// The sub-surface interface is removed from the wl_surface object
104    /// that was turned into a sub-surface with a
105    /// wl_subcompositor.get_subsurface request. The wl_surface's association
106    /// to the parent is deleted. The wl_surface is unmapped immediately.
107    #[inline]
108    pub fn try_send_destroy(
109        &self,
110    ) -> Result<(), ObjectError> {
111        let core = self.core();
112        let Some(id) = core.server_obj_id.get() else {
113            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
114        };
115        #[cfg(feature = "logging")]
116        if self.core.state.log {
117            #[cold]
118            fn log(state: &State, id: u32) {
119                let (millis, micros) = time_since_epoch();
120                let prefix = &state.log_prefix;
121                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_subsurface#{}.destroy()\n", id);
122                state.log(args);
123            }
124            log(&self.core.state, id);
125        }
126        let Some(endpoint) = &self.core.state.server else {
127            return Ok(());
128        };
129        if !endpoint.flush_queued.replace(true) {
130            self.core.state.add_flushable_endpoint(endpoint, None);
131        }
132        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
133        let outgoing = &mut *outgoing_ref;
134        let mut fmt = outgoing.formatter();
135        fmt.words([
136            id,
137            0,
138        ]);
139        self.core.handle_server_destroy();
140        Ok(())
141    }
142
143    /// remove sub-surface interface
144    ///
145    /// The sub-surface interface is removed from the wl_surface object
146    /// that was turned into a sub-surface with a
147    /// wl_subcompositor.get_subsurface request. The wl_surface's association
148    /// to the parent is deleted. The wl_surface is unmapped immediately.
149    #[inline]
150    pub fn send_destroy(
151        &self,
152    ) {
153        let res = self.try_send_destroy(
154        );
155        if let Err(e) = res {
156            log_send("wl_subsurface.destroy", &e);
157        }
158    }
159
160    /// Since when the set_position message is available.
161    pub const MSG__SET_POSITION__SINCE: u32 = 1;
162
163    /// reposition the sub-surface
164    ///
165    /// This sets the position of the sub-surface, relative to the parent
166    /// surface.
167    ///
168    /// The sub-surface will be moved so that its origin (top left
169    /// corner pixel) will be at the location x, y of the parent surface
170    /// coordinate system. The coordinates are not restricted to the parent
171    /// surface area. Negative values are allowed.
172    ///
173    /// The initial position is 0, 0.
174    ///
175    /// Position is double-buffered state on the parent surface, see
176    /// wl_subsurface and wl_surface.commit for more information.
177    ///
178    /// # Arguments
179    ///
180    /// - `x`: x coordinate in the parent surface
181    /// - `y`: y coordinate in the parent surface
182    #[inline]
183    pub fn try_send_set_position(
184        &self,
185        x: i32,
186        y: i32,
187    ) -> Result<(), ObjectError> {
188        let (
189            arg0,
190            arg1,
191        ) = (
192            x,
193            y,
194        );
195        let core = self.core();
196        let Some(id) = core.server_obj_id.get() else {
197            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
198        };
199        #[cfg(feature = "logging")]
200        if self.core.state.log {
201            #[cold]
202            fn log(state: &State, id: u32, arg0: i32, arg1: i32) {
203                let (millis, micros) = time_since_epoch();
204                let prefix = &state.log_prefix;
205                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_subsurface#{}.set_position(x: {}, y: {})\n", id, arg0, arg1);
206                state.log(args);
207            }
208            log(&self.core.state, id, arg0, arg1);
209        }
210        let Some(endpoint) = &self.core.state.server else {
211            return Ok(());
212        };
213        if !endpoint.flush_queued.replace(true) {
214            self.core.state.add_flushable_endpoint(endpoint, None);
215        }
216        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
217        let outgoing = &mut *outgoing_ref;
218        let mut fmt = outgoing.formatter();
219        fmt.words([
220            id,
221            1,
222            arg0 as u32,
223            arg1 as u32,
224        ]);
225        Ok(())
226    }
227
228    /// reposition the sub-surface
229    ///
230    /// This sets the position of the sub-surface, relative to the parent
231    /// surface.
232    ///
233    /// The sub-surface will be moved so that its origin (top left
234    /// corner pixel) will be at the location x, y of the parent surface
235    /// coordinate system. The coordinates are not restricted to the parent
236    /// surface area. Negative values are allowed.
237    ///
238    /// The initial position is 0, 0.
239    ///
240    /// Position is double-buffered state on the parent surface, see
241    /// wl_subsurface and wl_surface.commit for more information.
242    ///
243    /// # Arguments
244    ///
245    /// - `x`: x coordinate in the parent surface
246    /// - `y`: y coordinate in the parent surface
247    #[inline]
248    pub fn send_set_position(
249        &self,
250        x: i32,
251        y: i32,
252    ) {
253        let res = self.try_send_set_position(
254            x,
255            y,
256        );
257        if let Err(e) = res {
258            log_send("wl_subsurface.set_position", &e);
259        }
260    }
261
262    /// Since when the place_above message is available.
263    pub const MSG__PLACE_ABOVE__SINCE: u32 = 1;
264
265    /// restack the sub-surface
266    ///
267    /// This sub-surface is taken from the stack, and put back just
268    /// above the reference surface, changing the z-order of the sub-surfaces.
269    /// The reference surface must be one of the sibling surfaces, or the
270    /// parent surface. Using any other surface, including this sub-surface,
271    /// will cause a protocol error.
272    ///
273    /// A new sub-surface is initially added as the top-most in the stack
274    /// of its siblings and parent.
275    ///
276    /// Z-order is double-buffered state on the parent surface, see
277    /// wl_subsurface and wl_surface.commit for more information.
278    ///
279    /// # Arguments
280    ///
281    /// - `sibling`: the reference surface
282    #[inline]
283    pub fn try_send_place_above(
284        &self,
285        sibling: &Rc<WlSurface>,
286    ) -> Result<(), ObjectError> {
287        let (
288            arg0,
289        ) = (
290            sibling,
291        );
292        let arg0 = arg0.core();
293        let core = self.core();
294        let Some(id) = core.server_obj_id.get() else {
295            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
296        };
297        let arg0_id = match arg0.server_obj_id.get() {
298            None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("sibling"))),
299            Some(id) => id,
300        };
301        #[cfg(feature = "logging")]
302        if self.core.state.log {
303            #[cold]
304            fn log(state: &State, id: u32, arg0: u32) {
305                let (millis, micros) = time_since_epoch();
306                let prefix = &state.log_prefix;
307                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_subsurface#{}.place_above(sibling: wl_surface#{})\n", id, arg0);
308                state.log(args);
309            }
310            log(&self.core.state, id, arg0_id);
311        }
312        let Some(endpoint) = &self.core.state.server else {
313            return Ok(());
314        };
315        if !endpoint.flush_queued.replace(true) {
316            self.core.state.add_flushable_endpoint(endpoint, None);
317        }
318        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
319        let outgoing = &mut *outgoing_ref;
320        let mut fmt = outgoing.formatter();
321        fmt.words([
322            id,
323            2,
324            arg0_id,
325        ]);
326        Ok(())
327    }
328
329    /// restack the sub-surface
330    ///
331    /// This sub-surface is taken from the stack, and put back just
332    /// above the reference surface, changing the z-order of the sub-surfaces.
333    /// The reference surface must be one of the sibling surfaces, or the
334    /// parent surface. Using any other surface, including this sub-surface,
335    /// will cause a protocol error.
336    ///
337    /// A new sub-surface is initially added as the top-most in the stack
338    /// of its siblings and parent.
339    ///
340    /// Z-order is double-buffered state on the parent surface, see
341    /// wl_subsurface and wl_surface.commit for more information.
342    ///
343    /// # Arguments
344    ///
345    /// - `sibling`: the reference surface
346    #[inline]
347    pub fn send_place_above(
348        &self,
349        sibling: &Rc<WlSurface>,
350    ) {
351        let res = self.try_send_place_above(
352            sibling,
353        );
354        if let Err(e) = res {
355            log_send("wl_subsurface.place_above", &e);
356        }
357    }
358
359    /// Since when the place_below message is available.
360    pub const MSG__PLACE_BELOW__SINCE: u32 = 1;
361
362    /// restack the sub-surface
363    ///
364    /// The sub-surface is placed just below the reference surface.
365    ///
366    /// See wl_subsurface.place_above.
367    ///
368    /// # Arguments
369    ///
370    /// - `sibling`: the reference surface
371    #[inline]
372    pub fn try_send_place_below(
373        &self,
374        sibling: &Rc<WlSurface>,
375    ) -> Result<(), ObjectError> {
376        let (
377            arg0,
378        ) = (
379            sibling,
380        );
381        let arg0 = arg0.core();
382        let core = self.core();
383        let Some(id) = core.server_obj_id.get() else {
384            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
385        };
386        let arg0_id = match arg0.server_obj_id.get() {
387            None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("sibling"))),
388            Some(id) => id,
389        };
390        #[cfg(feature = "logging")]
391        if self.core.state.log {
392            #[cold]
393            fn log(state: &State, id: u32, arg0: u32) {
394                let (millis, micros) = time_since_epoch();
395                let prefix = &state.log_prefix;
396                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_subsurface#{}.place_below(sibling: wl_surface#{})\n", id, arg0);
397                state.log(args);
398            }
399            log(&self.core.state, id, arg0_id);
400        }
401        let Some(endpoint) = &self.core.state.server else {
402            return Ok(());
403        };
404        if !endpoint.flush_queued.replace(true) {
405            self.core.state.add_flushable_endpoint(endpoint, None);
406        }
407        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
408        let outgoing = &mut *outgoing_ref;
409        let mut fmt = outgoing.formatter();
410        fmt.words([
411            id,
412            3,
413            arg0_id,
414        ]);
415        Ok(())
416    }
417
418    /// restack the sub-surface
419    ///
420    /// The sub-surface is placed just below the reference surface.
421    ///
422    /// See wl_subsurface.place_above.
423    ///
424    /// # Arguments
425    ///
426    /// - `sibling`: the reference surface
427    #[inline]
428    pub fn send_place_below(
429        &self,
430        sibling: &Rc<WlSurface>,
431    ) {
432        let res = self.try_send_place_below(
433            sibling,
434        );
435        if let Err(e) = res {
436            log_send("wl_subsurface.place_below", &e);
437        }
438    }
439
440    /// Since when the set_sync message is available.
441    pub const MSG__SET_SYNC__SINCE: u32 = 1;
442
443    /// set sub-surface to synchronized mode
444    ///
445    /// Change the commit behaviour of the sub-surface to synchronized
446    /// mode.
447    ///
448    /// See wl_subsurface and wl_surface.commit for more information.
449    #[inline]
450    pub fn try_send_set_sync(
451        &self,
452    ) -> Result<(), ObjectError> {
453        let core = self.core();
454        let Some(id) = core.server_obj_id.get() else {
455            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
456        };
457        #[cfg(feature = "logging")]
458        if self.core.state.log {
459            #[cold]
460            fn log(state: &State, id: u32) {
461                let (millis, micros) = time_since_epoch();
462                let prefix = &state.log_prefix;
463                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_subsurface#{}.set_sync()\n", id);
464                state.log(args);
465            }
466            log(&self.core.state, id);
467        }
468        let Some(endpoint) = &self.core.state.server else {
469            return Ok(());
470        };
471        if !endpoint.flush_queued.replace(true) {
472            self.core.state.add_flushable_endpoint(endpoint, None);
473        }
474        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
475        let outgoing = &mut *outgoing_ref;
476        let mut fmt = outgoing.formatter();
477        fmt.words([
478            id,
479            4,
480        ]);
481        Ok(())
482    }
483
484    /// set sub-surface to synchronized mode
485    ///
486    /// Change the commit behaviour of the sub-surface to synchronized
487    /// mode.
488    ///
489    /// See wl_subsurface and wl_surface.commit for more information.
490    #[inline]
491    pub fn send_set_sync(
492        &self,
493    ) {
494        let res = self.try_send_set_sync(
495        );
496        if let Err(e) = res {
497            log_send("wl_subsurface.set_sync", &e);
498        }
499    }
500
501    /// Since when the set_desync message is available.
502    pub const MSG__SET_DESYNC__SINCE: u32 = 1;
503
504    /// set sub-surface to desynchronized mode
505    ///
506    /// Change the commit behaviour of the sub-surface to desynchronized
507    /// mode.
508    ///
509    /// See wl_subsurface and wl_surface.commit for more information.
510    #[inline]
511    pub fn try_send_set_desync(
512        &self,
513    ) -> Result<(), ObjectError> {
514        let core = self.core();
515        let Some(id) = core.server_obj_id.get() else {
516            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
517        };
518        #[cfg(feature = "logging")]
519        if self.core.state.log {
520            #[cold]
521            fn log(state: &State, id: u32) {
522                let (millis, micros) = time_since_epoch();
523                let prefix = &state.log_prefix;
524                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_subsurface#{}.set_desync()\n", id);
525                state.log(args);
526            }
527            log(&self.core.state, id);
528        }
529        let Some(endpoint) = &self.core.state.server else {
530            return Ok(());
531        };
532        if !endpoint.flush_queued.replace(true) {
533            self.core.state.add_flushable_endpoint(endpoint, None);
534        }
535        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
536        let outgoing = &mut *outgoing_ref;
537        let mut fmt = outgoing.formatter();
538        fmt.words([
539            id,
540            5,
541        ]);
542        Ok(())
543    }
544
545    /// set sub-surface to desynchronized mode
546    ///
547    /// Change the commit behaviour of the sub-surface to desynchronized
548    /// mode.
549    ///
550    /// See wl_subsurface and wl_surface.commit for more information.
551    #[inline]
552    pub fn send_set_desync(
553        &self,
554    ) {
555        let res = self.try_send_set_desync(
556        );
557        if let Err(e) = res {
558            log_send("wl_subsurface.set_desync", &e);
559        }
560    }
561}
562
563/// A message handler for [`WlSubsurface`] proxies.
564pub trait WlSubsurfaceHandler: Any {
565    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
566    ///
567    /// The default handler forwards the event to the client, if any.
568    #[inline]
569    fn delete_id(&mut self, slf: &Rc<WlSubsurface>) {
570        slf.core.delete_id();
571    }
572
573    /// remove sub-surface interface
574    ///
575    /// The sub-surface interface is removed from the wl_surface object
576    /// that was turned into a sub-surface with a
577    /// wl_subcompositor.get_subsurface request. The wl_surface's association
578    /// to the parent is deleted. The wl_surface is unmapped immediately.
579    #[inline]
580    fn handle_destroy(
581        &mut self,
582        slf: &Rc<WlSubsurface>,
583    ) {
584        if !slf.core.forward_to_server.get() {
585            return;
586        }
587        let res = slf.try_send_destroy(
588        );
589        if let Err(e) = res {
590            log_forward("wl_subsurface.destroy", &e);
591        }
592    }
593
594    /// reposition the sub-surface
595    ///
596    /// This sets the position of the sub-surface, relative to the parent
597    /// surface.
598    ///
599    /// The sub-surface will be moved so that its origin (top left
600    /// corner pixel) will be at the location x, y of the parent surface
601    /// coordinate system. The coordinates are not restricted to the parent
602    /// surface area. Negative values are allowed.
603    ///
604    /// The initial position is 0, 0.
605    ///
606    /// Position is double-buffered state on the parent surface, see
607    /// wl_subsurface and wl_surface.commit for more information.
608    ///
609    /// # Arguments
610    ///
611    /// - `x`: x coordinate in the parent surface
612    /// - `y`: y coordinate in the parent surface
613    #[inline]
614    fn handle_set_position(
615        &mut self,
616        slf: &Rc<WlSubsurface>,
617        x: i32,
618        y: i32,
619    ) {
620        if !slf.core.forward_to_server.get() {
621            return;
622        }
623        let res = slf.try_send_set_position(
624            x,
625            y,
626        );
627        if let Err(e) = res {
628            log_forward("wl_subsurface.set_position", &e);
629        }
630    }
631
632    /// restack the sub-surface
633    ///
634    /// This sub-surface is taken from the stack, and put back just
635    /// above the reference surface, changing the z-order of the sub-surfaces.
636    /// The reference surface must be one of the sibling surfaces, or the
637    /// parent surface. Using any other surface, including this sub-surface,
638    /// will cause a protocol error.
639    ///
640    /// A new sub-surface is initially added as the top-most in the stack
641    /// of its siblings and parent.
642    ///
643    /// Z-order is double-buffered state on the parent surface, see
644    /// wl_subsurface and wl_surface.commit for more information.
645    ///
646    /// # Arguments
647    ///
648    /// - `sibling`: the reference surface
649    ///
650    /// All borrowed proxies passed to this function are guaranteed to be
651    /// immutable and non-null.
652    #[inline]
653    fn handle_place_above(
654        &mut self,
655        slf: &Rc<WlSubsurface>,
656        sibling: &Rc<WlSurface>,
657    ) {
658        if !slf.core.forward_to_server.get() {
659            return;
660        }
661        let res = slf.try_send_place_above(
662            sibling,
663        );
664        if let Err(e) = res {
665            log_forward("wl_subsurface.place_above", &e);
666        }
667    }
668
669    /// restack the sub-surface
670    ///
671    /// The sub-surface is placed just below the reference surface.
672    ///
673    /// See wl_subsurface.place_above.
674    ///
675    /// # Arguments
676    ///
677    /// - `sibling`: the reference surface
678    ///
679    /// All borrowed proxies passed to this function are guaranteed to be
680    /// immutable and non-null.
681    #[inline]
682    fn handle_place_below(
683        &mut self,
684        slf: &Rc<WlSubsurface>,
685        sibling: &Rc<WlSurface>,
686    ) {
687        if !slf.core.forward_to_server.get() {
688            return;
689        }
690        let res = slf.try_send_place_below(
691            sibling,
692        );
693        if let Err(e) = res {
694            log_forward("wl_subsurface.place_below", &e);
695        }
696    }
697
698    /// set sub-surface to synchronized mode
699    ///
700    /// Change the commit behaviour of the sub-surface to synchronized
701    /// mode.
702    ///
703    /// See wl_subsurface and wl_surface.commit for more information.
704    #[inline]
705    fn handle_set_sync(
706        &mut self,
707        slf: &Rc<WlSubsurface>,
708    ) {
709        if !slf.core.forward_to_server.get() {
710            return;
711        }
712        let res = slf.try_send_set_sync(
713        );
714        if let Err(e) = res {
715            log_forward("wl_subsurface.set_sync", &e);
716        }
717    }
718
719    /// set sub-surface to desynchronized mode
720    ///
721    /// Change the commit behaviour of the sub-surface to desynchronized
722    /// mode.
723    ///
724    /// See wl_subsurface and wl_surface.commit for more information.
725    #[inline]
726    fn handle_set_desync(
727        &mut self,
728        slf: &Rc<WlSubsurface>,
729    ) {
730        if !slf.core.forward_to_server.get() {
731            return;
732        }
733        let res = slf.try_send_set_desync(
734        );
735        if let Err(e) = res {
736            log_forward("wl_subsurface.set_desync", &e);
737        }
738    }
739}
740
741impl ObjectPrivate for WlSubsurface {
742    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
743        Rc::<Self>::new_cyclic(|slf| Self {
744            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlSubsurface, version),
745            handler: Default::default(),
746        })
747    }
748
749    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
750        let Some(mut handler) = self.handler.try_borrow_mut() else {
751            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
752        };
753        if let Some(handler) = &mut *handler {
754            handler.delete_id(&self);
755        } else {
756            self.core.delete_id();
757        }
758        Ok(())
759    }
760
761    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
762        let Some(mut handler) = self.handler.try_borrow_mut() else {
763            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
764        };
765        let handler = &mut *handler;
766        match msg[1] & 0xffff {
767            0 => {
768                if msg.len() != 2 {
769                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
770                }
771                #[cfg(feature = "logging")]
772                if self.core.state.log {
773                    #[cold]
774                    fn log(state: &State, client_id: u64, id: u32) {
775                        let (millis, micros) = time_since_epoch();
776                        let prefix = &state.log_prefix;
777                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.destroy()\n", client_id, id);
778                        state.log(args);
779                    }
780                    log(&self.core.state, client.endpoint.id, msg[0]);
781                }
782                self.core.handle_client_destroy();
783                if let Some(handler) = handler {
784                    (**handler).handle_destroy(&self);
785                } else {
786                    DefaultHandler.handle_destroy(&self);
787                }
788            }
789            1 => {
790                let [
791                    arg0,
792                    arg1,
793                ] = msg[2..] else {
794                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
795                };
796                let arg0 = arg0 as i32;
797                let arg1 = arg1 as i32;
798                #[cfg(feature = "logging")]
799                if self.core.state.log {
800                    #[cold]
801                    fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32) {
802                        let (millis, micros) = time_since_epoch();
803                        let prefix = &state.log_prefix;
804                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.set_position(x: {}, y: {})\n", client_id, id, arg0, arg1);
805                        state.log(args);
806                    }
807                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1);
808                }
809                if let Some(handler) = handler {
810                    (**handler).handle_set_position(&self, arg0, arg1);
811                } else {
812                    DefaultHandler.handle_set_position(&self, arg0, arg1);
813                }
814            }
815            2 => {
816                let [
817                    arg0,
818                ] = msg[2..] else {
819                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
820                };
821                #[cfg(feature = "logging")]
822                if self.core.state.log {
823                    #[cold]
824                    fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
825                        let (millis, micros) = time_since_epoch();
826                        let prefix = &state.log_prefix;
827                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.place_above(sibling: wl_surface#{})\n", client_id, id, arg0);
828                        state.log(args);
829                    }
830                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
831                }
832                let arg0_id = arg0;
833                let Some(arg0) = client.endpoint.lookup(arg0_id) else {
834                    return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
835                };
836                let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlSurface>() else {
837                    let o = client.endpoint.lookup(arg0_id).unwrap();
838                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("sibling", o.core().interface, ObjectInterface::WlSurface)));
839                };
840                let arg0 = &arg0;
841                if let Some(handler) = handler {
842                    (**handler).handle_place_above(&self, arg0);
843                } else {
844                    DefaultHandler.handle_place_above(&self, arg0);
845                }
846            }
847            3 => {
848                let [
849                    arg0,
850                ] = msg[2..] else {
851                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
852                };
853                #[cfg(feature = "logging")]
854                if self.core.state.log {
855                    #[cold]
856                    fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
857                        let (millis, micros) = time_since_epoch();
858                        let prefix = &state.log_prefix;
859                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.place_below(sibling: wl_surface#{})\n", client_id, id, arg0);
860                        state.log(args);
861                    }
862                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
863                }
864                let arg0_id = arg0;
865                let Some(arg0) = client.endpoint.lookup(arg0_id) else {
866                    return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
867                };
868                let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlSurface>() else {
869                    let o = client.endpoint.lookup(arg0_id).unwrap();
870                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("sibling", o.core().interface, ObjectInterface::WlSurface)));
871                };
872                let arg0 = &arg0;
873                if let Some(handler) = handler {
874                    (**handler).handle_place_below(&self, arg0);
875                } else {
876                    DefaultHandler.handle_place_below(&self, arg0);
877                }
878            }
879            4 => {
880                if msg.len() != 2 {
881                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
882                }
883                #[cfg(feature = "logging")]
884                if self.core.state.log {
885                    #[cold]
886                    fn log(state: &State, client_id: u64, id: u32) {
887                        let (millis, micros) = time_since_epoch();
888                        let prefix = &state.log_prefix;
889                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.set_sync()\n", client_id, id);
890                        state.log(args);
891                    }
892                    log(&self.core.state, client.endpoint.id, msg[0]);
893                }
894                if let Some(handler) = handler {
895                    (**handler).handle_set_sync(&self);
896                } else {
897                    DefaultHandler.handle_set_sync(&self);
898                }
899            }
900            5 => {
901                if msg.len() != 2 {
902                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
903                }
904                #[cfg(feature = "logging")]
905                if self.core.state.log {
906                    #[cold]
907                    fn log(state: &State, client_id: u64, id: u32) {
908                        let (millis, micros) = time_since_epoch();
909                        let prefix = &state.log_prefix;
910                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subsurface#{}.set_desync()\n", client_id, id);
911                        state.log(args);
912                    }
913                    log(&self.core.state, client.endpoint.id, msg[0]);
914                }
915                if let Some(handler) = handler {
916                    (**handler).handle_set_desync(&self);
917                } else {
918                    DefaultHandler.handle_set_desync(&self);
919                }
920            }
921            n => {
922                let _ = client;
923                let _ = msg;
924                let _ = fds;
925                let _ = handler;
926                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
927            }
928        }
929        Ok(())
930    }
931
932    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
933        let Some(mut handler) = self.handler.try_borrow_mut() else {
934            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
935        };
936        let handler = &mut *handler;
937        match msg[1] & 0xffff {
938            n => {
939                let _ = server;
940                let _ = msg;
941                let _ = fds;
942                let _ = handler;
943                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
944            }
945        }
946    }
947
948    fn get_request_name(&self, id: u32) -> Option<&'static str> {
949        let name = match id {
950            0 => "destroy",
951            1 => "set_position",
952            2 => "place_above",
953            3 => "place_below",
954            4 => "set_sync",
955            5 => "set_desync",
956            _ => return None,
957        };
958        Some(name)
959    }
960
961    fn get_event_name(&self, id: u32) -> Option<&'static str> {
962        let _ = id;
963        None
964    }
965}
966
967impl Object for WlSubsurface {
968    fn core(&self) -> &ObjectCore {
969        &self.core
970    }
971
972    fn unset_handler(&self) {
973        self.handler.set(None);
974    }
975
976    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
977        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
978        if borrowed.is_none() {
979            return Err(HandlerAccessError::NoHandler);
980        }
981        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
982    }
983
984    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
985        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
986        if borrowed.is_none() {
987            return Err(HandlerAccessError::NoHandler);
988        }
989        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
990    }
991}
992
993impl WlSubsurface {
994    /// Since when the error.bad_surface enum variant is available.
995    pub const ENM__ERROR_BAD_SURFACE__SINCE: u32 = 1;
996}
997
998#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
999pub struct WlSubsurfaceError(pub u32);
1000
1001impl WlSubsurfaceError {
1002    /// wl_surface is not a sibling or the parent
1003    pub const BAD_SURFACE: Self = Self(0);
1004}
1005
1006impl Debug for WlSubsurfaceError {
1007    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1008        let name = match *self {
1009            Self::BAD_SURFACE => "BAD_SURFACE",
1010            _ => return Debug::fmt(&self.0, f),
1011        };
1012        f.write_str(name)
1013    }
1014}