diff --git a/jay-config/src/_private.rs b/jay-config/src/_private.rs index 59f34023..e7303d20 100644 --- a/jay-config/src/_private.rs +++ b/jay-config/src/_private.rs @@ -115,6 +115,7 @@ pub enum WindowCriterionIpc { Visible, Urgent, SeatFocus(Seat), + Fullscreen, } #[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 cacd9e91..09660de4 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -1661,6 +1661,7 @@ impl ConfigClient { WindowCriterion::Visible => WindowCriterionIpc::Visible, WindowCriterion::Urgent => WindowCriterionIpc::Urgent, WindowCriterion::Focus(seat) => WindowCriterionIpc::SeatFocus(seat), + WindowCriterion::Fullscreen => WindowCriterionIpc::Fullscreen, }; let res = self.send_with_response(&ClientMessage::CreateWindowMatcher { criterion }); get_response!( diff --git a/jay-config/src/window.rs b/jay-config/src/window.rs index ce7a6918..cb105c0b 100644 --- a/jay-config/src/window.rs +++ b/jay-config/src/window.rs @@ -253,6 +253,8 @@ pub enum WindowCriterion<'a> { Urgent, /// Matches if the window has the keyboard focus of the seat. Focus(Seat), + /// Matches if the window is fullscreen. + Fullscreen, } impl WindowCriterion<'_> { diff --git a/src/config/handler.rs b/src/config/handler.rs index 0f675b0d..62c957a1 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -2001,6 +2001,7 @@ impl ConfigProxyHandler { WindowCriterionIpc::Visible => mgr.visible(), WindowCriterionIpc::Urgent => mgr.urgent(), WindowCriterionIpc::SeatFocus(seat) => mgr.seat_focus(&*self.get_seat(*seat)?), + WindowCriterionIpc::Fullscreen => mgr.fullscreen(), }; let cached = Rc::new(CachedCriterion { crit: criterion.clone(), diff --git a/src/criteria/tlm.rs b/src/criteria/tlm.rs index 7a2652e6..658444b1 100644 --- a/src/criteria/tlm.rs +++ b/src/criteria/tlm.rs @@ -14,6 +14,7 @@ use { tlm::tlm_matchers::{ tlmm_client::TlmMatchClient, tlmm_floating::TlmMatchFloating, + tlmm_fullscreen::TlmMatchFullscreen, tlmm_kind::TlmMatchKind, tlmm_seat_focus::TlmMatchSeatFocus, tlmm_string::{TlmMatchAppId, TlmMatchTitle}, @@ -47,6 +48,7 @@ bitflags! { TL_CHANGED_VISIBLE = 1 << 5, TL_CHANGED_URGENT = 1 << 6, TL_CHANGED_SEAT_FOCI = 1 << 7, + TL_CHANGED_FULLSCREEN = 1 << 8, } type TlmFixedRootMatcher = FixedRootMatcher; @@ -59,6 +61,7 @@ pub struct TlMatcherManager { floating: TlmFixedRootMatcher, visible: TlmFixedRootMatcher, urgent: TlmFixedRootMatcher, + fullscreen: TlmFixedRootMatcher, matchers: Rc, } @@ -113,6 +116,7 @@ impl TlMatcherManager { floating: bool!(TlmMatchFloating), visible: bool!(TlmMatchVisible), urgent: bool!(TlmMatchUrgent), + fullscreen: bool!(TlmMatchFullscreen), changes: Default::default(), leaf_events: Default::default(), ids: ids.clone(), @@ -187,6 +191,7 @@ impl TlMatcherManager { fixed_conditional!(TL_CHANGED_FLOATING, floating); fixed_conditional!(TL_CHANGED_VISIBLE, visible); fixed_conditional!(TL_CHANGED_URGENT, urgent); + fixed_conditional!(TL_CHANGED_FULLSCREEN, fullscreen); false } @@ -257,6 +262,7 @@ impl TlMatcherManager { fixed_conditional!(TL_CHANGED_FLOATING, floating); fixed_conditional!(TL_CHANGED_VISIBLE, visible); fixed_conditional!(TL_CHANGED_URGENT, urgent); + fixed_conditional!(TL_CHANGED_FULLSCREEN, fullscreen); } pub fn title(&self, string: CritLiteralOrRegex) -> Rc { @@ -283,6 +289,10 @@ impl TlMatcherManager { self.visible[true].clone() } + pub fn fullscreen(&self) -> Rc { + self.fullscreen[true].clone() + } + pub fn urgent(&self) -> Rc { self.urgent[true].clone() } diff --git a/src/criteria/tlm/tlm_matchers.rs b/src/criteria/tlm/tlm_matchers.rs index 1d5bd6ec..550fc739 100644 --- a/src/criteria/tlm/tlm_matchers.rs +++ b/src/criteria/tlm/tlm_matchers.rs @@ -19,6 +19,7 @@ macro_rules! fixed_root_criterion { pub mod tlmm_client; pub mod tlmm_floating; +pub mod tlmm_fullscreen; pub mod tlmm_kind; pub mod tlmm_seat_focus; pub mod tlmm_string; diff --git a/src/criteria/tlm/tlm_matchers/tlmm_fullscreen.rs b/src/criteria/tlm/tlm_matchers/tlmm_fullscreen.rs new file mode 100644 index 00000000..5ed21689 --- /dev/null +++ b/src/criteria/tlm/tlm_matchers/tlmm_fullscreen.rs @@ -0,0 +1,11 @@ +use crate::{criteria::crit_graph::CritFixedRootCriterion, tree::ToplevelData}; + +pub struct TlmMatchFullscreen(pub bool); + +fixed_root_criterion!(TlmMatchFullscreen, fullscreen); + +impl CritFixedRootCriterion for TlmMatchFullscreen { + fn matches(&self, data: &ToplevelData) -> bool { + data.is_fullscreen.get() + } +} diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index afcf0e02..bab92811 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -4,8 +4,9 @@ use { criteria::{ CritDestroyListener, CritMatcherId, tlm::{ - TL_CHANGED_APP_ID, TL_CHANGED_DESTROYED, TL_CHANGED_FLOATING, TL_CHANGED_NEW, - TL_CHANGED_TITLE, TL_CHANGED_URGENT, TL_CHANGED_VISIBLE, TlMatcherChange, + TL_CHANGED_APP_ID, TL_CHANGED_DESTROYED, TL_CHANGED_FLOATING, + TL_CHANGED_FULLSCREEN, TL_CHANGED_NEW, TL_CHANGED_TITLE, TL_CHANGED_URGENT, + TL_CHANGED_VISIBLE, TlMatcherChange, }, }, ifs::{ @@ -579,6 +580,7 @@ impl ToplevelData { }); drop(data); self.is_fullscreen.set(true); + self.property_changed(TL_CHANGED_FULLSCREEN); node.tl_set_parent(ws.clone()); ws.set_fullscreen_node(&node); node.clone() @@ -601,6 +603,7 @@ impl ToplevelData { } }; self.is_fullscreen.set(false); + self.property_changed(TL_CHANGED_FULLSCREEN); match fd.workspace.fullscreen.get() { None => { log::error!( diff --git a/toml-config/src/config.rs b/toml-config/src/config.rs index dedc5049..34e54f75 100644 --- a/toml-config/src/config.rs +++ b/toml-config/src/config.rs @@ -263,6 +263,7 @@ pub struct WindowMatch { pub visible: Option, pub urgent: Option, pub focused: Option, + pub fullscreen: Option, } #[derive(Debug, Clone)] diff --git a/toml-config/src/config/parsers/window_match.rs b/toml-config/src/config/parsers/window_match.rs index 5f66362a..f2a51571 100644 --- a/toml-config/src/config/parsers/window_match.rs +++ b/toml-config/src/config/parsers/window_match.rs @@ -56,7 +56,7 @@ impl Parser for WindowMatchParser<'_> { title, title_regex, ), - (app_id, app_id_regex, floating, visible, urgent, focused), + (app_id, app_id_regex, floating, visible, urgent, focused, fullscreen), ) = ext.extract(( ( opt(str("name")), @@ -76,6 +76,7 @@ impl Parser for WindowMatchParser<'_> { opt(bol("visible")), opt(bol("urgent")), opt(bol("focused")), + opt(bol("fullscreen")), ), ))?; let mut not = None; @@ -125,6 +126,7 @@ impl Parser for WindowMatchParser<'_> { visible: visible.despan(), urgent: urgent.despan(), focused: focused.despan(), + fullscreen: fullscreen.despan(), types, client, }) diff --git a/toml-config/src/rules.rs b/toml-config/src/rules.rs index a37a0ab5..31f40a94 100644 --- a/toml-config/src/rules.rs +++ b/toml-config/src/rules.rs @@ -261,6 +261,7 @@ impl Rule for WindowRule { bool!(Floating, floating); bool!(Visible, visible); bool!(Urgent, urgent); + bool!(Fullscreen, fullscreen); if let Some(value) = match_.focused { let crit = WindowCriterion::Focus(state.persistent.seat); let matcher = match value { diff --git a/toml-spec/spec/spec.generated.json b/toml-spec/spec/spec.generated.json index 953900aa..fad46f11 100644 --- a/toml-spec/spec/spec.generated.json +++ b/toml-spec/spec/spec.generated.json @@ -1811,6 +1811,10 @@ "focused": { "type": "boolean", "description": "Matches if the window has/hasn't the keyboard focus." + }, + "fullscreen": { + "type": "boolean", + "description": "Matches if the window is/isn't fullscreen." } }, "required": [] diff --git a/toml-spec/spec/spec.generated.md b/toml-spec/spec/spec.generated.md index 058d2eda..66a42572 100644 --- a/toml-spec/spec/spec.generated.md +++ b/toml-spec/spec/spec.generated.md @@ -4058,6 +4058,12 @@ The table has the following fields: The value of this field should be a boolean. +- `fullscreen` (optional): + + Matches if the window is/isn't fullscreen. + + The value of this field should be a boolean. + ### `WindowMatchExactly` diff --git a/toml-spec/spec/spec.yaml b/toml-spec/spec/spec.yaml index 3f88b423..98c8f37d 100644 --- a/toml-spec/spec/spec.yaml +++ b/toml-spec/spec/spec.yaml @@ -3499,6 +3499,10 @@ WindowMatch: kind: boolean required: false description: Matches if the window has/hasn't the keyboard focus. + fullscreen: + kind: boolean + required: false + description: Matches if the window is/isn't fullscreen. WindowMatchExactly: