aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-12-25 17:26:05 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-12-30 20:12:37 +0300
commit2f380de73b0c4c6dddcd14ff71260c0882213077 (patch)
treebc0febcede9e968761ffcdc419eeca0c5e726730 /src
parente3a9a39c9aa106186272b60cda3d5a5177e7ee33 (diff)
downloadniri-2f380de73b0c4c6dddcd14ff71260c0882213077.tar.gz
niri-2f380de73b0c4c6dddcd14ff71260c0882213077.tar.bz2
niri-2f380de73b0c4c6dddcd14ff71260c0882213077.zip
floating: Take into account non-fixed min/max size window rule
Diffstat (limited to 'src')
-rw-r--r--src/layout/floating.rs15
-rw-r--r--src/layout/mod.rs31
-rw-r--r--src/tests/floating.rs69
-rw-r--r--src/utils/mod.rs10
4 files changed, 102 insertions, 23 deletions
diff --git a/src/layout/floating.rs b/src/layout/floating.rs
index dfeb18c1..39adf7aa 100644
--- a/src/layout/floating.rs
+++ b/src/layout/floating.rs
@@ -20,7 +20,7 @@ use crate::render_helpers::RenderTarget;
use crate::utils::transaction::TransactionBlocker;
use crate::utils::{
center_preferring_top_left_in_area, clamp_preferring_top_left_in_area, ensure_min_max_size,
- ResizeEdge,
+ ensure_min_max_size_maybe_zero, ResizeEdge,
};
use crate::window::ResolvedWindowRules;
@@ -386,15 +386,14 @@ impl<W: LayoutElement> FloatingSpace<W> {
// fullscreen until now), fall back to (0, 0).
floating_size.unwrap_or_else(|| win.expected_size().unwrap_or_default())
};
- // Make sure fixed-size through window rules keeps working.
+
+ // Apply min/max size window rules. If requesting a concrete size, apply completely; if
+ // requesting (0, 0), apply only when min/max results in a fixed size.
let min_size = win.min_size();
let max_size = win.max_size();
- if min_size.w != 0 && min_size.w == max_size.w {
- size.w = min_size.w;
- }
- if min_size.h != 0 && min_size.h == max_size.h {
- size.h = min_size.h;
- }
+ size.w = ensure_min_max_size_maybe_zero(size.w, min_size.w, max_size.w);
+ size.h = ensure_min_max_size_maybe_zero(size.h, min_size.h, max_size.h);
+
win.request_size_once(size, true);
if activate || self.tiles.is_empty() {
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index a09a9988..53549154 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -62,7 +62,10 @@ use crate::render_helpers::texture::TextureBuffer;
use crate::render_helpers::{BakedBuffer, RenderTarget, SplitElements};
use crate::rubber_band::RubberBand;
use crate::utils::transaction::{Transaction, TransactionBlocker};
-use crate::utils::{output_matches_name, output_size, round_logical_in_physical_max1, ResizeEdge};
+use crate::utils::{
+ ensure_min_max_size_maybe_zero, output_matches_name, output_size,
+ round_logical_in_physical_max1, ResizeEdge,
+};
use crate::window::ResolvedWindowRules;
pub mod closing_window;
@@ -2698,15 +2701,15 @@ impl<W: LayoutElement> Layout<W> {
let win = move_.tile.window_mut();
let mut size =
floating_size.unwrap_or_else(|| win.expected_size().unwrap_or_default());
- // Make sure fixed-size through window rules keeps working.
+
+ // Apply min/max size window rules. If requesting a concrete size, apply
+ // completely; if requesting (0, 0), apply only when min/max results in a fixed
+ // size.
let min_size = win.min_size();
let max_size = win.max_size();
- if min_size.w != 0 && min_size.w == max_size.w {
- size.w = min_size.w;
- }
- if min_size.h != 0 && min_size.h == max_size.h {
- size.h = min_size.h;
- }
+ size.w = ensure_min_max_size_maybe_zero(size.w, min_size.w, max_size.w);
+ size.h = ensure_min_max_size_maybe_zero(size.h, min_size.h, max_size.h);
+
win.request_size_once(size, true);
}
return;
@@ -3277,15 +3280,13 @@ impl<W: LayoutElement> Layout<W> {
Size::from((0, 0))
};
- // Make sure fixed-size through window rules keeps working.
+ // Apply min/max size window rules. If requesting a concrete size, apply
+ // completely; if requesting (0, 0), apply only when min/max results in a fixed
+ // size.
let min_size = win.min_size();
let max_size = win.max_size();
- if min_size.w != 0 && min_size.w == max_size.w {
- size.w = min_size.w;
- }
- if min_size.h != 0 && min_size.h == max_size.h {
- size.h = min_size.h;
- }
+ size.w = ensure_min_max_size_maybe_zero(size.w, min_size.w, max_size.w);
+ size.h = ensure_min_max_size_maybe_zero(size.h, min_size.h, max_size.h);
win.request_size_once(size, true);
diff --git a/src/tests/floating.rs b/src/tests/floating.rs
index ece1a5dc..8b63d55d 100644
--- a/src/tests/floating.rs
+++ b/src/tests/floating.rs
@@ -1,5 +1,6 @@
use client::ClientId;
use insta::assert_snapshot;
+use niri_config::Config;
use niri_ipc::SizeChange;
use smithay::utils::Point;
use wayland_client::protocol::wl_surface::WlSurface;
@@ -785,3 +786,71 @@ fn floating_doesnt_store_fullscreen_size() {
@"size: 100 × 100, bounds: 1920 × 1080, states: [Activated]"
);
}
+
+#[test]
+fn floating_respects_non_fixed_min_max_rule() {
+ let config = r##"
+window-rule {
+ min-width 200
+ max-width 300
+}
+"##;
+ let config = Config::parse("test.kdl", config).unwrap();
+ let mut f = Fixture::with_config(config);
+ f.add_output(1, (1920, 1080));
+ f.add_output(2, (1280, 720));
+
+ let id = f.add_client();
+ let window = f.client(id).create_window();
+ let surface = window.surface.clone();
+ window.commit();
+ f.roundtrip(id);
+
+ // Open with smaller width than min.
+ let window = f.client(id).window(&surface);
+ window.attach_new_buffer();
+ window.set_size(100, 100);
+ window.ack_last_and_commit();
+ f.double_roundtrip(id);
+
+ // Commit to the Activated state configure.
+ f.client(id).window(&surface).ack_last_and_commit();
+ f.double_roundtrip(id);
+
+ let _ = f.client(id).window(&surface).recent_configures();
+
+ // Make it floating.
+ f.niri().layout.toggle_window_floating(None);
+ f.double_roundtrip(id);
+
+ // This should clamp to min-width and request 200 × 100.
+ assert_snapshot!(
+ f.client(id).window(&surface).format_recent_configures(),
+ @"size: 200 × 100, bounds: 1920 × 1080, states: [Activated]"
+ );
+
+ // Commit with a bigger width than max.
+ let window = f.client(id).window(&surface);
+ window.set_size(400, 100);
+ window.ack_last_and_commit();
+ f.roundtrip(id);
+
+ // Make it tiling.
+ f.niri().layout.toggle_window_floating(None);
+ f.double_roundtrip(id);
+
+ let _ = f.client(id).window(&surface).recent_configures();
+
+ f.client(id).window(&surface).ack_last_and_commit();
+ f.roundtrip(id);
+
+ // Make it floating.
+ f.niri().layout.toggle_window_floating(None);
+ f.double_roundtrip(id);
+
+ // This should clamp to max-width and request 300 × 100.
+ assert_snapshot!(
+ f.client(id).window(&surface).format_recent_configures(),
+ @"size: 300 × 100, bounds: 1920 × 1080, states: [Activated]"
+ );
+}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 7ab89a72..28cebf2c 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -272,6 +272,16 @@ pub fn ensure_min_max_size(mut x: i32, min_size: i32, max_size: i32) -> i32 {
x
}
+pub fn ensure_min_max_size_maybe_zero(x: i32, min_size: i32, max_size: i32) -> i32 {
+ if x != 0 {
+ ensure_min_max_size(x, min_size, max_size)
+ } else if min_size > 0 && min_size == max_size {
+ min_size
+ } else {
+ 0
+ }
+}
+
pub fn clamp_preferring_top_left_in_area(
area: Rectangle<f64, Logical>,
rect: &mut Rectangle<f64, Logical>,