aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Finkernagel <finkernagel@imt.uni-marburg.de>2025-03-13 14:55:16 +0100
committerIvan Molodetskikh <yalterz@gmail.com>2025-03-22 01:00:43 -0700
commit7f72c358d56453633b57bc353a458709fe878b63 (patch)
treeb3ded6d3a1bb8129d08a7565fc25bd75dd3677b0
parent0d4f0f00c0cd83a72151468bc610ce230a550027 (diff)
downloadniri-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.rs34
-rw-r--r--src/niri.rs35
-rw-r--r--wiki/Configuration:-Input.md17
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.