Separate tile X and Y movement animations

Helps with the jank caused by lack of transactions when consuming to the
left/right. Resize triggers a few frames later and restarts the
movement. Now it only restarts the vertical and not the horizontal
movement.
This commit is contained in:
Ivan Molodetskikh
2024-04-19 12:44:24 +04:00
parent f51dd67f2d
commit 2c8d1030ab
2 changed files with 59 additions and 25 deletions
+52 -18
View File
@@ -57,8 +57,11 @@ pub struct Tile<W: LayoutElement> {
/// The animation of the window resizing.
resize_animation: Option<ResizeAnimation>,
/// The animation of a tile visually moving.
move_animation: Option<MoveAnimation>,
/// The animation of a tile visually moving horizontally.
move_x_animation: Option<MoveAnimation>,
/// The animation of a tile visually moving vertically.
move_y_animation: Option<MoveAnimation>,
/// Configurable properties of the layout.
pub options: Rc<Options>,
@@ -99,7 +102,7 @@ struct ResizeAnimation {
#[derive(Debug)]
struct MoveAnimation {
anim: Animation,
from: Point<i32, Logical>,
from: i32,
}
impl<W: LayoutElement> Tile<W> {
@@ -113,7 +116,8 @@ impl<W: LayoutElement> Tile<W> {
fullscreen_size: Default::default(),
open_animation: None,
resize_animation: None,
move_animation: None,
move_x_animation: None,
move_y_animation: None,
options,
}
}
@@ -177,10 +181,16 @@ impl<W: LayoutElement> Tile<W> {
}
}
if let Some(move_) = &mut self.move_animation {
if let Some(move_) = &mut self.move_x_animation {
move_.anim.set_current_time(current_time);
if move_.anim.is_done() {
self.move_animation = None;
self.move_x_animation = None;
}
}
if let Some(move_) = &mut self.move_y_animation {
move_.anim.set_current_time(current_time);
if move_.anim.is_done() {
self.move_y_animation = None;
}
}
@@ -206,14 +216,18 @@ impl<W: LayoutElement> Tile<W> {
pub fn are_animations_ongoing(&self) -> bool {
self.open_animation.is_some()
|| self.resize_animation.is_some()
|| self.move_animation.is_some()
|| self.move_x_animation.is_some()
|| self.move_y_animation.is_some()
}
pub fn render_offset(&self) -> Point<i32, Logical> {
let mut offset = Point::from((0., 0.));
if let Some(move_) = &self.move_animation {
offset += move_.from.to_f64().upscale(move_.anim.value());
if let Some(move_) = &self.move_x_animation {
offset.x += f64::from(move_.from) * move_.anim.value();
}
if let Some(move_) = &self.move_y_animation {
offset.y += f64::from(move_.from) * move_.anim.value();
}
offset.to_i32_round()
@@ -237,23 +251,43 @@ impl<W: LayoutElement> Tile<W> {
}
pub fn animate_move_from(&mut self, from: Point<i32, Logical>) {
self.animate_move_from_with_config(from, self.options.animations.window_movement.0);
self.animate_move_x_from(from.x);
self.animate_move_y_from(from.y);
}
pub fn animate_move_from_with_config(
&mut self,
from: Point<i32, Logical>,
config: niri_config::Animation,
) {
let current_offset = self.render_offset();
pub fn animate_move_x_from(&mut self, from: i32) {
self.animate_move_x_from_with_config(from, self.options.animations.window_movement.0);
}
pub fn animate_move_x_from_with_config(&mut self, from: i32, config: niri_config::Animation) {
let current_offset = self.render_offset().x;
// Preserve the previous config if ongoing.
let anim = self.move_animation.take().map(|move_| move_.anim);
let anim = self.move_x_animation.take().map(|move_| move_.anim);
let anim = anim
.map(|anim| anim.restarted(1., 0., 0.))
.unwrap_or_else(|| Animation::new(1., 0., 0., config));
self.move_animation = Some(MoveAnimation {
self.move_x_animation = Some(MoveAnimation {
anim,
from: from + current_offset,
});
}
pub fn animate_move_y_from(&mut self, from: i32) {
self.animate_move_y_from_with_config(from, self.options.animations.window_movement.0);
}
pub fn animate_move_y_from_with_config(&mut self, from: i32, config: niri_config::Animation) {
let current_offset = self.render_offset().y;
// Preserve the previous config if ongoing.
let anim = self.move_y_animation.take().map(|move_| move_.anim);
let anim = anim
.map(|anim| anim.restarted(1., 0., 0.))
.unwrap_or_else(|| Animation::new(1., 0., 0., config));
self.move_y_animation = Some(MoveAnimation {
anim,
from: from + current_offset,
});
+7 -7
View File
@@ -920,7 +920,7 @@ impl<W: LayoutElement> Workspace<W> {
// Animate movement of other tiles.
let offset_y = column.tile_y(window_idx + 1) - column.tile_y(window_idx);
for tile in &mut column.tiles[window_idx + 1..] {
tile.animate_move_from(Point::from((0, offset_y)));
tile.animate_move_y_from(offset_y);
}
let tile = column.tiles.remove(window_idx);
@@ -2323,8 +2323,8 @@ impl<W: LayoutElement> Column<W> {
// Move windows below in tandem with resizing.
if tile.resize_animation().is_some() && offset != 0 {
for tile in &mut self.tiles[tile_idx + 1..] {
tile.animate_move_from_with_config(
Point::from((0, offset)),
tile.animate_move_y_from_with_config(
offset,
self.options.animations.window_resize.0,
);
}
@@ -2525,8 +2525,8 @@ impl<W: LayoutElement> Column<W> {
// Animate the movement.
let new_active_y = self.tile_y(new_idx);
self.tiles[new_idx].animate_move_from(Point::from((0, active_y - new_active_y)));
self.tiles[new_idx + 1].animate_move_from(Point::from((0, active_y - next_y)));
self.tiles[new_idx].animate_move_y_from(active_y - new_active_y);
self.tiles[new_idx + 1].animate_move_y_from(active_y - next_y);
}
fn move_down(&mut self) {
@@ -2546,8 +2546,8 @@ impl<W: LayoutElement> Column<W> {
// Animate the movement.
let new_active_y = self.tile_y(new_idx);
self.tiles[new_idx].animate_move_from(Point::from((0, active_y - new_active_y)));
self.tiles[new_idx - 1].animate_move_from(Point::from((0, next_y - active_y)));
self.tiles[new_idx].animate_move_y_from(active_y - new_active_y);
self.tiles[new_idx - 1].animate_move_y_from(next_y - active_y);
}
#[cfg(test)]