mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
Implement warp-mouse-to-focus
This commit is contained in:
committed by
Ivan Molodetskikh
parent
0c57815fbf
commit
741bee461c
@@ -69,6 +69,8 @@ pub struct Input {
|
|||||||
pub touch: Touch,
|
pub touch: Touch,
|
||||||
#[knuffel(child)]
|
#[knuffel(child)]
|
||||||
pub disable_power_key_handling: bool,
|
pub disable_power_key_handling: bool,
|
||||||
|
#[knuffel(child)]
|
||||||
|
pub warp_mouse_to_focus: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq)]
|
#[derive(knuffel::Decode, Debug, Default, PartialEq, Eq)]
|
||||||
@@ -1592,6 +1594,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disable-power-key-handling
|
disable-power-key-handling
|
||||||
|
|
||||||
|
warp-mouse-to-focus
|
||||||
}
|
}
|
||||||
|
|
||||||
output "eDP-1" {
|
output "eDP-1" {
|
||||||
@@ -1731,6 +1735,7 @@ mod tests {
|
|||||||
map_to_output: Some("eDP-1".to_owned()),
|
map_to_output: Some("eDP-1".to_owned()),
|
||||||
},
|
},
|
||||||
disable_power_key_handling: true,
|
disable_power_key_handling: true,
|
||||||
|
warp_mouse_to_focus: true,
|
||||||
},
|
},
|
||||||
outputs: vec![Output {
|
outputs: vec![Output {
|
||||||
off: false,
|
off: false,
|
||||||
|
|||||||
@@ -67,6 +67,9 @@ input {
|
|||||||
// Uncomment this if you would like to configure the power button elsewhere
|
// Uncomment this if you would like to configure the power button elsewhere
|
||||||
// (i.e. logind.conf).
|
// (i.e. logind.conf).
|
||||||
// disable-power-key-handling
|
// disable-power-key-handling
|
||||||
|
|
||||||
|
// Uncomment this to make the mouse warp to the center of newly focused windows.
|
||||||
|
// warp-mouse-to-focus
|
||||||
}
|
}
|
||||||
|
|
||||||
// You can configure outputs by their name, which you can find
|
// You can configure outputs by their name, which you can find
|
||||||
|
|||||||
@@ -411,139 +411,166 @@ impl State {
|
|||||||
}
|
}
|
||||||
Action::MoveColumnLeft => {
|
Action::MoveColumnLeft => {
|
||||||
self.niri.layout.move_left();
|
self.niri.layout.move_left();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveColumnRight => {
|
Action::MoveColumnRight => {
|
||||||
self.niri.layout.move_right();
|
self.niri.layout.move_right();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveColumnToFirst => {
|
Action::MoveColumnToFirst => {
|
||||||
self.niri.layout.move_column_to_first();
|
self.niri.layout.move_column_to_first();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveColumnToLast => {
|
Action::MoveColumnToLast => {
|
||||||
self.niri.layout.move_column_to_last();
|
self.niri.layout.move_column_to_last();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveWindowDown => {
|
Action::MoveWindowDown => {
|
||||||
self.niri.layout.move_down();
|
self.niri.layout.move_down();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveWindowUp => {
|
Action::MoveWindowUp => {
|
||||||
self.niri.layout.move_up();
|
self.niri.layout.move_up();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveWindowDownOrToWorkspaceDown => {
|
Action::MoveWindowDownOrToWorkspaceDown => {
|
||||||
self.niri.layout.move_down_or_to_workspace_down();
|
self.niri.layout.move_down_or_to_workspace_down();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveWindowUpOrToWorkspaceUp => {
|
Action::MoveWindowUpOrToWorkspaceUp => {
|
||||||
self.niri.layout.move_up_or_to_workspace_up();
|
self.niri.layout.move_up_or_to_workspace_up();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::ConsumeOrExpelWindowLeft => {
|
Action::ConsumeOrExpelWindowLeft => {
|
||||||
self.niri.layout.consume_or_expel_window_left();
|
self.niri.layout.consume_or_expel_window_left();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::ConsumeOrExpelWindowRight => {
|
Action::ConsumeOrExpelWindowRight => {
|
||||||
self.niri.layout.consume_or_expel_window_right();
|
self.niri.layout.consume_or_expel_window_right();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusColumnLeft => {
|
Action::FocusColumnLeft => {
|
||||||
self.niri.layout.focus_left();
|
self.niri.layout.focus_left();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusColumnRight => {
|
Action::FocusColumnRight => {
|
||||||
self.niri.layout.focus_right();
|
self.niri.layout.focus_right();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusColumnFirst => {
|
Action::FocusColumnFirst => {
|
||||||
self.niri.layout.focus_column_first();
|
self.niri.layout.focus_column_first();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusColumnLast => {
|
Action::FocusColumnLast => {
|
||||||
self.niri.layout.focus_column_last();
|
self.niri.layout.focus_column_last();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusWindowDown => {
|
Action::FocusWindowDown => {
|
||||||
self.niri.layout.focus_down();
|
self.niri.layout.focus_down();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusWindowUp => {
|
Action::FocusWindowUp => {
|
||||||
self.niri.layout.focus_up();
|
self.niri.layout.focus_up();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusWindowOrWorkspaceDown => {
|
Action::FocusWindowOrWorkspaceDown => {
|
||||||
self.niri.layout.focus_window_or_workspace_down();
|
self.niri.layout.focus_window_or_workspace_down();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusWindowOrWorkspaceUp => {
|
Action::FocusWindowOrWorkspaceUp => {
|
||||||
self.niri.layout.focus_window_or_workspace_up();
|
self.niri.layout.focus_window_or_workspace_up();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
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();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveWindowToWorkspaceUp => {
|
Action::MoveWindowToWorkspaceUp => {
|
||||||
self.niri.layout.move_to_workspace_up();
|
self.niri.layout.move_to_workspace_up();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveWindowToWorkspace(idx) => {
|
Action::MoveWindowToWorkspace(idx) => {
|
||||||
let idx = idx.saturating_sub(1) as usize;
|
let idx = idx.saturating_sub(1) as usize;
|
||||||
self.niri.layout.move_to_workspace(idx);
|
self.niri.layout.move_to_workspace(idx);
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveColumnToWorkspaceDown => {
|
Action::MoveColumnToWorkspaceDown => {
|
||||||
self.niri.layout.move_column_to_workspace_down();
|
self.niri.layout.move_column_to_workspace_down();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveColumnToWorkspaceUp => {
|
Action::MoveColumnToWorkspaceUp => {
|
||||||
self.niri.layout.move_column_to_workspace_up();
|
self.niri.layout.move_column_to_workspace_up();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::MoveColumnToWorkspace(idx) => {
|
Action::MoveColumnToWorkspace(idx) => {
|
||||||
let idx = idx.saturating_sub(1) as usize;
|
let idx = idx.saturating_sub(1) as usize;
|
||||||
self.niri.layout.move_column_to_workspace(idx);
|
self.niri.layout.move_column_to_workspace(idx);
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusWorkspaceDown => {
|
Action::FocusWorkspaceDown => {
|
||||||
self.niri.layout.switch_workspace_down();
|
self.niri.layout.switch_workspace_down();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusWorkspaceUp => {
|
Action::FocusWorkspaceUp => {
|
||||||
self.niri.layout.switch_workspace_up();
|
self.niri.layout.switch_workspace_up();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::FocusWorkspace(idx) => {
|
Action::FocusWorkspace(idx) => {
|
||||||
let idx = idx.saturating_sub(1) as usize;
|
let idx = idx.saturating_sub(1) as usize;
|
||||||
self.niri.layout.switch_workspace(idx);
|
self.niri.layout.switch_workspace(idx);
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
@@ -559,11 +586,14 @@ impl State {
|
|||||||
}
|
}
|
||||||
Action::ConsumeWindowIntoColumn => {
|
Action::ConsumeWindowIntoColumn => {
|
||||||
self.niri.layout.consume_into_column();
|
self.niri.layout.consume_into_column();
|
||||||
|
// This does not cause immediate focus or window size change, so warping mouse to
|
||||||
|
// focus won't do anything here.
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
Action::ExpelWindowFromColumn => {
|
Action::ExpelWindowFromColumn => {
|
||||||
self.niri.layout.expel_from_column();
|
self.niri.layout.expel_from_column();
|
||||||
|
self.maybe_warp_cursor_to_focus();
|
||||||
// FIXME: granular
|
// FIXME: granular
|
||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
@@ -581,83 +611,107 @@ impl State {
|
|||||||
Action::FocusMonitorLeft => {
|
Action::FocusMonitorLeft => {
|
||||||
if let Some(output) = self.niri.output_left() {
|
if let Some(output) = self.niri.output_left() {
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::FocusMonitorRight => {
|
Action::FocusMonitorRight => {
|
||||||
if let Some(output) = self.niri.output_right() {
|
if let Some(output) = self.niri.output_right() {
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::FocusMonitorDown => {
|
Action::FocusMonitorDown => {
|
||||||
if let Some(output) = self.niri.output_down() {
|
if let Some(output) = self.niri.output_down() {
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::FocusMonitorUp => {
|
Action::FocusMonitorUp => {
|
||||||
if let Some(output) = self.niri.output_up() {
|
if let Some(output) = self.niri.output_up() {
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveWindowToMonitorLeft => {
|
Action::MoveWindowToMonitorLeft => {
|
||||||
if let Some(output) = self.niri.output_left() {
|
if let Some(output) = self.niri.output_left() {
|
||||||
self.niri.layout.move_to_output(&output);
|
self.niri.layout.move_to_output(&output);
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveWindowToMonitorRight => {
|
Action::MoveWindowToMonitorRight => {
|
||||||
if let Some(output) = self.niri.output_right() {
|
if let Some(output) = self.niri.output_right() {
|
||||||
self.niri.layout.move_to_output(&output);
|
self.niri.layout.move_to_output(&output);
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveWindowToMonitorDown => {
|
Action::MoveWindowToMonitorDown => {
|
||||||
if let Some(output) = self.niri.output_down() {
|
if let Some(output) = self.niri.output_down() {
|
||||||
self.niri.layout.move_to_output(&output);
|
self.niri.layout.move_to_output(&output);
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveWindowToMonitorUp => {
|
Action::MoveWindowToMonitorUp => {
|
||||||
if let Some(output) = self.niri.output_up() {
|
if let Some(output) = self.niri.output_up() {
|
||||||
self.niri.layout.move_to_output(&output);
|
self.niri.layout.move_to_output(&output);
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveColumnToMonitorLeft => {
|
Action::MoveColumnToMonitorLeft => {
|
||||||
if let Some(output) = self.niri.output_left() {
|
if let Some(output) = self.niri.output_left() {
|
||||||
self.niri.layout.move_column_to_output(&output);
|
self.niri.layout.move_column_to_output(&output);
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveColumnToMonitorRight => {
|
Action::MoveColumnToMonitorRight => {
|
||||||
if let Some(output) = self.niri.output_right() {
|
if let Some(output) = self.niri.output_right() {
|
||||||
self.niri.layout.move_column_to_output(&output);
|
self.niri.layout.move_column_to_output(&output);
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveColumnToMonitorDown => {
|
Action::MoveColumnToMonitorDown => {
|
||||||
if let Some(output) = self.niri.output_down() {
|
if let Some(output) = self.niri.output_down() {
|
||||||
self.niri.layout.move_column_to_output(&output);
|
self.niri.layout.move_column_to_output(&output);
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveColumnToMonitorUp => {
|
Action::MoveColumnToMonitorUp => {
|
||||||
if let Some(output) = self.niri.output_up() {
|
if let Some(output) = self.niri.output_up() {
|
||||||
self.niri.layout.move_column_to_output(&output);
|
self.niri.layout.move_column_to_output(&output);
|
||||||
self.niri.layout.focus_output(&output);
|
self.niri.layout.focus_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::SetColumnWidth(change) => {
|
Action::SetColumnWidth(change) => {
|
||||||
self.niri.layout.set_column_width(change);
|
self.niri.layout.set_column_width(change);
|
||||||
}
|
}
|
||||||
@@ -672,29 +726,37 @@ impl State {
|
|||||||
Action::MoveWorkspaceToMonitorLeft => {
|
Action::MoveWorkspaceToMonitorLeft => {
|
||||||
if let Some(output) = self.niri.output_left() {
|
if let Some(output) = self.niri.output_left() {
|
||||||
self.niri.layout.move_workspace_to_output(&output);
|
self.niri.layout.move_workspace_to_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveWorkspaceToMonitorRight => {
|
Action::MoveWorkspaceToMonitorRight => {
|
||||||
if let Some(output) = self.niri.output_right() {
|
if let Some(output) = self.niri.output_right() {
|
||||||
self.niri.layout.move_workspace_to_output(&output);
|
self.niri.layout.move_workspace_to_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveWorkspaceToMonitorDown => {
|
Action::MoveWorkspaceToMonitorDown => {
|
||||||
if let Some(output) = self.niri.output_down() {
|
if let Some(output) = self.niri.output_down() {
|
||||||
self.niri.layout.move_workspace_to_output(&output);
|
self.niri.layout.move_workspace_to_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Action::MoveWorkspaceToMonitorUp => {
|
Action::MoveWorkspaceToMonitorUp => {
|
||||||
if let Some(output) = self.niri.output_up() {
|
if let Some(output) = self.niri.output_up() {
|
||||||
self.niri.layout.move_workspace_to_output(&output);
|
self.niri.layout.move_workspace_to_output(&output);
|
||||||
|
if !self.maybe_warp_cursor_to_focus_centered() {
|
||||||
self.move_cursor_to_output(&output);
|
self.move_cursor_to_output(&output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn on_pointer_motion<I: InputBackend>(&mut self, event: I::PointerMotionEvent) {
|
fn on_pointer_motion<I: InputBackend>(&mut self, event: I::PointerMotionEvent) {
|
||||||
// We need an output to be able to move the pointer.
|
// We need an output to be able to move the pointer.
|
||||||
|
|||||||
@@ -583,6 +583,14 @@ impl<W: LayoutElement> Monitor<W> {
|
|||||||
self.clean_up_workspaces();
|
self.clean_up_workspaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the geometry of the active tile relative to and clamped to the output.
|
||||||
|
///
|
||||||
|
/// During animations, assumes the final view position.
|
||||||
|
pub fn active_tile_visual_rectangle(&self) -> Option<Rectangle<i32, Logical>> {
|
||||||
|
// FIXME: switch gesture.
|
||||||
|
self.active_workspace_ref().active_tile_visual_rectangle()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn window_under(
|
pub fn window_under(
|
||||||
&self,
|
&self,
|
||||||
pos_within_output: Point<f64, Logical>,
|
pos_within_output: Point<f64, Logical>,
|
||||||
|
|||||||
@@ -181,6 +181,15 @@ impl OutputId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ViewOffsetAdjustment {
|
||||||
|
pub fn target_view_offset(&self) -> f64 {
|
||||||
|
match self {
|
||||||
|
ViewOffsetAdjustment::Animation(anim) => anim.to(),
|
||||||
|
ViewOffsetAdjustment::Gesture(gesture) => gesture.current_view_offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ColumnWidth {
|
impl ColumnWidth {
|
||||||
fn resolve(self, options: &Options, view_width: i32) -> i32 {
|
fn resolve(self, options: &Options, view_width: i32) -> i32 {
|
||||||
match self {
|
match self {
|
||||||
@@ -1124,6 +1133,31 @@ impl<W: LayoutElement> Workspace<W> {
|
|||||||
first.chain(rest)
|
first.chain(rest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn active_column_ref(&self) -> Option<&Column<W>> {
|
||||||
|
if self.columns.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(&self.columns[self.active_column_idx])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the geometry of the active tile relative to and clamped to the view.
|
||||||
|
///
|
||||||
|
/// During animations, assumes the final view position.
|
||||||
|
pub fn active_tile_visual_rectangle(&self) -> Option<Rectangle<i32, Logical>> {
|
||||||
|
let col = self.active_column_ref()?;
|
||||||
|
let view_pos = self
|
||||||
|
.view_offset_adj
|
||||||
|
.as_ref()
|
||||||
|
.map_or(self.view_offset, |adj| adj.target_view_offset() as i32);
|
||||||
|
|
||||||
|
let tile_pos = Point::from((-view_pos, col.tile_y(col.active_tile_idx)));
|
||||||
|
let tile_size = col.active_tile_ref().tile_size();
|
||||||
|
let tile_rect = Rectangle::from_loc_and_size(tile_pos, tile_size);
|
||||||
|
|
||||||
|
let view = Rectangle::from_loc_and_size((0, 0), self.view_size);
|
||||||
|
view.intersection(tile_rect)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn window_under(
|
pub fn window_under(
|
||||||
&self,
|
&self,
|
||||||
pos: Point<f64, Logical>,
|
pos: Point<f64, Logical>,
|
||||||
@@ -2010,6 +2044,10 @@ impl<W: LayoutElement> Column<W> {
|
|||||||
pos
|
pos
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn active_tile_ref(&self) -> &Tile<W> {
|
||||||
|
&self.tiles[self.active_tile_idx]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_new_view_offset(
|
fn compute_new_view_offset(
|
||||||
|
|||||||
+78
-2
@@ -112,7 +112,7 @@ use crate::ui::hotkey_overlay::HotkeyOverlay;
|
|||||||
use crate::ui::screenshot_ui::{ScreenshotUi, ScreenshotUiRenderElement};
|
use crate::ui::screenshot_ui::{ScreenshotUi, ScreenshotUiRenderElement};
|
||||||
use crate::utils::spawning::CHILD_ENV;
|
use crate::utils::spawning::CHILD_ENV;
|
||||||
use crate::utils::{
|
use crate::utils::{
|
||||||
center, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8,
|
center, center_f64, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8,
|
||||||
};
|
};
|
||||||
use crate::window::Unmapped;
|
use crate::window::Unmapped;
|
||||||
use crate::{animation, niri_render_elements};
|
use crate::{animation, niri_render_elements};
|
||||||
@@ -197,7 +197,6 @@ pub struct Niri {
|
|||||||
// popup grabs are active (which means the real keyboard focus is on a popup descending from
|
// popup grabs are active (which means the real keyboard focus is on a popup descending from
|
||||||
// this toplevel surface).
|
// this toplevel surface).
|
||||||
pub keyboard_focus: Option<WlSurface>,
|
pub keyboard_focus: Option<WlSurface>,
|
||||||
|
|
||||||
pub idle_inhibiting_surfaces: HashSet<WlSurface>,
|
pub idle_inhibiting_surfaces: HashSet<WlSurface>,
|
||||||
pub is_fdo_idle_inhibited: Arc<AtomicBool>,
|
pub is_fdo_idle_inhibited: Arc<AtomicBool>,
|
||||||
|
|
||||||
@@ -314,6 +313,11 @@ struct SurfaceFrameThrottlingState {
|
|||||||
last_sent_at: RefCell<Option<(Output, u32)>>,
|
last_sent_at: RefCell<Option<(Output, u32)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum CenterCoords {
|
||||||
|
Seperately,
|
||||||
|
Both,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct WindowOffscreenId(pub RefCell<Option<Id>>);
|
pub struct WindowOffscreenId(pub RefCell<Option<Id>>);
|
||||||
|
|
||||||
@@ -401,6 +405,78 @@ impl State {
|
|||||||
self.niri.queue_redraw_all();
|
self.niri.queue_redraw_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Moves cursor within the specified rectangle, only adjusting coordinates if needed.
|
||||||
|
fn move_cursor_to_rect(&mut self, rect: Rectangle<f64, Logical>, mode: CenterCoords) -> bool {
|
||||||
|
let pointer = &self.niri.seat.get_pointer().unwrap();
|
||||||
|
let cur_loc = pointer.current_location();
|
||||||
|
let x_in_bound = cur_loc.x >= rect.loc.x && cur_loc.x <= rect.loc.x + rect.size.w;
|
||||||
|
let y_in_bound = cur_loc.y >= rect.loc.y && cur_loc.y <= rect.loc.y + rect.size.h;
|
||||||
|
|
||||||
|
let p = match mode {
|
||||||
|
CenterCoords::Seperately => {
|
||||||
|
if x_in_bound && y_in_bound {
|
||||||
|
return false;
|
||||||
|
} else if y_in_bound {
|
||||||
|
// adjust x
|
||||||
|
Point::from((rect.loc.x + rect.size.w / 2.0, cur_loc.y))
|
||||||
|
} else if x_in_bound {
|
||||||
|
// adjust y
|
||||||
|
Point::from((cur_loc.x, rect.loc.y + rect.size.h / 2.0))
|
||||||
|
} else {
|
||||||
|
// adjust x and y
|
||||||
|
center_f64(rect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CenterCoords::Both => {
|
||||||
|
if x_in_bound && y_in_bound {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// adjust x and y
|
||||||
|
center_f64(rect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.move_cursor(p);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn move_cursor_to_focused_tile(&mut self, mode: CenterCoords) -> bool {
|
||||||
|
let Some(output) = self.niri.layout.active_output() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let output = output.clone();
|
||||||
|
let monitor = self.niri.layout.monitor_for_output(&output).unwrap();
|
||||||
|
|
||||||
|
let mut rv = false;
|
||||||
|
let rect = monitor.active_tile_visual_rectangle();
|
||||||
|
|
||||||
|
if let Some(rect) = rect {
|
||||||
|
let output_geo = self.niri.global_space.output_geometry(&output).unwrap();
|
||||||
|
let mut rect = rect;
|
||||||
|
rect.loc += output_geo.loc;
|
||||||
|
rv = self.move_cursor_to_rect(rect.to_f64(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn maybe_warp_cursor_to_focus(&mut self) -> bool {
|
||||||
|
if !self.niri.config.borrow().input.warp_mouse_to_focus {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.move_cursor_to_focused_tile(CenterCoords::Seperately)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn maybe_warp_cursor_to_focus_centered(&mut self) -> bool {
|
||||||
|
if !self.niri.config.borrow().input.warp_mouse_to_focus {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.move_cursor_to_focused_tile(CenterCoords::Both)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn refresh_pointer_focus(&mut self) {
|
pub fn refresh_pointer_focus(&mut self) {
|
||||||
let _span = tracy_client::span!("Niri::refresh_pointer_focus");
|
let _span = tracy_client::span!("Niri::refresh_pointer_focus");
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ pub fn center(rect: Rectangle<i32, Logical>) -> Point<i32, Logical> {
|
|||||||
rect.loc + rect.size.downscale(2).to_point()
|
rect.loc + rect.size.downscale(2).to_point()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn center_f64(rect: Rectangle<f64, Logical>) -> Point<f64, Logical> {
|
||||||
|
rect.loc + rect.size.downscale(2.0).to_point()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn output_size(output: &Output) -> Size<i32, Logical> {
|
pub fn output_size(output: &Output) -> Size<i32, Logical> {
|
||||||
let output_scale = output.current_scale().integer_scale();
|
let output_scale = output.current_scale().integer_scale();
|
||||||
let output_transform = output.current_transform();
|
let output_transform = output.current_transform();
|
||||||
|
|||||||
Reference in New Issue
Block a user