aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMicah N Gorrell <m@minego.net>2024-05-22 13:53:44 -0600
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-24 16:44:20 +0400
commiteb0f7aa4293b7d65c47fd53df9a9880e7a2c75d7 (patch)
tree9d9b9df2a0df1fb19c3d21399fef9b8aca1d264e
parentbcca03cce7da9dc4125aa34943041cb65e0fd4bb (diff)
downloadniri-eb0f7aa4293b7d65c47fd53df9a9880e7a2c75d7.tar.gz
niri-eb0f7aa4293b7d65c47fd53df9a9880e7a2c75d7.tar.bz2
niri-eb0f7aa4293b7d65c47fd53df9a9880e7a2c75d7.zip
Added actions to allow focusing up or down as normal but to wrap to the column to the left or right if there is no window above or below
-rw-r--r--niri-config/src/lib.rs8
-rw-r--r--niri-ipc/src/lib.rs8
-rw-r--r--src/input/mod.rs24
-rw-r--r--src/layout/mod.rs44
-rw-r--r--src/layout/monitor.rs56
5 files changed, 140 insertions, 0 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index 437a3a2c..b3a00e79 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -909,6 +909,10 @@ pub enum Action {
FocusColumnLast,
FocusWindowDown,
FocusWindowUp,
+ FocusWindowDownOrColumnLeft,
+ FocusWindowDownOrColumnRight,
+ FocusWindowUpOrColumnLeft,
+ FocusWindowUpOrColumnRight,
FocusWindowOrWorkspaceDown,
FocusWindowOrWorkspaceUp,
MoveColumnLeft,
@@ -979,6 +983,10 @@ impl From<niri_ipc::Action> for Action {
niri_ipc::Action::FocusColumnLast => Self::FocusColumnLast,
niri_ipc::Action::FocusWindowDown => Self::FocusWindowDown,
niri_ipc::Action::FocusWindowUp => Self::FocusWindowUp,
+ niri_ipc::Action::FocusWindowDownOrColumnLeft => Self::FocusWindowDownOrColumnLeft,
+ niri_ipc::Action::FocusWindowDownOrColumnRight => Self::FocusWindowDownOrColumnRight,
+ niri_ipc::Action::FocusWindowUpOrColumnLeft => Self::FocusWindowUpOrColumnLeft,
+ niri_ipc::Action::FocusWindowUpOrColumnRight => Self::FocusWindowUpOrColumnRight,
niri_ipc::Action::FocusWindowOrWorkspaceDown => Self::FocusWindowOrWorkspaceDown,
niri_ipc::Action::FocusWindowOrWorkspaceUp => Self::FocusWindowOrWorkspaceUp,
niri_ipc::Action::MoveColumnLeft => Self::MoveColumnLeft,
diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs
index b57860d8..9d52546a 100644
--- a/niri-ipc/src/lib.rs
+++ b/niri-ipc/src/lib.rs
@@ -116,6 +116,14 @@ pub enum Action {
FocusWindowDown,
/// Focus the window above.
FocusWindowUp,
+ /// Focus the window below or the column to the left.
+ FocusWindowDownOrColumnLeft,
+ /// Focus the window below or the column to the right.
+ FocusWindowDownOrColumnRight,
+ /// Focus the window above or the column to the left.
+ FocusWindowUpOrColumnLeft,
+ /// Focus the window above or the column to the right.
+ FocusWindowUpOrColumnRight,
/// Focus the window or the workspace above.
FocusWindowOrWorkspaceDown,
/// Focus the window or the workspace above.
diff --git a/src/input/mod.rs b/src/input/mod.rs
index 0d2074a4..8bf94d15 100644
--- a/src/input/mod.rs
+++ b/src/input/mod.rs
@@ -563,6 +563,30 @@ impl State {
// FIXME: granular
self.niri.queue_redraw_all();
}
+ Action::FocusWindowDownOrColumnLeft => {
+ self.niri.layout.focus_down_or_left();
+ self.maybe_warp_cursor_to_focus();
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
+ Action::FocusWindowDownOrColumnRight => {
+ self.niri.layout.focus_down_or_right();
+ self.maybe_warp_cursor_to_focus();
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
+ Action::FocusWindowUpOrColumnLeft => {
+ self.niri.layout.focus_up_or_left();
+ self.maybe_warp_cursor_to_focus();
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
+ Action::FocusWindowUpOrColumnRight => {
+ self.niri.layout.focus_up_or_right();
+ self.maybe_warp_cursor_to_focus();
+ // FIXME: granular
+ self.niri.queue_redraw_all();
+ }
Action::FocusWindowOrWorkspaceDown => {
self.niri.layout.focus_window_or_workspace_down();
self.maybe_warp_cursor_to_focus();
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 02eeda3b..6e8fa292 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -1249,6 +1249,34 @@ impl<W: LayoutElement> Layout<W> {
monitor.focus_up();
}
+ pub fn focus_down_or_left(&mut self) {
+ let Some(monitor) = self.active_monitor() else {
+ return;
+ };
+ monitor.focus_down_or_left();
+ }
+
+ pub fn focus_down_or_right(&mut self) {
+ let Some(monitor) = self.active_monitor() else {
+ return;
+ };
+ monitor.focus_down_or_right();
+ }
+
+ pub fn focus_up_or_left(&mut self) {
+ let Some(monitor) = self.active_monitor() else {
+ return;
+ };
+ monitor.focus_up_or_left();
+ }
+
+ pub fn focus_up_or_right(&mut self) {
+ let Some(monitor) = self.active_monitor() else {
+ return;
+ };
+ monitor.focus_up_or_right();
+ }
+
pub fn focus_window_or_workspace_down(&mut self) {
let Some(monitor) = self.active_monitor() else {
return;
@@ -2603,6 +2631,10 @@ mod tests {
FocusColumnLast,
FocusWindowDown,
FocusWindowUp,
+ FocusWindowDownOrColumnLeft,
+ FocusWindowDownOrColumnRight,
+ FocusWindowUpOrColumnLeft,
+ FocusWindowUpOrColumnRight,
FocusWindowOrWorkspaceDown,
FocusWindowOrWorkspaceUp,
MoveColumnLeft,
@@ -2887,6 +2919,10 @@ mod tests {
Op::FocusColumnLast => layout.focus_column_last(),
Op::FocusWindowDown => layout.focus_down(),
Op::FocusWindowUp => layout.focus_up(),
+ Op::FocusWindowDownOrColumnLeft => layout.focus_down_or_left(),
+ Op::FocusWindowDownOrColumnRight => layout.focus_down_or_right(),
+ Op::FocusWindowUpOrColumnLeft => layout.focus_up_or_left(),
+ Op::FocusWindowUpOrColumnRight => layout.focus_up_or_right(),
Op::FocusWindowOrWorkspaceDown => layout.focus_window_or_workspace_down(),
Op::FocusWindowOrWorkspaceUp => layout.focus_window_or_workspace_up(),
Op::MoveColumnLeft => layout.move_left(),
@@ -3098,8 +3134,12 @@ mod tests {
Op::FocusColumnLeft,
Op::FocusColumnRight,
Op::FocusWindowUp,
+ Op::FocusWindowUpOrColumnLeft,
+ Op::FocusWindowUpOrColumnRight,
Op::FocusWindowOrWorkspaceUp,
Op::FocusWindowDown,
+ Op::FocusWindowDownOrColumnLeft,
+ Op::FocusWindowDownOrColumnRight,
Op::FocusWindowOrWorkspaceDown,
Op::MoveColumnLeft,
Op::MoveColumnRight,
@@ -3251,8 +3291,12 @@ mod tests {
Op::FocusColumnLeft,
Op::FocusColumnRight,
Op::FocusWindowUp,
+ Op::FocusWindowUpOrColumnLeft,
+ Op::FocusWindowUpOrColumnRight,
Op::FocusWindowOrWorkspaceUp,
Op::FocusWindowDown,
+ Op::FocusWindowDownOrColumnLeft,
+ Op::FocusWindowDownOrColumnRight,
Op::FocusWindowOrWorkspaceDown,
Op::MoveColumnLeft,
Op::MoveColumnRight,
diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs
index c56146a4..b9cd431a 100644
--- a/src/layout/monitor.rs
+++ b/src/layout/monitor.rs
@@ -328,6 +328,62 @@ impl<W: LayoutElement> Monitor<W> {
self.active_workspace().focus_up();
}
+ pub fn focus_down_or_left(&mut self) {
+ let workspace = self.active_workspace();
+ if !workspace.columns.is_empty() {
+ let column = &workspace.columns[workspace.active_column_idx];
+ let curr_idx = column.active_tile_idx;
+ let new_idx = min(column.active_tile_idx + 1, column.tiles.len() - 1);
+ if curr_idx == new_idx {
+ self.focus_left();
+ } else {
+ workspace.focus_down();
+ }
+ }
+ }
+
+ pub fn focus_down_or_right(&mut self) {
+ let workspace = self.active_workspace();
+ if !workspace.columns.is_empty() {
+ let column = &workspace.columns[workspace.active_column_idx];
+ let curr_idx = column.active_tile_idx;
+ let new_idx = min(column.active_tile_idx + 1, column.tiles.len() - 1);
+ if curr_idx == new_idx {
+ self.focus_right();
+ } else {
+ workspace.focus_down();
+ }
+ }
+ }
+
+ pub fn focus_up_or_left(&mut self) {
+ let workspace = self.active_workspace();
+ if !workspace.columns.is_empty() {
+ let curr_idx = workspace.columns[workspace.active_column_idx].active_tile_idx;
+ let new_idx = curr_idx.saturating_sub(1);
+ if curr_idx == new_idx {
+ self.focus_left();
+ } else {
+ workspace.focus_up();
+ }
+ }
+ }
+
+ pub fn focus_up_or_right(&mut self) {
+ let workspace = self.active_workspace();
+ if workspace.columns.is_empty() {
+ self.switch_workspace_up();
+ } else {
+ let curr_idx = workspace.columns[workspace.active_column_idx].active_tile_idx;
+ let new_idx = curr_idx.saturating_sub(1);
+ if curr_idx == new_idx {
+ self.focus_left();
+ } else {
+ workspace.focus_up();
+ }
+ }
+ }
+
pub fn focus_window_or_workspace_down(&mut self) {
let workspace = self.active_workspace();
if workspace.columns.is_empty() {