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 struct DelegateToMe;
166
167 impl<D> Dispatch<wl_output::WlOutput, (), D> for DelegateToMe
168 where
169 D: Dispatch<wl_output::WlOutput, ()> + AsMut<DelegateToMe>,
170 {
171 fn request(
172 _state: &mut D,
173 _client: &Client,
174 _resource: &wl_output::WlOutput,
175 _request: wl_output::Request,
176 _data: &(),
177 _dhandle: &DisplayHandle,
178 _data_init: &mut DataInit<'_, D>,
179 ) {
180 }
181 }
182 impl<D> GlobalDispatch<wl_output::WlOutput, (), D> for DelegateToMe
183 where
184 D: GlobalDispatch<wl_output::WlOutput, ()>,
185 D: Dispatch<wl_output::WlOutput, ()>,
186 D: AsMut<DelegateToMe>,
187 {
188 fn bind(
189 _state: &mut D,
190 _handle: &DisplayHandle,
191 _client: &Client,
192 _resource: New<wl_output::WlOutput>,
193 _global_data: &(),
194 _data_init: &mut DataInit<'_, D>,
195 ) {
196 }
197 }
198
199 struct ExampleApp {
200 delegate: DelegateToMe,
201 }
202
203 delegate_dispatch!(ExampleApp: [wl_output::WlOutput: ()] => DelegateToMe);
204 delegate_global_dispatch!(ExampleApp: [wl_output::WlOutput: ()] => DelegateToMe);
205
206 impl AsMut<DelegateToMe> for ExampleApp {
207 fn as_mut(&mut self) -> &mut DelegateToMe {
208 &mut self.delegate
209 }
210 }
211 }
212
213 #[test]
214 fn smoke_test_dispatch_global_dispatch_generics() {
215 use crate::{
216 delegate_dispatch, protocol::wl_output, Client, DataInit, Dispatch, DisplayHandle,
217 GlobalDispatch, New,
218 };
219
220 struct DelegateToMe<A>(A);
221
222 impl<A, D> Dispatch<wl_output::WlOutput, (), D> for DelegateToMe<A>
223 where
224 A: 'static,
225 D: Dispatch<wl_output::WlOutput, ()> + AsMut<DelegateToMe<A>>,
226 {
227 fn request(
228 _state: &mut D,
229 _client: &Client,
230 _resource: &wl_output::WlOutput,
231 _request: wl_output::Request,
232 _data: &(),
233 _dhandle: &DisplayHandle,
234 _data_init: &mut DataInit<'_, D>,
235 ) {
236 }
237 }
238 impl<A, D> GlobalDispatch<wl_output::WlOutput, (), D> for DelegateToMe<A>
239 where
240 A: 'static,
241 D: GlobalDispatch<wl_output::WlOutput, ()>,
242 D: Dispatch<wl_output::WlOutput, ()>,
243 D: AsMut<DelegateToMe<A>>,
244 {
245 fn bind(
246 _state: &mut D,
247 _handle: &DisplayHandle,
248 _client: &Client,
249 _resource: New<wl_output::WlOutput>,
250 _global_data: &(),
251 _data_init: &mut DataInit<'_, D>,
252 ) {
253 }
254 }
255
256 struct ExampleApp<A> {
257 delegate: DelegateToMe<A>,
258 }
259
260 delegate_dispatch!(@<A: 'static> ExampleApp<A>: [wl_output::WlOutput: ()] => DelegateToMe<A>);
261 delegate_global_dispatch!(@<A: 'static> ExampleApp<A>: [wl_output::WlOutput: ()] => DelegateToMe<A>);
262
263 impl<A> AsMut<DelegateToMe<A>> for ExampleApp<A> {
264 fn as_mut(&mut self) -> &mut DelegateToMe<A> {
265 &mut self.delegate
266 }
267 }
268 }
269}