wl_proxy/protocols/wayland/
wl_subcompositor.rs

1//! sub-surface compositing
2//!
3//! The global interface exposing sub-surface compositing capabilities.
4//! A wl_surface, that has sub-surfaces associated, is called the
5//! parent surface. Sub-surfaces can be arbitrarily nested and create
6//! a tree of sub-surfaces.
7//!
8//! The root surface in a tree of sub-surfaces is the main
9//! surface. The main surface cannot be a sub-surface, because
10//! sub-surfaces must always have a parent.
11//!
12//! A main surface with its sub-surfaces forms a (compound) window.
13//! For window management purposes, this set of wl_surface objects is
14//! to be considered as a single window, and it should also behave as
15//! such.
16//!
17//! The aim of sub-surfaces is to offload some of the compositing work
18//! within a window from clients to the compositor. A prime example is
19//! a video player with decorations and video in separate wl_surface
20//! objects. This should allow the compositor to pass YUV video buffer
21//! processing to dedicated overlay hardware when possible.
22
23use crate::protocol_helpers::prelude::*;
24use super::super::all_types::*;
25
26/// A wl_subcompositor object.
27///
28/// See the documentation of [the module][self] for the interface description.
29pub struct WlSubcompositor {
30    core: ObjectCore,
31    handler: HandlerHolder<dyn WlSubcompositorHandler>,
32}
33
34struct DefaultHandler;
35
36impl WlSubcompositorHandler for DefaultHandler { }
37
38impl ConcreteObject for WlSubcompositor {
39    const XML_VERSION: u32 = 1;
40    const INTERFACE: ObjectInterface = ObjectInterface::WlSubcompositor;
41    const INTERFACE_NAME: &str = "wl_subcompositor";
42}
43
44impl WlSubcompositor {
45    /// Sets a new handler.
46    pub fn set_handler(&self, handler: impl WlSubcompositorHandler) {
47        self.set_boxed_handler(Box::new(handler));
48    }
49
50    /// Sets a new, already boxed handler.
51    pub fn set_boxed_handler(&self, handler: Box<dyn WlSubcompositorHandler>) {
52        if self.core.state.destroyed.get() {
53            return;
54        }
55        self.handler.set(Some(handler));
56    }
57}
58
59impl Debug for WlSubcompositor {
60    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61        f.debug_struct("WlSubcompositor")
62            .field("server_obj_id", &self.core.server_obj_id.get())
63            .field("client_id", &self.core.client_id.get())
64            .field("client_obj_id", &self.core.client_obj_id.get())
65            .finish()
66    }
67}
68
69impl WlSubcompositor {
70    /// Since when the destroy message is available.
71    pub const MSG__DESTROY__SINCE: u32 = 1;
72
73    /// unbind from the subcompositor interface
74    ///
75    /// Informs the server that the client will not be using this
76    /// protocol object anymore. This does not affect any other
77    /// objects, wl_subsurface objects included.
78    #[inline]
79    pub fn try_send_destroy(
80        &self,
81    ) -> Result<(), ObjectError> {
82        let core = self.core();
83        let Some(id) = core.server_obj_id.get() else {
84            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
85        };
86        #[cfg(feature = "logging")]
87        if self.core.state.log {
88            #[cold]
89            fn log(state: &State, id: u32) {
90                let (millis, micros) = time_since_epoch();
91                let prefix = &state.log_prefix;
92                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_subcompositor#{}.destroy()\n", id);
93                state.log(args);
94            }
95            log(&self.core.state, id);
96        }
97        let Some(endpoint) = &self.core.state.server else {
98            return Ok(());
99        };
100        if !endpoint.flush_queued.replace(true) {
101            self.core.state.add_flushable_endpoint(endpoint, None);
102        }
103        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
104        let outgoing = &mut *outgoing_ref;
105        let mut fmt = outgoing.formatter();
106        fmt.words([
107            id,
108            0,
109        ]);
110        self.core.handle_server_destroy();
111        Ok(())
112    }
113
114    /// unbind from the subcompositor interface
115    ///
116    /// Informs the server that the client will not be using this
117    /// protocol object anymore. This does not affect any other
118    /// objects, wl_subsurface objects included.
119    #[inline]
120    pub fn send_destroy(
121        &self,
122    ) {
123        let res = self.try_send_destroy(
124        );
125        if let Err(e) = res {
126            log_send("wl_subcompositor.destroy", &e);
127        }
128    }
129
130    /// Since when the get_subsurface message is available.
131    pub const MSG__GET_SUBSURFACE__SINCE: u32 = 1;
132
133    /// give a surface the role sub-surface
134    ///
135    /// Create a sub-surface interface for the given surface, and
136    /// associate it with the given parent surface. This turns a
137    /// plain wl_surface into a sub-surface.
138    ///
139    /// The to-be sub-surface must not already have another role, and it
140    /// must not have an existing wl_subsurface object. Otherwise the
141    /// bad_surface protocol error is raised.
142    ///
143    /// Adding sub-surfaces to a parent is a double-buffered operation on the
144    /// parent (see wl_surface.commit). The effect of adding a sub-surface
145    /// becomes visible on the next time the state of the parent surface is
146    /// applied.
147    ///
148    /// The parent surface must not be one of the child surface's descendants,
149    /// and the parent must be different from the child surface, otherwise the
150    /// bad_parent protocol error is raised.
151    ///
152    /// This request modifies the behaviour of wl_surface.commit request on
153    /// the sub-surface, see the documentation on wl_subsurface interface.
154    ///
155    /// # Arguments
156    ///
157    /// - `id`: the new sub-surface object ID
158    /// - `surface`: the surface to be turned into a sub-surface
159    /// - `parent`: the parent surface
160    #[inline]
161    pub fn try_send_get_subsurface(
162        &self,
163        id: &Rc<WlSubsurface>,
164        surface: &Rc<WlSurface>,
165        parent: &Rc<WlSurface>,
166    ) -> Result<(), ObjectError> {
167        let (
168            arg0,
169            arg1,
170            arg2,
171        ) = (
172            id,
173            surface,
174            parent,
175        );
176        let arg0_obj = arg0;
177        let arg0 = arg0_obj.core();
178        let arg1 = arg1.core();
179        let arg2 = arg2.core();
180        let core = self.core();
181        let Some(id) = core.server_obj_id.get() else {
182            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
183        };
184        let arg1_id = match arg1.server_obj_id.get() {
185            None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("surface"))),
186            Some(id) => id,
187        };
188        let arg2_id = match arg2.server_obj_id.get() {
189            None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("parent"))),
190            Some(id) => id,
191        };
192        arg0.generate_server_id(arg0_obj.clone())
193            .map_err(|e| ObjectError(ObjectErrorKind::GenerateServerId("id", e)))?;
194        let arg0_id = arg0.server_obj_id.get().unwrap_or(0);
195        #[cfg(feature = "logging")]
196        if self.core.state.log {
197            #[cold]
198            fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: u32) {
199                let (millis, micros) = time_since_epoch();
200                let prefix = &state.log_prefix;
201                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_subcompositor#{}.get_subsurface(id: wl_subsurface#{}, surface: wl_surface#{}, parent: wl_surface#{})\n", id, arg0, arg1, arg2);
202                state.log(args);
203            }
204            log(&self.core.state, id, arg0_id, arg1_id, arg2_id);
205        }
206        let Some(endpoint) = &self.core.state.server else {
207            return Ok(());
208        };
209        if !endpoint.flush_queued.replace(true) {
210            self.core.state.add_flushable_endpoint(endpoint, None);
211        }
212        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
213        let outgoing = &mut *outgoing_ref;
214        let mut fmt = outgoing.formatter();
215        fmt.words([
216            id,
217            1,
218            arg0_id,
219            arg1_id,
220            arg2_id,
221        ]);
222        Ok(())
223    }
224
225    /// give a surface the role sub-surface
226    ///
227    /// Create a sub-surface interface for the given surface, and
228    /// associate it with the given parent surface. This turns a
229    /// plain wl_surface into a sub-surface.
230    ///
231    /// The to-be sub-surface must not already have another role, and it
232    /// must not have an existing wl_subsurface object. Otherwise the
233    /// bad_surface protocol error is raised.
234    ///
235    /// Adding sub-surfaces to a parent is a double-buffered operation on the
236    /// parent (see wl_surface.commit). The effect of adding a sub-surface
237    /// becomes visible on the next time the state of the parent surface is
238    /// applied.
239    ///
240    /// The parent surface must not be one of the child surface's descendants,
241    /// and the parent must be different from the child surface, otherwise the
242    /// bad_parent protocol error is raised.
243    ///
244    /// This request modifies the behaviour of wl_surface.commit request on
245    /// the sub-surface, see the documentation on wl_subsurface interface.
246    ///
247    /// # Arguments
248    ///
249    /// - `id`: the new sub-surface object ID
250    /// - `surface`: the surface to be turned into a sub-surface
251    /// - `parent`: the parent surface
252    #[inline]
253    pub fn send_get_subsurface(
254        &self,
255        id: &Rc<WlSubsurface>,
256        surface: &Rc<WlSurface>,
257        parent: &Rc<WlSurface>,
258    ) {
259        let res = self.try_send_get_subsurface(
260            id,
261            surface,
262            parent,
263        );
264        if let Err(e) = res {
265            log_send("wl_subcompositor.get_subsurface", &e);
266        }
267    }
268
269    /// give a surface the role sub-surface
270    ///
271    /// Create a sub-surface interface for the given surface, and
272    /// associate it with the given parent surface. This turns a
273    /// plain wl_surface into a sub-surface.
274    ///
275    /// The to-be sub-surface must not already have another role, and it
276    /// must not have an existing wl_subsurface object. Otherwise the
277    /// bad_surface protocol error is raised.
278    ///
279    /// Adding sub-surfaces to a parent is a double-buffered operation on the
280    /// parent (see wl_surface.commit). The effect of adding a sub-surface
281    /// becomes visible on the next time the state of the parent surface is
282    /// applied.
283    ///
284    /// The parent surface must not be one of the child surface's descendants,
285    /// and the parent must be different from the child surface, otherwise the
286    /// bad_parent protocol error is raised.
287    ///
288    /// This request modifies the behaviour of wl_surface.commit request on
289    /// the sub-surface, see the documentation on wl_subsurface interface.
290    ///
291    /// # Arguments
292    ///
293    /// - `surface`: the surface to be turned into a sub-surface
294    /// - `parent`: the parent surface
295    #[inline]
296    pub fn new_try_send_get_subsurface(
297        &self,
298        surface: &Rc<WlSurface>,
299        parent: &Rc<WlSurface>,
300    ) -> Result<Rc<WlSubsurface>, ObjectError> {
301        let id = self.core.create_child();
302        self.try_send_get_subsurface(
303            &id,
304            surface,
305            parent,
306        )?;
307        Ok(id)
308    }
309
310    /// give a surface the role sub-surface
311    ///
312    /// Create a sub-surface interface for the given surface, and
313    /// associate it with the given parent surface. This turns a
314    /// plain wl_surface into a sub-surface.
315    ///
316    /// The to-be sub-surface must not already have another role, and it
317    /// must not have an existing wl_subsurface object. Otherwise the
318    /// bad_surface protocol error is raised.
319    ///
320    /// Adding sub-surfaces to a parent is a double-buffered operation on the
321    /// parent (see wl_surface.commit). The effect of adding a sub-surface
322    /// becomes visible on the next time the state of the parent surface is
323    /// applied.
324    ///
325    /// The parent surface must not be one of the child surface's descendants,
326    /// and the parent must be different from the child surface, otherwise the
327    /// bad_parent protocol error is raised.
328    ///
329    /// This request modifies the behaviour of wl_surface.commit request on
330    /// the sub-surface, see the documentation on wl_subsurface interface.
331    ///
332    /// # Arguments
333    ///
334    /// - `surface`: the surface to be turned into a sub-surface
335    /// - `parent`: the parent surface
336    #[inline]
337    pub fn new_send_get_subsurface(
338        &self,
339        surface: &Rc<WlSurface>,
340        parent: &Rc<WlSurface>,
341    ) -> Rc<WlSubsurface> {
342        let id = self.core.create_child();
343        self.send_get_subsurface(
344            &id,
345            surface,
346            parent,
347        );
348        id
349    }
350}
351
352/// A message handler for [`WlSubcompositor`] proxies.
353pub trait WlSubcompositorHandler: Any {
354    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
355    ///
356    /// The default handler forwards the event to the client, if any.
357    #[inline]
358    fn delete_id(&mut self, slf: &Rc<WlSubcompositor>) {
359        slf.core.delete_id();
360    }
361
362    /// unbind from the subcompositor interface
363    ///
364    /// Informs the server that the client will not be using this
365    /// protocol object anymore. This does not affect any other
366    /// objects, wl_subsurface objects included.
367    #[inline]
368    fn handle_destroy(
369        &mut self,
370        slf: &Rc<WlSubcompositor>,
371    ) {
372        if !slf.core.forward_to_server.get() {
373            return;
374        }
375        let res = slf.try_send_destroy(
376        );
377        if let Err(e) = res {
378            log_forward("wl_subcompositor.destroy", &e);
379        }
380    }
381
382    /// give a surface the role sub-surface
383    ///
384    /// Create a sub-surface interface for the given surface, and
385    /// associate it with the given parent surface. This turns a
386    /// plain wl_surface into a sub-surface.
387    ///
388    /// The to-be sub-surface must not already have another role, and it
389    /// must not have an existing wl_subsurface object. Otherwise the
390    /// bad_surface protocol error is raised.
391    ///
392    /// Adding sub-surfaces to a parent is a double-buffered operation on the
393    /// parent (see wl_surface.commit). The effect of adding a sub-surface
394    /// becomes visible on the next time the state of the parent surface is
395    /// applied.
396    ///
397    /// The parent surface must not be one of the child surface's descendants,
398    /// and the parent must be different from the child surface, otherwise the
399    /// bad_parent protocol error is raised.
400    ///
401    /// This request modifies the behaviour of wl_surface.commit request on
402    /// the sub-surface, see the documentation on wl_subsurface interface.
403    ///
404    /// # Arguments
405    ///
406    /// - `id`: the new sub-surface object ID
407    /// - `surface`: the surface to be turned into a sub-surface
408    /// - `parent`: the parent surface
409    ///
410    /// All borrowed proxies passed to this function are guaranteed to be
411    /// immutable and non-null.
412    #[inline]
413    fn handle_get_subsurface(
414        &mut self,
415        slf: &Rc<WlSubcompositor>,
416        id: &Rc<WlSubsurface>,
417        surface: &Rc<WlSurface>,
418        parent: &Rc<WlSurface>,
419    ) {
420        if !slf.core.forward_to_server.get() {
421            return;
422        }
423        let res = slf.try_send_get_subsurface(
424            id,
425            surface,
426            parent,
427        );
428        if let Err(e) = res {
429            log_forward("wl_subcompositor.get_subsurface", &e);
430        }
431    }
432}
433
434impl ObjectPrivate for WlSubcompositor {
435    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
436        Rc::<Self>::new_cyclic(|slf| Self {
437            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlSubcompositor, version),
438            handler: Default::default(),
439        })
440    }
441
442    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
443        let Some(mut handler) = self.handler.try_borrow_mut() else {
444            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
445        };
446        if let Some(handler) = &mut *handler {
447            handler.delete_id(&self);
448        } else {
449            self.core.delete_id();
450        }
451        Ok(())
452    }
453
454    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
455        let Some(mut handler) = self.handler.try_borrow_mut() else {
456            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
457        };
458        let handler = &mut *handler;
459        match msg[1] & 0xffff {
460            0 => {
461                if msg.len() != 2 {
462                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
463                }
464                #[cfg(feature = "logging")]
465                if self.core.state.log {
466                    #[cold]
467                    fn log(state: &State, client_id: u64, id: u32) {
468                        let (millis, micros) = time_since_epoch();
469                        let prefix = &state.log_prefix;
470                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subcompositor#{}.destroy()\n", client_id, id);
471                        state.log(args);
472                    }
473                    log(&self.core.state, client.endpoint.id, msg[0]);
474                }
475                self.core.handle_client_destroy();
476                if let Some(handler) = handler {
477                    (**handler).handle_destroy(&self);
478                } else {
479                    DefaultHandler.handle_destroy(&self);
480                }
481            }
482            1 => {
483                let [
484                    arg0,
485                    arg1,
486                    arg2,
487                ] = msg[2..] else {
488                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
489                };
490                #[cfg(feature = "logging")]
491                if self.core.state.log {
492                    #[cold]
493                    fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: u32) {
494                        let (millis, micros) = time_since_epoch();
495                        let prefix = &state.log_prefix;
496                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_subcompositor#{}.get_subsurface(id: wl_subsurface#{}, surface: wl_surface#{}, parent: wl_surface#{})\n", client_id, id, arg0, arg1, arg2);
497                        state.log(args);
498                    }
499                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2);
500                }
501                let arg0_id = arg0;
502                let arg0 = WlSubsurface::new(&self.core.state, self.core.version);
503                arg0.core().set_client_id(client, arg0_id, arg0.clone())
504                    .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg0_id, "id", e)))?;
505                let arg1_id = arg1;
506                let Some(arg1) = client.endpoint.lookup(arg1_id) else {
507                    return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg1_id)));
508                };
509                let Ok(arg1) = (arg1 as Rc<dyn Any>).downcast::<WlSurface>() else {
510                    let o = client.endpoint.lookup(arg1_id).unwrap();
511                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("surface", o.core().interface, ObjectInterface::WlSurface)));
512                };
513                let arg2_id = arg2;
514                let Some(arg2) = client.endpoint.lookup(arg2_id) else {
515                    return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg2_id)));
516                };
517                let Ok(arg2) = (arg2 as Rc<dyn Any>).downcast::<WlSurface>() else {
518                    let o = client.endpoint.lookup(arg2_id).unwrap();
519                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("parent", o.core().interface, ObjectInterface::WlSurface)));
520                };
521                let arg0 = &arg0;
522                let arg1 = &arg1;
523                let arg2 = &arg2;
524                if let Some(handler) = handler {
525                    (**handler).handle_get_subsurface(&self, arg0, arg1, arg2);
526                } else {
527                    DefaultHandler.handle_get_subsurface(&self, arg0, arg1, arg2);
528                }
529            }
530            n => {
531                let _ = client;
532                let _ = msg;
533                let _ = fds;
534                let _ = handler;
535                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
536            }
537        }
538        Ok(())
539    }
540
541    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
542        let Some(mut handler) = self.handler.try_borrow_mut() else {
543            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
544        };
545        let handler = &mut *handler;
546        match msg[1] & 0xffff {
547            n => {
548                let _ = server;
549                let _ = msg;
550                let _ = fds;
551                let _ = handler;
552                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
553            }
554        }
555    }
556
557    fn get_request_name(&self, id: u32) -> Option<&'static str> {
558        let name = match id {
559            0 => "destroy",
560            1 => "get_subsurface",
561            _ => return None,
562        };
563        Some(name)
564    }
565
566    fn get_event_name(&self, id: u32) -> Option<&'static str> {
567        let _ = id;
568        None
569    }
570}
571
572impl Object for WlSubcompositor {
573    fn core(&self) -> &ObjectCore {
574        &self.core
575    }
576
577    fn unset_handler(&self) {
578        self.handler.set(None);
579    }
580
581    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
582        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
583        if borrowed.is_none() {
584            return Err(HandlerAccessError::NoHandler);
585        }
586        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
587    }
588
589    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
590        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
591        if borrowed.is_none() {
592            return Err(HandlerAccessError::NoHandler);
593        }
594        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
595    }
596}
597
598impl WlSubcompositor {
599    /// Since when the error.bad_surface enum variant is available.
600    pub const ENM__ERROR_BAD_SURFACE__SINCE: u32 = 1;
601    /// Since when the error.bad_parent enum variant is available.
602    pub const ENM__ERROR_BAD_PARENT__SINCE: u32 = 1;
603}
604
605#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
606pub struct WlSubcompositorError(pub u32);
607
608impl WlSubcompositorError {
609    /// the to-be sub-surface is invalid
610    pub const BAD_SURFACE: Self = Self(0);
611
612    /// the to-be sub-surface parent is invalid
613    pub const BAD_PARENT: Self = Self(1);
614}
615
616impl Debug for WlSubcompositorError {
617    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
618        let name = match *self {
619            Self::BAD_SURFACE => "BAD_SURFACE",
620            Self::BAD_PARENT => "BAD_PARENT",
621            _ => return Debug::fmt(&self.0, f),
622        };
623        f.write_str(name)
624    }
625}