wayland_server/
dispatch.rs

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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
use std::os::unix::io::OwnedFd;
use std::sync::Arc;

use wayland_backend::{
    protocol::ProtocolError,
    server::{ClientId, DisconnectReason, 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.
///
///  ## General usage
///
/// You need to implement this trait on your `State` for every type of Wayland object that will be processed
/// by the [`Display`][crate::Display] working with your `State`.
///
/// You can have different implementations of the trait for the same interface but different `UserData` type,
/// this way the events for a given object will be processed by the adequate implementation depending on
/// which `UserData` was assigned to it at creation.
///
/// The way this trait works is that the [`Dispatch::request()`] method will be invoked by the
/// [`Display`][crate::Display] for every request received by an object. Your implementation can then match
/// on the associated [`Resource::Request`] enum and do any processing needed with that event.
///
/// If the request being processed created a new object, you'll receive it as a [`New<I>`]. When that is the
/// case, you *must* initialize it using the [`DataInit`] argument. **Failing to do so will cause a **panic**.
///
/// ## Modularity
///
/// To provide generic handlers for downstream usage, it is possible to make an implementation of the trait
/// that is generic over the last type argument, as illustrated below. Users will then be able to
/// automatically delegate their implementation to yours using the [`delegate_dispatch!()`] macro.
///
/// [`delegate_dispatch!()`]: crate::delegate_dispatch!()
///
/// As a result, when your implementation is instanciated, the last type parameter `State` will be the state
/// struct of the app using your generic implementation. You can put additional trait constraints on it to
/// specify an interface between your module and downstream code, as illustrated in this example:
///
/// ```
/// # // Maintainers: If this example changes, please make sure you also carry those changes over to the
/// # // delegate_dispatch macro.
/// use wayland_server::{protocol::wl_output, Dispatch};
///
/// /// The type we want to delegate to
/// struct DelegateToMe;
///
/// /// The user data relevant for your implementation.
/// /// When providing delegate implementation, it is recommended to use your own type here, even if it is
/// /// just a unit struct: using () would cause a risk of clashing with an other such implementation.
/// struct MyUserData;
///
/// // Now a generic implementation of Dispatch, we are generic over the last type argument instead of using
/// // the default State=Self.
/// impl<State> Dispatch<wl_output::WlOutput, MyUserData, State> for DelegateToMe
/// where
///     // State is the type which has delegated to this type, so it needs to have an impl of Dispatch itself
///     State: Dispatch<wl_output::WlOutput, MyUserData>,
///     // If your delegate type has some internal state, it'll need to access it, and you can
///     // require it by adding custom trait bounds.
///     // In this example, we just require an AsMut implementation
///     State: AsMut<DelegateToMe>,
/// {
///     fn request(
///         state: &mut State,
///         _client: &wayland_server::Client,
///         _resource: &wl_output::WlOutput,
///         _request: wl_output::Request,
///         _udata: &MyUserData,
///         _dhandle: &wayland_server::DisplayHandle,
///         _data_init: &mut wayland_server::DataInit<'_, State>,
///     ) {
///         // Here the delegate may handle incoming requests as it pleases.
///
///         // For example, it retrives its state and does some processing with it
///         let me: &mut DelegateToMe = state.as_mut();
///         // do something with `me` ...
/// #       std::mem::drop(me) // use `me` to avoid a warning
///     }
/// }
/// ```
///
/// **Note:** Due to limitations in Rust's trait resolution algorithm, a type providing a generic
/// implementation of [`Dispatch`] cannot be used directly as the dispatching state, as rustc
/// currently fails to understand that it also provides `Dispatch<I, U, Self>` (assuming all other
/// trait bounds are respected as well).
pub trait Dispatch<I: Resource, UserData, State = Self>: 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 State,
        client: &Client,
        resource: &I,
        request: I::Request,
        data: &UserData,
        dhandle: &DisplayHandle,
        data_init: &mut DataInit<'_, State>,
    );

    /// 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 State,
        _client: wayland_backend::server::ClientId,
        _resource: &I,
        _data: &UserData,
    ) {
    }
}

/// The [`ObjectData`] implementation that is internally used by this crate
#[derive(Debug)]
pub struct ResourceData<I, U> {
    marker: std::marker::PhantomData<fn(I)>,
    /// The user-data associated with this object
    pub udata: U,
}

/// A newly created object that needs to be initialized. See [`DataInit`].
#[derive(Debug)]
#[must_use = "The protocol object must be initialized using DataInit"]
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 }
    }
}

