aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/animation.rs4
-rw-r--r--src/layout.rs71
2 files changed, 68 insertions, 7 deletions
diff --git a/src/animation.rs b/src/animation.rs
index 430e3516..e2b9dc39 100644
--- a/src/animation.rs
+++ b/src/animation.rs
@@ -46,4 +46,8 @@ impl Animation {
let x = (passed / total).clamp(0., 1.);
EaseOutCubic.y(x) * (self.to - self.from) + self.from
}
+
+ pub fn to(&self) -> f64 {
+ self.to
+ }
}
diff --git a/src/layout.rs b/src/layout.rs
index 753529ab..3d85ecbe 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -1340,14 +1340,21 @@ impl<W: LayoutElement> Workspace<W> {
self.active_column_idx = idx;
- self.view_offset = 0;
- let new_x = self.view_pos();
-
+ let new_x = self.column_x(idx) - PADDING;
+ let new_view_offset = compute_new_view_offset(
+ current_x,
+ self.view_size.w,
+ new_x,
+ self.columns[idx].size().w,
+ );
+
+ let from_view_offset = current_x - new_x;
self.view_offset_anim = Some(Animation::new(
- (current_x - new_x) as f64,
- 0.,
+ from_view_offset as f64,
+ new_view_offset as f64,
Duration::from_millis(250),
));
+ self.view_offset = from_view_offset;
}
fn has_windows(&self) -> bool {
@@ -1419,12 +1426,41 @@ impl<W: LayoutElement> Workspace<W> {
}
fn update_window(&mut self, window: &W) {
- let column = self
+ let (idx, column) = self
.columns
.iter_mut()
- .find(|col| col.contains(window))
+ .enumerate()
+ .find(|(_, col)| col.contains(window))
.unwrap();
column.update_window_sizes(self.view_size);
+
+ if idx == self.active_column_idx {
+ // We might need to move the view to ensure the resized window is still visible.
+ let current_x = self.view_pos();
+ let new_x = self.column_x(idx) - PADDING;
+
+ let new_view_offset = compute_new_view_offset(
+ current_x,
+ self.view_size.w,
+ new_x,
+ self.columns[idx].size().w,
+ );
+
+ let cur_view_offset = self
+ .view_offset_anim
+ .as_ref()
+ .map(|a| a.to().round() as i32)
+ .unwrap_or(self.view_offset);
+ if cur_view_offset != new_view_offset {
+ let from_view_offset = current_x - new_x;
+ self.view_offset_anim = Some(Animation::new(
+ from_view_offset as f64,
+ new_view_offset as f64,
+ Duration::from_millis(250),
+ ));
+ self.view_offset = from_view_offset;
+ }
+ }
}
fn activate_window(&mut self, window: &W) {
@@ -1974,6 +2010,27 @@ pub fn configure_new_window(view_size: Size<i32, Logical>, window: &Window) {
});
}
+fn compute_new_view_offset(cur_x: i32, view_width: i32, new_x: i32, new_col_width: i32) -> i32 {
+ // If the column is wider than the view, always left-align it.
+ if new_col_width + PADDING * 2 >= view_width {
+ return 0;
+ }
+
+ // If the column is already fully visible, leave the view as is.
+ if new_x >= cur_x && new_x + new_col_width + PADDING * 2 <= cur_x + view_width {
+ return -(new_x - cur_x);
+ }
+
+ // Otherwise, prefer the aligment that results in less motion from the current position.
+ let dist_to_left = cur_x.abs_diff(new_x);
+ let dist_to_right = (cur_x + view_width).abs_diff(new_x + new_col_width + PADDING * 2);
+ if dist_to_left <= dist_to_right {
+ 0
+ } else {
+ -(view_width - new_col_width - PADDING * 2)
+ }
+}
+
#[cfg(test)]
mod tests {
use std::cell::Cell;