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 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);
@ -922,8 +927,34 @@ usbmodule(void)
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.
* (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)