1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
use std::sync::Arc;

use wayland_backend::server::{ClientId, ObjectData, ObjectId};

use crate::{Client, DisplayHandle, Resource};

/// A trait which provides an implementation for handling a client's requests from a resource with some type
/// of associated user data.
pub trait Dispatch<I: Resource, U>: Sized {
    /// Called when a request from a client is processed.
    ///
    /// The implementation of this function will vary depending on what protocol is being implemented. Typically
    /// the server may respond to clients by sending events to the resource, or some other resource stored in
    /// the user data.
    fn request(
        &mut self,
        client: &Client,
        resource: &I,
        request: I::Request,
        data: &U,
        dhandle: &DisplayHandle,
        data_init: &mut DataInit<'_, Self>,
    );

    /// Called when the object this user data is associated with has been destroyed.
    ///
    /// Note this type only provides an immutable reference to the user data, you will need to use
    /// interior mutability to change it.
    ///
    /// Typically a [`Mutex`](std::sync::Mutex) would be used to have interior mutability.
    ///
    /// You are given the [`ObjectId`] and [`ClientId`] associated with the destroyed object for cleanup
    /// convenience.
    ///
    /// By default this method does nothing.
    fn destroyed(&mut self, _client: ClientId, _resource: ObjectId, _data: &U) {}
}

#[derive(Debug)]
pub struct ResourceData<I, U> {
    marker: std::marker::PhantomData<fn(I)>,
    pub udata: U,
}

#[derive(Debug)]
pub struct New<I> {
    id: I,
}

impl<I> New<I> {
    #[doc(hidden)]
    // This is only to be used by code generated by wayland-scanner
    pub fn wrap(id: I) -> New<I> {
        New { id }
    }
}

#[derive(Debug)]
pub struct DataInit<'a, D: 'static> {
    pub(crate) store: &'a mut Option<Arc<dyn ObjectData<D>>>,
}

impl<'a, D> DataInit<'a, D> {
    pub fn init<I: Resource + 'static, U: Send + Sync + 'static>(
        &mut self,
        resource: New<I>,
        data: U,
    ) -> I
    where
        D: Dispatch<I, U> + 'static,
    {
        let arc = Arc::new(ResourceData::<I, _>::new(data));
        *self.store = Some(arc.clone() as Arc<_>);
        let mut obj = resource.id;
        obj.__set_object_data(arc);
        obj
    }

    /// Set a custom [`ObjectData`] for this object
    ///
    /// This object data is not managed by `wayland-server`, as a result you will not
    /// be able to retreive it through [`Resource::data()`](Resource::data).
    /// Instead, you'll need to directly retrieve it using
    /// [`DisplayHandle::get_object_data()`](DisplayHandle::get_object_data).
    pub fn custom_init<I: Resource + 'static>(
        &mut self,
        resource: New<I>,
        data: Arc<dyn ObjectData<D>>,
    ) -> I {
        *self.store = Some(data.clone());
        let mut obj = resource.id;
        obj.__set_object_data(data.into_any_arc());
        obj
    }
}

/*
 * Dispatch delegation helpers.
 */

/// A trait which defines a delegate to handle some type of resource.
///
/// This trait is useful for building modular handlers of resources.
pub trait DelegateDispatch<I: Resource, U, D: Dispatch<I, U>>: Sized {
    /// Called when a request from a client is processed.
    ///
    /// The implementation of this function will vary depending on what protocol is being implemented. Typically
    /// the server may respond to clients by sending events to the resource, or some other resource stored in
    /// the user data.
    fn request(
        state: &mut D,
        client: &Client,
        resource: &I,
        request: I::Request,
        data: &U,
        dhandle: &DisplayHandle,
        data_init: &mut DataInit<'_, D>,
    );

    /// Called when the object this user data is associated with has been destroyed.
    ///
    /// Note this type only provides an immutable reference to the user data, you will need to use
    /// interior mutability to change it.
    ///
    /// Typically a [`Mutex`](std::sync::Mutex) would be used to have interior mutability.
    ///
    /// You are given the [`ObjectId`] and [`ClientId`] associated with the destroyed object for cleanup
    /// convenience.
    ///
    /// By default this method does nothing.
    fn destroyed(_state: &mut D, _client: ClientId, _resource: ObjectId, _data: &U) {}
}

impl<I, U> ResourceData<I, U> {
    pub(crate) fn new(udata: U) -> Self {
        ResourceData { marker: std::marker::PhantomData, udata }
    }
}

