Skip to main content

wayland_server/
global.rs

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, D: 'static, U: GlobalDispatch<I, D> + Send + Sync + '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        self.data.can_view(&client)
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        self.data.bind(
43            data,
44            &handle,
45            &client,
46            New::wrap(resource.clone()),
47            &mut DataInit { store: &mut new_data, error: &mut protocol_error },
48        );
49
50        match new_data {
51            Some(data) => data,
52            None => match protocol_error {
53                Some((code, msg)) => {
54                    resource.post_error(code, msg);
55                    Arc::new(ProtocolErrorData)
56                }
57
58                None => panic!(
59                    "Bind callback for interface {} did not init new instance.",
60                    I::interface().name
61                ),
62            },
63        }
64    }
65}
66
67struct ProtocolErrorData;
68
69impl<D> ObjectData<D> for ProtocolErrorData {
70    fn request(
71        self: Arc<Self>,
72        _handle: &Handle,
73        _data: &mut D,
74        _client_id: ClientId,
75        _msg: wayland_backend::protocol::Message<ObjectId, OwnedFd>,
76    ) -> Option<Arc<dyn ObjectData<D>>> {
77        None
78    }
79
80    fn destroyed(
81        self: Arc<Self>,
82        _handle: &Handle,
83        _data: &mut D,
84        _client_id: ClientId,
85        _object_id: ObjectId,
86    ) {
87    }
88}
89
90/// A trait which provides an implementation for handling advertisement of a global to clients with some type
91/// of associated user data.
92///
93/// Its behavior is similar to the [`Dispatch`][crate::Dispatch] trait.
94pub trait GlobalDispatch<I: Resource, State> {
95    /// Called when a client has bound this global.
96    ///
97    /// The return value of this function should contain user data to associate the object created by the
98    /// client.
99    fn bind(
100        &self,
101        state: &mut State,
102        handle: &DisplayHandle,
103        client: &Client,
104        resource: New<I>,
105        data_init: &mut DataInit<'_, State>,
106    );
107
108    /// Checks if the global should be advertised to some client.
109    ///
110    /// The implementation of this function determines whether a client may see and bind some global. If this
111    /// function returns false, the client will not be told the global exists and attempts to bind the global
112    /// will raise a protocol error.
113    ///
114    /// One use of this function is implementing privileged protocols such as XWayland keyboard grabbing
115    /// which must only be used by XWayland.
116    ///
117    /// The default implementation allows all clients to see the global.
118    fn can_view(&self, _client: &Client) -> bool {
119        true
120    }
121}