aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/layout/mod.rs17
-rw-r--r--src/tests/floating.rs74
2 files changed, 91 insertions, 0 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index be5eadc1..74afa501 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -2717,6 +2717,23 @@ impl<W: LayoutElement> Layout<W> {
if let Some(InteractiveMoveState::Moving(move_)) = &mut self.interactive_move {
if window.is_none() || window == Some(move_.tile.window().id()) {
move_.is_floating = !move_.is_floating;
+
+ // When going to floating, restore the floating window size.
+ if move_.is_floating {
+ let floating_size = move_.tile.floating_window_size();
+ let win = move_.tile.window_mut();
+ let mut size = floating_size.unwrap_or_else(|| win.expected_size());
+ // Make sure fixed-size through window rules keeps working.
+ 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;
+ }
+ win.request_size_once(size, true);
+ }
return;
}
}
diff --git a/src/tests/floating.rs b/src/tests/floating.rs
index 62657378..b880745f 100644
--- a/src/tests/floating.rs
+++ b/src/tests/floating.rs
@@ -651,3 +651,77 @@ fn state_change_doesnt_break_use_window_size() {
@"size: 300 × 600, bounds: 1920 × 1080, states: [Activated]"
);
}
+
+#[test]
+fn interactive_move_restores_floating_size_when_set_to_floating() {
+ let (mut f, id, surface) = set_up();
+
+ f.niri().layout.toggle_window_floating(None);
+ f.double_roundtrip(id);
+
+ // Change size while we're floating and commit to make niri remember it.
+ let window = f.client(id).window(&surface);
+ window.set_size(200, 200);
+ window.ack_last_and_commit();
+ f.double_roundtrip(id);
+
+ let _ = f.client(id).window(&surface).recent_configures();
+
+ // Change back to tiling.
+ f.niri().layout.toggle_window_floating(None);
+ f.double_roundtrip(id);
+
+ // We should get a tiled size configure.
+ assert_snapshot!(
+ f.client(id).window(&surface).format_recent_configures(),
+ @"size: 200 × 1048, bounds: 1888 × 1048, states: [Activated]"
+ );
+
+ // Resize as requested.
+ let window = f.client(id).window(&surface);
+ let (_, configure) = window.configures_received.last().unwrap();
+ window.set_size(configure.size.0 as u16, configure.size.1 as u16);
+ window.ack_last_and_commit();
+ f.roundtrip(id);
+
+ // Start an interactive move.
+ let output = f.niri_output(1);
+ let niri = f.niri();
+ let mapped = niri.layout.windows().next().unwrap().1;
+ let window_id = mapped.window.clone();
+ niri.layout
+ .interactive_move_begin(window_id.clone(), &output, Point::default());
+ niri.layout.interactive_move_update(
+ &window_id,
+ Point::from((1000., 0.)),
+ output,
+ Point::default(),
+ );
+ f.double_roundtrip(id);
+
+ // This shouldn't request any new size because interactive move targets tiling.
+ assert_snapshot!(
+ f.client(id).window(&surface).format_recent_configures(),
+ @"size: 200 × 1048, bounds: 1920 × 1080, states: [Activated]"
+ );
+
+ // Change interactive move to target floating.
+ f.niri().layout.toggle_window_floating(None);
+ f.double_roundtrip(id);
+
+ // This should restore the floating window size (200 × 200).
+ assert_snapshot!(
+ f.client(id).window(&surface).format_recent_configures(),
+ @"size: 200 × 200, bounds: 1920 × 1080, states: [Activated]"
+ );
+
+ // End the interactive move, placing the window into floating.
+ f.niri().layout.interactive_move_end(&window_id);
+ f.double_roundtrip(id);
+
+ // This should keep the floating window size (200 × 200).
+ assert_snapshot!(
+ f.client(id).window(&surface).format_recent_configures(),
+ @""
+ );
+}