1use std::os::unix::io::OwnedFd;
2use std::sync::Arc;
3
4use wayland_backend::server::{
5 ClientData, ClientId, GlobalHandler, GlobalId, Handle, ObjectData, ObjectId,
6};
7
8use crate::{Client, DataInit, DisplayHandle, New, Resource};
9
10pub(crate) struct GlobalData<I, U, D> {
11 pub(crate) data: U,
12 pub(crate) _types: std::marker::PhantomData<(I, D)>,
13}
14
15unsafe impl<I, D, U: Send + Sync> Send for GlobalData<I, U, D> {}
16unsafe impl<I, D, U: Send + Sync> Sync for GlobalData<I, U, D> {}
17
18impl<I: Resource + 'static, U: Send + Sync + 'static, D: GlobalDispatch<I, U> + 'static>
19 GlobalHandler<D> for GlobalData<I, U, D>
20{
21 fn can_view(&self, id: ClientId, data: &Arc<dyn ClientData>, _: GlobalId) -> bool {
22 let client = Client { id, data: data.clone() };
23 <D as GlobalDispatch<I, U>>::can_view(client, &self.data)
24 }
25
26 fn bind(
27 self: Arc<Self>,
28 handle: &Handle,
29 data: &mut D,
30 client_id: ClientId,
31 _: GlobalId,
32 object_id: ObjectId,
33 ) -> Arc<dyn ObjectData<D>> {
34 let handle = DisplayHandle::from(handle.clone());
35 let client = Client::from_id(&handle, client_id).expect("Dead client in bind ?!");
36 let resource = <I as Resource>::from_id(&handle, object_id)
37 .expect("Wrong object_id in GlobalHandler ?!");
38
39 let mut new_data = None;
40 let mut protocol_error = None;
41
42 <D as GlobalDispatch<I, U>>::bind(
43 data,
44 &handle,
45 &client,
46 New::wrap(resource.clone()),
47 &self.data,
48 &mut DataInit { store: &mut new_data, error: &mut protocol_error },
49 );
50
51 match new_data {
52 Some(data) => data,
53 None => match protocol_error {
54 Some((code, msg)) => {
55 resource.post_error(code, msg);
56 Arc::new(ProtocolErrorData)
57 }
58
59 None => panic!(
60 "Bind callback for interface {} did not init new instance.",
61 I::interface().name
62 ),
63 },
64 }
65 }
66}
67
68struct ProtocolErrorData;
69
70impl<D> ObjectData<D> for ProtocolErrorData {
71 fn request(
72 self: Arc<Self>,
73 _handle: &Handle,
74 _data: &mut D,
75 _client_id: ClientId,
76 _msg: wayland_backend::protocol::Message<ObjectId, OwnedFd>,
77 ) -> Option<Arc<dyn ObjectData<D>>> {
78 None
79 }
80
81 fn destroyed(
82 self: Arc<Self>,
83 _handle: &Handle,
84 _data: &mut D,
85 _client_id: ClientId,
86 _object_id: ObjectId,
87 ) {
88 }
89}
90
91pub trait GlobalDispatch<I: Resource, GlobalData, State = Self>: Sized {
96 fn bind(
101 state: &mut State,
102 handle: &DisplayHandle,
103 client: &Client,
104 resource: New<I>,
105 global_data: &GlobalData,
106 data_init: &mut DataInit<'_, State>,
107 );
108
109 fn can_view(_client: Client, _global_data: &GlobalData) -> bool {
120 true
121 }
122}
123
124#[macro_export]
135macro_rules! delegate_global_dispatch {
136 ($(@< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? $dispatch_from:ty : [$interface: ty: $udata: ty] => $dispatch_to: ty) => {
137 impl$(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::GlobalDispatch<$interface, $udata> for $dispatch_from {
138 fn bind(
139 state: &mut Self,
140 dhandle: &$crate::DisplayHandle,
141 client: &$crate::Client,
142 resource: $crate::New<$interface>,
143 global_data: &$udata,
144 data_init: &mut $crate::DataInit<'_, Self>,
145 ) {
146 <$dispatch_to as $crate::GlobalDispatch<$interface, $udata, Self>>::bind(state, dhandle, client, resource, global_data, data_init)
147 }
148
149 fn can_view(client: $crate::Client, global_data: &$udata) -> bool {
150 <$dispatch_to as $crate::GlobalDispatch<$interface, $udata, Self>>::can_view(client, global_data)
151 }
152 }
153 };
154}
155
156#[cfg(test)]
157mod tests {
158 #[test]
159 fn smoke_test_dispatch_global_dispatch() {
160 use crate::{
161 delegate_dispatch, protocol::wl_output, Client, DataInit, Dispatch, DisplayHandle,
162 GlobalDispatch, New,
163 };
164
165 #[allow(dead_code)]
166 struct DelegateToMe;
167
168 impl<D> Dispatch<wl_output::WlOutput, (), D> for DelegateToMe
169 where
170 D: Dispatch<wl_output::WlOutput, ()> + AsMut<DelegateToMe>,
171 {
172 fn request(
173 _state: &mut D,
174 _client: &Client,
175 _resource: &wl_output::WlOutput,
176 _request: wl_output::Request,
177 _data: &(),
178 _dhandle: &DisplayHandle,
179 _data_init: &mut DataInit<'_, D>,
180 ) {
181 }
182 }
183 impl<D> GlobalDispatch<wl_output::WlOutput, (), D> for DelegateToMe
184 where
185 D: GlobalDispatch<wl_output::WlOutput, ()>,
186 D: Dispatch<wl_output::WlOutput, ()>,
187 D: AsMut<DelegateToMe>,
188 {
189 fn bind(
190 _state: &mut D,
191 _handle: &DisplayHandle,
192 _client: &Client,
193 _resource: New<wl_output::WlOutput>,
194 _global_data: &(),
195 _data_init: &mut DataInit<'_, D>,
196 ) {
197 }
198 }
199
200 #[allow(dead_code)]
201 struct ExampleApp {
202 delegate: DelegateToMe,
203 }
204
205 delegate_dispatch!(ExampleApp: [wl_output::WlOutput: ()] => DelegateToMe);
206 delegate_global_dispatch!(ExampleApp: [wl_output::WlOutput: ()] => DelegateToMe);
207
208 impl AsMut<DelegateToMe> for ExampleApp {
209 fn as_mut(&mut self) -> &mut DelegateToMe {
210 &mut self.delegate
211 }
212 }
213 }
214
215 #[test]
216 fn smoke_test_dispatch_global_dispatch_generics() {
217 use crate::{
218 delegate_dispatch, protocol::wl_output, Client, DataInit, Dispatch, DisplayHandle,
219 GlobalDispatch, New,
220 };
221
222 #[allow(dead_code)]
223 struct DelegateToMe<A>(A);
224
225 impl<A, D> Dispatch<wl_output::WlOutput, (), D> for DelegateToMe<A>
226 where
227 A: 'static,
228 D: Dispatch<wl_output::WlOutput, ()> + AsMut<DelegateToMe<A>>,
229 {
230 fn request(
231 _state: &mut D,
232 _client: &Client,
233 _resource: &wl_output::WlOutput,
234 _request: wl_output::Request,
235 _data: &(),
236 _dhandle: &DisplayHandle,
237 _data_init: &mut DataInit<'_, D>,
238 ) {
239 }
240 }
241 impl<A, D> GlobalDispatch<wl_output::WlOutput, (), D> for DelegateToMe<A>
242 where
243 A: 'static,
244 D: GlobalDispatch<wl_output::WlOutput, ()>,
245 D: Dispatch<wl_output::WlOutput, ()>,
246 D: AsMut<DelegateToMe<A>>,
247 {
248 fn bind(
249 _state: &mut D,
250 _handle: &DisplayHandle,
251 _client: &Client,
252 _resource: New<wl_output::WlOutput>,
253 _global_data: &(),
254 _data_init: &mut DataInit<'_, D>,
255 ) {
256 }
257 }
258
259 #[allow(dead_code)]
260 struct ExampleApp<A> {
261 delegate: DelegateToMe<A>,
262 }
263
264 delegate_dispatch!(@<A: 'static> ExampleApp<A>: [wl_output::WlOutput: ()] => DelegateToMe<A>);
265 delegate_global_dispatch!(@<A: 'static> ExampleApp<A>: [wl_output::WlOutput: ()] => DelegateToMe<A>);
266
267 impl<A> AsMut<DelegateToMe<A>> for ExampleApp<A> {
268 fn as_mut(&mut self) -> &mut DelegateToMe<A> {
269 &mut self.delegate
270 }
271 }
272 }
273}