aboutsummaryrefslogtreecommitdiff
path: root/src/layout/scrolling.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-04-24 21:06:24 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-04-25 02:00:18 -0700
commitce3103949fe07bb656970da30c87accde83852fa (patch)
tree21559b95255187a107f16e585538b34358491774 /src/layout/scrolling.rs
parentef60dd81d7f72a7b452857be02bbed2a1ab6a60f (diff)
downloadniri-ce3103949fe07bb656970da30c87accde83852fa.tar.gz
niri-ce3103949fe07bb656970da30c87accde83852fa.tar.bz2
niri-ce3103949fe07bb656970da30c87accde83852fa.zip
layout/scrolling: Support view offset anim during gesture
Brings back moving the newly active window into focus upon interactive move dragging out.
Diffstat (limited to 'src/layout/scrolling.rs')
-rw-r--r--src/layout/scrolling.rs78
1 files changed, 58 insertions, 20 deletions
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs
index a0fccb5f..925c6d19 100644
--- a/src/layout/scrolling.rs
+++ b/src/layout/scrolling.rs
@@ -113,6 +113,10 @@ pub(super) enum ViewOffset {
#[derive(Debug)]
pub(super) struct ViewGesture {
current_view_offset: f64,
+ /// Animation for the extra offset to the current position.
+ ///
+ /// For example, when we need to activate a specific window during a DnD scroll.
+ animation: Option<Animation>,
tracker: SwipeTracker,
delta_from_tracker: f64,
// The view offset we'll use if needed for activate_prev_column_on_removal.
@@ -321,6 +325,12 @@ impl<W: LayoutElement> ScrollingSpace<W> {
gesture.dnd_nonzero_start_time = None;
}
}
+
+ if let Some(anim) = &mut gesture.animation {
+ if anim.is_done() {
+ gesture.animation = None;
+ }
+ }
}
for col in &mut self.columns {
@@ -334,7 +344,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
}
pub fn are_animations_ongoing(&self) -> bool {
- self.view_offset.is_animation()
+ self.view_offset.is_animation_ongoing()
|| self.columns.iter().any(Column::are_animations_ongoing)
|| !self.closing_windows.is_empty()
}
@@ -626,8 +636,6 @@ impl<W: LayoutElement> ScrollingSpace<W> {
new_view_offset: f64,
config: niri_config::Animation,
) {
- self.view_offset.cancel_gesture();
-
let new_col_x = self.column_x(idx);
let old_col_x = self.column_x(self.active_column_idx);
let offset_delta = old_col_x - new_col_x;
@@ -644,14 +652,28 @@ impl<W: LayoutElement> ScrollingSpace<W> {
return;
}
- // FIXME: also compute and use current velocity.
- self.view_offset = ViewOffset::Animation(Animation::new(
- self.clock.clone(),
- self.view_offset.current(),
- new_view_offset,
- 0.,
- config,
- ));
+ match &mut self.view_offset {
+ ViewOffset::Gesture(gesture) if gesture.dnd_last_event_time.is_some() => {
+ gesture.stationary_view_offset = new_view_offset;
+
+ let current_pos = gesture.current_view_offset - gesture.delta_from_tracker;
+ gesture.delta_from_tracker = new_view_offset - current_pos;
+ let offset_delta = new_view_offset - gesture.current_view_offset;
+ gesture.current_view_offset = new_view_offset;
+
+ gesture.animate_from(-offset_delta, self.clock.clone(), config);
+ }
+ _ => {
+ // FIXME: also compute and use current velocity.
+ self.view_offset = ViewOffset::Animation(Animation::new(
+ self.clock.clone(),
+ self.view_offset.current(),
+ new_view_offset,
+ 0.,
+ config,
+ ));
+ }
+ }
}
fn animate_view_offset_to_column_centered(
@@ -1563,7 +1585,6 @@ impl<W: LayoutElement> ScrollingSpace<W> {
// Preserve the camera position when moving to the left.
let view_offset_delta = -self.column_x(self.active_column_idx) + current_col_x;
- self.view_offset.cancel_gesture();
self.view_offset.offset(view_offset_delta);
// The column we just moved is offset by the difference between its new and old position.
@@ -2784,6 +2805,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let gesture = ViewGesture {
current_view_offset: self.view_offset.current(),
+ animation: None,
tracker: SwipeTracker::new(),
delta_from_tracker: self.view_offset.current(),
stationary_view_offset: self.view_offset.stationary(),
@@ -2806,6 +2828,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
let gesture = ViewGesture {
current_view_offset: self.view_offset.current(),
+ animation: None,
tracker: SwipeTracker::new(),
delta_from_tracker: self.view_offset.current(),
stationary_view_offset: self.view_offset.stationary(),
@@ -3500,7 +3523,10 @@ impl ViewOffset {
match self {
ViewOffset::Static(offset) => *offset,
ViewOffset::Animation(anim) => anim.value(),
- ViewOffset::Gesture(gesture) => gesture.current_view_offset,
+ ViewOffset::Gesture(gesture) => {
+ gesture.current_view_offset
+ + gesture.animation.as_ref().map_or(0., |anim| anim.value())
+ }
}
}
@@ -3530,21 +3556,26 @@ impl ViewOffset {
matches!(self, Self::Static(_))
}
- pub fn is_animation(&self) -> bool {
- matches!(self, Self::Animation(_))
- }
-
pub fn is_gesture(&self) -> bool {
matches!(self, Self::Gesture(_))
}
+ pub fn is_animation_ongoing(&self) -> bool {
+ match self {
+ ViewOffset::Static(_) => false,
+ ViewOffset::Animation(_) => true,
+ ViewOffset::Gesture(gesture) => gesture.animation.is_some(),
+ }
+ }
+
pub fn offset(&mut self, delta: f64) {
match self {
ViewOffset::Static(offset) => *offset += delta,
ViewOffset::Animation(anim) => anim.offset(delta),
- ViewOffset::Gesture(_gesture) => {
- // Is this needed?
- error!("cancel gesture before offsetting");
+ ViewOffset::Gesture(gesture) => {
+ gesture.stationary_view_offset += delta;
+ gesture.delta_from_tracker += delta;
+ gesture.current_view_offset += delta;
}
}
}
@@ -3560,6 +3591,13 @@ impl ViewOffset {
}
}
+impl ViewGesture {
+ fn animate_from(&mut self, from: f64, clock: Clock, config: niri_config::Animation) {
+ let current = self.animation.as_ref().map_or(0., Animation::value);
+ self.animation = Some(Animation::new(clock, from + current, 0., 0., config));
+ }
+}
+
impl ColumnData {
pub fn new<W: LayoutElement>(column: &Column<W>) -> Self {
let mut rv = Self { width: 0. };