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