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. /// The animation of the window resizing.
resize_animation: Option<ResizeAnimation>, resize_animation: Option<ResizeAnimation>,
/// The animation of a tile visually moving. /// The animation of a tile visually moving horizontally.
move_animation: Option<MoveAnimation>, move_x_animation: Option<MoveAnimation>,
/// The animation of a tile visually moving vertically.
move_y_animation: Option<MoveAnimation>,
/// Configurable properties of the layout. /// Configurable properties of the layout.
pub options: Rc<Options>, pub options: Rc<Options>,
@@ -99,7 +102,7 @@ struct ResizeAnimation {
#[derive(Debug)] #[derive(Debug)]
struct MoveAnimation { struct MoveAnimation {
anim: Animation, anim: Animation,
from: Point<i32, Logical>, from: i32,
} }
impl<W: LayoutElement> Tile<W> { impl<W: LayoutElement> Tile<W> {
@@ -113,7 +116,8 @@ impl<W: LayoutElement> Tile<W> {
fullscreen_size: Default::default(), fullscreen_size: Default::default(),
open_animation: None, open_animation: None,
resize_animation: None, resize_animation: None,
move_animation: None, move_x_animation: None,
move_y_animation: None,
options, 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); move_.anim.set_current_time(current_time);
if move_.anim.is_done() { 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 { pub fn are_animations_ongoing(&self) -> bool {
self.open_animation.is_some() self.open_animation.is_some()
|| self.resize_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> { pub fn render_offset(&self) -> Point<i32, Logical> {
let mut offset = Point::from((0., 0.)); let mut offset = Point::from((0., 0.));
if let Some(move_) = &self.move_animation { if let Some(move_) = &self.move_x_animation {
offset += move_.from.to_f64().upscale(move_.anim.value()); 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() offset.to_i32_round()
@@ -237,23 +251,43 @@ impl<W: LayoutElement> Tile<W> {
} }
pub fn animate_move_from(&mut self, from: Point<i32, Logical>) { 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( pub fn animate_move_x_from(&mut self, from: i32) {
&mut self, self.animate_move_x_from_with_config(from, self.options.animations.window_movement.0);
from: Point<i32, Logical>, }
config: niri_config::Animation,
) { pub fn animate_move_x_from_with_config(&mut self, from: i32, config: niri_config::Animation) {
let current_offset = self.render_offset(); let current_offset = self.render_offset().x;
// Preserve the previous config if ongoing. // 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 let anim = anim
.map(|anim| anim.restarted(1., 0., 0.)) .map(|anim| anim.restarted(1., 0., 0.))
.unwrap_or_else(|| Animation::new(1., 0., 0., config)); .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, anim,
from: from + current_offset, from: from + current_offset,
}); });
+7 -7
View File
@@ -920,7 +920,7 @@ impl<W: LayoutElement> Workspace<W> {
// Animate movement of other tiles. // Animate movement of other tiles.
let offset_y = column.tile_y(window_idx + 1) - column.tile_y(window_idx); let offset_y = column.tile_y(window_idx + 1) - column.tile_y(window_idx);
for tile in &mut column.tiles[window_idx + 1..] { 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); let tile = column.tiles.remove(window_idx);
@@ -2323,8 +2323,8 @@ impl<W: LayoutElement> Column<W> {
// Move windows below in tandem with resizing. // Move windows below in tandem with resizing.
if tile.resize_animation().is_some() && offset != 0 { if tile.resize_animation().is_some() && offset != 0 {
for tile in &mut self.tiles[tile_idx + 1..] { for tile in &mut self.tiles[tile_idx + 1..] {
tile.animate_move_from_with_config( tile.animate_move_y_from_with_config(
Point::from((0, offset)), offset,
self.options.animations.window_resize.0, self.options.animations.window_resize.0,
); );
} }
@@ -2525,8 +2525,8 @@ impl<W: LayoutElement> Column<W> {
// Animate the movement. // Animate the movement.
let new_active_y = self.tile_y(new_idx); 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].animate_move_y_from(active_y - new_active_y);
self.tiles[new_idx + 1].animate_move_from(Point::from((0, active_y - next_y))); self.tiles[new_idx + 1].animate_move_y_from(active_y - next_y);
} }
fn move_down(&mut self) { fn move_down(&mut self) {
@@ -2546,8 +2546,8 @@ impl<W: LayoutElement> Column<W> {
// Animate the movement. // Animate the movement.
let new_active_y = self.tile_y(new_idx); 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].animate_move_y_from(active_y - new_active_y);
self.tiles[new_idx - 1].animate_move_from(Point::from((0, next_y - active_y))); self.tiles[new_idx - 1].animate_move_y_from(next_y - active_y);
} }
#[cfg(test)] #[cfg(test)]