Skip to main content

wayland_server/
client.rs

1use std::{any::Any, sync::Arc};
2
3use wayland_backend::{
4    protocol::ProtocolError,
5    server::{ClientData, ClientId, DisconnectReason, InvalidId, ObjectData},
6};
7
8use crate::{Dispatch, DisplayHandle, Resource, dispatch::ResourceData};
9
10/// A struct representing a Wayland client connected to your compositor.
11#[derive(Clone, Debug)]
12pub struct Client {
13    pub(crate) id: ClientId,
14    pub(crate) data: Arc<dyn ClientData>,
15}
16
17impl Client {
18    pub(crate) fn from_id(handle: &DisplayHandle, id: ClientId) -> Result<Self, InvalidId> {
19        let data = handle.handle.get_client_data(id.clone())?;
20        Ok(Self { id, data })
21    }
22
23    /// The backend [`ClientId`] of this client
24    pub fn id(&self) -> ClientId {
25        self.id.clone()
26    }
27
28    /// Access the data associated to this client
29    ///
30    /// Returns [`None`] if the provided `Data` type parameter is not the correct one.
31    pub fn get_data<Data: ClientData + 'static>(&self) -> Option<&Data> {
32        (&*self.data as &dyn Any).downcast_ref()
33    }
34
35    /// Access the pid/uid/gid of this client
36    ///
37    /// **Note:** You should be careful if you plan tu use this for security purposes, as it is possible for
38    /// programs to spoof this kind of information.
39    ///
40    /// For a discussion about the subject of securely identifying clients, see
41    /// <https://gitlab.freedesktop.org/wayland/weston/-/issues/206>
42    pub fn get_credentials(
43        &self,
44        handle: &DisplayHandle,
45    ) -> Result<crate::backend::Credentials, InvalidId> {
46        handle.handle.get_client_credentials(self.id.clone())
47    }
48
49    /// Create a new Wayland object in the protocol state of this client
50    ///
51    /// The newly created resource should be immediately sent to the client through an associated event with
52    /// a `new_id` argument. Not doing so risks corrupting the protocol state and causing protocol errors at
53    /// a later time.
54    pub fn create_resource<I, U, D>(
55        &self,
56        handle: &DisplayHandle,
57        version: u32,
58        user_data: U,
59    ) -> Result<I, InvalidId>
60    where
61        I: Resource + 'static,
62        U: Dispatch<I, D> + Send + Sync + 'static,
63        D: 'static,
64    {
65        let id = handle.handle.create_object::<D>(
66            self.id.clone(),
67            I::interface(),
68            version,
69            Arc::new(ResourceData::<I, U>::new(user_data)),
70        )?;
71        I::from_id(handle, id)
72    }
73
74    /// Create a new Wayland object in the protocol state of this client, from an [`ObjectData`]
75    ///
76    /// This is a lower-level method than [`create_resource()`][Self::create_resource()], in case you need to
77    /// bypass the [`Dispatch`] machinery.
78    ///
79    /// The newly created resource should be immediately sent to the client through an associated event with
80    /// a `new_id` argument. Not doing so risks corrupting the protocol state and causing protocol errors at
81    /// a later time.
82    pub fn create_resource_from_objdata<I: Resource + 'static, D: 'static>(
83        &self,
84        handle: &DisplayHandle,
85        version: u32,
86        obj_data: Arc<dyn ObjectData<D>>,
87    ) -> Result<I, InvalidId> {
88        let id =
89            handle.handle.create_object::<D>(self.id.clone(), I::interface(), version, obj_data)?;
90        I::from_id(handle, id)
91    }
92
93    /// Attempt to retrieve an object from this client's protocol state from its protocol id
94    ///
95    /// Will fail if either the provided protocol id does not correspond to any object, or if the
96    /// corresponding object is not of the interface `I`.
97    pub fn object_from_protocol_id<I: Resource + 'static>(
98        &self,
99        handle: &DisplayHandle,
100        protocol_id: u32,
101    ) -> Result<I, InvalidId> {
102        let object_id =
103            handle.handle.object_for_protocol_id(self.id.clone(), I::interface(), protocol_id)?;
104        I::from_id(handle, object_id)
105    }
106
107    /// Kill this client by triggering a protocol error
108    pub fn kill(&self, handle: &DisplayHandle, error: ProtocolError) {
109        handle.handle.kill_client(self.id.clone(), DisconnectReason::ProtocolError(error))
110    }
111
112    /// Get the name of the global for given client.
113    #[cfg(feature = "libwayland_1_22")]
114    pub fn global_name(
115        &self,
116        handle: &DisplayHandle,
117        global: crate::backend::GlobalId,
118    ) -> Option<u32> {
119        handle.handle.global_name(global, self.id.clone())
120    }
121
122    /// Set maximum buffer size for client.
123    #[cfg(feature = "libwayland_1_23")]
124    pub fn set_max_buffer_size(&self, handle: &DisplayHandle, max_buffer_size: usize) {
125        handle.handle.set_client_max_buffer_size(self.id.clone(), max_buffer_size);
126    }
127}
128
129impl PartialEq for Client {
130    fn eq(&self, other: &Self) -> bool {
131        self.id == other.id
132    }
133}