mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
Add focus-window-top/bottom/down-or-top/up-or-bottom actions
This commit is contained in:
@@ -1342,6 +1342,10 @@ pub enum Action {
|
||||
FocusWindowUpOrColumnRight,
|
||||
FocusWindowOrWorkspaceDown,
|
||||
FocusWindowOrWorkspaceUp,
|
||||
FocusWindowTop,
|
||||
FocusWindowBottom,
|
||||
FocusWindowDownOrTop,
|
||||
FocusWindowUpOrBottom,
|
||||
MoveColumnLeft,
|
||||
MoveColumnRight,
|
||||
MoveColumnToFirst,
|
||||
@@ -1521,6 +1525,10 @@ impl From<niri_ipc::Action> for Action {
|
||||
niri_ipc::Action::FocusWindowUpOrColumnRight {} => Self::FocusWindowUpOrColumnRight,
|
||||
niri_ipc::Action::FocusWindowOrWorkspaceDown {} => Self::FocusWindowOrWorkspaceDown,
|
||||
niri_ipc::Action::FocusWindowOrWorkspaceUp {} => Self::FocusWindowOrWorkspaceUp,
|
||||
niri_ipc::Action::FocusWindowTop {} => Self::FocusWindowTop,
|
||||
niri_ipc::Action::FocusWindowBottom {} => Self::FocusWindowBottom,
|
||||
niri_ipc::Action::FocusWindowDownOrTop {} => Self::FocusWindowDownOrTop,
|
||||
niri_ipc::Action::FocusWindowUpOrBottom {} => Self::FocusWindowUpOrBottom,
|
||||
niri_ipc::Action::MoveColumnLeft {} => Self::MoveColumnLeft,
|
||||
niri_ipc::Action::MoveColumnRight {} => Self::MoveColumnRight,
|
||||
niri_ipc::Action::MoveColumnToFirst {} => Self::MoveColumnToFirst,
|
||||
|
||||
@@ -253,6 +253,14 @@ pub enum Action {
|
||||
FocusWindowOrWorkspaceDown {},
|
||||
/// Focus the window or the workspace above.
|
||||
FocusWindowOrWorkspaceUp {},
|
||||
/// Focus the topmost window.
|
||||
FocusWindowTop {},
|
||||
/// Focus the bottommost window.
|
||||
FocusWindowBottom {},
|
||||
/// Focus the window below or the topmost window.
|
||||
FocusWindowDownOrTop {},
|
||||
/// Focus the window above or the bottommost window.
|
||||
FocusWindowUpOrBottom {},
|
||||
/// Move the focused column to the left.
|
||||
MoveColumnLeft {},
|
||||
/// Move the focused column to the right.
|
||||
|
||||
@@ -987,6 +987,34 @@ impl State {
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWindowTop => {
|
||||
self.niri.layout.focus_window_top();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
self.niri.layer_shell_on_demand_focus = None;
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWindowBottom => {
|
||||
self.niri.layout.focus_window_bottom();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
self.niri.layer_shell_on_demand_focus = None;
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWindowDownOrTop => {
|
||||
self.niri.layout.focus_window_down_or_top();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
self.niri.layer_shell_on_demand_focus = None;
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::FocusWindowUpOrBottom => {
|
||||
self.niri.layout.focus_window_up_or_bottom();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
self.niri.layer_shell_on_demand_focus = None;
|
||||
// FIXME: granular
|
||||
self.niri.queue_redraw_all();
|
||||
}
|
||||
Action::MoveWindowToWorkspaceDown => {
|
||||
self.niri.layout.move_to_workspace_down();
|
||||
self.maybe_warp_cursor_to_focus();
|
||||
|
||||
@@ -833,6 +833,26 @@ impl<W: LayoutElement> FloatingSpace<W> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_topmost(&mut self) {
|
||||
let result = self
|
||||
.tiles_with_offsets()
|
||||
.min_by(|(_, pos_a), (_, pos_b)| f64::total_cmp(&pos_a.y, &pos_b.y));
|
||||
if let Some((tile, _)) = result {
|
||||
let id = tile.window().id().clone();
|
||||
self.activate_window(&id);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_bottommost(&mut self) {
|
||||
let result = self
|
||||
.tiles_with_offsets()
|
||||
.max_by(|(_, pos_a), (_, pos_b)| f64::total_cmp(&pos_a.y, &pos_b.y));
|
||||
if let Some((tile, _)) = result {
|
||||
let id = tile.window().id().clone();
|
||||
self.activate_window(&id);
|
||||
}
|
||||
}
|
||||
|
||||
fn move_to(&mut self, idx: usize, new_pos: Point<f64, Logical>, animate: bool) {
|
||||
if animate {
|
||||
self.move_and_animate(idx, new_pos);
|
||||
|
||||
@@ -1949,6 +1949,34 @@ impl<W: LayoutElement> Layout<W> {
|
||||
monitor.focus_window_or_workspace_up();
|
||||
}
|
||||
|
||||
pub fn focus_window_top(&mut self) {
|
||||
let Some(monitor) = self.active_monitor() else {
|
||||
return;
|
||||
};
|
||||
monitor.focus_window_top();
|
||||
}
|
||||
|
||||
pub fn focus_window_bottom(&mut self) {
|
||||
let Some(monitor) = self.active_monitor() else {
|
||||
return;
|
||||
};
|
||||
monitor.focus_window_bottom();
|
||||
}
|
||||
|
||||
pub fn focus_window_down_or_top(&mut self) {
|
||||
let Some(monitor) = self.active_monitor() else {
|
||||
return;
|
||||
};
|
||||
monitor.focus_window_down_or_top();
|
||||
}
|
||||
|
||||
pub fn focus_window_up_or_bottom(&mut self) {
|
||||
let Some(monitor) = self.active_monitor() else {
|
||||
return;
|
||||
};
|
||||
monitor.focus_window_up_or_bottom();
|
||||
}
|
||||
|
||||
pub fn move_to_workspace_up(&mut self) {
|
||||
let Some(monitor) = self.active_monitor() else {
|
||||
return;
|
||||
|
||||
@@ -493,6 +493,22 @@ impl<W: LayoutElement> Monitor<W> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_window_top(&mut self) {
|
||||
self.active_workspace().focus_window_top();
|
||||
}
|
||||
|
||||
pub fn focus_window_bottom(&mut self) {
|
||||
self.active_workspace().focus_window_bottom();
|
||||
}
|
||||
|
||||
pub fn focus_window_down_or_top(&mut self) {
|
||||
self.active_workspace().focus_window_down_or_top();
|
||||
}
|
||||
|
||||
pub fn focus_window_up_or_bottom(&mut self) {
|
||||
self.active_workspace().focus_window_up_or_bottom();
|
||||
}
|
||||
|
||||
pub fn move_to_workspace_up(&mut self) {
|
||||
let source_workspace_idx = self.active_workspace_idx;
|
||||
|
||||
|
||||
@@ -1422,6 +1422,22 @@ impl<W: LayoutElement> ScrollingSpace<W> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_top(&mut self) {
|
||||
if self.columns.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.columns[self.active_column_idx].focus_top()
|
||||
}
|
||||
|
||||
pub fn focus_bottom(&mut self) {
|
||||
if self.columns.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.columns[self.active_column_idx].focus_bottom()
|
||||
}
|
||||
|
||||
fn move_column_to(&mut self, new_idx: usize) {
|
||||
if self.active_column_idx == new_idx {
|
||||
return;
|
||||
@@ -3616,6 +3632,14 @@ impl<W: LayoutElement> Column<W> {
|
||||
true
|
||||
}
|
||||
|
||||
fn focus_top(&mut self) {
|
||||
self.active_tile_idx = 0;
|
||||
}
|
||||
|
||||
fn focus_bottom(&mut self) {
|
||||
self.active_tile_idx = self.tiles.len() - 1;
|
||||
}
|
||||
|
||||
fn move_up(&mut self) -> bool {
|
||||
let new_idx = self.active_tile_idx.saturating_sub(1);
|
||||
if self.active_tile_idx == new_idx {
|
||||
|
||||
@@ -380,6 +380,10 @@ enum Op {
|
||||
FocusWindowOrWorkspaceDown,
|
||||
FocusWindowOrWorkspaceUp,
|
||||
FocusWindow(#[proptest(strategy = "1..=5usize")] usize),
|
||||
FocusWindowTop,
|
||||
FocusWindowBottom,
|
||||
FocusWindowDownOrTop,
|
||||
FocusWindowUpOrBottom,
|
||||
MoveColumnLeft,
|
||||
MoveColumnRight,
|
||||
MoveColumnToFirst,
|
||||
@@ -924,6 +928,10 @@ 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::FocusWindowTop => layout.focus_window_top(),
|
||||
Op::FocusWindowBottom => layout.focus_window_bottom(),
|
||||
Op::FocusWindowDownOrTop => layout.focus_window_down_or_top(),
|
||||
Op::FocusWindowUpOrBottom => layout.focus_window_up_or_bottom(),
|
||||
Op::MoveColumnLeft => layout.move_left(),
|
||||
Op::MoveColumnRight => layout.move_right(),
|
||||
Op::MoveColumnToFirst => layout.move_column_to_first(),
|
||||
|
||||
@@ -896,6 +896,34 @@ impl<W: LayoutElement> Workspace<W> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_window_top(&mut self) {
|
||||
if self.floating_is_active.get() {
|
||||
self.floating.focus_topmost();
|
||||
} else {
|
||||
self.scrolling.focus_top();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_window_bottom(&mut self) {
|
||||
if self.floating_is_active.get() {
|
||||
self.floating.focus_bottommost();
|
||||
} else {
|
||||
self.scrolling.focus_bottom();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_window_down_or_top(&mut self) {
|
||||
if !self.focus_down() {
|
||||
self.focus_window_top();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_window_up_or_bottom(&mut self) {
|
||||
if !self.focus_up() {
|
||||
self.focus_window_bottom();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_left(&mut self) -> bool {
|
||||
if self.floating_is_active.get() {
|
||||
self.floating.move_left();
|
||||
|
||||
Reference in New Issue
Block a user