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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use std::sync::Arc;

#[cfg(feature = "use_system_lib")]
use wayland_sys::server::wl_client;

use crate::imp::ClientInner;

use crate::{Interface, Main, Resource, UserDataMap};

/// Holds the client credentials the can be
/// retrieved from the socket with [`Client::credentials`]
#[derive(Debug, Clone, Copy)]
pub struct Credentials {
    /// pid of the client
    pub pid: libc::pid_t,
    /// uid of the client
    pub uid: libc::uid_t,
    /// gid of the client
    pub gid: libc::gid_t,
}

impl From<nix::sys::socket::UnixCredentials> for Credentials {
    fn from(credentials: nix::sys::socket::UnixCredentials) -> Self {
        Self { pid: credentials.pid(), uid: credentials.uid(), gid: credentials.gid() }
    }
}

/// A handle to a client connected to your server
///
/// There can be several handles referring to the same client.
#[derive(Clone, PartialEq)]
pub struct Client {
    inner: ClientInner,
}

impl std::fmt::Debug for Client {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("Client { ... }")
    }
}

impl Client {
    #[cfg(feature = "use_system_lib")]
    /// Creates a client from a pointer
    ///
    /// # Safety
    ///
    /// The provided pointer must be a valid pointer from `libwayland-server`.
    pub unsafe fn from_ptr(ptr: *mut wl_client) -> Client {
        Client { inner: ClientInner::from_ptr(ptr) }
    }

    #[cfg(feature = "use_system_lib")]
    /// Returns a pointer to the underlying `wl_client` of `libwayland-server`
    pub fn c_ptr(&self) -> *mut wl_client {
        self.inner.ptr()
    }

    pub(crate) fn make(inner: ClientInner) -> Client {
        Client { inner }
    }

    /// Checks whether this client is still connected to the server
    pub fn alive(&self) -> bool {
        self.inner.alive()
    }

    /// Checks whether `self` and `other` refer to the same client
    pub fn equals(&self, other: &Client) -> bool {
        self.inner.equals(&other.inner)
    }

    /// Flushes the pending events to this client
    pub fn flush(&self) {
        self.inner.flush()
    }

    /// Kills this client
    ///
    /// Does nothing if the client is already dead.
    pub fn kill(&self) {
        self.inner.kill()
    }

    /// Returns the [`Credentials`] from the socket of this
    /// client.
    ///
    /// The credentials come from getsockopt() with SO_PEERCRED, on the client socket fd.
    ///
    /// Be aware that for clients that a compositor forks and execs and then connects using
    /// socketpair(), this function will return the credentials for the compositor.
    /// The credentials for the socketpair are set at creation time in the compositor.
    ///
    /// Returns [None] if the client is already dead.
    pub fn credentials(&self) -> Option<Credentials> {
        self.inner.credentials()
    }

    /// Returns a reference to the `UserDataMap` associated with this client
    ///
    /// See `UserDataMap` documentation for details about its use.
    pub fn data_map(&self) -> &UserDataMap {
        self.inner.user_data_map()
    }

    /// Adds a destructor for this client
    ///
    /// This filter will be called when the client disconnects or is killed.
    /// It has access to the `UserDataMap` associated with this client.
    ///
    /// You can add several destructors which will all be called sequentially. Note
    /// that if you accidentally add two copies of the same closure, it will be called
    /// twice.
    ///
    /// The destructors will be executed on the thread containing the wayland event loop.
    ///
    /// **Panics**: This function will panic if called from an other thread than the one
    /// hosting the Display.
    pub fn add_destructor(&self, destructor: crate::Filter<Arc<UserDataMap>>) {
        self.inner.add_destructor(move |ud, data| destructor.send(ud, data));
    }

    /// Creates a new resource for this client
    ///
    /// To ensure the state coherence between client and server, this
    /// resource should immediately be assigned to a filter and sent to the client
    /// through an appropriate event. Failure to do so will likely cause
    /// protocol errors.
    ///
    /// **Panics**: This function will panic if called from an other thread than the one
    /// hosting the Display.
    pub fn create_resource<I: Interface + From<Resource<I>> + AsRef<Resource<I>>>(
        &self,
        version: u32,
    ) -> Option<Main<I>> {
        self.inner.create_resource::<I>(version).map(Main::wrap)
    }

    /// Retrieve a resource of this client for a given id
    ///
    /// You need to know in advance which is the interface of this object. If the given id does
    /// not correspond to an existing object or the existing object is not of the requested
    /// interface, this call returns `None`.
    pub fn get_resource<I: Interface + From<Resource<I>> + AsRef<Resource<I>>>(
        &self,
        id: u32,
    ) -> Option<I> {
        self.inner.get_resource::<I>(id).map(|obj| Resource::wrap(obj).into())
    }
}