mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
layout: Offset Y animations for non-animated resizes
This commit is contained in:
+29
-6
@@ -4056,12 +4056,35 @@ impl<W: LayoutElement> Column<W> {
|
|||||||
// windows in the column, so they should all be animated. How should this interact with
|
// windows in the column, so they should all be animated. How should this interact with
|
||||||
// animated vs. non-animated resizes? For example, an animated +20 resize followed by two
|
// animated vs. non-animated resizes? For example, an animated +20 resize followed by two
|
||||||
// non-animated -10 resizes.
|
// non-animated -10 resizes.
|
||||||
if !is_tabbed && tile.resize_animation().is_some() && offset != 0. {
|
if !is_tabbed && offset != 0. {
|
||||||
for tile in &mut self.tiles[tile_idx + 1..] {
|
if tile.resize_animation().is_some() {
|
||||||
tile.animate_move_y_from_with_config(
|
// If there's a resize animation (that may have just started in
|
||||||
offset,
|
// tile.update_window()), then the apparent size change is smooth with no sudden
|
||||||
self.options.animations.window_resize.anim,
|
// jumps. This corresponds to adding an Y animation to tiles below.
|
||||||
);
|
for tile in &mut self.tiles[tile_idx + 1..] {
|
||||||
|
tile.animate_move_y_from_with_config(
|
||||||
|
offset,
|
||||||
|
self.options.animations.window_resize.anim,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There's no resize animation, but the offset is nonzero. 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 tiles below shouldn't react to this offset change in any way,
|
||||||
|
// i.e. their apparent Y position should jump together with the resize. However,
|
||||||
|
// tiles below that are already animating an Y movement should offset their
|
||||||
|
// animations to avoid the jump.
|
||||||
|
//
|
||||||
|
// Notably, this is necessary to fix the animation jump when resizing height back
|
||||||
|
// and forth in quick succession (in a way that cancels the resize animation).
|
||||||
|
for tile in &mut self.tiles[tile_idx + 1..] {
|
||||||
|
tile.offset_move_y_anim_current(offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,14 +269,20 @@ fn height_resize_and_cancel() {
|
|||||||
];
|
];
|
||||||
check_ops_on_layout(&mut layout, &ops);
|
check_ops_on_layout(&mut layout, &ops);
|
||||||
|
|
||||||
// Since the resize animation is cancelled, the height goes to the new value immediately, and
|
// Since the resize animation is cancelled, the height goes to the new value immediately. The Y
|
||||||
// the Y position should also go to 100 immediately, cancelling the movement.
|
// position doesn't jump, instead the animation is offset to preserve the current position.
|
||||||
//
|
|
||||||
// FIXME: right now, the Y position jumps to 5 and will continue animating to 100 from there
|
|
||||||
// because cancelling the resize anim doesn't cancel the induced Y movement.
|
|
||||||
assert_snapshot!(format_tiles(&layout), @r"
|
assert_snapshot!(format_tiles(&layout), @r"
|
||||||
100 × 100 at x: 0 y: 0
|
100 × 100 at x: 0 y: 0
|
||||||
200 × 200 at x: 0 y: 5
|
200 × 200 at x: 0 y:105
|
||||||
|
");
|
||||||
|
|
||||||
|
// Advance to the end of the move animation.
|
||||||
|
Op::AdvanceAnimations { msec_delta: 950 }.apply(&mut layout);
|
||||||
|
|
||||||
|
// Final state.
|
||||||
|
assert_snapshot!(format_tiles(&layout), @r"
|
||||||
|
100 × 100 at x: 0 y: 0
|
||||||
|
200 × 200 at x: 0 y:100
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,23 +512,30 @@ fn height_resize_and_cancel_during_another_y_anim() {
|
|||||||
];
|
];
|
||||||
check_ops_on_layout(&mut layout, &ops);
|
check_ops_on_layout(&mut layout, &ops);
|
||||||
|
|
||||||
// Since the resize anim was cancelled, second window's Y should jump a little to go back to
|
// Since the resize anim was cancelled, second window's Y anim is adjusted to preserve the
|
||||||
// its original trajectory.
|
// current position while targeting the new final position.
|
||||||
//
|
|
||||||
// FIXME: right now, the Y position jumps and will continue to animate from there because
|
|
||||||
// cancelling the resize anim doesn't cancel the induced Y movement.
|
|
||||||
assert_snapshot!(format_tiles(&layout), @r"
|
assert_snapshot!(format_tiles(&layout), @r"
|
||||||
100 × 100 at x: 0 y: 0
|
100 × 100 at x: 0 y: 0
|
||||||
200 × 200 at x: 45 y:-43
|
200 × 200 at x: 45 y: 58
|
||||||
");
|
");
|
||||||
|
|
||||||
// Advance the time to complete the consume movement.
|
// Advance the time to complete the consume movement.
|
||||||
Op::AdvanceAnimations { msec_delta: 450 }.apply(&mut layout);
|
Op::AdvanceAnimations { msec_delta: 450 }.apply(&mut layout);
|
||||||
|
|
||||||
// Final state. Y should be at 100 since the resize-induced Y anim was cancelled.
|
// Since we don't cancel the resize-induced part of the anim (in fact the move Y anim isn't
|
||||||
|
// split into parts, so there's no way to tell), it keeps going still.
|
||||||
assert_snapshot!(format_tiles(&layout), @r"
|
assert_snapshot!(format_tiles(&layout), @r"
|
||||||
100 × 100 at x: 0 y: 0
|
100 × 100 at x: 0 y: 0
|
||||||
200 × 200 at x: 0 y: 25
|
200 × 200 at x: 0 y: 78
|
||||||
|
");
|
||||||
|
|
||||||
|
// Advance the time to complete the resize-induced anim.
|
||||||
|
Op::AdvanceAnimations { msec_delta: 550 }.apply(&mut layout);
|
||||||
|
|
||||||
|
// Final state.
|
||||||
|
assert_snapshot!(format_tiles(&layout), @r"
|
||||||
|
100 × 100 at x: 0 y: 0
|
||||||
|
200 × 200 at x: 0 y:100
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,14 +736,10 @@ fn height_resize_before_another_y_anim_then_cancel() {
|
|||||||
];
|
];
|
||||||
check_ops_on_layout(&mut layout, &ops);
|
check_ops_on_layout(&mut layout, &ops);
|
||||||
|
|
||||||
// This should cause the second window's trajectory to readjust to the new final position at
|
// The second window's trajectory readjusts to the new final position at 100 px, without jumps.
|
||||||
// 100px. Ideally without big jumps because even though the first window's actual size changed
|
|
||||||
// from 200 px to 100 px, the cancelled resize only shifted it from 104 px to 100 px.
|
|
||||||
//
|
|
||||||
// FIXME: currently causes a 100 px jump due to the change in the actual window size.
|
|
||||||
assert_snapshot!(format_tiles(&layout), @r"
|
assert_snapshot!(format_tiles(&layout), @r"
|
||||||
100 × 100 at x: 0 y: 0
|
100 × 100 at x: 0 y: 0
|
||||||
200 × 200 at x: 98 y:-96
|
200 × 200 at x: 98 y: 4
|
||||||
");
|
");
|
||||||
|
|
||||||
// Advance the time to complete the consume movement.
|
// Advance the time to complete the consume movement.
|
||||||
@@ -791,13 +800,10 @@ fn clientside_height_change_during_another_y_anim() {
|
|||||||
];
|
];
|
||||||
check_ops_on_layout(&mut layout, &ops);
|
check_ops_on_layout(&mut layout, &ops);
|
||||||
|
|
||||||
// This should cause the second window's trajectory to readjust to the new final position at
|
// The second window's trajectory readjusts to the new final position at 200 px, without jumps.
|
||||||
// 200px. Ideally without big jumps.
|
|
||||||
//
|
|
||||||
// FIXME: currently causes a 100 px jump due to the change in the window size.
|
|
||||||
assert_snapshot!(format_tiles(&layout), @r"
|
assert_snapshot!(format_tiles(&layout), @r"
|
||||||
100 × 200 at x: 0 y: 0
|
100 × 200 at x: 0 y: 0
|
||||||
200 × 200 at x: 80 y:120
|
200 × 200 at x: 80 y: 20
|
||||||
");
|
");
|
||||||
|
|
||||||
// Advance the time to complete the consume movement.
|
// Advance the time to complete the consume movement.
|
||||||
|
|||||||
@@ -485,6 +485,17 @@ impl<W: LayoutElement> Tile<W> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn offset_move_y_anim_current(&mut self, offset: f64) {
|
||||||
|
if let Some(move_) = self.move_y_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 stop_move_animations(&mut self) {
|
pub fn stop_move_animations(&mut self) {
|
||||||
self.move_x_animation = None;
|
self.move_x_animation = None;
|
||||||
self.move_y_animation = None;
|
self.move_y_animation = None;
|
||||||
|
|||||||
Reference in New Issue
Block a user