Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion PKGBUILD
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pkgname=maccel-dkms
_pkgname="maccel"
pkgver=0.6.0
pkgver=0.5.9
pkgrel=1
pkgdesc="Mouse acceleration driver and kernel module for Linux."
arch=("x86_64")
Expand Down
11 changes: 0 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,6 @@ maccel set angle-rotation 15 # rotate input 15 degrees
maccel set angle-rotation 0 # disable rotation (default)
```

## Angle Snapping

Angle snapping projects movement near the horizontal or vertical axis exactly
onto that axis while preserving its magnitude; values range from `0` (disabled)
to `45` degrees, and snapping is applied after rotation.

```sh
maccel set param angle-snap 10
maccel set param angle-snap 0 # disable snapping (default)
```

### Known limitation

When the mouse moves along a single axis (purely horizontal or vertical), some mice and kernel versions only report one `EV_REL` event (`REL_X` or `REL_Y`) instead of both. The rotation transform produces a cross-axis component that needs to be injected as a synthetic event.
Expand Down
1 change: 0 additions & 1 deletion README_NIXOS.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ Create your `maccel.nix` module:
yxRatio = 1.0;
inputDpi = 1000.0;
angleRotation = 0.0;
angleSnap = 0.0;
mode = "synchronous";

# Linear mode
Expand Down
2 changes: 1 addition & 1 deletion cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "maccel-cli"
version = "0.7.0"
version = "0.6.0"
edition = "2021"

[[bin]]
Expand Down
12 changes: 0 additions & 12 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,6 @@ struct Cli {
command: Option<CLiCommands>,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn common_bulk_set_keeps_angle_snap_optional() {
let cli = Cli::try_parse_from(["maccel", "set", "all", "common", "1", "1", "1000", "0"]);

assert!(cli.is_ok());
}
}

#[derive(clap::Subcommand, Default)]
enum CLiCommands {
/// Open the Terminal UI to manage the parameters
Expand Down
1 change: 0 additions & 1 deletion crates/core/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ impl<PS: ParamStore> TuiContext<PS> {
motivity: get!(Motivity),
sync_speed: get!(SyncSpeed),
angle_rotation: get!(AngleRotation),
angle_snap: get!(AngleSnap),
}
}
}
Expand Down
36 changes: 3 additions & 33 deletions crates/core/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,14 @@ macro_rules! make_curve_params_struct {
}

macro_rules! declare_params {
(
Common { $($common_param:tt),+$(,)? },
OptionalCommon { $($optional_common_param:tt),+$(,)? },
$( $mode:tt { $($param:tt),*$(,)? }, )+
) => {
( Common { $($common_param:tt),+$(,)? } , $( $mode:tt { $($param:tt),*$(,)? }, )+) => {
declare_common_params! {
$( $common_param, )+
$( $optional_common_param, )+
$( $( $param, )* )+
}

/// Array of all the common parameters for convenience.
pub const ALL_COMMON_PARAMS: &[Param] = &[
$( Param::$common_param, )+
$( Param::$optional_common_param ),+
];
pub const ALL_COMMON_PARAMS: &[Param] = &[ $( Param::$common_param),+ ];


#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
Expand All @@ -80,7 +72,6 @@ macro_rules! declare_params {
#[repr(C)]
pub struct AccelParams {
$( pub [< $common_param:snake:lower >] : Fpt, )+
$( pub [< $optional_common_param:snake:lower >] : Fpt, )+
pub by_mode: AccelParamsByMode,
}

Expand All @@ -97,8 +88,7 @@ macro_rules! declare_params {
#[cfg_attr(feature = "clap", derive(clap::Args))]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CommonParamArgs {
$( pub [< $common_param:snake:lower >]: f64, )+
$( pub [< $optional_common_param:snake:lower >]: Option<f64> ),+
$( pub [< $common_param:snake:lower >]: f64 ),+
}
}

Expand Down Expand Up @@ -186,7 +176,6 @@ declare_params!(
InputDpi,
AngleRotation
},
OptionalCommon { AngleSnap },
Linear {
Accel,
OffsetLinear,
Expand Down Expand Up @@ -244,7 +233,6 @@ impl Param {
Param::Motivity => "MOTIVITY",
Param::SyncSpeed => "SYNC_SPEED",
Param::AngleRotation => "ANGLE_ROTATION",
Param::AngleSnap => "ANGLE_SNAP",
}
}

Expand All @@ -264,7 +252,6 @@ impl Param {
Param::Motivity => "Motivity",
Param::SyncSpeed => "Sync Speed",
Param::AngleRotation => "Angle Rotation",
Param::AngleSnap => "Angle Snap",
}
}

Expand All @@ -278,9 +265,6 @@ impl Param {
"Mouse DPI. Used to normalize to 1000 DPI equivalent for consistent acceleration."
}
Param::AngleRotation => "Rotation angle in degrees for sensitivity direction.",
Param::AngleSnap => {
"Snap movement to the nearest horizontal or vertical axis within 0-45 degrees."
}
Param::Accel => "Acceleration strength. Higher values = faster cursor at high speeds.",
Param::OffsetLinear => "Speed threshold (counts/ms) before acceleration begins.",
Param::OutputCap => "Maximum sensitivity multiplier cap. Prevents excessive speed.",
Expand Down Expand Up @@ -322,15 +306,6 @@ fn format_param_value_works() {
assert_eq!(format_param_value(0.055000), "0.055");
}

#[cfg(test)]
#[test]
fn angle_snap_must_be_between_zero_and_forty_five_degrees() {
assert!(validate_param_value(Param::AngleSnap, 0.0).is_ok());
assert!(validate_param_value(Param::AngleSnap, 45.0).is_ok());
assert!(validate_param_value(Param::AngleSnap, -0.1).is_err());
assert!(validate_param_value(Param::AngleSnap, 45.1).is_err());
}

pub(crate) fn validate_param_value(param_tag: Param, value: f64) -> anyhow::Result<()> {
match param_tag {
Param::SensMult => {}
Expand All @@ -341,11 +316,6 @@ pub(crate) fn validate_param_value(param_tag: Param, value: f64) -> anyhow::Resu
}
}
Param::AngleRotation => {}
Param::AngleSnap => {
if !(0.0..=45.0).contains(&value) {
anyhow::bail!("Angle snap must be between 0 and 45 degrees");
}
}
Param::Accel => {}
Param::OutputCap => {}
Param::OffsetLinear | Param::OffsetNatural => {
Expand Down
4 changes: 0 additions & 4 deletions crates/core/src/persist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,12 @@ impl SysFsStore {
yx_ratio,
input_dpi,
angle_rotation,
angle_snap,
} = args;

self.set(Param::SensMult, sens_mult)?;
self.set(Param::YxRatio, yx_ratio)?;
self.set(Param::InputDpi, input_dpi)?;
self.set(Param::AngleRotation, angle_rotation)?;
if let Some(angle_snap) = angle_snap {
self.set(Param::AngleSnap, angle_snap)?;
}

Ok(())
}
Expand Down
1 change: 0 additions & 1 deletion crates/core/src/sens_fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ impl AllParamArgs {
yx_ratio: self.yx_ratio,
input_dpi: self.input_dpi,
angle_rotation: self.angle_rotation,
angle_snap: self.angle_snap,
by_mode: params_by_mode,
}
}
Expand Down
50 changes: 6 additions & 44 deletions driver/accel.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ struct accel_args {
fpt yx_ratio;
fpt input_dpi;
fpt angle_rotation_deg;
fpt angle_snap_threshold;

enum accel_mode tag;
union __accel_args args;
Expand Down Expand Up @@ -67,27 +66,6 @@ static inline struct vector sensitivity(fpt input_speed,

const fpt DEG_TO_RAD_FACTOR = fpt_xdiv(FIXEDPT_PI, fpt_rconst(180));

static inline fpt snap_threshold(fpt degrees) {
return fpt_tan(fpt_mul(degrees, DEG_TO_RAD_FACTOR));
}

static inline struct vector snap_to_axis(struct vector input, fpt threshold) {
fpt abs_x = fpt_abs(input.x);
fpt abs_y = fpt_abs(input.y);

if (abs_x < fpt_mul(abs_y, threshold)) {
fpt length = scaled_magnitude(input);
return (struct vector){0, input.y < 0 ? -length : length};
}

if (abs_y < fpt_mul(abs_x, threshold)) {
fpt length = scaled_magnitude(input);
return (struct vector){input.x < 0 ? -length : length, 0};
}

return input;
}

static inline void f_accelerate(int *x, int *y, fpt time_interval_ms,
struct accel_args args) {
static fpt carry_x = 0;
Expand All @@ -96,7 +74,10 @@ static inline void f_accelerate(int *x, int *y, fpt time_interval_ms,
fpt dx = fpt_fromint(*x);
fpt dy = fpt_fromint(*y);

if (args.angle_rotation_deg != 0) {
{
if (args.angle_rotation_deg == 0) {
goto accel_routine;
}
// Add rotation of input vector
fpt degrees = args.angle_rotation_deg;
fpt radians =
Expand All @@ -120,20 +101,7 @@ static inline void f_accelerate(int *x, int *y, fpt time_interval_ms,
dx = dx_rot;
dy = dy_rot;
}

if (args.angle_snap_threshold > 0) {
struct vector snapped =
snap_to_axis((struct vector){dx, dy}, args.angle_snap_threshold);
dx = snapped.x;
dy = snapped.y;

if (dx == 0) {
carry_x = 0;
}
if (dy == 0) {
carry_y = 0;
}
}
accel_routine:

dbg("in (%d, %d)", *x, *y);
dbg("in: x (fpt conversion) %s", fptoa(dx));
Expand All @@ -144,13 +112,7 @@ static inline void f_accelerate(int *x, int *y, fpt time_interval_ms,
dx = fpt_mul(dx, dpi_factor);
dy = fpt_mul(dy, dpi_factor);

fpt speed_in;
if (args.angle_snap_threshold > 0 && (dx == 0 || dy == 0)) {
fpt distance = dx == 0 ? fpt_abs(dy) : fpt_abs(dx);
speed_in = input_speed_from_distance(distance, time_interval_ms);
} else {
speed_in = input_speed(dx, dy, time_interval_ms);
}
fpt speed_in = input_speed(dx, dy, time_interval_ms);
struct vector sens = sensitivity(speed_in, args);
dbg("scale x %s", fptoa(sens.x));
dbg("scale y %s", fptoa(sens.y));
Expand Down
1 change: 0 additions & 1 deletion driver/accel_k.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ static struct accel_args collect_args(void) {
accel.yx_ratio = atofp(PARAM_YX_RATIO);
accel.input_dpi = atofp(PARAM_INPUT_DPI);
accel.angle_rotation_deg = atofp(PARAM_ANGLE_ROTATION);
accel.angle_snap_threshold = PARAM_ANGLE_SNAP_THRESHOLD;

switch (mode) {
case synchronous: {
Expand Down
19 changes: 0 additions & 19 deletions driver/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,6 @@ static inline fpt magnitude(struct vector v) {
return fpt_sqrt(x_square_plus_y_square);
}

static inline fpt scaled_magnitude(struct vector v) {
fpt abs_x = fpt_abs(v.x);
fpt abs_y = fpt_abs(v.y);
fpt larger = abs_x > abs_y ? abs_x : abs_y;
fpt smaller = abs_x > abs_y ? abs_y : abs_x;

if (larger == 0) {
return 0;
}

fpt ratio = fpt_div(smaller, larger);
fpt normalized = fpt_sqrt(fpt_add(FIXEDPT_ONE, fpt_mul(ratio, ratio)));
fpt max_value = (fpt)(((fptu)~0) >> 1);
if (larger > fpt_div(max_value, normalized)) {
return max_value;
}
return fpt_mul(larger, normalized);
}

static inline fpt minsd(fpt a, fpt b) { return (a < b) ? a : b; }

#endif // !_MATH_H_
28 changes: 0 additions & 28 deletions driver/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,6 @@ PARAM(INPUT_DPI, 65536000, // 1000 << 16

PARAM(ANGLE_ROTATION, 0,
"Apply rotation (degrees) to the mouse movement input");
char *PARAM_ANGLE_SNAP = "0";
fpt PARAM_ANGLE_SNAP_THRESHOLD = 0;

static int _set_angle_snap(const char *value, const struct kernel_param *param) {
int result = param_set_charp(value, param);
if (result != 0) {
return result;
}

fpt degrees = atofp(PARAM_ANGLE_SNAP);
if (degrees > fpt_fromint(45)) {
degrees = fpt_fromint(45);
}
PARAM_ANGLE_SNAP_THRESHOLD =
fpt_tan(fpt_mul(degrees, fpt_div(FIXEDPT_PI, fpt_fromint(180))));
return 0;
}

static const struct kernel_param_ops _angle_snap_ops = {
.set = _set_angle_snap,
.get = param_get_charp,
.free = param_free_charp,
};

module_param_cb(ANGLE_SNAP, &_angle_snap_ops, &PARAM_ANGLE_SNAP, RW_USER_GROUP);
MODULE_PARM_DESC(
ANGLE_SNAP,
"Snap mouse movement to the nearest axis within this angle (degrees)");
// For Linear Mode

PARAM(ACCEL, 0, "Control the sensitivity calculation.");
Expand Down
13 changes: 3 additions & 10 deletions driver/speed.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
*/
static fpt LAST_INPUT_MOUSE_SPEED = 0;

static inline fpt input_speed_from_distance(fpt distance, fpt time_ms) {
static inline fpt input_speed(fpt dx, fpt dy, fpt time_ms) {
if (time_ms <= 0) {
LAST_INPUT_MOUSE_SPEED = 0;
return 0;
}

fpt distance = magnitude((struct vector){dx, dy});

if (distance == -1) {
dbg("distance calculation failed: t = %s", fptoa(time_ms));
LAST_INPUT_MOUSE_SPEED = 0;
Expand All @@ -34,13 +36,4 @@ static inline fpt input_speed_from_distance(fpt distance, fpt time_ms) {
return speed;
}

static inline fpt input_speed(fpt dx, fpt dy, fpt time_ms) {
if (time_ms <= 0) {
LAST_INPUT_MOUSE_SPEED = 0;
return 0;
}

return input_speed_from_distance(magnitude((struct vector){dx, dy}), time_ms);
}

#endif // !__SPEED_H__
Loading
Loading