/// Helper to initialize client-created objects
///
/// This helper is provided to you in your [`Dispatch`] and [`GlobalDispatch`][super::GlobalDispatch] to
/// initialize objects created by the client, by assigning them their user-data (or [`ObjectData`] if you
/// need to go this lower-level route).
///
/// This step is mandatory, and **failing to initialize a newly created object will cause a panic**.
#[derive(Debug)]
pub struct DataInit<'a, D: 'static> {
    pub(crate) store: &'a mut Option<Arc<dyn ObjectData<D>>>,
    pub(crate) error: &'a mut Option<(u32, String)>,
}

impl<D> DataInit<'_, D> {
    /// Initialize an object by assigning it its user-data
    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()`].
    /// Instead, you'll need to retrieve it using [`Resource::object_data()`] and
    /// handle the downcasting yourself.
    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
    }

    /// Post an error on an uninitialized object.
    ///
    /// This is only meant to be used in [`GlobalDispatch`][crate::GlobalDispatch] where a global protocol
    /// object is instantiated.
    pub fn post_error<I: Resource + 'static>(
        &mut self,
        _resource: New<I>,
        code: impl Into<u32>,
        error: impl Into<String>,
    ) {
        *self.error = Some((code.into(), error.into()));
        // This function takes ownership of the New, ensuring the handler never sees an uninitialized
        // protocol object.
        // drop(_resource);
    }
}

/*
 * Dispatch delegation helpers.
 */

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, OwnedFd>,
    ) -> Option<Arc<dyn ObjectData<D>>> {
        let dhandle = DisplayHandle::from(handle.clone());
        let client = match Client::from_id(&dhandle, client_id) {
            Ok(v) => v,
            Err(_) => {
                crate::log_error!("Receiving a request from a dead client ?!");
                return None;
            }
        };

        let (sender_id, opcode) = (msg.sender_id.protocol_id(), msg.opcode);

        let (resource, request) = match I::parse_request(&dhandle, msg) {
            Ok(v) => v,
            Err(e) => {
                crate::log_warn!("Dispatching error encountered: {:?}, killing client.", e);
                handle.kill_client(
                    client.id(),
                    DisconnectReason::ProtocolError(ProtocolError {
                        code: 1,
                        object_id: 0,
                        object_interface: "wl_display".into(),
                        message: format!(
                            "Malformed request received for id {} and opcode {}.",
                            sender_id, opcode
                        ),
                    }),
                );
                return None;
            }
        };
        let udata = resource.data::<U>().expect("Wrong user_data value for object");

        let mut new_data = None;

        <D as Dispatch<I, U>>::request(
            data,
            &client,
            &resource,
            request,
            udata,
            &dhandle,
            // The error is None since the creating object posts an error.
            &mut DataInit { store: &mut new_data, error: &mut None },
        );

        new_data
    }

    fn destroyed(
        self: Arc<Self>,
        handle: &wayland_backend::server::Handle,
        data: &mut D,
        client_id: ClientId,
        object_id: ObjectId,
    ) {
        let dhandle = DisplayHandle::from(handle.clone());
        let mut resource = I::from_id(&dhandle, object_id).unwrap();

        // Proxy::from_id will return an inert protocol object wrapper inside of ObjectData::destroyed,
        // therefore manually initialize the data associated with protocol object wrapper.
        resource.__set_object_data(self.clone());

        <D as Dispatch<I, U>>::destroyed(data, client_id, &resource, &self.udata)
    }
}

/// A helper macro which delegates a set of [`Dispatch`] implementations for a resource to some other type which
/// provides a generic [`Dispatch`] implementation.
///
/// 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 the `DelegateToMe` type from the [`Dispatch`] documentation.
///
/// ```
/// use wayland_server::{delegate_dispatch, protocol::wl_output};
/// #
/// # use wayland_server::Dispatch;
/// #
/// # struct DelegateToMe;
/// #
/// # impl<D> Dispatch<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 MyUserData = ();
///
/// // 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, MyUserData> for ExampleApp.
/// delegate_dispatch!(ExampleApp: [wl_output::WlOutput: MyUserData] => DelegateToMe);
///
/// // DelegateToMe requires that ExampleApp implements AsMut<DelegateToMe>, so we provide the trait implementation.
/// impl AsMut<DelegateToMe> for ExampleApp {
///     fn as_mut(&mut self) -> &mut DelegateToMe {
///         &mut self.delegate
///     }
/// }
/// ```
#[macro_export]
macro_rules! delegate_dispatch {
    ($(@< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? $dispatch_from:ty : [$interface: ty: $udata: ty] => $dispatch_to: ty) => {
        impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::Dispatch<$interface, $udata> for $dispatch_from {
            fn request(
                state: &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::Dispatch<$interface, $udata, Self>>::request(state, client, resource, request, data, dhandle, data_init)
            }

            fn destroyed(state: &mut Self, client: $crate::backend::ClientId, resource: &$interface, data: &$udata) {
                <$dispatch_to as $crate::Dispatch<$interface, $udata, Self>>::destroyed(state, client, resource, data)
            }
        }
    };
}