aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-06-13 08:52:09 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-06-13 08:54:59 +0300
commit83ec36953611ab11dd36c3c3632db7bd3fea9b82 (patch)
tree2c9d8be1b9c882fc36e81b54ce775a6c908392d1
parent97dfd2b1a00bcb9b765a8fa92ce39d2e0c79abc2 (diff)
downloadniri-83ec36953611ab11dd36c3c3632db7bd3fea9b82.tar.gz
niri-83ec36953611ab11dd36c3c3632db7bd3fea9b82.tar.bz2
niri-83ec36953611ab11dd36c3c3632db7bd3fea9b82.zip
layout/scrolling: Take unfullscreen view offset unconditionally
It might get set and unset all while the view is frozen with a gesture.
-rw-r--r--src/layout/scrolling.rs34
-rw-r--r--src/layout/tests.rs63
2 files changed, 84 insertions, 13 deletions
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs
index 0c70fc7a..37feb227 100644
--- a/src/layout/scrolling.rs
+++ b/src/layout/scrolling.rs
@@ -1291,20 +1291,28 @@ impl<W: LayoutElement> ScrollingSpace<W> {
self.view_offset.offset(offset);
}
- if self.interactive_resize.is_none() && !self.view_offset.is_gesture() {
- // We might need to move the view to ensure the resized window is still visible.
+ // 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
+ // particular unfullscreen.
+ self.view_offset_before_fullscreen.take()
+ } else {
+ None
+ };
- // 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);
- if was_fullscreen && !is_fullscreen {
- if let Some(prev_offset) = self.view_offset_before_fullscreen.take() {
- self.animate_view_offset(col_idx, prev_offset);
- }
+ // We might need to move the view to ensure the resized window is still visible. But
+ // only do it when the view isn't frozen by an interactive resize or a view gesture.
+ if self.interactive_resize.is_none() && !self.view_offset.is_gesture() {
+ // Restore the view offset upon unfullscreening if needed.
+ if let Some(prev_offset) = unfullscreen_offset {
+ self.animate_view_offset(col_idx, prev_offset);
}
// Synchronize the horizontal view movement with the resize so that it looks nice.
diff --git a/src/layout/tests.rs b/src/layout/tests.rs
index acfced00..524ade8b 100644
--- a/src/layout/tests.rs
+++ b/src/layout/tests.rs
@@ -3471,6 +3471,69 @@ fn interactive_move_unfullscreen_to_floating_stops_dnd_scroll() {
check_ops(&ops);
}
+#[test]
+fn unfullscreen_view_offset_not_reset_during_dnd_gesture() {
+ let ops = [
+ Op::AddOutput(1),
+ Op::AddWindow {
+ params: TestWindowParams::new(3),
+ },
+ Op::FullscreenWindow(3),
+ Op::Communicate(3),
+ Op::DndUpdate {
+ output_idx: 1,
+ px: 0.0,
+ py: 0.0,
+ },
+ Op::FullscreenWindow(3),
+ Op::Communicate(3),
+ ];
+
+ check_ops(&ops);
+}
+
+#[test]
+fn unfullscreen_view_offset_not_reset_during_gesture() {
+ let ops = [
+ Op::AddOutput(1),
+ Op::AddWindow {
+ params: TestWindowParams::new(3),
+ },
+ Op::FullscreenWindow(3),
+ Op::Communicate(3),
+ Op::ViewOffsetGestureBegin {
+ output_idx: 1,
+ workspace_idx: None,
+ is_touchpad: false,
+ },
+ Op::FullscreenWindow(3),
+ Op::Communicate(3),
+ ];
+
+ check_ops(&ops);
+}
+
+#[test]
+fn unfullscreen_view_offset_not_reset_during_ongoing_gesture() {
+ let ops = [
+ Op::AddOutput(1),
+ Op::AddWindow {
+ params: TestWindowParams::new(3),
+ },
+ Op::ViewOffsetGestureBegin {
+ output_idx: 1,
+ workspace_idx: None,
+ is_touchpad: false,
+ },
+ Op::FullscreenWindow(3),
+ Op::Communicate(3),
+ Op::FullscreenWindow(3),
+ Op::Communicate(3),
+ ];
+
+ check_ops(&ops);
+}
+
fn parent_id_causes_loop(layout: &Layout<TestWindow>, id: usize, mut parent_id: usize) -> bool {
if parent_id == id {
return true;