mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
layout: Round focus ring/border width to physical at the right place
Before this, focus ring/border width was incorrectly rounded only for layout config, which does not take into account window rules overrides. This means that setting width in window rules prevented correct rounding altogether. Tests didn't check this because window rules weren't tested. This commit also adds basic window rules random generation, making the tests catch this problem too.
This commit is contained in:
+1
-6
@@ -618,12 +618,7 @@ impl Options {
|
||||
}
|
||||
|
||||
fn adjusted_for_scale(mut self, scale: f64) -> Self {
|
||||
let round = |logical: f64| round_logical_in_physical_max1(scale, logical);
|
||||
|
||||
self.layout.gaps = round(self.layout.gaps);
|
||||
self.layout.focus_ring.width = round(self.layout.focus_ring.width);
|
||||
self.layout.border.width = round(self.layout.border.width);
|
||||
|
||||
self.layout.gaps = round_logical_in_physical_max1(scale, self.layout.gaps);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
+26
-6
@@ -40,12 +40,13 @@ struct TestWindowInner {
|
||||
is_pending_windowed_fullscreen: Cell<bool>,
|
||||
animate_next_configure: Cell<bool>,
|
||||
animation_snapshot: RefCell<Option<LayoutElementRenderSnapshot>>,
|
||||
rules: ResolvedWindowRules,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct TestWindow(Rc<TestWindowInner>);
|
||||
|
||||
#[derive(Debug, Clone, Copy, Arbitrary)]
|
||||
#[derive(Debug, Clone, Arbitrary)]
|
||||
struct TestWindowParams {
|
||||
#[proptest(strategy = "1..=5usize")]
|
||||
id: usize,
|
||||
@@ -56,6 +57,8 @@ struct TestWindowParams {
|
||||
bbox: Rectangle<i32, Logical>,
|
||||
#[proptest(strategy = "arbitrary_min_max_size()")]
|
||||
min_max_size: (Size<i32, Logical>, Size<i32, Logical>),
|
||||
#[proptest(strategy = "prop::option::of(arbitrary_rules())")]
|
||||
rules: Option<ResolvedWindowRules>,
|
||||
}
|
||||
|
||||
impl TestWindowParams {
|
||||
@@ -66,6 +69,7 @@ impl TestWindowParams {
|
||||
is_floating: false,
|
||||
bbox: Rectangle::from_size(Size::from((100, 200))),
|
||||
min_max_size: Default::default(),
|
||||
rules: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,6 +92,7 @@ impl TestWindow {
|
||||
is_pending_windowed_fullscreen: Cell::new(false),
|
||||
animate_next_configure: Cell::new(false),
|
||||
animation_snapshot: RefCell::new(None),
|
||||
rules: params.rules.unwrap_or(ResolvedWindowRules::empty()),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -262,8 +267,7 @@ impl LayoutElement for TestWindow {
|
||||
fn refresh(&self) {}
|
||||
|
||||
fn rules(&self) -> &ResolvedWindowRules {
|
||||
static EMPTY: ResolvedWindowRules = ResolvedWindowRules::empty();
|
||||
&EMPTY
|
||||
&self.0.rules
|
||||
}
|
||||
|
||||
fn take_animation_snapshot(&mut self) -> Option<LayoutElementRenderSnapshot> {
|
||||
@@ -345,6 +349,19 @@ fn arbitrary_min_max_size() -> impl Strategy<Value = (Size<i32, Logical>, Size<i
|
||||
]
|
||||
}
|
||||
|
||||
prop_compose! {
|
||||
fn arbitrary_rules()(
|
||||
focus_ring in arbitrary_focus_ring(),
|
||||
border in arbitrary_border(),
|
||||
) -> ResolvedWindowRules {
|
||||
ResolvedWindowRules {
|
||||
focus_ring,
|
||||
border,
|
||||
..ResolvedWindowRules::empty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn arbitrary_view_offset_gesture_delta() -> impl Strategy<Value = f64> {
|
||||
prop_oneof![(-10f64..10f64), (-50000f64..50000f64),]
|
||||
}
|
||||
@@ -891,6 +908,7 @@ impl Op {
|
||||
}
|
||||
}
|
||||
|
||||
let is_floating = params.is_floating;
|
||||
let win = TestWindow::new(params);
|
||||
layout.add_window(
|
||||
win,
|
||||
@@ -898,7 +916,7 @@ impl Op {
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
params.is_floating,
|
||||
is_floating,
|
||||
ActivateWindow::default(),
|
||||
);
|
||||
}
|
||||
@@ -959,6 +977,7 @@ impl Op {
|
||||
}
|
||||
}
|
||||
|
||||
let is_floating = params.is_floating;
|
||||
let win = TestWindow::new(params);
|
||||
layout.add_window(
|
||||
win,
|
||||
@@ -966,7 +985,7 @@ impl Op {
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
params.is_floating,
|
||||
is_floating,
|
||||
ActivateWindow::default(),
|
||||
);
|
||||
}
|
||||
@@ -1032,6 +1051,7 @@ impl Op {
|
||||
}
|
||||
}
|
||||
|
||||
let is_floating = params.is_floating;
|
||||
let win = TestWindow::new(params);
|
||||
layout.add_window(
|
||||
win,
|
||||
@@ -1039,7 +1059,7 @@ impl Op {
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
params.is_floating,
|
||||
is_floating,
|
||||
ActivateWindow::default(),
|
||||
);
|
||||
}
|
||||
|
||||
+16
-5
@@ -29,7 +29,9 @@ use crate::render_helpers::snapshot::RenderSnapshot;
|
||||
use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
|
||||
use crate::render_helpers::RenderTarget;
|
||||
use crate::utils::transaction::Transaction;
|
||||
use crate::utils::{baba_is_float_offset, round_logical_in_physical};
|
||||
use crate::utils::{
|
||||
baba_is_float_offset, round_logical_in_physical, round_logical_in_physical_max1,
|
||||
};
|
||||
|
||||
/// Toplevel window with decorations.
|
||||
#[derive(Debug)]
|
||||
@@ -228,16 +230,20 @@ impl<W: LayoutElement> Tile<W> {
|
||||
self.scale = scale;
|
||||
self.options = options;
|
||||
|
||||
let round_max1 = |logical| round_logical_in_physical_max1(self.scale, logical);
|
||||
|
||||
let rules = self.window.rules();
|
||||
|
||||
let border_config = self.options.layout.border.merged_with(&rules.border);
|
||||
let mut border_config = self.options.layout.border.merged_with(&rules.border);
|
||||
border_config.width = round_max1(border_config.width);
|
||||
self.border.update_config(border_config.into());
|
||||
|
||||
let focus_ring_config = self
|
||||
let mut focus_ring_config = self
|
||||
.options
|
||||
.layout
|
||||
.focus_ring
|
||||
.merged_with(&rules.focus_ring);
|
||||
focus_ring_config.width = round_max1(focus_ring_config.width);
|
||||
self.focus_ring.update_config(focus_ring_config);
|
||||
|
||||
let shadow_config = self.options.layout.shadow.merged_with(&rules.shadow);
|
||||
@@ -373,14 +379,19 @@ impl<W: LayoutElement> Tile<W> {
|
||||
}
|
||||
}
|
||||
|
||||
let round_max1 = |logical| round_logical_in_physical_max1(self.scale, logical);
|
||||
|
||||
let rules = self.window.rules();
|
||||
let border_config = self.options.layout.border.merged_with(&rules.border);
|
||||
let mut border_config = self.options.layout.border.merged_with(&rules.border);
|
||||
border_config.width = round_max1(border_config.width);
|
||||
self.border.update_config(border_config.into());
|
||||
let focus_ring_config = self
|
||||
|
||||
let mut focus_ring_config = self
|
||||
.options
|
||||
.layout
|
||||
.focus_ring
|
||||
.merged_with(&rules.focus_ring);
|
||||
focus_ring_config.width = round_max1(focus_ring_config.width);
|
||||
self.focus_ring.update_config(focus_ring_config);
|
||||
|
||||
let shadow_config = self.options.layout.shadow.merged_with(&rules.shadow);
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ pub enum WindowRef<'a> {
|
||||
}
|
||||
|
||||
/// Rules fully resolved for a window.
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct ResolvedWindowRules {
|
||||
/// Default width for this window.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user