diff options
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/floating.rs | 37 | ||||
| -rw-r--r-- | src/layout/mod.rs | 34 | ||||
| -rw-r--r-- | src/layout/tile.rs | 15 |
3 files changed, 56 insertions, 30 deletions
diff --git a/src/layout/floating.rs b/src/layout/floating.rs index 4565e2f2..f870b2f2 100644 --- a/src/layout/floating.rs +++ b/src/layout/floating.rs @@ -366,24 +366,27 @@ impl<W: LayoutElement> FloatingSpace<W> { ) { tile.update_config(self.scale, self.options.clone()); + // Restore the previous floating window size, and in case the tile is fullscreen, + // unfullscreen it. + let floating_size = tile.floating_window_size(); let win = tile.window_mut(); - let size = if win.is_pending_fullscreen() { - let mut size = Size::from((0, 0)); - - // 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 == max_size.w { - size.w = min_size.w; - } - if min_size.h == max_size.h { - size.h = min_size.h; - } - - size + let mut size = if win.is_pending_fullscreen() { + // If the window was fullscreen without a floating size, ask for (0, 0). + floating_size.unwrap_or_default() } else { - win.size() + // If the window wasn't fullscreen without a floating size (e.g. it was tiled before), + // ask for the current size. + floating_size.unwrap_or_else(|| win.size_to_request()) }; + // 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); if activate || self.tiles.is_empty() { @@ -761,6 +764,10 @@ impl<W: LayoutElement> FloatingSpace<W> { tile.update_window(); data.update(tile); + // Update the stored floating window size. + let floating_size = tile.window().size_to_request(); + tile.set_floating_window_size(floating_size); + // When resizing by top/left edge, update the position accordingly. if let Some(resize) = resize { let mut offset = Point::from((0., 0.)); diff --git a/src/layout/mod.rs b/src/layout/mod.rs index acc5257f..8e86c0ca 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1152,6 +1152,12 @@ impl<W: LayoutElement> Layout<W> { if let Some(InteractiveMoveState::Moving(move_)) = &mut self.interactive_move { if move_.tile.window().id() == window { move_.tile.update_window(); + + // Update the floating size in case the window resizes itself during an interactive + // move. + let floating_size = move_.tile.window().size_to_request(); + move_.tile.set_floating_window_size(floating_size); + return; } } @@ -3254,35 +3260,33 @@ impl<W: LayoutElement> Layout<W> { Rc::new(Options::clone(&self.options).adjusted_for_scale(scale)), ); - // Unfullscreen and let the window pick a natural size. - // - // TODO - // When we have floating, we will want to always send a (0, 0) size here, not just - // to unfullscreen. However, when implementing that, remember to check how GTK - // tiled window size restoration works. It seems to remember *some* last size with - // prefer-no-csd, and occasionally that last size can become the full-width size - // rather than a smaller size, which is annoying. Need to see if niri can use some - // heuristics to make this case behave better. + // Unfullscreen. + let floating_size = tile.floating_window_size(); + let unfullscreen_to_floating = tile.unfullscreen_to_floating(); let win = tile.window_mut(); if win.is_pending_fullscreen() { - let mut size = Size::from((0, 0)); + // If we're unfullscreening to floating, use the stored floating size, + // otherwise use (0, 0). + let mut size = if unfullscreen_to_floating { + floating_size.unwrap_or_default() + } else { + Size::from((0, 0)) + }; // 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 == max_size.w { + if min_size.w != 0 && min_size.w == max_size.w { size.w = min_size.w; } - if min_size.h == max_size.h { + if min_size.h != 0 && min_size.h == max_size.h { size.h = min_size.h; } win.request_size_once(size, true); // If we're unfullscreening to floating, default to the floating layout. - is_floating = tile.unfullscreen_to_floating(); - } else { - win.request_size_once(win.size(), true); + is_floating = unfullscreen_to_floating; } let mut data = InteractiveMoveData { diff --git a/src/layout/tile.rs b/src/layout/tile.rs index 1b9aac2d..13adbd50 100644 --- a/src/layout/tile.rs +++ b/src/layout/tile.rs @@ -54,6 +54,12 @@ pub struct Tile<W: LayoutElement> { /// Whether the tile should float upon unfullscreening. unfullscreen_to_floating: bool, + /// The size that the window should assume when going floating. + /// + /// This is generally the last size the window had when it was floating. It can be unknown if + /// the window starts out in the tiling layout or fullscreen. + floating_window_size: Option<Size<i32, Logical>>, + /// The animation upon opening a window. open_animation: Option<OpenAnimation>, @@ -128,6 +134,7 @@ impl<W: LayoutElement> Tile<W> { fullscreen_backdrop: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]), fullscreen_size: Default::default(), unfullscreen_to_floating: false, + floating_window_size: None, open_animation: None, resize_animation: None, move_x_animation: None, @@ -935,6 +942,14 @@ impl<W: LayoutElement> Tile<W> { self.unfullscreen_to_floating = value; } + pub fn floating_window_size(&self) -> Option<Size<i32, Logical>> { + self.floating_window_size + } + + pub fn set_floating_window_size(&mut self, floating_window_size: Size<i32, Logical>) { + self.floating_window_size = Some(floating_window_size); + } + #[cfg(test)] pub fn verify_invariants(&self) { use approx::assert_abs_diff_eq; |
