diff options
| author | Florian Finkernagel <finkernagel@imt.uni-marburg.de> | 2025-03-13 14:55:16 +0100 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-03-22 01:00:43 -0700 |
| commit | 7f72c358d56453633b57bc353a458709fe878b63 (patch) | |
| tree | b3ded6d3a1bb8129d08a7565fc25bd75dd3677b0 | |
| parent | 0d4f0f00c0cd83a72151468bc610ce230a550027 (diff) | |
| download | niri-7f72c358d56453633b57bc353a458709fe878b63.tar.gz niri-7f72c358d56453633b57bc353a458709fe878b63.tar.bz2 niri-7f72c358d56453633b57bc353a458709fe878b63.zip | |
Add option to warp-mouse-to-focus to always center
| -rw-r--r-- | niri-config/src/lib.rs | 34 | ||||
| -rw-r--r-- | src/niri.rs | 35 | ||||
| -rw-r--r-- | wiki/Configuration:-Input.md | 17 |
3 files changed, 71 insertions, 15 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index 99628649..db379746 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -95,7 +95,7 @@ pub struct Input { #[knuffel(child)] pub disable_power_key_handling: bool, #[knuffel(child)] - pub warp_mouse_to_focus: bool, + pub warp_mouse_to_focus: Option<WarpMouseToFocus>, #[knuffel(child)] pub focus_follows_mouse: Option<FocusFollowsMouse>, #[knuffel(child)] @@ -369,6 +369,32 @@ pub struct FocusFollowsMouse { pub max_scroll_amount: Option<Percent>, } +#[derive(knuffel::Decode, Debug, PartialEq, Eq, Clone, Copy)] +pub struct WarpMouseToFocus { + #[knuffel(property, str)] + pub mode: Option<WarpMouseToFocusMode>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum WarpMouseToFocusMode { + CenterXy, + CenterXyAlways, +} + +impl FromStr for WarpMouseToFocusMode { + type Err = miette::Error; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "center-xy" => Ok(Self::CenterXy), + "center-xy-always" => Ok(Self::CenterXyAlways), + _ => Err(miette!( + r#"invalid mode for warp-mouse-to-focus, can be "center-xy" or "center-xy-always" (or leave unset for separate centering)"# + )), + } + } +} + #[derive(Debug, Clone, Copy, PartialEq)] pub struct Percent(pub f64); @@ -4023,7 +4049,11 @@ mod tests { ), }, disable_power_key_handling: true, - warp_mouse_to_focus: true, + warp_mouse_to_focus: Some( + WarpMouseToFocus { + mode: None, + }, + ), focus_follows_mouse: Some( FocusFollowsMouse { max_scroll_amount: None, diff --git a/src/niri.rs b/src/niri.rs index ac8b90a3..30042fc9 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -14,8 +14,8 @@ use _server_decoration::server::org_kde_kwin_server_decoration_manager::Mode as use anyhow::{bail, ensure, Context}; use calloop::futures::Scheduler; use niri_config::{ - Config, FloatOrInt, Key, Modifiers, OutputName, PreviewRender, TrackLayout, WorkspaceReference, - DEFAULT_BACKGROUND_COLOR, + Config, FloatOrInt, Key, Modifiers, OutputName, PreviewRender, TrackLayout, + WarpMouseToFocusMode, WorkspaceReference, DEFAULT_BACKGROUND_COLOR, }; use smithay::backend::allocator::Fourcc; use smithay::backend::input::Keycode; @@ -510,6 +510,8 @@ struct SurfaceFrameThrottlingState { pub enum CenterCoords { Separately, Both, + // Force centering even if the cursor is already in the rectangle. + BothAlways, } #[derive(Clone, PartialEq, Eq)] @@ -753,6 +755,7 @@ impl State { center_f64(rect) } } + CenterCoords::BothAlways => center_f64(rect), }; self.move_cursor(p); @@ -808,19 +811,27 @@ impl State { } 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::Separately) + let focused = match self.niri.config.borrow().input.warp_mouse_to_focus { + None => return false, + Some(inner) => match inner.mode { + None => CenterCoords::Separately, + Some(WarpMouseToFocusMode::CenterXy) => CenterCoords::Both, + Some(WarpMouseToFocusMode::CenterXyAlways) => CenterCoords::BothAlways, + }, + }; + self.move_cursor_to_focused_tile(focused) } 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) + let focused = match self.niri.config.borrow().input.warp_mouse_to_focus { + None => return false, + Some(inner) => match inner.mode { + None => CenterCoords::Both, + Some(WarpMouseToFocusMode::CenterXy) => CenterCoords::Both, + Some(WarpMouseToFocusMode::CenterXyAlways) => CenterCoords::BothAlways, + }, + }; + self.move_cursor_to_focused_tile(focused) } pub fn refresh_pointer_contents(&mut self) { diff --git a/wiki/Configuration:-Input.md b/wiki/Configuration:-Input.md index 9245583b..4a4c62ec 100644 --- a/wiki/Configuration:-Input.md +++ b/wiki/Configuration:-Input.md @@ -243,7 +243,7 @@ input { Makes the mouse warp to newly focused windows. -X and Y coordinates are computed separately, i.e. if moving the mouse only horizontally is enough to put it inside the newly focused window, then it will move only horizontally. +Does not make the cursor visible if it had been hidden. ```kdl input { @@ -251,6 +251,21 @@ input { } ``` +By default, the cursor warps *separately* horizontally and vertically. +I.e. if moving the mouse only horizontally is enough to put it inside the newly focused window, then the mouse will move only horizontally, and not vertically. + +<sup>Since: next release</sup> You can customize this with the `mode` property. + +- `mode="center-xy"`: warps by both X and Y coordinates together. +So if the mouse was anywhere outside the newly focused window, it will warp to the center of the window. +- `mode="center-xy-always"`: warps by both X and Y coordinates together, even if the mouse was already somewhere inside the newly focused window. + +```kdl +input { + warp-mouse-to-focus mode="center-xy" +} +``` + #### `focus-follows-mouse` Focuses windows and outputs automatically when moving the mouse over them. |
