diff options
| author | Julian Schuler <julianschuler@users.noreply.github.com> | 2024-12-15 16:04:42 +0100 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-01-02 15:15:23 +0300 |
| commit | c17d4dc050327c974535369b0b70726b269fd82b (patch) | |
| tree | bbaf75157b6cd20826bde16a67f60f3484746c3e | |
| parent | 4e33f4552226fbadb156ca16b483cda10d04b433 (diff) | |
| download | niri-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.rs | 18 | ||||
| -rw-r--r-- | niri-ipc/src/lib.rs | 16 | ||||
| -rw-r--r-- | src/input/mod.rs | 68 | ||||
| -rw-r--r-- | src/niri.rs | 34 |
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, |
