aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Schuler <julianschuler@users.noreply.github.com>2024-12-15 16:04:42 +0100
committerIvan Molodetskikh <yalterz@gmail.com>2025-01-02 15:15:23 +0300
commitc17d4dc050327c974535369b0b70726b269fd82b (patch)
treebbaf75157b6cd20826bde16a67f60f3484746c3e
parent4e33f4552226fbadb156ca16b483cda10d04b433 (diff)
downloadniri-c17d4dc050327c974535369b0b70726b269fd82b.tar.gz
niri-c17d4dc050327c974535369b0b70726b269fd82b.tar.bz2
niri-c17d4dc050327c974535369b0b70726b269fd82b.zip
Add actions to focus/move to next/previous monitor
-rw-r--r--niri-config/src/lib.rs18
-rw-r--r--niri-ipc/src/lib.rs16
-rw-r--r--src/input/mod.rs68
-rw-r--r--src/niri.rs34
4 files changed, 136 insertions, 0 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index ef9ef5b2..5e6e56e7 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -1265,14 +1265,20 @@ pub enum Action {
FocusMonitorRight,
FocusMonitorDown,
FocusMonitorUp,
+ FocusMonitorPrevious,
+ FocusMonitorNext,
MoveWindowToMonitorLeft,
MoveWindowToMonitorRight,
MoveWindowToMonitorDown,
MoveWindowToMonitorUp,
+ MoveWindowToMonitorPrevious,
+ MoveWindowToMonitorNext,
MoveColumnToMonitorLeft,
MoveColumnToMonitorRight,
MoveColumnToMonitorDown,
MoveColumnToMonitorUp,
+ MoveColumnToMonitorPrevious,
+ MoveColumnToMonitorNext,
SetWindowWidth(#[knuffel(argument, str)] SizeChange),
#[knuffel(skip)]
SetWindowWidthById {
@@ -1303,6 +1309,8 @@ pub enum Action {
MoveWorkspaceToMonitorRight,
MoveWorkspaceToMonitorDown,
MoveWorkspaceToMonitorUp,
+ MoveWorkspaceToMonitorPrevious,
+ MoveWorkspaceToMonitorNext,
ToggleWindowFloating,
#[knuffel(skip)]
ToggleWindowFloatingById(u64),
@@ -1422,14 +1430,20 @@ impl From<niri_ipc::Action> for Action {
niri_ipc::Action::FocusMonitorRight {} => Self::FocusMonitorRight,
niri_ipc::Action::FocusMonitorDown {} => Self::FocusMonitorDown,
niri_ipc::Action::FocusMonitorUp {} => Self::FocusMonitorUp,
+ niri_ipc::Action::FocusMonitorPrevious {} => Self::FocusMonitorPrevious,
+ niri_ipc::Action::FocusMonitorNext {} => Self::FocusMonitorNext,
niri_ipc::Action::MoveWindowToMonitorLeft {} => Self::MoveWindowToMonitorLeft,
niri_ipc::Action::MoveWindowToMonitorRight {} => Self::MoveWindowToMonitorRight,
niri_ipc::Action::MoveWindowToMonitorDown {} => Self::MoveWindowToMonitorDown,
niri_ipc::Action::MoveWindowToMonitorUp {} => Self::MoveWindowToMonitorUp,
+ niri_ipc::Action::MoveWindowToMonitorPrevious {} => Self::MoveWindowToMonitorPrevious,
+ niri_ipc::Action::MoveWindowToMonitorNext {} => Self::MoveWindowToMonitorNext,
niri_ipc::Action::MoveColumnToMonitorLeft {} => Self::MoveColumnToMonitorLeft,
niri_ipc::Action::MoveColumnToMonitorRight {} => Self::MoveColumnToMonitorRight,
niri_ipc::Action::MoveColumnToMonitorDown {} => Self::MoveColumnToMonitorDown,
niri_ipc::Action::MoveColumnToMonitorUp {} => Self::MoveColumnToMonitorUp,
+ niri_ipc::Action::MoveColumnToMonitorPrevious {} => Self::MoveColumnToMonitorPrevious,
+ niri_ipc::Action::MoveColumnToMonitorNext {} => Self::MoveColumnToMonitorNext,
niri_ipc::Action::SetWindowWidth { id: None, change } => Self::SetWindowWidth(change),
niri_ipc::Action::SetWindowWidth {
id: Some(id),
@@ -1461,6 +1475,10 @@ impl From<niri_ipc::Action> for Action {
niri_ipc::Action::MoveWorkspaceToMonitorRight {} => Self::MoveWorkspaceToMonitorRight,
niri_ipc::Action::MoveWorkspaceToMonitorDown {} => Self::MoveWorkspaceToMonitorDown,
niri_ipc::Action::MoveWorkspaceToMonitorUp {} => Self::MoveWorkspaceToMonitorUp,
+ niri_ipc::Action::MoveWorkspaceToMonitorPrevious {} => {
+ Self::MoveWorkspaceToMonitorPrevious
+ }
+ niri_ipc::Action::MoveWorkspaceToMonitorNext {} => Self::MoveWorkspaceToMonitorNext,
niri_ipc::Action::ToggleDebugTint {} => Self::ToggleDebugTint,
niri_ipc::Action::DebugToggleOpaqueRegions {} => Self::DebugToggleOpaqueRegions,
niri_ipc::Action::DebugToggleDamage {} => Self::DebugToggleDamage,
diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs
index a53ac8ab..856f6757 100644
--- a/niri-ipc/src/lib.rs
+++ b/niri-ipc/src/lib.rs
@@ -358,6 +358,10 @@ pub enum Action {
FocusMonitorDown {},
/// Focus the monitor above.
FocusMonitorUp {},
+ /// Focus the previous monitor.
+ FocusMonitorPrevious {},
+ /// Focus the next monitor.
+ FocusMonitorNext {},
/// Move the focused window to the monitor to the left.
MoveWindowToMonitorLeft {},
/// Move the focused window to the monitor to the right.
@@ -366,6 +370,10 @@ pub enum Action {
MoveWindowToMonitorDown {},
/// Move the focused window to the monitor above.
MoveWindowToMonitorUp {},
+ /// Move the focused window to the previous monitor.
+ MoveWindowToMonitorPrevious {},
+ /// Move the focused window to the next monitor.
+ MoveWindowToMonitorNext {},
/// Move the focused column to the monitor to the left.
MoveColumnToMonitorLeft {},
/// Move the focused column to the monitor to the right.
@@ -374,6 +382,10 @@ pub enum Action {
MoveColumnToMonitorDown {},
/// Move the focused column to the monitor above.
MoveColumnToMonitorUp {},
+ /// Move the focused column to the previous monitor.
+ MoveColumnToMonitorPrevious {},
+ /// Move the focused column to the next monitor.
+ MoveColumnToMonitorNext {},
/// Change the width of a window.
#[cfg_attr(
feature = "clap",
@@ -460,6 +472,10 @@ pub enum Action {
MoveWorkspaceToMonitorDown {},
/// Move the focused workspace to the monitor above.
MoveWorkspaceToMonitorUp {},
+ /// Move the focused workspace to the previous monitor.
+ MoveWorkspaceToMonitorPrevious {},
+ /// Move the focused workspace to the next monitor.
+ MoveWorkspaceToMonitorNext {},
/// Toggle a debug tint on windows.
ToggleDebugTint {},
/// Toggle visualization of render element opaque regions.
diff --git a/src/input/mod.rs b/src/input/mod.rs
index c86e1467..f30bf168 100644
--- a/src/input/mod.rs
+++ b/src/input/mod.rs
@@ -1186,6 +1186,22 @@ impl State {
}
}
}
+ Action::FocusMonitorPrevious => {
+ if let Some(output) = self.niri.output_previous() {
+ self.niri.layout.focus_output(&output);
+ if !self.maybe_warp_cursor_to_focus_centered() {
+ self.move_cursor_to_output(&output);
+ }
+ }
+ }
+ Action::FocusMonitorNext => {
+ if let Some(output) = self.niri.output_next() {
+ self.niri.layout.focus_output(&output);
+ if !self.maybe_warp_cursor_to_focus_centered() {
+ self.move_cursor_to_output(&output);
+ }
+ }
+ }
Action::MoveWindowToMonitorLeft => {
if let Some(output) = self.niri.output_left() {
self.niri.layout.move_to_output(None, &output, None);
@@ -1222,6 +1238,24 @@ impl State {
}
}
}
+ Action::MoveWindowToMonitorPrevious => {
+ if let Some(output) = self.niri.output_previous() {
+ self.niri.layout.move_to_output(None, &output, None);
+ self.niri.layout.focus_output(&output);
+ if !self.maybe_warp_cursor_to_focus_centered() {
+ self.move_cursor_to_output(&output);
+ }
+ }
+ }
+ Action::MoveWindowToMonitorNext => {
+ if let Some(output) = self.niri.output_next() {
+ self.niri.layout.move_to_output(None, &output, None);
+ self.niri.layout.focus_output(&output);
+ if !self.maybe_warp_cursor_to_focus_centered() {
+ self.move_cursor_to_output(&output);
+ }
+ }
+ }
Action::MoveColumnToMonitorLeft => {
if let Some(output) = self.niri.output_left() {
self.niri.layout.move_column_to_output(&output);
@@ -1258,6 +1292,24 @@ impl State {
}
}
}
+ Action::MoveColumnToMonitorPrevious => {
+ if let Some(output) = self.niri.output_previous() {
+ self.niri.layout.move_column_to_output(&output);
+ self.niri.layout.focus_output(&output);
+ if !self.maybe_warp_cursor_to_focus_centered() {
+ self.move_cursor_to_output(&output);
+ }
+ }
+ }
+ Action::MoveColumnToMonitorNext => {
+ if let Some(output) = self.niri.output_next() {
+ self.niri.layout.move_column_to_output(&output);
+ self.niri.layout.focus_output(&output);
+ if !self.maybe_warp_cursor_to_focus_centered() {
+ self.move_cursor_to_output(&output);
+ }
+ }
+ }
Action::SetColumnWidth(change) => {
self.niri.layout.set_column_width(change);
}
@@ -1328,6 +1380,22 @@ impl State {
}
}
}
+ Action::MoveWorkspaceToMonitorPrevious => {
+ if let Some(output) = self.niri.output_previous() {
+ self.niri.layout.move_workspace_to_output(&output);
+ if !self.maybe_warp_cursor_to_focus_centered() {
+ self.move_cursor_to_output(&output);
+ }
+ }
+ }
+ Action::MoveWorkspaceToMonitorNext => {
+ if let Some(output) = self.niri.output_next() {
+ self.niri.layout.move_workspace_to_output(&output);
+ if !self.maybe_warp_cursor_to_focus_centered() {
+ self.move_cursor_to_output(&output);
+ }
+ }
+ }
Action::ToggleWindowFloating => {
self.niri.layout.toggle_window_floating(None);
// FIXME: granular
diff --git a/src/niri.rs b/src/niri.rs
index ada6039e..5786bf54 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -194,6 +194,9 @@ pub struct Niri {
// according to their global position.
pub global_space: Space<Window>,
+ /// Mapped outputs, sorted by their name and position.
+ pub sorted_outputs: Vec<Output>,
+
// Windows which don't have a buffer attached yet.
pub unmapped_windows: HashMap<WlSurface, Unmapped>,
@@ -1959,6 +1962,7 @@ impl Niri {
layout,
global_space: Space::default(),
+ sorted_outputs: Vec::default(),
output_state: HashMap::new(),
unmapped_windows: HashMap::new(),
unmapped_layer_surfaces: HashSet::new(),
@@ -2148,6 +2152,11 @@ impl Niri {
outputs.iter().map(|d| &d.name.connector)
);
+ self.sorted_outputs = outputs
+ .iter()
+ .map(|Data { output, .. }| output.clone())
+ .collect();
+
for data in outputs.into_iter() {
let Data {
output,
@@ -2658,6 +2667,31 @@ impl Niri {
.cloned()
}
+ pub fn output_previous(&self) -> Option<Output> {
+ let active = self.layout.active_output()?;
+
+ self.sorted_outputs
+ .iter()
+ .rev()
+ .skip_while(|&output| output != active)
+ .nth(1)
+ .or(self.sorted_outputs.last())
+ .filter(|&output| output != active)
+ .cloned()
+ }
+
+ pub fn output_next(&self) -> Option<Output> {
+ let active = self.layout.active_output()?;
+
+ self.sorted_outputs
+ .iter()
+ .skip_while(|&output| output != active)
+ .nth(1)
+ .or(self.sorted_outputs.first())
+ .filter(|&output| output != active)
+ .cloned()
+ }
+
pub fn find_output_and_workspace_index(
&self,
workspace_reference: WorkspaceReference,