From db49deb7fd2fbe805ceec060aa4dec65009ad7a7 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 19 Mar 2024 18:22:25 +0400 Subject: Implement draw-border-with-background window rule --- src/handlers/compositor.rs | 2 +- src/layout/mod.rs | 8 ++++++++ src/layout/tile.rs | 26 ++++++++++++++++++++++---- src/window/mapped.rs | 4 ++++ src/window/mod.rs | 27 +++++++++++++++++++++++++-- 5 files changed, 60 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs index 188ba831..19489f2c 100644 --- a/src/handlers/compositor.rs +++ b/src/handlers/compositor.rs @@ -123,7 +123,7 @@ impl CompositorHandler for State { (rules, width, is_full_width, output) } else { error!("window map must happen after initial configure"); - (ResolvedWindowRules::default(), None, false, None) + (ResolvedWindowRules::empty(), None, false, None) }; let parent = window diff --git a/src/layout/mod.rs b/src/layout/mod.rs index c2c4bf4e..7162c3e3 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -49,6 +49,7 @@ use self::workspace::{compute_working_area, Column, ColumnWidth, OutputId, Works use crate::niri_render_elements; use crate::render_helpers::renderer::NiriRenderer; use crate::utils::output_size; +use crate::window::ResolvedWindowRules; pub mod focus_ring; pub mod monitor; @@ -121,6 +122,8 @@ pub trait LayoutElement { /// This *will* switch immediately after a [`LayoutElement::request_fullscreen()`] call. fn is_pending_fullscreen(&self) -> bool; + fn rules(&self) -> &ResolvedWindowRules; + /// Runs periodic clean-up tasks. fn refresh(&self); } @@ -1905,6 +1908,11 @@ mod tests { } fn refresh(&self) {} + + fn rules(&self) -> &ResolvedWindowRules { + static EMPTY: ResolvedWindowRules = ResolvedWindowRules::empty(); + &EMPTY + } } fn arbitrary_bbox() -> impl Strategy> { diff --git a/src/layout/tile.rs b/src/layout/tile.rs index 589b2fc0..0609583e 100644 --- a/src/layout/tile.rs +++ b/src/layout/tile.rs @@ -85,11 +85,22 @@ impl Tile { } pub fn advance_animations(&mut self, current_time: Duration, is_active: bool) { + let draw_border_with_background = self + .window + .rules() + .draw_border_with_background + .unwrap_or_else(|| !self.window.has_ssd()); self.border - .update(self.window.size(), self.window.has_ssd()); + .update(self.window.size(), !draw_border_with_background); self.border.set_active(is_active); - self.focus_ring.update(self.tile_size(), self.has_ssd()); + let draw_focus_ring_with_background = if self.effective_border_width().is_some() { + false + } else { + draw_border_with_background + }; + self.focus_ring + .update(self.tile_size(), !draw_focus_ring_with_background); self.focus_ring.set_active(is_active); match &mut self.open_animation { @@ -295,8 +306,15 @@ impl Tile { size } - pub fn has_ssd(&self) -> bool { - self.effective_border_width().is_some() || self.window.has_ssd() + pub fn draw_border_with_background(&self) -> bool { + if self.effective_border_width().is_some() { + return false; + } + + self.window + .rules() + .draw_border_with_background + .unwrap_or_else(|| !self.window.has_ssd()) } fn render_inner( diff --git a/src/window/mapped.rs b/src/window/mapped.rs index 6afd995e..b5caf8e2 100644 --- a/src/window/mapped.rs +++ b/src/window/mapped.rs @@ -184,4 +184,8 @@ impl LayoutElement for Mapped { fn refresh(&self) { self.window.refresh(); } + + fn rules(&self) -> &ResolvedWindowRules { + &self.rules + } } diff --git a/src/window/mod.rs b/src/window/mod.rs index 25b3531f..bb6f2151 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -13,7 +13,7 @@ pub mod unmapped; pub use unmapped::{InitialConfigureState, Unmapped}; /// Rules fully resolved for a window. -#[derive(Debug, Default, PartialEq)] +#[derive(Debug, PartialEq)] pub struct ResolvedWindowRules { /// Default width for this window. /// @@ -39,13 +39,32 @@ pub struct ResolvedWindowRules { pub max_width: Option, /// Extra bound on the maximum window height. pub max_height: Option, + + /// Whether or not to draw the border with a solid background. + /// + /// `None` means using the SSD heuristic. + pub draw_border_with_background: Option, } impl ResolvedWindowRules { + pub const fn empty() -> Self { + Self { + default_width: None, + open_on_output: None, + open_maximized: None, + open_fullscreen: None, + min_width: None, + min_height: None, + max_width: None, + max_height: None, + draw_border_with_background: None, + } + } + pub fn compute(rules: &[WindowRule], toplevel: &ToplevelSurface) -> Self { let _span = tracy_client::span!("ResolvedWindowRules::compute"); - let mut resolved = ResolvedWindowRules::default(); + let mut resolved = ResolvedWindowRules::empty(); with_states(toplevel.wl_surface(), |states| { let role = states @@ -100,6 +119,10 @@ impl ResolvedWindowRules { if let Some(x) = rule.max_height { resolved.max_height = Some(x); } + + if let Some(x) = rule.draw_border_with_background { + resolved.draw_border_with_background = Some(x); + } } resolved.open_on_output = open_on_output.map(|x| x.to_owned()); -- cgit