Add focus-window-in-column (by index) action

This commit is contained in:
Ivan Molodetskikh
2025-02-05 17:18:21 +03:00
parent c41f93a468
commit a444efd0eb
8 changed files with 49 additions and 0 deletions

View File

@@ -1323,6 +1323,7 @@ pub enum Action {
FullscreenWindowById(u64),
#[knuffel(skip)]
FocusWindow(u64),
FocusWindowInColumn(#[knuffel(argument)] u8),
FocusWindowPrevious,
FocusColumnLeft,
FocusColumnRight,
@@ -1506,6 +1507,7 @@ impl From<niri_ipc::Action> for Action {
niri_ipc::Action::FullscreenWindow { id: None } => Self::FullscreenWindow,
niri_ipc::Action::FullscreenWindow { id: Some(id) } => Self::FullscreenWindowById(id),
niri_ipc::Action::FocusWindow { id } => Self::FocusWindow(id),
niri_ipc::Action::FocusWindowInColumn { index } => Self::FocusWindowInColumn(index),
niri_ipc::Action::FocusWindowPrevious {} => Self::FocusWindowPrevious,
niri_ipc::Action::FocusColumnLeft {} => Self::FocusColumnLeft,
niri_ipc::Action::FocusColumnRight {} => Self::FocusColumnRight,

View File

@@ -215,6 +215,14 @@ pub enum Action {
#[cfg_attr(feature = "clap", arg(long))]
id: u64,
},
/// Focus a window in the focused column by index.
FocusWindowInColumn {
/// Index of the window in the column.
///
/// The index starts from 1 for the topmost window.
#[cfg_attr(feature = "clap", arg())]
index: u8,
},
/// Focus the previously focused window.
FocusWindowPrevious {},
/// Focus the column to the left.

View File

@@ -681,6 +681,13 @@ impl State {
self.focus_window(&window);
}
}
Action::FocusWindowInColumn(index) => {
self.niri.layout.focus_window_in_column(index);
self.maybe_warp_cursor_to_focus();
self.niri.layer_shell_on_demand_focus = None;
// FIXME: granular
self.niri.queue_redraw_all();
}
Action::FocusWindowPrevious => {
if let Some(window) = self.niri.previously_focused_window.clone() {
self.focus_window(&window);

View File

@@ -1893,6 +1893,13 @@ impl<W: LayoutElement> Layout<W> {
true
}
pub fn focus_window_in_column(&mut self, index: u8) {
let Some(monitor) = self.active_monitor() else {
return;
};
monitor.focus_window_in_column(index);
}
pub fn focus_down(&mut self) {
let Some(monitor) = self.active_monitor() else {
return;

View File

@@ -457,6 +457,10 @@ impl<W: LayoutElement> Monitor<W> {
self.active_workspace().focus_column_left_or_last();
}
pub fn focus_window_in_column(&mut self, index: u8) {
self.active_workspace().focus_window_in_column(index);
}
pub fn focus_down(&mut self) -> bool {
self.active_workspace().focus_down()
}

View File

@@ -1362,6 +1362,14 @@ impl<W: LayoutElement> ScrollingSpace<W> {
self.activate_column(self.columns.len() - 1);
}
pub fn focus_window_in_column(&mut self, index: u8) {
if self.columns.is_empty() {
return;
}
self.columns[self.active_column_idx].focus_index(index);
}
pub fn focus_down(&mut self) -> bool {
if self.columns.is_empty() {
return false;
@@ -3614,6 +3622,10 @@ impl<W: LayoutElement> Column<W> {
.unwrap()
}
fn focus_index(&mut self, index: u8) {
self.active_tile_idx = min(usize::from(index.saturating_sub(1)), self.tiles.len() - 1);
}
fn focus_up(&mut self) -> bool {
if self.active_tile_idx == 0 {
return false;

View File

@@ -380,6 +380,7 @@ enum Op {
FocusWindowOrWorkspaceDown,
FocusWindowOrWorkspaceUp,
FocusWindow(#[proptest(strategy = "1..=5usize")] usize),
FocusWindowInColumn(#[proptest(strategy = "1..=5u8")] u8),
FocusWindowTop,
FocusWindowBottom,
FocusWindowDownOrTop,
@@ -928,6 +929,7 @@ impl Op {
Op::FocusWindowOrWorkspaceDown => layout.focus_window_or_workspace_down(),
Op::FocusWindowOrWorkspaceUp => layout.focus_window_or_workspace_up(),
Op::FocusWindow(id) => layout.activate_window(&id),
Op::FocusWindowInColumn(index) => layout.focus_window_in_column(index),
Op::FocusWindowTop => layout.focus_window_top(),
Op::FocusWindowBottom => layout.focus_window_bottom(),
Op::FocusWindowDownOrTop => layout.focus_window_down_or_top(),

View File

@@ -848,6 +848,13 @@ impl<W: LayoutElement> Workspace<W> {
}
}
pub fn focus_window_in_column(&mut self, index: u8) {
if self.floating_is_active.get() {
return;
}
self.scrolling.focus_window_in_column(index);
}
pub fn focus_down(&mut self) -> bool {
if self.floating_is_active.get() {
self.floating.focus_down()