diff options
author | philip <philip@FreeBSD.org> | 2007-06-17 20:27:54 +0000 |
---|---|---|
committer | philip <philip@FreeBSD.org> | 2007-06-17 20:27:54 +0000 |
commit | c7a9176e2cb880ef422f7d6d68815b59b2de4537 (patch) | |
tree | 7e0f3ed59e309c6a54707c19a9d780435e37beb8 /usr.sbin/moused/moused.c | |
parent | ca1ca54cb0ab727e0b19a308a6ae21e0fbe660d5 (diff) | |
download | FreeBSD-src-c7a9176e2cb880ef422f7d6d68815b59b2de4537.zip FreeBSD-src-c7a9176e2cb880ef422f7d6d68815b59b2de4537.tar.gz |
Fix a (very) longstanding bug in moused(8) affecting high-resolution rodents
when linear acceleration (-a) was enabled with a <1 value to slow them down.
Previously, rounding errors would eat small movements so the mouse had to be
moved a certain distance to get any movement at all. We now calculate the
rounding errors and take them into account when reporting movement.
PR: bin/113749
Submitted by: Oliver Fromme <olli -at- secnetix.de>
MFC after: 3 days
Diffstat (limited to 'usr.sbin/moused/moused.c')
-rw-r--r-- | usr.sbin/moused/moused.c | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/usr.sbin/moused/moused.c b/usr.sbin/moused/moused.c index a751774..ea5062e 100644 --- a/usr.sbin/moused/moused.c +++ b/usr.sbin/moused/moused.c @@ -398,6 +398,8 @@ static struct rodentparam { float accely; /* Acceleration in the Y axis */ float expoaccel; /* Exponential acceleration */ float expoffset; /* Movement offset for exponential accel. */ + float remainx; /* Remainder on X and Y axis, respectively... */ + float remainy; /* ... to compensate for rounding errors. */ int scrollthreshold; /* Movement distance before virtual scrolling */ } rodent = { .flags = 0, @@ -419,6 +421,8 @@ static struct rodentparam { .accely = 1.0, .expoaccel = 1.0, .expoffset = 1.0, + .remainx = 0.0, + .remainy = 0.0, .scrollthreshold = DFLT_SCROLLTHRESHOLD, }; @@ -498,6 +502,7 @@ static struct drift_xy drift_previous={0,0}; /* steps in previous drift_time */ /* function prototypes */ +static void linacc(int, int, int*, int*); static void expoacc(int, int, int*, int*); static void moused(void); static void hup(int sig); @@ -923,7 +928,33 @@ usbmodule(void) } /* + * Function to calculate linear acceleration. + * + * If there are any rounding errors, the remainder + * is stored in the remainx and remainy variables + * and taken into account upon the next movement. + */ + +static void +linacc(int dx, int dy, int *movex, int *movey) +{ + float fdx, fdy; + + if (dx == 0 && dy == 0) { + *movex = *movey = 0; + return; + } + fdx = dx * rodent.accelx + rodent.remainx; + fdy = dy * rodent.accely + rodent.remainy; + *movex = lround(fdx); + *movey = lround(fdy); + rodent.remainx = fdx - *movex; + rodent.remainy = fdy - *movey; +} + +/* * Function to calculate exponential acceleration. + * (Also includes linear acceleration if enabled.) * * In order to give a smoother behaviour, we record the four * most recent non-zero movements and use their average value @@ -946,8 +977,12 @@ expoacc(int dx, int dy, int *movex, int *movey) length = (length + lastlength[0] + lastlength[1] + lastlength[2]) / 4; lbase = length / rodent.expoffset; accel = powf(lbase, rodent.expoaccel) / lbase; - *movex = lroundf(fdx * accel); - *movey = lroundf(fdy * accel); + fdx = fdx * accel + rodent.remainx; + fdy = fdy * accel + rodent.remainy; + *movex = lroundf(fdx); + *movey = lroundf(fdy); + rodent.remainx = fdx - *movex; + rodent.remainy = fdy - *movey; lastlength[2] = lastlength[1]; lastlength[1] = lastlength[0]; lastlength[0] = length; /* Insert new average, not original length! */ @@ -1217,8 +1252,8 @@ moused(void) &mouse.u.data.x, &mouse.u.data.y); } else { - mouse.u.data.x = action2.dx * rodent.accelx; - mouse.u.data.y = action2.dy * rodent.accely; + linacc(action2.dx, action2.dy, + &mouse.u.data.x, &mouse.u.data.y); } mouse.u.data.z = action2.dz; if (debug < 2) @@ -1233,8 +1268,8 @@ moused(void) &mouse.u.data.x, &mouse.u.data.y); } else { - mouse.u.data.x = action2.dx * rodent.accelx; - mouse.u.data.y = action2.dy * rodent.accely; + linacc(action2.dx, action2.dy, + &mouse.u.data.x, &mouse.u.data.y); } mouse.u.data.z = action2.dz; if (debug < 2) |