diff --git a/jay-config/src/_private.rs b/jay-config/src/_private.rs index 1a5a5b62..ba22f5a8 100644 --- a/jay-config/src/_private.rs +++ b/jay-config/src/_private.rs @@ -84,6 +84,7 @@ pub enum ClientCriterionIpc { Sandboxed, Uid(i32), Pid(i32), + IsXwayland, } #[derive(Serialize, Deserialize, Clone, Debug, Hash, Eq, PartialEq)] diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 5deb5c9a..93993232 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -1544,6 +1544,7 @@ impl ConfigClient { ClientCriterion::Sandboxed => ClientCriterionIpc::Sandboxed, ClientCriterion::Uid(p) => ClientCriterionIpc::Uid(p), ClientCriterion::Pid(p) => ClientCriterionIpc::Pid(p), + ClientCriterion::IsXwayland => ClientCriterionIpc::IsXwayland, }; let res = self.send_with_response(&ClientMessage::CreateClientMatcher { criterion }); get_response!( diff --git a/jay-config/src/client.rs b/jay-config/src/client.rs index d8c5a547..9fed07ea 100644 --- a/jay-config/src/client.rs +++ b/jay-config/src/client.rs @@ -81,6 +81,8 @@ pub enum ClientCriterion<'a> { Uid(i32), /// Matches the process ID of the client. Pid(i32), + /// Matches if the client is Xwayland. + IsXwayland, } impl ClientCriterion<'_> { diff --git a/src/config/handler.rs b/src/config/handler.rs index c513894b..b329947e 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -1887,6 +1887,7 @@ impl ConfigProxyHandler { ClientCriterionIpc::Sandboxed => mgr.sandboxed(), ClientCriterionIpc::Uid(p) => mgr.uid(*p), ClientCriterionIpc::Pid(p) => mgr.pid(*p), + ClientCriterionIpc::IsXwayland => mgr.is_xwayland(), }; let cached = Rc::new(CachedCriterion { crit: criterion.clone(), diff --git a/src/criteria/clm.rs b/src/criteria/clm.rs index 7027e703..243ae514 100644 --- a/src/criteria/clm.rs +++ b/src/criteria/clm.rs @@ -7,6 +7,7 @@ use { CritDestroyListener, CritLiteralOrRegex, CritMatcherId, CritMatcherIds, CritMgrExt, CritUpstreamNode, FixedRootMatcher, RootMatcherMap, clm::clm_matchers::{ + clmm_is_xwayland::ClmMatchIsXwayland, clmm_pid::ClmMatchPid, clmm_sandboxed::ClmMatchSandboxed, clmm_string::{ @@ -44,6 +45,7 @@ pub struct ClMatcherManager { leaf_events: Rc>>>, constant: ClmFixedRootMatcher>>, sandboxed: ClmFixedRootMatcher, + is_xwayland: ClmFixedRootMatcher, matchers: Rc, } @@ -96,6 +98,7 @@ impl ClMatcherManager { Self { constant: CritMatchConstant::create(&matchers, ids), sandboxed: bool!(ClmMatchSandboxed), + is_xwayland: bool!(ClmMatchIsXwayland), changes: Default::default(), leaf_events: Default::default(), ids: ids.clone(), @@ -158,6 +161,7 @@ impl ClMatcherManager { unconditional!(uid); unconditional!(pid); fixed!(sandboxed); + fixed!(is_xwayland); self.constant[true].handle(data); } } @@ -185,6 +189,10 @@ impl ClMatcherManager { pub fn pid(&self, pid: i32) -> Rc { self.root(ClmMatchPid(pid as _)) } + + pub fn is_xwayland(&self) -> Rc { + self.is_xwayland[true].clone() + } } impl CritTarget for Rc { diff --git a/src/criteria/clm/clm_matchers.rs b/src/criteria/clm/clm_matchers.rs index 422a44f4..bd661aa4 100644 --- a/src/criteria/clm/clm_matchers.rs +++ b/src/criteria/clm/clm_matchers.rs @@ -17,6 +17,7 @@ macro_rules! fixed_root_criterion { }; } +pub mod clmm_is_xwayland; pub mod clmm_pid; pub mod clmm_sandboxed; pub mod clmm_string; diff --git a/src/criteria/clm/clm_matchers/clmm_is_xwayland.rs b/src/criteria/clm/clm_matchers/clmm_is_xwayland.rs new file mode 100644 index 00000000..4f71c47f --- /dev/null +++ b/src/criteria/clm/clm_matchers/clmm_is_xwayland.rs @@ -0,0 +1,14 @@ +use { + crate::{client::Client, criteria::crit_graph::CritFixedRootCriterion}, + std::rc::Rc, +}; + +pub struct ClmMatchIsXwayland(pub bool); + +fixed_root_criterion!(ClmMatchIsXwayland, is_xwayland); + +impl CritFixedRootCriterion> for ClmMatchIsXwayland { + fn matches(&self, data: &Rc) -> bool { + data.is_xwayland + } +} diff --git a/toml-config/src/config.rs b/toml-config/src/config.rs index 381b24f4..207adfc9 100644 --- a/toml-config/src/config.rs +++ b/toml-config/src/config.rs @@ -234,6 +234,7 @@ pub struct ClientMatch { pub sandboxed: Option, pub uid: Option, pub pid: Option, + pub is_xwayland: Option, } #[derive(Debug, Clone)] diff --git a/toml-config/src/config/parsers/client_match.rs b/toml-config/src/config/parsers/client_match.rs index a6076b46..31be8bbb 100644 --- a/toml-config/src/config/parsers/client_match.rs +++ b/toml-config/src/config/parsers/client_match.rs @@ -49,7 +49,7 @@ impl Parser for ClientMatchParser<'_> { sandbox_app_id, sandbox_app_id_regex, ), - (sandbox_instance_id, sandbox_instance_id_regex, uid, pid), + (sandbox_instance_id, sandbox_instance_id_regex, uid, pid, is_xwayland), ) = ext.extract(( ( opt(str("name")), @@ -68,6 +68,7 @@ impl Parser for ClientMatchParser<'_> { opt(str("sandbox-instance-id-regex")), opt(s32("uid")), opt(s32("pid")), + opt(bol("is-xwayland")), ), ))?; let mut not = None; @@ -110,6 +111,7 @@ impl Parser for ClientMatchParser<'_> { sandboxed: sandboxed.despan(), uid: uid.despan(), pid: pid.despan(), + is_xwayland: is_xwayland.despan(), }) } } diff --git a/toml-config/src/rules.rs b/toml-config/src/rules.rs index e5ce8978..9f482fdb 100644 --- a/toml-config/src/rules.rs +++ b/toml-config/src/rules.rs @@ -123,6 +123,7 @@ impl Rule for ClientRule { value!(Uid, uid); value!(Pid, pid); bool!(Sandboxed, sandboxed); + bool!(IsXwayland, is_xwayland); Some(()) } diff --git a/toml-spec/spec/spec.generated.json b/toml-spec/spec/spec.generated.json index af20bc5f..3ec70136 100644 --- a/toml-spec/spec/spec.generated.json +++ b/toml-spec/spec/spec.generated.json @@ -567,6 +567,10 @@ "pid": { "type": "integer", "description": "Matches the process ID of the client." + }, + "is-xwayland": { + "type": "boolean", + "description": "Matches if the client is/isn't Xwayland." } }, "required": [] diff --git a/toml-spec/spec/spec.generated.md b/toml-spec/spec/spec.generated.md index 19878aaf..a20505dd 100644 --- a/toml-spec/spec/spec.generated.md +++ b/toml-spec/spec/spec.generated.md @@ -887,6 +887,12 @@ The table has the following fields: The numbers should be integers. +- `is-xwayland` (optional): + + Matches if the client is/isn't Xwayland. + + The value of this field should be a boolean. + ### `ClientMatchExactly` diff --git a/toml-spec/spec/spec.yaml b/toml-spec/spec/spec.yaml index fc0ae7c7..1c93dd78 100644 --- a/toml-spec/spec/spec.yaml +++ b/toml-spec/spec/spec.yaml @@ -3247,6 +3247,10 @@ ClientMatch: integer_only: true required: false description: Matches the process ID of the client. + is-xwayland: + kind: boolean + required: false + description: Matches if the client is/isn't Xwayland. ClientMatchExactly: