aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/input/mod.rs5
-rw-r--r--src/layout/mod.rs7
-rw-r--r--src/layout/scrolling.rs58
-rw-r--r--src/layout/tests.rs2
-rw-r--r--src/layout/workspace.rs7
5 files changed, 79 insertions, 0 deletions
diff --git a/src/input/mod.rs b/src/input/mod.rs
index 1204ff5b..35343288 100644
--- a/src/input/mod.rs
+++ b/src/input/mod.rs
@@ -1445,6 +1445,11 @@ impl State {
self.niri.queue_redraw_all();
}
}
+ Action::CenterVisibleColumns => {
+ self.niri.layout.center_visible_columns();
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
Action::MaximizeColumn => {
self.niri.layout.toggle_full_width();
}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index b2726bef..6a497c81 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -2332,6 +2332,13 @@ impl<W: LayoutElement> Layout<W> {
workspace.center_window(id);
}
+ pub fn center_visible_columns(&mut self) {
+ let Some(workspace) = self.active_workspace_mut() else {
+ return;
+ };
+ workspace.center_visible_columns();
+ }
+
pub fn focus(&self) -> Option<&W> {
self.focus_with_output().map(|(win, _out)| win)
}
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs
index bd68a65a..e2d3a6db 100644
--- a/src/layout/scrolling.rs
+++ b/src/layout/scrolling.rs
@@ -2139,6 +2139,64 @@ impl<W: LayoutElement> ScrollingSpace<W> {
self.center_column();
}
+ pub fn center_visible_columns(&mut self) {
+ if self.columns.is_empty() {
+ return;
+ }
+
+ if self.is_centering_focused_column() {
+ return;
+ }
+
+ // Consider the end of an ongoing animation because that's what compute to fit does too.
+ let view_x = self.target_view_pos();
+ let working_x = self.working_area.loc.x;
+ let working_w = self.working_area.size.w;
+
+ // Count all columns that are fully visible inside the working area.
+ let mut width_taken = 0.;
+ let mut leftmost_col_x = None;
+ let mut active_col_x = None;
+
+ let gap = self.options.gaps;
+ let col_xs = self.column_xs(self.data.iter().copied());
+ for (idx, col_x) in col_xs.take(self.columns.len()).enumerate() {
+ if col_x < view_x + working_x + gap {
+ // Column goes off-screen to the left.
+ continue;
+ }
+
+ leftmost_col_x.get_or_insert(col_x);
+
+ let width = self.data[idx].width;
+ if view_x + working_x + working_w < col_x + width + gap {
+ // Column goes off-screen to the right. We can stop here.
+ break;
+ }
+
+ if idx == self.active_column_idx {
+ active_col_x = Some(col_x);
+ }
+
+ width_taken += width + gap;
+ }
+
+ if active_col_x.is_none() {
+ // The active column wasn't fully on screen, so we can't meaningfully do anything.
+ return;
+ }
+
+ let col = &mut self.columns[self.active_column_idx];
+ cancel_resize_for_column(&mut self.interactive_resize, col);
+
+ let free_space = working_w - width_taken + gap;
+ let new_view_x = leftmost_col_x.unwrap() - free_space / 2. - working_x;
+
+ self.animate_view_offset(self.active_column_idx, new_view_x - active_col_x.unwrap());
+ // Just in case.
+ self.animate_view_offset_to_column(None, self.active_column_idx, None);
+ }
+
pub fn view_pos(&self) -> f64 {
self.column_x(self.active_column_idx) + self.view_offset.current()
}
diff --git a/src/layout/tests.rs b/src/layout/tests.rs
index a02d1120..acfced00 100644
--- a/src/layout/tests.rs
+++ b/src/layout/tests.rs
@@ -464,6 +464,7 @@ enum Op {
#[proptest(strategy = "proptest::option::of(1..=5usize)")]
id: Option<usize>,
},
+ CenterVisibleColumns,
FocusWorkspaceDown,
FocusWorkspaceUp,
FocusWorkspace(#[proptest(strategy = "0..=4usize")] usize),
@@ -1068,6 +1069,7 @@ impl Op {
let id = id.filter(|id| layout.has_window(id));
layout.center_window(id.as_ref());
}
+ Op::CenterVisibleColumns => layout.center_visible_columns(),
Op::FocusWorkspaceDown => layout.switch_workspace_down(),
Op::FocusWorkspaceUp => layout.switch_workspace_up(),
Op::FocusWorkspace(idx) => layout.switch_workspace(idx),
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index c6662214..2f631f2f 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -1100,6 +1100,13 @@ impl<W: LayoutElement> Workspace<W> {
}
}
+ pub fn center_visible_columns(&mut self) {
+ if self.floating_is_active.get() {
+ return;
+ }
+ self.scrolling.center_visible_columns();
+ }
+
pub fn toggle_width(&mut self) {
if self.floating_is_active.get() {
self.floating.toggle_window_width(None);