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}