wayland_server/
dispatch.rs

1use std::os::unix::io::OwnedFd;
2use std::sync::Arc;
3
4use wayland_backend::{
5    protocol::ProtocolError,
6    server::{ClientId, DisconnectReason, ObjectData, ObjectId},
7};
8
9use crate::{Client, DisplayHandle, Resource};
10
11/// A trait which provides an implementation for handling a client's requests from a resource with some type
12/// of associated user data.
13///
14///  ## General usage
15///
16/// You need to implement this trait on your `State` for every type of Wayland object that will be processed
17/// by the [`Display`][crate::Display] working with your `State`.
18///
19/// You can have different implementations of the trait for the same interface but different `UserData` type,
20/// this way the events for a given object will be processed by the adequate implementation depending on
21/// which `UserData` was assigned to it at creation.
22///
23/// The way this trait works is that the [`Dispatch::request()`] method will be invoked by the
24/// [`Display`][crate::Display] for every request received by an object. Your implementation can then match
25/// on the associated [`Resource::Request`] enum and do any processing needed with that event.
26///
27/// If the request being processed created a new object, you'll receive it as a [`New<I>`]. When that is the
28/// case, you *must* initialize it using the [`DataInit`] argument. **Failing to do so will cause a **panic**.
29///
30/// ## Modularity
31///
32/// To provide generic handlers for downstream usage, it is possible to make an implementation of the trait
33/// that is generic over the last type argument, as illustrated below. Users will then be able to
34/// automatically delegate their implementation to yours using the [`delegate_dispatch!()`] macro.
35///
36/// [`delegate_dispatch!()`]: crate::delegate_dispatch!()
37///
38/// As a result, when your implementation is instanciated, the last type parameter `State` will be the state
39/// struct of the app using your generic implementation. You can put additional trait constraints on it to
40/// specify an interface between your module and downstream code, as illustrated in this example:
41///
42/// ```
43/// # // Maintainers: If this example changes, please make sure you also carry those changes over to the
44/// # // delegate_dispatch macro.
45/// use wayland_server::{protocol::wl_output, Dispatch};
46///
47/// /// The type we want to delegate to
48/// struct DelegateToMe;
49///
50/// /// The user data relevant for your implementation.
51/// /// When providing delegate implementation, it is recommended to use your own type here, even if it is
52/// /// just a unit struct: using () would cause a risk of clashing with an other such implementation.
53/// struct MyUserData;
54///
55/// // Now a generic implementation of Dispatch, we are generic over the last type argument instead of using
56/// // the default State=Self.
57/// impl<State> Dispatch<wl_output::WlOutput, MyUserData, State> for DelegateToMe
58/// where
59///     // State is the type which has delegated to this type, so it needs to have an impl of Dispatch itself
60///     State: Dispatch<wl_output::WlOutput, MyUserData>,
61///     // If your delegate type has some internal state, it'll need to access it, and you can
62///     // require it by adding custom trait bounds.
63///     // In this example, we just require an AsMut implementation
64///     State: AsMut<DelegateToMe>,
65/// {
66///     fn request(
67///         state: &mut State,
68///         _client: &wayland_server::Client,
69///         _resource: &wl_output::WlOutput,
70///         _request: wl_output::Request,
71///         _udata: &MyUserData,
72///         _dhandle: &wayland_server::DisplayHandle,
73///         _data_init: &mut wayland_server::DataInit<'_, State>,
74///     ) {
75///         // Here the delegate may handle incoming requests as it pleases.
76///
77///         // For example, it retrives its state and does some processing with it
78///         let me: &mut DelegateToMe = state.as_mut();
79///         // do something with `me` ...
80/// #       std::mem::drop(me) // use `me` to avoid a warning
81///     }
82/// }
83/// ```
84///
85/// **Note:** Due to limitations in Rust's trait resolution algorithm, a type providing a generic
86/// implementation of [`Dispatch`] cannot be used directly as the dispatching state, as rustc
87/// currently fails to understand that it also provides `Dispatch<I, U, Self>` (assuming all other
88/// trait bounds are respected as well).
89pub trait Dispatch<I: Resource, UserData, State = Self>: Sized {
90    /// Called when a request from a client is processed.
91    ///
92    /// The implementation of this function will vary depending on what protocol is being implemented. Typically
93    /// the server may respond to clients by sending events to the resource, or some other resource stored in
94    /// the user data.
95    fn request(
96        state: &mut State,
97        client: &Client,
98        resource: &I,
99        request: I::Request,
100        data: &UserData,
101        dhandle: &DisplayHandle,
102        data_init: &mut DataInit<'_, State>,
103    );
104
105    /// Called when the object this user data is associated with has been destroyed.
106    ///
107    /// Note this type only provides an immutable reference to the user data, you will need to use
108    /// interior mutability to change it.
109    ///
110    /// Typically a [`Mutex`][std::sync::Mutex] would be used to have interior mutability.
111    ///
112    /// You are given the [`ObjectId`] and [`ClientId`] associated with the destroyed object for cleanup
113    /// convenience.
114    ///
115    /// By default this method does nothing.
116    fn destroyed(
117        _state: &mut State,
118        _client: wayland_backend::server::ClientId,
119        _resource: &I,
120        _data: &UserData,
121    ) {
122    }
123}
124
125/// The [`ObjectData`] implementation that is internally used by this crate
126#[derive(Debug)]
127pub struct ResourceData<I, U> {
128    marker: std::marker::PhantomData<fn(I)>,
129    /// The user-data associated with this object
130    pub udata: U,
131}
132
133/// A newly created object that needs to be initialized. See [`DataInit`].
134#[derive(Debug)]
135#[must_use = "The protocol object must be initialized using DataInit"]
136pub struct New<I> {
137    id: I,
138}
139
140impl<I> New<I> {
141    #[doc(hidden)]
142    // This is only to be used by code generated by wayland-scanner
143    pub fn wrap(id: I) -> New<I> {
144        New { id }
145    }
146}
147
148/// Helper to initialize client-created objects
149///
150/// This helper is provided to you in your [`Dispatch`] and [`GlobalDispatch`][super::GlobalDispatch] to
151/// initialize objects created by the client, by assigning them their user-data (or [`ObjectData`] if you
152/// need to go this lower-level route).
153///
154/// This step is mandatory, and **failing to initialize a newly created object will cause a panic**.
155#[derive(Debug)]
156pub struct DataInit<'a, D: 'static> {
157    pub(crate) store: &'a mut Option<Arc<dyn ObjectData<D>>>,
158    pub(crate) error: &'a mut Option<(u32, String)>,
159}
160
161impl<D> DataInit<'_, D> {
162    /// Initialize an object by assigning it its user-data
163    pub fn init<I: Resource + 'static, U: Send + Sync + 'static>(
164        &mut self,
165        resource: New<I>,
166        data: U,
167    ) -> I
168    where
169        D: Dispatch<I, U> + 'static,
170    {
171        let arc = Arc::new(ResourceData::<I, _>::new(data));
172        *self.store = Some(arc.clone() as Arc<_>);
173        let mut obj = resource.id;
174        obj.__set_object_data(arc);
175        obj
176    }
177
178    /// Set a custom [`ObjectData`] for this object
179    ///
180    /// This object data is not managed by `wayland-server`, as a result you will not
181    /// be able to retreive it through [`Resource::data()`].
182    /// Instead, you'll need to retrieve it using [`Resource::object_data()`] and
183    /// handle the downcasting yourself.
184    pub fn custom_init<I: Resource + 'static>(
185        &mut self,
186        resource: New<I>,
187        data: Arc<dyn ObjectData<D>>,
188    ) -> I {
189        *self.store = Some(data.clone());
190        let mut obj = resource.id;
191        obj.__set_object_data(data.into_any_arc());
192        obj
193    }
194
195    /// Post an error on an uninitialized object.
196    ///
197    /// This is only meant to be used in [`GlobalDispatch`][crate::GlobalDispatch] where a global protocol
198    /// object is instantiated.
199    pub fn post_error<I: Resource + 'static>(
200        &mut self,
201        _resource: New<I>,
202        code: impl Into<u32>,
203        error: impl Into<String>,
204    ) {
205        *self.error = Some((code.into(), error.into()));
206        // This function takes ownership of the New, ensuring the handler never sees an uninitialized
207        // protocol object.
208        // drop(_resource);
209    }
210}
211
212/*
213 * Dispatch delegation helpers.
214 */
215
216impl<I, U> ResourceData<I, U> {
217    pub(crate) fn new(udata: U) -> Self {
218        ResourceData { marker: std::marker::PhantomData, udata }
219    }
220}
221
222impl<I: Resource + 'static, U: Send + Sync + 'static, D: Dispatch<I, U> + 'static> ObjectData<D>
223    for ResourceData<I, U>
224{
225    fn request(
226        self: Arc<Self>,
227        handle: &wayland_backend::server::Handle,
228        data: &mut D,
229        client_id: wayland_backend::server::ClientId,
230        msg: wayland_backend::protocol::Message<wayland_backend::server::ObjectId, OwnedFd>,
231    ) -> Option<Arc<dyn ObjectData<D>>> {
232        let dhandle = DisplayHandle::from(handle.clone());
233        let client = match Client::from_id(&dhandle, client_id) {
234            Ok(v) => v,
235            Err(_) => {
236                crate::log_error!("Receiving a request from a dead client ?!");
237                return None;
238            }
239        };
240
241        let (sender_id, opcode) = (msg.sender_id.protocol_id(), msg.opcode);
242
243        let (resource, request) = match I::parse_request(&dhandle, msg) {
244            Ok(v) => v,
245            Err(e) => {
246                crate::log_warn!("Dispatching error encountered: {:?}, killing client.", e);
247                handle.kill_client(
248                    client.id(),
249                    DisconnectReason::ProtocolError(ProtocolError {
250                        code: 1,
251                        object_id: 0,
252                        object_interface: "wl_display".into(),
253                        message: format!(
254                            "Malformed request received for id {} and opcode {}.",
255                            sender_id, opcode
256                        ),
257                    }),
258                );
259                return None;
260            }
261        };
262        let udata = resource.data::<U>().expect("Wrong user_data value for object");
263
264        let mut new_data = None;
265
266        <D as Dispatch<I, U>>::request(
267            data,
268            &client,
269            &resource,
270            request,
271            udata,
272            &dhandle,
273            // The error is None since the creating object posts an error.
274            &mut DataInit { store: &mut new_data, error: &mut None },
275        );
276
277        new_data
278    }
279
280    fn destroyed(
281        self: Arc<Self>,
282        handle: &wayland_backend::server::Handle,
283        data: &mut D,
284        client_id: ClientId,
285        object_id: ObjectId,
286    ) {
287        let dhandle = DisplayHandle::from(handle.clone());
288        let mut resource = I::from_id(&dhandle, object_id).unwrap();
289
290        // Proxy::from_id will return an inert protocol object wrapper inside of ObjectData::destroyed,
291        // therefore manually initialize the data associated with protocol object wrapper.
292        resource.__set_object_data(self.clone());
293
294        <D as Dispatch<I, U>>::destroyed(data, client_id, &resource, &self.udata)
295    }
296}
297
298/// A helper macro which delegates a set of [`Dispatch`] implementations for a resource to some other type which
299/// provides a generic [`Dispatch`] implementation.
300///
301/// This macro allows more easily delegating smaller parts of the protocol a compositor may wish to handle
302/// in a modular fashion.
303///
304/// # Usage
305///
306/// For example, say you want to delegate events for [`WlOutput`][crate::protocol::wl_output::WlOutput]
307/// to the `DelegateToMe` type from the [`Dispatch`] documentation.
308///
309/// ```
310/// use wayland_server::{delegate_dispatch, protocol::wl_output};
311/// #
312/// # use wayland_server::Dispatch;
313/// #
314/// # struct DelegateToMe;
315/// #
316/// # impl<D> Dispatch<wl_output::WlOutput, (), D> for DelegateToMe
317/// # where
318/// #     D: Dispatch<wl_output::WlOutput, ()> + AsMut<DelegateToMe>,
319/// # {
320/// #     fn request(
321/// #         _state: &mut D,
322/// #         _client: &wayland_server::Client,
323/// #         _resource: &wl_output::WlOutput,
324/// #         _request: wl_output::Request,
325/// #         _data: &(),
326/// #         _dhandle: &wayland_server::DisplayHandle,
327/// #         _data_init: &mut wayland_server::DataInit<'_, D>,
328/// #     ) {
329/// #     }
330/// # }
331/// #
332/// # type MyUserData = ();
333///
334/// // ExampleApp is the type events will be dispatched to.
335///
336/// /// The application state
337/// struct ExampleApp {
338///     /// The delegate for handling wl_registry events.
339///     delegate: DelegateToMe,
340/// }
341///
342/// // Use delegate_dispatch to implement Dispatch<wl_output::WlOutput, MyUserData> for ExampleApp.
343/// delegate_dispatch!(ExampleApp: [wl_output::WlOutput: MyUserData] => DelegateToMe);
344///
345/// // DelegateToMe requires that ExampleApp implements AsMut<DelegateToMe>, so we provide the trait implementation.
346/// impl AsMut<DelegateToMe> for ExampleApp {
347///     fn as_mut(&mut self) -> &mut DelegateToMe {
348///         &mut self.delegate
349///     }
350/// }
351/// ```
352#[macro_export]
353macro_rules! delegate_dispatch {
354    ($(@< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? $dispatch_from:ty : [$interface: ty: $udata: ty] => $dispatch_to: ty) => {
355        impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::Dispatch<$interface, $udata> for $dispatch_from {
356            fn request(
357                state: &mut Self,
358                client: &$crate::Client,
359                resource: &$interface,
360                request: <$interface as $crate::Resource>::Request,
361                data: &$udata,
362                dhandle: &$crate::DisplayHandle,
363                data_init: &mut $crate::DataInit<'_, Self>,
364            ) {
365                <$dispatch_to as $crate::Dispatch<$interface, $udata, Self>>::request(state, client, resource, request, data, dhandle, data_init)
366            }
367
368            fn destroyed(state: &mut Self, client: $crate::backend::ClientId, resource: &$interface, data: &$udata) {
369                <$dispatch_to as $crate::Dispatch<$interface, $udata, Self>>::destroyed(state, client, resource, data)
370            }
371        }
372    };
373}