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
This commit is contained in:
Philip Paeps 2007-06-17 20:27:54 +00:00
parent 75298de2a0
commit d933824786
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=170895

View File

@ -398,6 +398,8 @@ static struct rodentparam {
float accely; /* Acceleration in the Y axis */ float accely; /* Acceleration in the Y axis */
float expoaccel; /* Exponential acceleration */ float expoaccel; /* Exponential acceleration */
float expoffset; /* Movement offset for exponential accel. */ 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 */ int scrollthreshold; /* Movement distance before virtual scrolling */
} rodent = { } rodent = {
.flags = 0, .flags = 0,
@ -419,6 +421,8 @@ static struct rodentparam {
.accely = 1.0, .accely = 1.0,
.expoaccel = 1.0, .expoaccel = 1.0,
.expoffset = 1.0, .expoffset = 1.0,
.remainx = 0.0,
.remainy = 0.0,
.scrollthreshold = DFLT_SCROLLTHRESHOLD, .scrollthreshold = DFLT_SCROLLTHRESHOLD,
}; };
@ -498,6 +502,7 @@ static struct drift_xy drift_previous={0,0}; /* steps in previous drift_time */
/* function prototypes */ /* function prototypes */
static void linacc(int, int, int*, int*);
static void expoacc(int, int, int*, int*); static void expoacc(int, int, int*, int*);
static void moused(void); static void moused(void);
static void hup(int sig); static void hup(int sig);
@ -922,8 +927,34 @@ usbmodule(void)
return (kld_isloaded("uhub/ums") || kld_load("ums") != -1); return (kld_isloaded("uhub/ums") || kld_load("ums") != -1);
} }
/*
* 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. * Function to calculate exponential acceleration.
* (Also includes linear acceleration if enabled.)
* *
* In order to give a smoother behaviour, we record the four * In order to give a smoother behaviour, we record the four
* most recent non-zero movements and use their average value * 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; length = (length + lastlength[0] + lastlength[1] + lastlength[2]) / 4;
lbase = length / rodent.expoffset; lbase = length / rodent.expoffset;
accel = powf(lbase, rodent.expoaccel) / lbase; accel = powf(lbase, rodent.expoaccel) / lbase;
*movex = lroundf(fdx * accel); fdx = fdx * accel + rodent.remainx;
*movey = lroundf(fdy * accel); fdy = fdy * accel + rodent.remainy;
*movex = lroundf(fdx);
*movey = lroundf(fdy);
rodent.remainx = fdx - *movex;
rodent.remainy = fdy - *movey;
lastlength[2] = lastlength[1]; lastlength[2] = lastlength[1];
lastlength[1] = lastlength[0]; lastlength[1] = lastlength[0];
lastlength[0] = length; /* Insert new average, not original length! */ lastlength[0] = length; /* Insert new average, not original length! */
@ -1217,8 +1252,8 @@ moused(void)
&mouse.u.data.x, &mouse.u.data.y); &mouse.u.data.x, &mouse.u.data.y);
} }
else { else {
mouse.u.data.x = action2.dx * rodent.accelx; linacc(action2.dx, action2.dy,
mouse.u.data.y = action2.dy * rodent.accely; &mouse.u.data.x, &mouse.u.data.y);
} }
mouse.u.data.z = action2.dz; mouse.u.data.z = action2.dz;
if (debug < 2) if (debug < 2)
@ -1233,8 +1268,8 @@ moused(void)
&mouse.u.data.x, &mouse.u.data.y); &mouse.u.data.x, &mouse.u.data.y);
} }
else { else {
mouse.u.data.x = action2.dx * rodent.accelx; linacc(action2.dx, action2.dy,
mouse.u.data.y = action2.dy * rodent.accely; &mouse.u.data.x, &mouse.u.data.y);
} }
mouse.u.data.z = action2.dz; mouse.u.data.z = action2.dz;
if (debug < 2) if (debug < 2)