1use std::sync::Arc;
23use wayland_backend::{
4 protocol::ProtocolError,
5 server::{ClientData, ClientId, DisconnectReason, InvalidId, ObjectData},
6};
78use crate::{dispatch::ResourceData, Dispatch, DisplayHandle, Resource};
910/// A struct representing a Wayland client connected to your compositor.
11#[derive(Clone, Debug)]
12pub struct Client {
13pub(crate) id: ClientId,
14pub(crate) data: Arc<dyn ClientData>,
15}
1617impl Client {
18pub(crate) fn from_id(handle: &DisplayHandle, id: ClientId) -> Result<Self, InvalidId> {
19let data = handle.handle.get_client_data(id.clone())?;
20Ok(Self { id, data })
21 }
2223/// The backend [`ClientId`] of this client
24pub fn id(&self) -> ClientId {
25self.id.clone()
26 }
2728/// Access the data associated to this client
29 ///
30 /// Returns [`None`] if the provided `Data` type parameter is not the correct one.
31pub fn get_data<Data: ClientData + 'static>(&self) -> Option<&Data> {
32 (*self.data).downcast_ref()
33 }
3435/// 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>
42pub fn get_credentials(
43&self,
44 handle: &DisplayHandle,
45 ) -> Result<crate::backend::Credentials, InvalidId> {
46 handle.handle.get_client_credentials(self.id.clone())
47 }
4849/// 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.
54pub fn create_resource<
55 I: Resource + 'static,
56 U: Send + Sync + 'static,
57 D: Dispatch<I, U> + 'static,
58 >(
59&self,
60 handle: &DisplayHandle,
61 version: u32,
62 user_data: U,
63 ) -> Result<I, InvalidId> {
64let id = handle.handle.create_object::<D>(
65self.id.clone(),
66 I::interface(),
67 version,
68 Arc::new(ResourceData::<I, U>::new(user_data)) as Arc<_>,
69 )?;
70 I::from_id(handle, id)
71 }
7273/// Create a new Wayland object in the protocol state of this client, from an [`ObjectData`]
74 ///
75 /// This is a lower-level method than [`create_resource()`][Self::create_resource()], in case you need to
76 /// bypass the [`Dispatch`] machinery.
77 ///
78 /// The newly created resource should be immediately sent to the client through an associated event with
79 /// a `new_id` argument. Not doing so risks corrupting the protocol state and causing protocol errors at
80 /// a later time.
81pub fn create_resource_from_objdata<I: Resource + 'static, D: 'static>(
82&self,
83 handle: &DisplayHandle,
84 version: u32,
85 obj_data: Arc<dyn ObjectData<D>>,
86 ) -> Result<I, InvalidId> {
87let id =
88 handle.handle.create_object::<D>(self.id.clone(), I::interface(), version, obj_data)?;
89 I::from_id(handle, id)
90 }
9192/// Attempt to retrieve an object from this client's protocol state from its protocol id
93 ///
94 /// Will fail if either the provided protocol id does not correspond to any object, or if the
95 /// corresponding object is not of the interface `I`.
96pub fn object_from_protocol_id<I: Resource + 'static>(
97&self,
98 handle: &DisplayHandle,
99 protocol_id: u32,
100 ) -> Result<I, InvalidId> {
101let object_id =
102 handle.handle.object_for_protocol_id(self.id.clone(), I::interface(), protocol_id)?;
103 I::from_id(handle, object_id)
104 }
105106/// Kill this client by triggering a protocol error
107pub fn kill(&self, handle: &DisplayHandle, error: ProtocolError) {
108 handle.handle.kill_client(self.id.clone(), DisconnectReason::ProtocolError(error))
109 }
110}
111112impl PartialEq for Client {
113fn eq(&self, other: &Self) -> bool {
114self.id == other.id
115 }
116}