diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-08-13 18:45:02 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-08-14 15:58:59 +0300 |
| commit | 25c1c0434907ebee85b1e9df5fd5ef60fa1a15fd (patch) | |
| tree | 48abd9be3e77cfdf36d8a35604835bd183f8af1f /src/layout | |
| parent | 36af02ad34efb3be9184d1d0449fc1ab42c432ca (diff) | |
| download | niri-25c1c0434907ebee85b1e9df5fd5ef60fa1a15fd.tar.gz niri-25c1c0434907ebee85b1e9df5fd5ef60fa1a15fd.tar.bz2 niri-25c1c0434907ebee85b1e9df5fd5ef60fa1a15fd.zip | |
layout: Offset ongoing column X move anims for non-animated resizes
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/scrolling.rs | 60 | ||||
| -rw-r--r-- | src/layout/tests/animations.rs | 16 |
2 files changed, 54 insertions, 22 deletions
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs index 5dfbb6ef..a60581af 100644 --- a/src/layout/scrolling.rs +++ b/src/layout/scrolling.rs @@ -1249,22 +1249,47 @@ impl<W: LayoutElement> ScrollingSpace<W> { let offset = prev_width - self.data[col_idx].width; // Move other columns in tandem with resizing. - let started_resize_anim = - column.tiles[tile_idx].resize_animation().is_some() && offset != 0.; - if started_resize_anim { + let ongoing_resize_anim = column.tiles[tile_idx].resize_animation().is_some(); + if offset != 0. { if self.active_column_idx <= col_idx { for col in &mut self.columns[col_idx + 1..] { - col.animate_move_from_with_config( - offset, - self.options.animations.window_resize.anim, - ); + // If there's a resize animation on the tile (that may have just started in + // column.update_window()), then the apparent size change is smooth with no + // sudden jumps. This corresponds to adding an X animation to adjacent columns. + // + // There could also be no resize animation with nonzero offset. This could + // happen for example: + // - if the window resized on its own, which we don't animate + // - if the window resized by less than 10 px (the resize threshold) + // + // The latter case could also cancel an ongoing resize animation. + // + // Now, stationary columns shouldn't react to this offset change in any way, + // i.e. their apparent X position should jump together with the resize. + // However, adjacent columns that are already animating an X movement should + // offset their animations to avoid the jump. + // + // Notably, this is necessary to fix the animation jump when resizing width back + // and forth in quick succession (in a way that cancels the resize animation). + if ongoing_resize_anim { + col.animate_move_from_with_config( + offset, + self.options.animations.window_resize.anim, + ); + } else { + col.offset_move_anim_current(offset); + } } } else { for col in &mut self.columns[..=col_idx] { - col.animate_move_from_with_config( - -offset, - self.options.animations.window_resize.anim, - ); + if ongoing_resize_anim { + col.animate_move_from_with_config( + -offset, + self.options.animations.window_resize.anim, + ); + } else { + col.offset_move_anim_current(-offset); + } } } } @@ -1323,7 +1348,7 @@ impl<W: LayoutElement> ScrollingSpace<W> { // Synchronize the horizontal view movement with the resize so that it looks nice. // This is especially important for always-centered view. - let config = if started_resize_anim { + let config = if ongoing_resize_anim { self.options.animations.window_resize.anim } else { self.options.animations.horizontal_view_movement.0 @@ -3981,6 +4006,17 @@ impl<W: LayoutElement> Column<W> { }); } + pub fn offset_move_anim_current(&mut self, offset: f64) { + if let Some(move_) = self.move_animation.as_mut() { + // If the anim is almost done, there's little point trying to offset it; we can let + // things jump. If it turns out like a bad idea, we could restart the anim intead. + let value = move_.anim.value(); + if value > 0.001 { + move_.from += offset / value; + } + } + } + pub fn contains(&self, window: &W::Id) -> bool { self.tiles .iter() diff --git a/src/layout/tests/animations.rs b/src/layout/tests/animations.rs index 00101195..bae2d512 100644 --- a/src/layout/tests/animations.rs +++ b/src/layout/tests/animations.rs @@ -989,16 +989,14 @@ fn width_resize_and_cancel() { check_ops_on_layout(&mut layout, &ops); // Since the resize animation is cancelled, the width goes to the new value immediately. The X - // position doesn't jump, instead the animation is offset to preserve the current position. - // - // FIXME: this is not currently the case! + // position doesn't jump, instead the animation is restarted to preserve the current position. assert_snapshot!(format_tiles(&layout), @r" 100 × 100 at x: 0 y: 0 - 200 × 200 at x: 5 y: 0 + 200 × 200 at x:105 y: 0 "); // Advance to the end of the move animation. - Op::AdvanceAnimations { msec_delta: 950 }.apply(&mut layout); + Op::AdvanceAnimations { msec_delta: 1000 }.apply(&mut layout); // Final state. assert_snapshot!(format_tiles(&layout), @r" @@ -1081,16 +1079,14 @@ fn width_resize_and_cancel_of_column_to_the_left() { check_ops_on_layout(&mut layout, &ops); // Since the resize animation is cancelled, the width goes to the new value immediately. The X - // position doesn't jump, instead the animation is offset to preserve the current position. - // - // FIXME: this is not currently the case! + // position doesn't jump, instead the animation is restarted to preserve the current position. assert_snapshot!(format_tiles(&layout), @r" - 100 × 100 at x: 95 y: 0 + 100 × 100 at x: -5 y: 0 200 × 200 at x:100 y: 0 "); // Advance to the end of the move animation. - Op::AdvanceAnimations { msec_delta: 950 }.apply(&mut layout); + Op::AdvanceAnimations { msec_delta: 1000 }.apply(&mut layout); // Final state. assert_snapshot!(format_tiles(&layout), @r" |
