jay_config/
client.rs

1//! Tools for inspecting and manipulating clients.
2
3use {
4    serde::{Deserialize, Serialize},
5    std::ops::Deref,
6};
7
8/// A client connected to the compositor.
9#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
10pub struct Client(pub u64);
11
12impl Client {
13    /// Returns whether the client exists.
14    pub fn exists(self) -> bool {
15        self.0 != 0 && get!(false).client_exists(self)
16    }
17
18    /// Returns whether the client does not exist.
19    ///
20    /// This is a shorthand for `!self.exists()`.
21    pub fn does_not_exist(self) -> bool {
22        !self.exists()
23    }
24
25    /// Returns whether this client is XWayland.
26    pub fn is_xwayland(self) -> bool {
27        get!(false).client_is_xwayland(self)
28    }
29
30    /// Disconnects the client.
31    pub fn kill(self) {
32        get!().client_kill(self)
33    }
34}
35
36/// Returns all current clients.
37pub fn clients() -> Vec<Client> {
38    get!().clients()
39}
40
41/// A client matcher.
42#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
43pub struct ClientMatcher(pub u64);
44
45/// A matched client.
46#[derive(Serialize, Deserialize, Copy, Clone, Debug, Hash, Eq, PartialEq)]
47pub struct MatchedClient {
48    pub(crate) matcher: ClientMatcher,
49    pub(crate) client: Client,
50}
51
52/// A criterion for matching a client.
53#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
54#[non_exhaustive]
55pub enum ClientCriterion<'a> {
56    /// Matches if the contained matcher matches.
57    Matcher(ClientMatcher),
58    /// Matches if the contained criterion does not match.
59    Not(&'a ClientCriterion<'a>),
60    /// Matches if all of the contained criteria match.
61    All(&'a [ClientCriterion<'a>]),
62    /// Matches if any of the contained criteria match.
63    Any(&'a [ClientCriterion<'a>]),
64    /// Matches if an exact number of the contained criteria match.
65    Exactly(usize, &'a [ClientCriterion<'a>]),
66    /// Matches the engine name of the client's sandbox verbatim.
67    SandboxEngine(&'a str),
68    /// Matches the engine name of the client's sandbox with a regular expression.
69    SandboxEngineRegex(&'a str),
70    /// Matches the app id of the client's sandbox verbatim.
71    SandboxAppId(&'a str),
72    /// Matches the app id of the client's sandbox with a regular expression.
73    SandboxAppIdRegex(&'a str),
74    /// Matches the instance id of the client's sandbox verbatim.
75    SandboxInstanceId(&'a str),
76    /// Matches the instance id of the client's sandbox with a regular expression.
77    SandboxInstanceIdRegex(&'a str),
78    /// Matches if the client is sandboxed.
79    Sandboxed,
80    /// Matches the user ID of the client.
81    Uid(i32),
82    /// Matches the process ID of the client.
83    Pid(i32),
84    /// Matches if the client is Xwayland.
85    IsXwayland,
86    /// Matches the `/proc/pid/comm` of the client verbatim.
87    Comm(&'a str),
88    /// Matches the `/proc/pid/comm` of the client with a regular expression.
89    CommRegex(&'a str),
90    /// Matches the `/proc/pid/exe` of the client verbatim.
91    Exe(&'a str),
92    /// Matches the `/proc/pid/exe` of the client with a regular expression.
93    ExeRegex(&'a str),
94}
95
96impl ClientCriterion<'_> {
97    /// Converts the criterion to a matcher.
98    pub fn to_matcher(self) -> ClientMatcher {
99        get!(ClientMatcher(0)).create_client_matcher(self)
100    }
101
102    /// Binds a function to execute when the criterion matches a client.
103    ///
104    /// This leaks the matcher.
105    pub fn bind<F: FnMut(MatchedClient) + 'static>(self, cb: F) {
106        self.to_matcher().bind(cb);
107    }
108}
109
110impl ClientMatcher {
111    /// Destroys the matcher.
112    ///
113    /// Any bound callback will no longer be executed.
114    pub fn destroy(self) {
115        get!().destroy_client_matcher(self);
116    }
117
118    /// Sets a function to execute when the criterion matches a client.
119    ///
120    /// Replaces any already bound callback.
121    pub fn bind<F: FnMut(MatchedClient) + 'static>(self, cb: F) {
122        get!().set_client_matcher_handler(self, cb);
123    }
124}
125
126impl MatchedClient {
127    /// Returns the client that matched.
128    pub fn client(self) -> Client {
129        self.client
130    }
131
132    /// Returns the matcher.
133    pub fn matcher(self) -> ClientMatcher {
134        self.matcher
135    }
136
137    /// Latches a function to be executed when the client no longer matches the criteria.
138    pub fn latch<F: FnOnce() + 'static>(self, cb: F) {
139        get!().set_client_matcher_latch_handler(self.matcher, self.client, cb);
140    }
141}
142
143impl Deref for MatchedClient {
144    type Target = Client;
145
146    fn deref(&self) -> &Self::Target {
147        &self.client
148    }
149}