aboutsummaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-09-02 17:20:41 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-09-17 22:04:23 +0300
commitb8995a12d1191053628c0df7b986435e156fb79c (patch)
tree12579e935930cdc3512d1e2ef48733c3dbf88660 /src/layout
parent2f9832aa367e9038d3e1374cf61fe2235175b936 (diff)
downloadniri-b8995a12d1191053628c0df7b986435e156fb79c.tar.gz
niri-b8995a12d1191053628c0df7b986435e156fb79c.tar.bz2
niri-b8995a12d1191053628c0df7b986435e156fb79c.zip
layout/scrolling: Store view_offset_before_fullscreen when column actually goes fullscreen
Simplifies the handling and correctly saves/restores view offset for clients that are slow to fullscreen, as can be seen from the fixed test.
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/scrolling.rs70
1 files changed, 22 insertions, 48 deletions
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs
index 39892609..20e4c388 100644
--- a/src/layout/scrolling.rs
+++ b/src/layout/scrolling.rs
@@ -868,18 +868,10 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let target_column = &mut self.columns[col_idx];
let tile_idx = tile_idx.unwrap_or(target_column.tiles.len());
let mut prev_active_tile_idx = target_column.active_tile_idx;
- let was_fullscreen = target_column.tiles[prev_active_tile_idx].is_fullscreen();
target_column.add_tile_at(tile_idx, tile, true);
self.data[col_idx].update(target_column);
- // If the target column is the active column and its window was requested to, but hasn't
- // gone into fullscreen yet, then clear the stored view offset, if we just asked it to
- // stop going into fullscreen.
- if col_idx == self.active_column_idx && !was_fullscreen && !target_column.is_fullscreen {
- self.view_offset_before_fullscreen = None;
- }
-
if tile_idx <= prev_active_tile_idx {
target_column.active_tile_idx += 1;
prev_active_tile_idx += 1;
@@ -1060,13 +1052,14 @@ impl<W: LayoutElement> ScrollingSpace<W> {
tile.animate_alpha(0., 1., movement_config);
}
+ let was_fullscreen = column.is_any_fullscreen();
+
let tile = column.tiles.remove(tile_idx);
column.data.remove(tile_idx);
- // If we're removing a pending-unfullscreen window, we need to clear the stored view
- // offset. There might be other pending-unfullscreen windows in this column but that's kind
- // of an edge case, don't think we need to handle that.
- if column_idx == self.active_column_idx && tile.is_fullscreen() && !column.is_fullscreen {
+ // If an active column became non-fullscreen after removing the tile, clear the stored
+ // unfullscreen offset.
+ if column_idx == self.active_column_idx && was_fullscreen && !column.is_any_fullscreen() {
self.view_offset_before_fullscreen = None;
}
@@ -1225,6 +1218,8 @@ impl<W: LayoutElement> ScrollingSpace<W> {
.enumerate()
.find(|(_, col)| col.contains(window))
.unwrap();
+ let was_fullscreen = column.is_any_fullscreen();
+
let (tile_idx, tile) = column
.tiles
.iter_mut()
@@ -1232,7 +1227,6 @@ impl<W: LayoutElement> ScrollingSpace<W> {
.find(|(_, tile)| tile.window().id() == window)
.unwrap();
- let was_fullscreen = tile.is_fullscreen();
let resize = tile.window_mut().interactive_resize_data();
// Do this before calling update_window() so it can get up-to-date info.
@@ -1322,13 +1316,18 @@ impl<W: LayoutElement> ScrollingSpace<W> {
self.view_offset.offset(offset);
}
+ // When the active column goes fullscreen, store the view offset to restore later.
+ let is_fullscreen = self.columns[col_idx].is_any_fullscreen();
+ if !was_fullscreen && is_fullscreen {
+ self.view_offset_before_fullscreen = Some(self.view_offset.stationary());
+ }
+
// Upon unfullscreening, restore the view offset.
//
// In tabbed display mode, there can be multiple tiles in a fullscreen column. They
// will unfullscreen one by one, and the column width will shrink only when the
// last tile unfullscreens. This is when we want to restore the view offset,
// otherwise it will immediately reset back by the animate_view_offset below.
- let is_fullscreen = self.columns[col_idx].tiles.iter().any(Tile::is_fullscreen);
let unfullscreen_offset = if was_fullscreen && !is_fullscreen {
// Take the value unconditionally, even if the view is currently frozen by
// a view gesture. It shouldn't linger around because it's only valid for this
@@ -2773,11 +2772,6 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let mut col = &mut self.columns[col_idx];
let is_tabbed = col.display_mode == ColumnDisplay::Tabbed;
- if is_fullscreen && col_idx == self.active_column_idx && (col.tiles.len() == 1 || is_tabbed)
- {
- self.view_offset_before_fullscreen = Some(self.view_offset.stationary());
- }
-
cancel_resize_for_column(&mut self.interactive_resize, col);
if is_fullscreen && (col.tiles.len() > 1 && !is_tabbed) {
@@ -2806,18 +2800,6 @@ impl<W: LayoutElement> ScrollingSpace<W> {
// With place_within_column, the tab indicator changes the column size immediately.
self.data[col_idx].update(col);
- // If we quickly fullscreen and unfullscreen before any window has a chance to receive the
- // request, we need to reset the offset.
- if col_idx == self.active_column_idx
- && !is_fullscreen
- && !col
- .tiles
- .iter()
- .any(|tile| tile.is_fullscreen() || tile.window().is_pending_fullscreen())
- {
- self.view_offset_before_fullscreen = None;
- }
-
true
}
@@ -3394,11 +3376,10 @@ impl<W: LayoutElement> ScrollingSpace<W> {
return false;
}
- let (col_idx, col) = self
+ let col = self
.columns
.iter_mut()
- .enumerate()
- .find(|(_, col)| col.contains(&window))
+ .find(|col| col.contains(&window))
.unwrap();
if col.is_fullscreen {
@@ -3422,14 +3403,6 @@ impl<W: LayoutElement> ScrollingSpace<W> {
self.view_offset.stop_anim_and_gesture();
- // If this is the active column, clear the stored unfullscreen view offset in case one of
- // the tiles in the column is still pending unfullscreen. Normally it is cleared and
- // applied in update_window(), but we skip that during interactive resize because the view
- // is frozen.
- if col_idx == self.active_column_idx {
- self.view_offset_before_fullscreen = None;
- }
-
true
}
@@ -3655,14 +3628,11 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let col = &self.columns[self.active_column_idx];
- // When we have an unfullscreen view offset stored, the active column should have a
- // fullscreen tile.
if self.view_offset_before_fullscreen.is_some() {
assert!(
- col.is_fullscreen
- || col.tiles.iter().any(|tile| {
- tile.is_fullscreen() || tile.window().is_pending_fullscreen()
- })
+ col.is_any_fullscreen(),
+ "when view_offset_before_fullscreen is set, \
+ the active column must be fullscreen"
);
}
}
@@ -4033,6 +4003,10 @@ impl<W: LayoutElement> Column<W> {
}
}
+ fn is_any_fullscreen(&self) -> bool {
+ self.tiles.iter().any(|tile| tile.is_fullscreen())
+ }
+
pub fn contains(&self, window: &W::Id) -> bool {
self.tiles
.iter()