smithay_client_toolkit/
subcompositor.rs

1use crate::reexports::client::globals::{BindError, GlobalList};
2use crate::reexports::client::protocol::wl_compositor::WlCompositor;
3use crate::reexports::client::protocol::wl_subcompositor::WlSubcompositor;
4use crate::reexports::client::protocol::wl_subsurface::WlSubsurface;
5use crate::reexports::client::protocol::wl_surface::WlSurface;
6use crate::reexports::client::{Connection, Dispatch, Proxy, QueueHandle};
7
8use crate::compositor::SurfaceData;
9use crate::globals::GlobalData;
10
11#[derive(Debug)]
12pub struct SubcompositorState {
13    compositor: WlCompositor,
14    subcompositor: WlSubcompositor,
15}
16
17impl SubcompositorState {
18    pub fn bind<State>(
19        compositor: WlCompositor,
20        globals: &GlobalList,
21        queue_handle: &QueueHandle<State>,
22    ) -> Result<Self, BindError>
23    where
24        State: Dispatch<WlSubcompositor, GlobalData, State> + 'static,
25    {
26        let subcompositor = globals.bind(queue_handle, 1..=1, GlobalData)?;
27        Ok(SubcompositorState { compositor, subcompositor })
28    }
29
30    pub fn create_subsurface<State>(
31        &self,
32        parent: WlSurface,
33        queue_handle: &QueueHandle<State>,
34    ) -> (WlSubsurface, WlSurface)
35    where
36        State: Dispatch<WlSurface, SurfaceData> + Dispatch<WlSubsurface, SubsurfaceData> + 'static,
37    {
38        let surface_data = SurfaceData::new(Some(parent.clone()), 1);
39        let surface = self.compositor.create_surface(queue_handle, surface_data);
40        let subsurface_data = SubsurfaceData::new(surface.clone());
41        let subsurface =
42            self.subcompositor.get_subsurface(&surface, &parent, queue_handle, subsurface_data);
43        (subsurface, surface)
44    }
45
46    pub fn subsurface_from_surface<State>(
47        &self,
48        surface: &WlSurface,
49        queue_handle: &QueueHandle<State>,
50    ) -> Option<WlSubsurface>
51    where
52        State: Dispatch<WlSurface, SurfaceData> + Dispatch<WlSubsurface, SubsurfaceData> + 'static,
53    {
54        let parent = surface.data::<SurfaceData>().unwrap().parent_surface();
55        let subsurface_data = SubsurfaceData::new(surface.clone());
56        parent.map(|parent| {
57            self.subcompositor.get_subsurface(surface, parent, queue_handle, subsurface_data)
58        })
59    }
60}
61
62impl<D> Dispatch<WlSubsurface, SubsurfaceData, D> for SubcompositorState
63where
64    D: Dispatch<WlSubsurface, SubsurfaceData>,
65{
66    fn event(
67        _: &mut D,
68        _: &WlSubsurface,
69        _: <WlSubsurface as Proxy>::Event,
70        _: &SubsurfaceData,
71        _: &Connection,
72        _: &QueueHandle<D>,
73    ) {
74        unreachable!("wl_subsurface has no events")
75    }
76}
77
78impl<D> Dispatch<WlSubcompositor, GlobalData, D> for SubcompositorState
79where
80    D: Dispatch<WlSubcompositor, GlobalData>,
81{
82    fn event(
83        _: &mut D,
84        _: &WlSubcompositor,
85        _: <WlSubcompositor as Proxy>::Event,
86        _: &GlobalData,
87        _: &Connection,
88        _: &QueueHandle<D>,
89    ) {
90        unreachable!("wl_subcompositor has no events")
91    }
92}
93
94/// The data assoctiated with the subsurface.
95#[derive(Debug)]
96pub struct SubsurfaceData {
97    /// The surface used when creating this subsurface.
98    surface: WlSurface,
99}
100
101impl SubsurfaceData {
102    pub(crate) fn new(surface: WlSurface) -> Self {
103        Self { surface }
104    }
105
106    /// Get the surface used when creating the given subsurface.
107    pub fn surface(&self) -> &WlSurface {
108        &self.surface
109    }
110}
111
112#[macro_export]
113macro_rules! delegate_subcompositor {
114    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
115        $crate::delegate_subcompositor!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; subsurface: []);
116        $crate::delegate_subcompositor!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; subsurface-only: $crate::subcompositor::SubsurfaceData);
117    };
118    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty, subsurface: [$($subsurface: ty),*$(,)?]) => {
119        $crate::delegate_subcompositor!(@{ $(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty }; subsurface: [ $($subsurface),* ]);
120    };
121    (@{$($ty:tt)*}; subsurface: []) => {
122        $crate::reexports::client::delegate_dispatch!($($ty)*:
123            [
124                $crate::reexports::client::protocol::wl_subcompositor::WlSubcompositor: $crate::globals::GlobalData
125            ] => $crate::subcompositor::SubcompositorState
126        );
127    };
128    (@{$($ty:tt)*}; subsurface-only: $subsurface:ty) => {
129        $crate::reexports::client::delegate_dispatch!($($ty)*:
130            [
131                    $crate::reexports::client::protocol::wl_subsurface::WlSubsurface: $subsurface
132            ] => $crate::subcompositor::SubcompositorState
133        );
134    };
135    (@$ty:tt; subsurface: [ $($subsurface:ty),+ ]) => {
136        $crate::delegate_subcompositor!(@$ty; subsurface: []);
137        $( $crate::delegate_subcompositor!(@$ty; subsurface-only: $subsurface); )*
138    };
139}