Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions niri-config/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ pub struct Touchpad {
pub accel_speed: FloatOrInt<-1, 1>,
#[knuffel(child, unwrap(argument, str))]
pub accel_profile: Option<AccelProfile>,
#[knuffel(child, unwrap(argument))]
pub sensitivity: Option<FloatOrInt<0, 100>>,
#[knuffel(child, unwrap(argument, str))]
pub scroll_method: Option<ScrollMethod>,
#[knuffel(child, unwrap(argument))]
Expand Down Expand Up @@ -233,6 +235,8 @@ pub struct Mouse {
pub accel_speed: FloatOrInt<-1, 1>,
#[knuffel(child, unwrap(argument, str))]
pub accel_profile: Option<AccelProfile>,
#[knuffel(child, unwrap(argument))]
pub sensitivity: Option<FloatOrInt<0, 100>>,
#[knuffel(child, unwrap(argument, str))]
pub scroll_method: Option<ScrollMethod>,
#[knuffel(child, unwrap(argument))]
Expand All @@ -257,6 +261,8 @@ pub struct Trackpoint {
pub accel_speed: FloatOrInt<-1, 1>,
#[knuffel(child, unwrap(argument, str))]
pub accel_profile: Option<AccelProfile>,
#[knuffel(child, unwrap(argument))]
pub sensitivity: Option<FloatOrInt<0, 100>>,
#[knuffel(child, unwrap(argument, str))]
pub scroll_method: Option<ScrollMethod>,
#[knuffel(child, unwrap(argument))]
Expand All @@ -279,6 +285,8 @@ pub struct Trackball {
pub accel_speed: FloatOrInt<-1, 1>,
#[knuffel(child, unwrap(argument, str))]
pub accel_profile: Option<AccelProfile>,
#[knuffel(child, unwrap(argument))]
pub sensitivity: Option<FloatOrInt<0, 100>>,
#[knuffel(child, unwrap(argument, str))]
pub scroll_method: Option<ScrollMethod>,
#[knuffel(child, unwrap(argument))]
Expand Down Expand Up @@ -566,6 +574,23 @@ mod tests {
"#);
}

#[test]
fn parse_sensitivity() {
let parsed = do_parse(
r#"
mouse {
sensitivity 2.5
}
touchpad {
sensitivity 0.5
}
"#,
);

assert_eq!(parsed.mouse.sensitivity.unwrap().0, 2.5);
assert_eq!(parsed.touchpad.sensitivity.unwrap().0, 0.5);
}

#[test]
fn parse_scroll_factor_split() {
// Test split horizontal/vertical syntax
Expand Down
4 changes: 4 additions & 0 deletions niri-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,7 @@ mod tests {
accel_profile: Some(
Flat,
),
sensitivity: None,
scroll_method: Some(
TwoFinger,
),
Expand Down Expand Up @@ -1039,6 +1040,7 @@ mod tests {
accel_profile: Some(
Flat,
),
sensitivity: None,
scroll_method: Some(
NoScroll,
),
Expand Down Expand Up @@ -1069,6 +1071,7 @@ mod tests {
accel_profile: Some(
Flat,
),
sensitivity: None,
scroll_method: Some(
OnButtonDown,
),
Expand All @@ -1088,6 +1091,7 @@ mod tests {
accel_profile: Some(
Flat,
),
sensitivity: None,
scroll_method: Some(
Edge,
),
Expand Down
3 changes: 3 additions & 0 deletions resources/default-config.kdl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ input {
natural-scroll
// accel-speed 0.2
// accel-profile "flat"
// sensitivity 1.0
// scroll-method "two-finger"
// disabled-on-external-mouse
}
Expand All @@ -47,6 +48,7 @@ input {
// natural-scroll
// accel-speed 0.2
// accel-profile "flat"
// sensitivity 1.0
// scroll-method "no-scroll"
}

Expand All @@ -55,6 +57,7 @@ input {
// natural-scroll
// accel-speed 0.2
// accel-profile "flat"
// sensitivity 1.0
// scroll-method "on-button-down"
// scroll-button 273
// scroll-button-lock
Expand Down
53 changes: 48 additions & 5 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2411,7 +2411,10 @@ impl State {
}
}

fn on_pointer_motion<I: InputBackend>(&mut self, event: I::PointerMotionEvent) {
fn on_pointer_motion<I: InputBackend + 'static>(&mut self, event: I::PointerMotionEvent)
where
I::Device: 'static,
{
let was_inside_hot_corner = self.niri.pointer_inside_hot_corner;
// Any of the early returns here mean that the pointer is not inside the hot corner.
self.niri.pointer_inside_hot_corner = false;
Expand All @@ -2427,8 +2430,13 @@ impl State {

let pos = pointer.current_location();

let delta = event.delta();
let sensitivity =
pointer_sensitivity_factor(&self.niri.config.borrow().input, &event.device());
let delta = Point::from((delta.x * sensitivity, delta.y * sensitivity));

// We have an output, so we can compute the new location and focus.
let mut new_pos = pos + event.delta();
let mut new_pos = pos + delta;

// We received an event for the regular pointer, so show it now.
self.niri.pointer_visibility = PointerVisibility::Visible;
Expand Down Expand Up @@ -2474,7 +2482,7 @@ impl State {
self,
Some(under.clone()),
&RelativeMotionEvent {
delta: event.delta(),
delta,
delta_unaccel: event.delta_unaccel(),
utime: event.time(),
},
Expand Down Expand Up @@ -2585,7 +2593,7 @@ impl State {
self,
Some(focus_surface),
&RelativeMotionEvent {
delta: event.delta(),
delta,
delta_unaccel: event.delta_unaccel(),
utime: event.time(),
},
Expand Down Expand Up @@ -2615,7 +2623,7 @@ impl State {
self,
under.surface,
&RelativeMotionEvent {
delta: event.delta(),
delta,
delta_unaccel: event.delta_unaccel(),
utime: event.time(),
},
Expand Down Expand Up @@ -5010,6 +5018,41 @@ pub fn apply_libinput_settings(config: &niri_config::Input, device: &mut input::
}
}

fn pointer_sensitivity_factor<D: Device + Any>(config: &niri_config::Input, device: &D) -> f64 {
let Some(device) = (device as &dyn Any).downcast_ref::<input::Device>() else {
return 1.;
};

let is_touchpad = device.config_tap_finger_count() > 0;
if is_touchpad {
return config.touchpad.sensitivity.map(|x| x.0).unwrap_or(1.);
}

let mut is_trackball = false;
let mut is_trackpoint = false;
if let Some(udev_device) = unsafe { device.udev_device() } {
if udev_device.property_value("ID_INPUT_TRACKBALL").is_some() {
is_trackball = true;
}
if udev_device
.property_value("ID_INPUT_POINTINGSTICK")
.is_some()
{
is_trackpoint = true;
}
}

if is_trackball {
config.trackball.sensitivity.map(|x| x.0).unwrap_or(1.)
} else if is_trackpoint {
config.trackpoint.sensitivity.map(|x| x.0).unwrap_or(1.)
} else if device.has_capability(input::DeviceCapability::Pointer) {
config.mouse.sensitivity.map(|x| x.0).unwrap_or(1.)
} else {
1.
}
}

pub fn mods_with_binds(mod_key: ModKey, binds: &Binds, triggers: &[Trigger]) -> HashSet<Modifiers> {
let mut rv = HashSet::new();
for bind in &binds.0 {
Expand Down