Add dynamic acceleration to moused(8). This introduces a '-A' flag to control

the acceleration algorithm.  It can be used together with the '-a' flag for
regular acceleration.

PR:		bin/110003
Submitted by:	Oliver Fromme <olli -at- lurza.secnetix.de>
MFC after:	1 week
This commit is contained in:
Philip Paeps 2007-03-11 20:02:26 +00:00
parent 1267d00111
commit 86b3ea3634
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=167461
3 changed files with 116 additions and 8 deletions

View File

@ -3,8 +3,8 @@
PROG= moused
MAN= moused.8
DPADD= ${LIBUTIL}
LDADD= -lutil
DPADD= ${LIBUTIL} ${LIBM}
LDADD= -lutil -lm
#BINMODE=4555
#PRECIOUSPROG=

View File

@ -44,6 +44,7 @@
.Op Fl r Ar resolution
.Op Fl S Ar baudrate
.Op Fl VH Op Fl U Ar distance
.Op Fl A Ar exp Ns Op , Ns Ar offset
.Op Fl a Ar X Ns Op , Ns Ar Y
.Op Fl C Ar threshold
.Op Fl m Ar N=M
@ -213,12 +214,55 @@ mode is activated.
The default
.Ar distance
is 3 pixels.
.It Fl A Ar exp Ns Op , Ns Ar offset
Apply exponential (dynamic) acceleration to mouse movements:
the faster you move the mouse, the more it will be accelerated.
That means that small mouse movements are not accelerated,
so they are still very accurate, while a faster movement will
drive the pointer quickly across the screen.
.Pp
The
.Ar exp
value specifies the exponent, which is basically
the amount of acceleration. Useful values are in the
range 1.1 to 2.0, but it depends on your mouse hardware
and your personal preference. A value of 1.0 means no
exponential acceleration. A value of 2.0 means squared
acceleration (i.e. if you move the mouse twice as fast,
the pointer will move four times as fast on the screen).
Values beyond 2.0 are possible but not recommended.
A good value to start is probably 1.5.
.Pp
The optional
.Ar offset
value specifies the distance at which the acceleration
begins. The default is 1.0, which means that the
acceleration is applied to movements larger than one unit.
If you specify a larger value, it takes more speed for
the acceleration to kick in, i.e. the speed range for
small and accurate movements is wider.
Usually the default should be sufficient, but if you're
not satisfied with the behaviour, try a value of 2.0.
.Pp
Note that the
.Fl A
option interacts badly with the X server's own acceleration,
which doesn't work very well anyway. Therefore it is
recommended to switch it off if necessary:
.Dq xset m 1 .
.It Fl a Ar X Ns Op , Ns Ar Y
Accelerate or decelerate the mouse input.
This is a linear acceleration only.
Values less than 1.0 slow down movement, values greater than 1.0 speed it
up.
Specifying only one value sets the acceleration for both axes.
.Pp
You can use the
.Fl a
and
.Fl A
options at the same time to have the combined effect
of linear and exponential acceleration.
.It Fl c
Some mice report middle button down events
as if the left and right buttons are being pressed.
@ -758,6 +802,7 @@ option to assign the physical right button to the logical middle button:
.Sh SEE ALSO
.Xr kill 1 ,
.Xr vidcontrol 1 ,
.Xr xset 1 ,
.Xr keyboard 4 ,
.Xr mse 4 ,
.Xr psm 4 ,

View File

