wl_proxy/
client.rs

1//! Wayland clients connected to the proxy.
2
3use {
4    crate::{
5        endpoint::Endpoint, handler::HandlerHolder, object::Object,
6        protocols::wayland::wl_display::WlDisplay, state::State,
7    },
8    std::{cell::Cell, rc::Rc},
9};
10
11#[cfg(test)]
12mod tests;
13
14/// A client connected to the proxy.
15///
16/// Clients are usually created by having them connect to an
17/// [`Acceptor`](crate::acceptor::Acceptor). See [`State::create_acceptor`].
18///
19/// Clients can also be created manually with [`State::connect`] and
20/// [`State::add_client`].
21pub struct Client {
22    pub(crate) state: Rc<State>,
23    pub(crate) endpoint: Rc<Endpoint>,
24    pub(crate) display: Rc<WlDisplay>,
25    pub(crate) destroyed: Cell<bool>,
26    pub(crate) handler: HandlerHolder<dyn ClientHandler>,
27}
28
29/// A handler for events emitted by a [`Client`].
30pub trait ClientHandler: 'static {
31    /// The client disconnected.
32    ///
33    /// This is not emitted if the client is disconnected with [`Client::disconnect`].
34    fn disconnected(self: Box<Self>) {
35        // nothing
36    }
37}
38
39impl Client {
40    /// Sets a new handler.
41    pub fn set_handler(&self, handler: impl ClientHandler) {
42        self.set_boxed_handler(Box::new(handler));
43    }
44
45    /// Sets a new, already boxed handler.
46    pub fn set_boxed_handler(&self, handler: Box<dyn ClientHandler>) {
47        if self.destroyed.get() {
48            return;
49        }
50        self.handler.set(Some(handler));
51    }
52
53    /// Unsets the handler.
54    pub fn unset_handler(&self) {
55        self.handler.set(None);
56    }
57
58    /// Returns all objects associated with this client.
59    ///
60    /// This can be used when a client disconnects to perform cleanup in a multi-client
61    /// proxy.
62    pub fn objects(&self, objects: &mut Vec<Rc<dyn Object>>) {
63        objects.extend(self.endpoint.objects.borrow().values().cloned());
64    }
65
66    /// Returns the wl_display object of this client.
67    pub fn display(&self) -> &Rc<WlDisplay> {
68        &self.display
69    }
70
71    /// Disconnects this client.
72    ///
73    /// The [`ClientHandler::disconnected`] event is not emitted.
74    pub fn disconnect(&self) {
75        if self.destroyed.replace(true) {
76            return;
77        }
78        let proxies = &mut *self.state.object_stash.borrow();
79        for (_, object) in self.endpoint.objects.borrow_mut().drain() {
80            let core = object.core();
81            core.client.take();
82            core.client_id.take();
83            core.client_obj_id.take();
84            proxies.push(object);
85        }
86        self.handler.set(None);
87        self.state.remove_endpoint(&self.endpoint);
88    }
89}