impl<I: Resource + 'static, U: Send + Sync + 'static, D: Dispatch<I, U> + 'static> ObjectData<D>
    for ResourceData<I, U>
{
    fn request(
        self: Arc<Self>,
        handle: &wayland_backend::server::Handle,
        data: &mut D,
        client_id: wayland_backend::server::ClientId,
        msg: wayland_backend::protocol::Message<wayland_backend::server::ObjectId>,
    ) -> Option<Arc<dyn ObjectData<D>>> {
        let dhandle = DisplayHandle::from(handle.clone());
        let client = match Client::from_id(&dhandle, client_id) {
            Ok(v) => v,
            Err(_) => {
                log::error!("Receiving a request from a dead client ?!");
                return None;
            }
        };

        let (resource, request) = match I::parse_request(&dhandle, msg) {
            Ok(v) => v,
            Err(e) => {
                log::warn!("Dispatching error encountered: {:?}, killing client.", e);
                // TODO: Kill client
                return None;
            }
        };
        let udata = resource.data::<U>().expect("Wrong user_data value for object");

        let mut new_data = None;

        data.request(
            &client,
            &resource,
            request,
            udata,
            &dhandle,
            &mut DataInit { store: &mut new_data },
        );

        new_data
    }

    fn destroyed(
        &self,
        data: &mut D,
        client_id: wayland_backend::server::ClientId,
        object_id: wayland_backend::server::ObjectId,
    ) {
        data.destroyed(client_id, object_id, &self.udata)
    }
}

/// A helper macro which delegates a set of [`Dispatch`] implementations for a resource to some other type which
/// implements [`DelegateDispatch`] for each resource.
///
/// This macro allows more easily delegating smaller parts of the protocol a compositor may wish to handle
/// in a modular fashion.
///
/// # Usage
///
/// For example, say you want to delegate events for [`WlOutput`](crate::protocol::wl_output::WlOutput)
/// to some other type.
///
/// For brevity, we will use the example in the documentation for [`DelegateDispatch`], `DelegateToMe`.
///
/// ```
/// use wayland_server::{delegate_dispatch, protocol::wl_output};
/// #
/// # use wayland_server::{DelegateDispatch, Dispatch};
/// #
/// # struct DelegateToMe;
/// #
/// # impl<D> DelegateDispatch<wl_output::WlOutput, (), D> for DelegateToMe
/// # where
/// #     D: Dispatch<wl_output::WlOutput, ()> + AsMut<DelegateToMe>,
/// # {
/// #     fn request(
/// #         _state: &mut D,
/// #         _client: &wayland_server::Client,
/// #         _resource: &wl_output::WlOutput,
/// #         _request: wl_output::Request,
/// #         _data: &(),
/// #         _dhandle: &wayland_server::DisplayHandle,
/// #         _data_init: &mut wayland_server::DataInit<'_, D>,
/// #     ) {
/// #     }
/// # }
/// #
/// # type UserData = ();
///
/// // ExampleApp is the type events will be dispatched to.
///
/// /// The application state
/// struct ExampleApp {
///     /// The delegate for handling wl_registry events.
///     delegate: DelegateToMe,
/// }
///
/// // Use delegate_dispatch to implement Dispatch<wl_output::WlOutput> for ExampleApp.
/// delegate_dispatch!(ExampleApp: [wl_output::WlOutput: UserData] => DelegateToMe);
///
/// // But DelegateToMe requires that ExampleApp implements AsMut<DelegateToMe>, so we provide this impl
/// impl AsMut<DelegateToMe> for ExampleApp {
///     fn as_mut(&mut self) -> &mut DelegateToMe {
///         &mut self.delegate
///     }
/// }
/// ```
///
/// You may also delegate multiple proxies to a single type. This is especially useful for handling multiple
/// related protocols in the same modular component.
///
/// For example, a type which can dispatch both the `wl_output` and `xdg_output` protocols may be used as a
/// delegate:
///
/// ```ignore
/// # // This is not tested because xdg_output is in wayland-protocols.
/// delegate_dispatch!(ExampleApp: [wl_output::WlOutput, xdg_output::XdgOutput] => OutputDelegate);
/// ```
#[macro_export]
macro_rules! delegate_dispatch {
    (@impl $dispatch_from:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? : ($interface:ty, $udata:ty) => $dispatch_to: ty) => {
        impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::Dispatch<$interface, $udata> for $dispatch_from$(< $( $lt ),+ >)? {
            fn request(
                &mut self,
                client: &$crate::Client,
                resource: &$interface,
                request: <$interface as $crate::Resource>::Request,
                data: &$udata,
                dhandle: &$crate::DisplayHandle,
                data_init: &mut $crate::DataInit<'_, Self>,
            ) {
                <$dispatch_to as $crate::DelegateDispatch<$interface, $udata, Self>>::request(self, client, resource, request, data, dhandle, data_init)
            }

            fn destroyed(&mut self, client: $crate::backend::ClientId, resource: $crate::backend::ObjectId, data: &$udata) {
                <$dispatch_to as $crate::DelegateDispatch<$interface, $udata, Self>>::destroyed(self, client, resource, data)
            }
        }
    };
    ($impl:tt : [$($interface: ty: $udata: ty),*] => $dispatch_to: ty) => {
        $(
            $crate::delegate_dispatch!(@impl $impl : ($interface, $udata) => $dispatch_to);
        )*
    };
}