layout/scrolling: Take unfullscreen view offset unconditionally

It might get set and unset all while the view is frozen with a gesture.
This commit is contained in:
Ivan Molodetskikh
2025-06-13 08:52:09 +03:00
parent 97dfd2b1a0
commit 83ec369536
2 changed files with 84 additions and 13 deletions
+21 -13
View File
@@ -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.
+63
View File
@@ -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;