aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--niri-config/src/lib.rs14
-rw-r--r--src/layout/workspace.rs63
-rw-r--r--wiki/Configuration:-Animations.md19
3 files changed, 92 insertions, 4 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index d03de0ff..bb453ce3 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -483,6 +483,8 @@ pub struct Animations {
pub workspace_switch: Animation,
#[knuffel(child, default = Animation::default_horizontal_view_movement())]
pub horizontal_view_movement: Animation,
+ #[knuffel(child, default = Animation::default_window_movement())]
+ pub window_movement: Animation,
#[knuffel(child, default = Animation::default_window_open())]
pub window_open: Animation,
#[knuffel(child, default = Animation::default_config_notification_open_close())]
@@ -496,6 +498,7 @@ impl Default for Animations {
slowdown: 1.,
workspace_switch: Animation::default_workspace_switch(),
horizontal_view_movement: Animation::default_horizontal_view_movement(),
+ window_movement: Animation::default_window_movement(),
window_open: Animation::default_window_open(),
config_notification_open_close: Animation::default_config_notification_open_close(),
}
@@ -545,6 +548,17 @@ impl Animation {
}
}
+ pub const fn default_window_movement() -> Self {
+ Self {
+ off: false,
+ kind: AnimationKind::Spring(SpringParams {
+ damping_ratio: 1.,
+ stiffness: 800,
+ epsilon: 0.0001,
+ }),
+ }
+ }
+
pub const fn default_config_notification_open_close() -> Self {
Self {
off: false,
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index dda8b7c9..40d55622 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -181,6 +181,9 @@ pub struct Column<W: LayoutElement> {
/// Whether this column contains a single full-screened window.
pub is_fullscreen: bool,
+ /// Animation of the render offset during window swapping.
+ move_animation: Option<Animation>,
+
/// Latest known view size for this column's workspace.
view_size: Size<i32, Logical>,
@@ -967,7 +970,10 @@ impl<W: LayoutElement> Workspace<W> {
return;
}
- let current_x = self.view_pos();
+ let current_col_x = self.column_x(self.active_column_idx);
+ let next_col_x = self.column_x(self.active_column_idx + 1);
+
+ let current_x = current_col_x + self.view_offset;
let column = self.columns.remove(self.active_column_idx);
self.columns.insert(new_idx, column);
@@ -975,6 +981,22 @@ impl<W: LayoutElement> Workspace<W> {
// Preserve the camera position when moving to the left.
self.view_offset = current_x - self.column_x(self.active_column_idx);
+ // The column we just moved is offset by the difference between its new and old position.
+ let new_col_x = self.column_x(new_idx);
+ self.columns[new_idx].animate_move_from(current_col_x - new_col_x);
+
+ // All columns in between moved by the width of the column that we just moved.
+ let others_x_offset = next_col_x - current_col_x;
+ if self.active_column_idx < new_idx {
+ for col in &mut self.columns[self.active_column_idx..new_idx] {
+ col.animate_move_from(others_x_offset);
+ }
+ } else {
+ for col in &mut self.columns[new_idx + 1..=self.active_column_idx] {
+ col.animate_move_from(-others_x_offset);
+ }
+ }
+
self.activate_column(new_idx);
}
@@ -1150,7 +1172,7 @@ impl<W: LayoutElement> Workspace<W> {
let tile_pos = Point::from((
self.visual_column_x(self.active_column_idx) - view_pos,
col.tile_y(col.active_tile_idx),
- ));
+ )) + col.render_offset();
let first = iter::once((tile, tile_pos));
let mut x = -view_pos;
@@ -1172,7 +1194,7 @@ impl<W: LayoutElement> Workspace<W> {
return None;
}
- let tile_pos = Point::from((x, y));
+ let tile_pos = Point::from((x, y)) + col.render_offset();
Some((tile, tile_pos))
},
)
@@ -1604,6 +1626,7 @@ impl<W: LayoutElement> Column<W> {
width,
is_full_width,
is_fullscreen: false,
+ move_animation: None,
view_size,
working_area,
options,
@@ -1669,6 +1692,16 @@ impl<W: LayoutElement> Column<W> {
}
pub fn advance_animations(&mut self, current_time: Duration, is_active: bool) {
+ match &mut self.move_animation {
+ Some(anim) => {
+ anim.set_current_time(current_time);
+ if anim.is_done() {
+ self.move_animation = None;
+ }
+ }
+ None => (),
+ }
+
for (tile_idx, tile) in self.tiles.iter_mut().enumerate() {
let is_active = is_active && tile_idx == self.active_tile_idx;
tile.advance_animations(current_time, is_active);
@@ -1676,7 +1709,29 @@ impl<W: LayoutElement> Column<W> {
}
pub fn are_animations_ongoing(&self) -> bool {
- self.tiles.iter().any(Tile::are_animations_ongoing)
+ self.move_animation.is_some() || self.tiles.iter().any(Tile::are_animations_ongoing)
+ }
+
+ pub fn render_offset(&self) -> Point<i32, Logical> {
+ let mut offset = Point::from((0., 0.));
+
+ if let Some(anim) = &self.move_animation {
+ offset.x += anim.value();
+ }
+
+ offset.to_i32_round()
+ }
+
+ pub fn animate_move_from(&mut self, from_x_offset: i32) {
+ let current_offset = self.move_animation.as_ref().map_or(0., Animation::value);
+
+ self.move_animation = Some(Animation::new(
+ f64::from(from_x_offset) + current_offset,
+ 0.,
+ 0.,
+ self.options.animations.window_movement,
+ niri_config::Animation::default_window_movement(),
+ ));
}
pub fn contains(&self, window: &W::Id) -> bool {
diff --git a/wiki/Configuration:-Animations.md b/wiki/Configuration:-Animations.md
index 4db9346c..e74af219 100644
--- a/wiki/Configuration:-Animations.md
+++ b/wiki/Configuration:-Animations.md
@@ -24,6 +24,10 @@ animations {
spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
}
+ window-movement {
+ spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
+ }
+
window-open {
duration-ms 150
curve "ease-out-expo"
@@ -131,6 +135,21 @@ animations {
}
```
+#### `window-movement`
+
+Window movement animations, currently cover only horizontal column movement.
+
+This animation runs on actions like `move-column-left` and `move-column-right` to move the windows themselves.
+It can sometimes run together with the `horizontal-view-movement` animation, if the camera also moves.
+
+```
+animations {
+ window-movement {
+ spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
+ }
+}
+```
+
#### `window-open`
Window opening animation.