@ -70,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <syslog.h>
#include <termios.h>
#include <unistd.h>
#include <math.h>
#define MAX_CLICKTHRESHOLD 2000 /* 2 seconds */
#define MAX_BUTTON2TIMEOUT 2000 /* 2 seconds */
@ -99,6 +100,7 @@ __FBSDID("$FreeBSD$");
#define NoPnP 0x0010
#define VirtualScroll 0x0020
#define HVirtualScroll 0x0040
#define ExponentialAcc 0x0080
#define ID_NONE 0
#define ID_PORT 1
@ -394,6 +396,8 @@ static struct rodentparam {
mousemode_t mode; /* protocol information */
float accelx; /* Acceleration in the X axis */
float accely; /* Acceleration in the Y axis */
float expoaccel; /* Exponential acceleration */
float expoffset; /* Movement offset for exponential accel. */
int scrollthreshold; /* Movement distance before virtual scrolling */
} rodent = {
.flags = 0,
@ -413,6 +417,8 @@ static struct rodentparam {
.button2timeout = DFLT_BUTTON2TIMEOUT,
.accelx = 1.0,
.accely = 1.0,
.expoaccel = 1.0,
.expoffset = 1.0,
.scrollthreshold = DFLT_SCROLLTHRESHOLD,
};
@ -492,6 +498,7 @@ static struct drift_xy drift_previous={0,0}; /* steps in previous drift_time */
/* function prototypes */
static void expoacc(int, int, int*, int*);
static void moused(void);
static void hup(int sig);
static void cleanup(int sig);
@ -542,7 +549,7 @@ main(int argc, char *argv[])
for (i = 0; i < MOUSE_MAXBUTTON; ++i)
mstate[i] = &bstate[i];
while ((c = getopt(argc, argv, "3C:DE:F:HI:PRS:T:VU:a:cdfhi:l:m:p:r:st:w:z:")) != -1)
while ((c = getopt(argc, argv, "3A:C:DE:F:HI:PRS:T:VU:a:cdfhi:l:m:p:r:st:w:z:")) != -1)
switch(c) {
case '3':
@ -561,7 +568,7 @@ main(int argc, char *argv[])
case 'a':
i = sscanf(optarg, "%f,%f", &rodent.accelx, &rodent.accely);
if (i == 0) {
warnx("invalid acceleration argument '%s'", optarg);
warnx("invalid linear acceleration argument '%s'", optarg);
usage();
}
@ -570,6 +577,19 @@ main(int argc, char *argv[])
break;
case 'A':
rodent.flags |= ExponentialAcc;
i = sscanf(optarg, "%f,%f", &rodent.expoaccel, &rodent.expoffset);
if (i == 0) {
warnx("invalid exponential acceleration argument '%s'", optarg);
usage();
}
if (i == 1)
rodent.expoffset = 1.0;
break;
case 'c':
rodent.flags |= ChordMiddle;
break;
@ -902,6 +922,37 @@ usbmodule(void)
return (kld_isloaded("uhub/ums") || kld_load("ums") != -1);
}
/*
* Function to calculate exponential acceleration.
*
* In order to give a smoother behaviour, we record the four
* most recent non-zero movements and use their average value
* to calculate the acceleration.
*/
static void
expoacc(int dx, int dy, int *movex, int *movey)
{
static float lastlength[3] = {0.0, 0.0, 0.0};
float fdx, fdy, length, lbase, accel;
if (dx == 0 && dy == 0) {
*movex = *movey = 0;
return;
}
fdx = dx * rodent.accelx;
fdy = dy * rodent.accely;
length = sqrtf((fdx * fdx) + (fdy * fdy)); /* Pythagoras */
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);
lastlength[2] = lastlength[1];
lastlength[1] = lastlength[0];
lastlength[0] = length; /* Insert new average, not original length! */
}
static void
moused(void)
{
@ -1161,8 +1212,14 @@ moused(void)
if (action2.flags & MOUSE_POSCHANGED) {
mouse.operation = MOUSE_MOTION_EVENT;
mouse.u.data.buttons = action2.button;
mouse.u.data.x = action2.dx * rodent.accelx;
mouse.u.data.y = action2.dy * rodent.accely;
if (rodent.flags & ExponentialAcc) {
expoacc(action2.dx, action2.dy,
&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;
}
mouse.u.data.z = action2.dz;
if (debug < 2)
if (!paused)
@ -1171,8 +1228,14 @@ moused(void)
} else {
mouse.operation = MOUSE_ACTION;
mouse.u.data.buttons = action2.button;
mouse.u.data.x = action2.dx * rodent.accelx;
mouse.u.data.y = action2.dy * rodent.accely;
if (rodent.flags & ExponentialAcc) {
expoacc(action2.dx, action2.dy,
&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;
}
mouse.u.data.z = action2.dz;
if (debug < 2)
if (!paused)