aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-12-29 22:44:19 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-12-30 20:12:37 +0300
commit6c897d520165bfcaf3833b6e3d4bdbd836d26063 (patch)
tree29fa7697f53facfe8bca4d12cbff1cca7e9065e7
parent6cb5135f3477e63ed1738e19ba95a07ce52093ae (diff)
downloadniri-6c897d520165bfcaf3833b6e3d4bdbd836d26063.tar.gz
niri-6c897d520165bfcaf3833b6e3d4bdbd836d26063.tar.bz2
niri-6c897d520165bfcaf3833b6e3d4bdbd836d26063.zip
Add center-window by-id action
-rw-r--r--niri-config/src/lib.rs5
-rw-r--r--niri-ipc/src/lib.rs12
-rw-r--r--src/input/mod.rs14
-rw-r--r--src/layout/floating.rs6
-rw-r--r--src/layout/mod.rs21
-rw-r--r--src/layout/scrolling.rs22
-rw-r--r--src/layout/workspace.rs12
7 files changed, 88 insertions, 4 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index 747ae9cb..20440d79 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -1225,6 +1225,9 @@ pub enum Action {
ConsumeWindowIntoColumn,
ExpelWindowFromColumn,
CenterColumn,
+ CenterWindow,
+ #[knuffel(skip)]
+ CenterWindowById(u64),
FocusWorkspaceDown,
FocusWorkspaceUp,
FocusWorkspace(#[knuffel(argument)] WorkspaceReference),
@@ -1368,6 +1371,8 @@ impl From<niri_ipc::Action> for Action {
niri_ipc::Action::ConsumeWindowIntoColumn {} => Self::ConsumeWindowIntoColumn,
niri_ipc::Action::ExpelWindowFromColumn {} => Self::ExpelWindowFromColumn,
niri_ipc::Action::CenterColumn {} => Self::CenterColumn,
+ niri_ipc::Action::CenterWindow { id: None } => Self::CenterWindow,
+ niri_ipc::Action::CenterWindow { id: Some(id) } => Self::CenterWindowById(id),
niri_ipc::Action::FocusWorkspaceDown {} => Self::FocusWorkspaceDown,
niri_ipc::Action::FocusWorkspaceUp {} => Self::FocusWorkspaceUp,
niri_ipc::Action::FocusWorkspace { reference } => {
diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs
index 30704b40..1f09e912 100644
--- a/niri-ipc/src/lib.rs
+++ b/niri-ipc/src/lib.rs
@@ -292,6 +292,18 @@ pub enum Action {
ExpelWindowFromColumn {},
/// Center the focused column on the screen.
CenterColumn {},
+ /// Center a window on the screen.
+ #[cfg_attr(
+ feature = "clap",
+ clap(about = "Center the focused window on the screen")
+ )]
+ CenterWindow {
+ /// Id of the window to center.
+ ///
+ /// If `None`, uses the focused window.
+ #[cfg_attr(feature = "clap", arg(long))]
+ id: Option<u64>,
+ },
/// Focus the workspace below.
FocusWorkspaceDown {},
/// Focus the workspace above.
diff --git a/src/input/mod.rs b/src/input/mod.rs
index d45d0e8a..98bbbb8e 100644
--- a/src/input/mod.rs
+++ b/src/input/mod.rs
@@ -1127,6 +1127,20 @@ impl State {
// FIXME: granular
self.niri.queue_redraw_all();
}
+ Action::CenterWindow => {
+ self.niri.layout.center_window(None);
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
+ Action::CenterWindowById(id) => {
+ let window = self.niri.layout.windows().find(|(_, m)| m.id().get() == id);
+ let window = window.map(|(_, m)| m.window.clone());
+ if let Some(window) = window {
+ self.niri.layout.center_window(Some(&window));
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
+ }
Action::MaximizeColumn => {
self.niri.layout.toggle_full_width();
}
diff --git a/src/layout/floating.rs b/src/layout/floating.rs
index 6192d119..5302e158 100644
--- a/src/layout/floating.rs
+++ b/src/layout/floating.rs
@@ -902,11 +902,11 @@ impl<W: LayoutElement> FloatingSpace<W> {
self.move_to(idx, new_pos, animate);
}
- pub fn center_window(&mut self) {
- let Some(active_id) = &self.active_window_id else {
+ pub fn center_window(&mut self, id: Option<&W::Id>) {
+ let Some(id) = id.or(self.active_window_id.as_ref()).cloned() else {
return;
};
- let idx = self.idx_of(active_id).unwrap();
+ let idx = self.idx_of(&id).unwrap();
let new_pos = center_preferring_top_left_in_area(self.working_area, self.data[idx].size);
self.move_to(idx, new_pos, true);
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 433cae43..571411fc 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -1993,6 +1993,19 @@ impl<W: LayoutElement> Layout<W> {
monitor.center_column();
}
+ pub fn center_window(&mut self, id: Option<&W::Id>) {
+ let workspace = if let Some(id) = id {
+ Some(self.workspaces_mut().find(|ws| ws.has_window(id)).unwrap())
+ } else {
+ self.active_workspace_mut()
+ };
+
+ let Some(workspace) = workspace else {
+ return;
+ };
+ workspace.center_window(id);
+ }
+
pub fn focus(&self) -> Option<&W> {
self.focus_with_output().map(|(win, _out)| win)
}
@@ -4390,6 +4403,10 @@ mod tests {
ConsumeWindowIntoColumn,
ExpelWindowFromColumn,
CenterColumn,
+ CenterWindow {
+ #[proptest(strategy = "proptest::option::of(1..=5usize)")]
+ id: Option<usize>,
+ },
FocusWorkspaceDown,
FocusWorkspaceUp,
FocusWorkspace(#[proptest(strategy = "0..=4usize")] usize),
@@ -4901,6 +4918,10 @@ mod tests {
Op::ConsumeWindowIntoColumn => layout.consume_into_column(),
Op::ExpelWindowFromColumn => layout.expel_from_column(),
Op::CenterColumn => layout.center_column(),
+ Op::CenterWindow { id } => {
+ let id = id.filter(|id| layout.has_window(id));
+ layout.center_window(id.as_ref());
+ }
Op::FocusWorkspaceDown => layout.switch_workspace_down(),
Op::FocusWorkspaceUp => layout.switch_workspace_up(),
Op::FocusWorkspace(idx) => layout.switch_workspace(idx),
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs
index a378c461..6fa6fbfc 100644
--- a/src/layout/scrolling.rs
+++ b/src/layout/scrolling.rs
@@ -1747,6 +1747,28 @@ impl<W: LayoutElement> ScrollingSpace<W> {
cancel_resize_for_column(&mut self.interactive_resize, col);
}
+ pub fn center_window(&mut self, window: Option<&W::Id>) {
+ if self.columns.is_empty() {
+ return;
+ }
+
+ let col_idx = if let Some(window) = window {
+ self.columns
+ .iter()
+ .position(|col| col.contains(window))
+ .unwrap()
+ } else {
+ self.active_column_idx
+ };
+
+ // We can reasonably center only the active column.
+ if col_idx != self.active_column_idx {
+ return;
+ }
+
+ self.center_column();
+ }
+
pub fn view_pos(&self) -> f64 {
self.column_x(self.active_column_idx) + self.view_offset.current()
}
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index 991e7e42..0e67f3b3 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -971,12 +971,22 @@ impl<W: LayoutElement> Workspace<W> {
pub fn center_column(&mut self) {
if self.floating_is_active.get() {
- self.floating.center_window();
+ self.floating.center_window(None);
} else {
self.scrolling.center_column();
}
}
+ pub fn center_window(&mut self, id: Option<&W::Id>) {
+ if id.map_or(self.floating_is_active.get(), |id| {
+ self.floating.has_window(id)
+ }) {
+ self.floating.center_window(id);
+ } else {
+ self.scrolling.center_window(id);
+ }
+ }
+
pub fn toggle_width(&mut self) {
if self.floating_is_active.get() {
self.floating.toggle_window_width(None);