diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/layout/mod.rs | 17 | ||||
| -rw-r--r-- | src/tests/floating.rs | 74 |
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(), + @"" + ); +} |
