diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/input/mod.rs | 5 | ||||
| -rw-r--r-- | src/layout/mod.rs | 7 | ||||
| -rw-r--r-- | src/layout/scrolling.rs | 58 | ||||
| -rw-r--r-- | src/layout/tests.rs | 2 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 7 |
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); |
