mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
Add center-visible-columns action
This commit is contained in:
@@ -1749,6 +1749,7 @@ pub enum Action {
|
|||||||
CenterWindow,
|
CenterWindow,
|
||||||
#[knuffel(skip)]
|
#[knuffel(skip)]
|
||||||
CenterWindowById(u64),
|
CenterWindowById(u64),
|
||||||
|
CenterVisibleColumns,
|
||||||
FocusWorkspaceDown,
|
FocusWorkspaceDown,
|
||||||
#[knuffel(skip)]
|
#[knuffel(skip)]
|
||||||
FocusWorkspaceDownUnderMouse,
|
FocusWorkspaceDownUnderMouse,
|
||||||
@@ -1992,6 +1993,7 @@ impl From<niri_ipc::Action> for Action {
|
|||||||
niri_ipc::Action::CenterColumn {} => Self::CenterColumn,
|
niri_ipc::Action::CenterColumn {} => Self::CenterColumn,
|
||||||
niri_ipc::Action::CenterWindow { id: None } => Self::CenterWindow,
|
niri_ipc::Action::CenterWindow { id: None } => Self::CenterWindow,
|
||||||
niri_ipc::Action::CenterWindow { id: Some(id) } => Self::CenterWindowById(id),
|
niri_ipc::Action::CenterWindow { id: Some(id) } => Self::CenterWindowById(id),
|
||||||
|
niri_ipc::Action::CenterVisibleColumns {} => Self::CenterVisibleColumns,
|
||||||
niri_ipc::Action::FocusWorkspaceDown {} => Self::FocusWorkspaceDown,
|
niri_ipc::Action::FocusWorkspaceDown {} => Self::FocusWorkspaceDown,
|
||||||
niri_ipc::Action::FocusWorkspaceUp {} => Self::FocusWorkspaceUp,
|
niri_ipc::Action::FocusWorkspaceUp {} => Self::FocusWorkspaceUp,
|
||||||
niri_ipc::Action::FocusWorkspace { reference } => {
|
niri_ipc::Action::FocusWorkspace { reference } => {
|
||||||
|
|||||||
@@ -426,6 +426,8 @@ pub enum Action {
|
|||||||
#[cfg_attr(feature = "clap", arg(long))]
|
#[cfg_attr(feature = "clap", arg(long))]
|
||||||
id: Option<u64>,
|
id: Option<u64>,
|
||||||
},
|
},
|
||||||
|
/// Center all fully visible columns on the screen.
|
||||||
|
CenterVisibleColumns {},
|
||||||
/// Focus the workspace below.
|
/// Focus the workspace below.
|
||||||
FocusWorkspaceDown {},
|
FocusWorkspaceDown {},
|
||||||
/// Focus the workspace above.
|
/// Focus the workspace above.
|
||||||
|
|||||||
@@ -525,6 +525,9 @@ binds {
|
|||||||
|
|
||||||
Mod+C { center-column; }
|
Mod+C { center-column; }
|
||||||
|
|
||||||
|
// Center all fully visible columns on screen.
|
||||||
|
Mod+Ctrl+C { center-visible-columns; }
|
||||||
|
|
||||||
// Finer width adjustments.
|
// Finer width adjustments.
|
||||||
// This command can also:
|
// This command can also:
|
||||||
// * set width in pixels: "1000"
|
// * set width in pixels: "1000"
|
||||||
|
|||||||
@@ -1445,6 +1445,11 @@ impl State {
|
|||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Action::CenterVisibleColumns => {
|
||||||
|
self.niri.layout.center_visible_columns();
|
||||||
|
// FIXME: granular
|
||||||
|
self.niri.queue_redraw_all();
|
||||||
|
}
|
||||||
Action::MaximizeColumn => {
|
Action::MaximizeColumn => {
|
||||||
self.niri.layout.toggle_full_width();
|
self.niri.layout.toggle_full_width();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2332,6 +2332,13 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
workspace.center_window(id);
|
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> {
|
pub fn focus(&self) -> Option<&W> {
|
||||||
self.focus_with_output().map(|(win, _out)| win)
|
self.focus_with_output().map(|(win, _out)| win)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2139,6 +2139,64 @@ impl<W: LayoutElement> ScrollingSpace<W> {
|
|||||||
self.center_column();
|
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 {
|
pub fn view_pos(&self) -> f64 {
|
||||||
self.column_x(self.active_column_idx) + self.view_offset.current()
|
self.column_x(self.active_column_idx) + self.view_offset.current()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -464,6 +464,7 @@ enum Op {
|
|||||||
#[proptest(strategy = "proptest::option::of(1..=5usize)")]
|
#[proptest(strategy = "proptest::option::of(1..=5usize)")]
|
||||||
id: Option<usize>,
|
id: Option<usize>,
|
||||||
},
|
},
|
||||||
|
CenterVisibleColumns,
|
||||||
FocusWorkspaceDown,
|
FocusWorkspaceDown,
|
||||||
FocusWorkspaceUp,
|
FocusWorkspaceUp,
|
||||||
FocusWorkspace(#[proptest(strategy = "0..=4usize")] usize),
|
FocusWorkspace(#[proptest(strategy = "0..=4usize")] usize),
|
||||||
@@ -1068,6 +1069,7 @@ impl Op {
|
|||||||
let id = id.filter(|id| layout.has_window(id));
|
let id = id.filter(|id| layout.has_window(id));
|
||||||
layout.center_window(id.as_ref());
|
layout.center_window(id.as_ref());
|
||||||
}
|
}
|
||||||
|
Op::CenterVisibleColumns => layout.center_visible_columns(),
|
||||||
Op::FocusWorkspaceDown => layout.switch_workspace_down(),
|
Op::FocusWorkspaceDown => layout.switch_workspace_down(),
|
||||||
Op::FocusWorkspaceUp => layout.switch_workspace_up(),
|
Op::FocusWorkspaceUp => layout.switch_workspace_up(),
|
||||||
Op::FocusWorkspace(idx) => layout.switch_workspace(idx),
|
Op::FocusWorkspace(idx) => layout.switch_workspace(idx),
|
||||||
|
|||||||
@@ -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) {
|
pub fn toggle_width(&mut self) {
|
||||||
if self.floating_is_active.get() {
|
if self.floating_is_active.get() {
|
||||||
self.floating.toggle_window_width(None);
|
self.floating.toggle_window_width(None);
|
||||||
|
|||||||
Reference in New Issue
Block a user