mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +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,
|
FocusWindowUpOrColumnRight,
|
||||||
FocusWindowOrWorkspaceDown,
|
FocusWindowOrWorkspaceDown,
|
||||||
FocusWindowOrWorkspaceUp,
|
FocusWindowOrWorkspaceUp,
|
||||||
|
FocusWindowTop,
|
||||||
|
FocusWindowBottom,
|
||||||
|
FocusWindowDownOrTop,
|
||||||
|
FocusWindowUpOrBottom,
|
||||||
MoveColumnLeft,
|
MoveColumnLeft,
|
||||||
MoveColumnRight,
|
MoveColumnRight,
|
||||||
MoveColumnToFirst,
|
MoveColumnToFirst,
|
||||||
@@ -1521,6 +1525,10 @@ impl From<niri_ipc::Action> for Action {
|
|||||||
niri_ipc::Action::FocusWindowUpOrColumnRight {} => Self::FocusWindowUpOrColumnRight,
|
niri_ipc::Action::FocusWindowUpOrColumnRight {} => Self::FocusWindowUpOrColumnRight,
|
||||||
niri_ipc::Action::FocusWindowOrWorkspaceDown {} => Self::FocusWindowOrWorkspaceDown,
|
niri_ipc::Action::FocusWindowOrWorkspaceDown {} => Self::FocusWindowOrWorkspaceDown,
|
||||||
niri_ipc::Action::FocusWindowOrWorkspaceUp {} => Self::FocusWindowOrWorkspaceUp,
|
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::MoveColumnLeft {} => Self::MoveColumnLeft,
|
||||||
niri_ipc::Action::MoveColumnRight {} => Self::MoveColumnRight,
|
niri_ipc::Action::MoveColumnRight {} => Self::MoveColumnRight,
|
||||||
niri_ipc::Action::MoveColumnToFirst {} => Self::MoveColumnToFirst,
|
niri_ipc::Action::MoveColumnToFirst {} => Self::MoveColumnToFirst,
|
||||||
|
|||||||
@@ -253,6 +253,14 @@ pub enum Action {
|
|||||||
FocusWindowOrWorkspaceDown {},
|
FocusWindowOrWorkspaceDown {},
|
||||||
/// Focus the window or the workspace above.
|
/// Focus the window or the workspace above.
|
||||||
FocusWindowOrWorkspaceUp {},
|
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.
|
/// Move the focused column to the left.
|
||||||
MoveColumnLeft {},
|
MoveColumnLeft {},
|
||||||
/// Move the focused column to the right.
|
/// Move the focused column to the right.
|
||||||
|
|||||||
@@ -987,6 +987,34 @@ impl State {
|
|||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
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 => {
|
Action::MoveWindowToWorkspaceDown => {
|
||||||
self.niri.layout.move_to_workspace_down();
|
self.niri.layout.move_to_workspace_down();
|
||||||
self.maybe_warp_cursor_to_focus();
|
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) {
|
fn move_to(&mut self, idx: usize, new_pos: Point<f64, Logical>, animate: bool) {
|
||||||
if animate {
|
if animate {
|
||||||
self.move_and_animate(idx, new_pos);
|
self.move_and_animate(idx, new_pos);
|
||||||
|
|||||||
@@ -1949,6 +1949,34 @@ impl<W: LayoutElement> Layout<W> {
|
|||||||
monitor.focus_window_or_workspace_up();
|
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) {
|
pub fn move_to_workspace_up(&mut self) {
|
||||||
let Some(monitor) = self.active_monitor() else {
|
let Some(monitor) = self.active_monitor() else {
|
||||||
return;
|
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) {
|
pub fn move_to_workspace_up(&mut self) {
|
||||||
let source_workspace_idx = self.active_workspace_idx;
|
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) {
|
fn move_column_to(&mut self, new_idx: usize) {
|
||||||
if self.active_column_idx == new_idx {
|
if self.active_column_idx == new_idx {
|
||||||
return;
|
return;
|
||||||
@@ -3616,6 +3632,14 @@ impl<W: LayoutElement> Column<W> {
|
|||||||
true
|
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 {
|
fn move_up(&mut self) -> bool {
|
||||||
let new_idx = self.active_tile_idx.saturating_sub(1);
|
let new_idx = self.active_tile_idx.saturating_sub(1);
|
||||||
if self.active_tile_idx == new_idx {
|
if self.active_tile_idx == new_idx {
|
||||||
|
|||||||
@@ -380,6 +380,10 @@ enum Op {
|
|||||||
FocusWindowOrWorkspaceDown,
|
FocusWindowOrWorkspaceDown,
|
||||||
FocusWindowOrWorkspaceUp,
|
FocusWindowOrWorkspaceUp,
|
||||||
FocusWindow(#[proptest(strategy = "1..=5usize")] usize),
|
FocusWindow(#[proptest(strategy = "1..=5usize")] usize),
|
||||||
|
FocusWindowTop,
|
||||||
|
FocusWindowBottom,
|
||||||
|
FocusWindowDownOrTop,
|
||||||
|
FocusWindowUpOrBottom,
|
||||||
MoveColumnLeft,
|
MoveColumnLeft,
|
||||||
MoveColumnRight,
|
MoveColumnRight,
|
||||||
MoveColumnToFirst,
|
MoveColumnToFirst,
|
||||||
@@ -924,6 +928,10 @@ impl Op {
|
|||||||
Op::FocusWindowOrWorkspaceDown => layout.focus_window_or_workspace_down(),
|
Op::FocusWindowOrWorkspaceDown => layout.focus_window_or_workspace_down(),
|
||||||
Op::FocusWindowOrWorkspaceUp => layout.focus_window_or_workspace_up(),
|
Op::FocusWindowOrWorkspaceUp => layout.focus_window_or_workspace_up(),
|
||||||
Op::FocusWindow(id) => layout.activate_window(&id),
|
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::MoveColumnLeft => layout.move_left(),
|
||||||
Op::MoveColumnRight => layout.move_right(),
|
Op::MoveColumnRight => layout.move_right(),
|
||||||
Op::MoveColumnToFirst => layout.move_column_to_first(),
|
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 {
|
pub fn move_left(&mut self) -> bool {
|
||||||
if self.floating_is_active.get() {
|
if self.floating_is_active.get() {
|
||||||
self.floating.move_left();
|
self.floating.move_left();
|
||||||
|
|||||||
Reference in New Issue
Block a user