aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Ranke <dennis.ranke@gmail.com>2024-02-03 20:25:08 +0100
committerIvan Molodetskikh <yalterz@gmail.com>2024-02-05 14:09:47 +0400
commit3a23417e980de908c3183749da9309e9dabc9ece (patch)
treed7dcc59da493ecf5f79d730db76aa84514250c1b
parent6bb83757ee907e5ce3be617251c441c02917388e (diff)
downloadniri-3a23417e980de908c3183749da9309e9dabc9ece.tar.gz
niri-3a23417e980de908c3183749da9309e9dabc9ece.tar.bz2
niri-3a23417e980de908c3183749da9309e9dabc9ece.zip
Add consume-or-expel-window-left/right commands
-rw-r--r--niri-config/src/lib.rs2
-rw-r--r--resources/default-config.kdl4
-rw-r--r--src/input.rs10
-rw-r--r--src/layout/mod.rs22
-rw-r--r--src/layout/monitor.rs8
-rw-r--r--src/layout/workspace.rs68
6 files changed, 114 insertions, 0 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index f00eed9c..d8ccad58 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -459,6 +459,8 @@ pub enum Action {
MoveWindowUp,
MoveWindowDownOrToWorkspaceDown,
MoveWindowUpOrToWorkspaceUp,
+ ConsumeOrExpelWindowLeft,
+ ConsumeOrExpelWindowRight,
ConsumeWindowIntoColumn,
ExpelWindowFromColumn,
CenterColumn,
diff --git a/resources/default-config.kdl b/resources/default-config.kdl
index 6765e9ba..5ec5eb35 100644
--- a/resources/default-config.kdl
+++ b/resources/default-config.kdl
@@ -322,6 +322,10 @@ binds {
Mod+Comma { consume-window-into-column; }
Mod+Period { expel-window-from-column; }
+ // There are also commands that consume or expel a single window to the side.
+ // Mod+BracketLeft { consume-or-expel-window-left; }
+ // Mod+BracketRight { consume-or-expel-window-right; }
+
Mod+R { switch-preset-column-width; }
Mod+F { maximize-column; }
Mod+Shift+F { fullscreen-window; }
diff --git a/src/input.rs b/src/input.rs
index f06f6142..0371e933 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -407,6 +407,16 @@ impl State {
// FIXME: granular
self.niri.queue_redraw_all();
}
+ Action::ConsumeOrExpelWindowLeft => {
+ self.niri.layout.consume_or_expel_window_left();
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
+ Action::ConsumeOrExpelWindowRight => {
+ self.niri.layout.consume_or_expel_window_right();
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
Action::FocusColumnLeft => {
self.niri.layout.focus_left();
// FIXME: granular
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 111562cd..9ae89f03 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -898,6 +898,20 @@ impl<W: LayoutElement> Layout<W> {
monitor.move_up_or_to_workspace_up();
}
+ pub fn consume_or_expel_window_left(&mut self) {
+ let Some(monitor) = self.active_monitor() else {
+ return;
+ };
+ monitor.consume_or_expel_window_left();
+ }
+
+ pub fn consume_or_expel_window_right(&mut self) {
+ let Some(monitor) = self.active_monitor() else {
+ return;
+ };
+ monitor.consume_or_expel_window_right();
+ }
+
pub fn focus_left(&mut self) {
let Some(monitor) = self.active_monitor() else {
return;
@@ -1780,6 +1794,8 @@ mod tests {
MoveWindowUp,
MoveWindowDownOrToWorkspaceDown,
MoveWindowUpOrToWorkspaceUp,
+ ConsumeOrExpelWindowLeft,
+ ConsumeOrExpelWindowRight,
ConsumeWindowIntoColumn,
ExpelWindowFromColumn,
CenterColumn,
@@ -1906,6 +1922,8 @@ mod tests {
Op::MoveWindowUp => layout.move_up(),
Op::MoveWindowDownOrToWorkspaceDown => layout.move_down_or_to_workspace_down(),
Op::MoveWindowUpOrToWorkspaceUp => layout.move_up_or_to_workspace_up(),
+ Op::ConsumeOrExpelWindowLeft => layout.consume_or_expel_window_left(),
+ Op::ConsumeOrExpelWindowRight => layout.consume_or_expel_window_right(),
Op::ConsumeWindowIntoColumn => layout.consume_into_column(),
Op::ExpelWindowFromColumn => layout.expel_from_column(),
Op::CenterColumn => layout.center_column(),
@@ -2072,6 +2090,8 @@ mod tests {
Op::MoveWindowDownOrToWorkspaceDown,
Op::MoveWindowUp,
Op::MoveWindowUpOrToWorkspaceUp,
+ Op::ConsumeOrExpelWindowLeft,
+ Op::ConsumeOrExpelWindowRight,
Op::MoveWorkspaceToOutput(1),
];
@@ -2203,6 +2223,8 @@ mod tests {
Op::MoveWindowDownOrToWorkspaceDown,
Op::MoveWindowUp,
Op::MoveWindowUpOrToWorkspaceUp,
+ Op::ConsumeOrExpelWindowLeft,
+ Op::ConsumeOrExpelWindowRight,
];
for third in every_op {
diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs
index f63b0c75..cd6d1eba 100644
--- a/src/layout/monitor.rs
+++ b/src/layout/monitor.rs
@@ -215,6 +215,14 @@ impl<W: LayoutElement> Monitor<W> {
}
}
+ pub fn consume_or_expel_window_left(&mut self) {
+ self.active_workspace().consume_or_expel_window_left();
+ }
+
+ pub fn consume_or_expel_window_right(&mut self) {
+ self.active_workspace().consume_or_expel_window_right();
+ }
+
pub fn focus_left(&mut self) {
self.active_workspace().focus_left();
}
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index fbae0064..4eb8c347 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -866,6 +866,70 @@ impl<W: LayoutElement> Workspace<W> {
self.columns[self.active_column_idx].move_up();
}
+ pub fn consume_or_expel_window_left(&mut self) {
+ if self.columns.is_empty() {
+ return;
+ }
+
+ let source_column = &self.columns[self.active_column_idx];
+ if source_column.tiles.len() == 1 {
+ if self.active_column_idx == 0 {
+ return;
+ }
+
+ // Move into adjacent column.
+ let target_column_idx = self.active_column_idx - 1;
+ let window = self.remove_window_by_idx(self.active_column_idx, 0);
+ self.enter_output_for_window(&window);
+
+ let target_column = &mut self.columns[target_column_idx];
+ target_column.add_window(window);
+ target_column.focus_last();
+ self.activate_column(target_column_idx);
+ } else {
+ // Move out of column.
+ let width = source_column.width;
+ let is_full_width = source_column.is_full_width;
+ let window =
+ self.remove_window_by_idx(self.active_column_idx, source_column.active_tile_idx);
+
+ self.add_window(window, true, width, is_full_width);
+ // Window was added to the right of current column, so move the new column left.
+ self.move_left();
+ }
+ }
+
+ pub fn consume_or_expel_window_right(&mut self) {
+ if self.columns.is_empty() {
+ return;
+ }
+
+ let source_column = &self.columns[self.active_column_idx];
+ if source_column.tiles.len() == 1 {
+ if self.active_column_idx + 1 == self.columns.len() {
+ return;
+ }
+
+ // Move into adjacent column.
+ let target_column_idx = self.active_column_idx;
+ let window = self.remove_window_by_idx(self.active_column_idx, 0);
+ self.enter_output_for_window(&window);
+
+ let target_column = &mut self.columns[target_column_idx];
+ target_column.add_window(window);
+ target_column.focus_last();
+ self.activate_column(target_column_idx);
+ } else {
+ // Move out of column.
+ let width = source_column.width;
+ let is_full_width = source_column.is_full_width;
+ let window =
+ self.remove_window_by_idx(self.active_column_idx, source_column.active_tile_idx);
+
+ self.add_window(window, true, width, is_full_width);
+ }
+ }
+
pub fn consume_into_column(&mut self) {
if self.columns.len() < 2 {
return;
@@ -1414,6 +1478,10 @@ impl<W: LayoutElement> Column<W> {
self.active_tile_idx = min(self.active_tile_idx + 1, self.tiles.len() - 1);
}
+ fn focus_last(&mut self) {
+ self.active_tile_idx = self.tiles.len() - 1;
+ }
+
fn move_up(&mut self) {
let new_idx = self.active_tile_idx.saturating_sub(1);
if self.active_tile_idx == new_idx {