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