Add an option to stop 'mouse drift' in some defective/cheap mice. This stops

the pointer slowly wandering away on its own in an annoying way when the mouse
isn't physically moved.

PR:		bin/83970
Submitted by:	Lena -at- lena.kiev.ua
X-MFC after:	6.0-RELEASE
This commit is contained in:
Philip Paeps 2005-09-19 06:58:39 +00:00
parent 9b00ca1961
commit d5f2946a42
2 changed files with 89 additions and 4 deletions

View File

@ -52,6 +52,7 @@
.Op Fl t Ar mousetype
.Op Fl l Ar level
.Op Fl 3 Op Fl E Ar timeout
.Op Fl T Ar distance Ns Op , Ns Ar time Ns Op , Ns Ar after
.Fl p Ar port
.Pp
.Nm
@ -171,6 +172,16 @@ mode.
.It Fl S Ar baudrate
Select the baudrate for the serial port (1200 to 9600).
Not all serial mice support this option.
.It Fl T Ar distance Ns Op , Ns Ar time Ns Op , Ns Ar after
Terminate drifT.
Use this option if mouse pointer slowly wanders when mouse is not moved.
Movements up to
.Ar distance
(for example 4) pixels (X+Y) in
.Ar time
msec (default 500) are ignored, except during
.Ar after
msec (default 4000) since last real mouse movement.
.It Fl V
Enable
.Dq Virtual Scrolling .

View File

@ -476,6 +476,21 @@ static int mouse_move_delayed;
static jmp_buf env;
static int drift_distance = 4; /* max steps X+Y */
static int drift_time = 500; /* in 0.5 sec */
static struct timeval drift_time_tv;
static struct timeval drift_2time_tv; /* 2*drift_time */
static int drift_after = 4000; /* 4 sec */
static struct timeval drift_after_tv;
static int drift_terminate = FALSE;
static struct timeval drift_current_tv;
static struct timeval drift_tmp;
static struct timeval drift_last_activity = {0,0};
static struct drift_xy {
int x; int y; } drift_last = {0,0}; /* steps in last drift_time */
static struct timeval drift_since = {0,0};
static struct drift_xy drift_previous={0,0}; /* steps in previous drift_time */
/* function prototypes */
static void moused(void);
@ -527,7 +542,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:VU:a:cdfhi:l:m:p:r:st:w:z:")) != -1)
while ((c = getopt(argc, argv, "3C:DE:F:HI:PRS:T:VU:a:cdfhi:l:m:p:r:st:w:z:")) != -1)
switch(c) {
case '3':
@ -717,6 +732,24 @@ main(int argc, char *argv[])
debug("rodent baudrate %d", rodent.baudrate);
break;
case 'T':
drift_terminate = TRUE;
sscanf(optarg, "%d,%d,%d", &drift_distance, &drift_time,
&drift_after);
if (drift_distance <= 0 || drift_time <= 0 || drift_after <= 0) {
warnx("invalid argument `%s'", optarg);
usage();
}
debug("terminate drift: distance %d, time %d, after %d",
drift_distance, drift_time, drift_after);
drift_time_tv.tv_sec = drift_time/1000;
drift_time_tv.tv_usec = (drift_time%1000)*1000;
drift_2time_tv.tv_sec = (drift_time*=2)/1000;
drift_2time_tv.tv_usec = (drift_time%1000)*1000;
drift_after_tv.tv_sec = drift_after/1000;
drift_after_tv.tv_usec = (drift_after%1000)*1000;
break;
case 't':
if (strcmp(optarg, "auto") == 0) {
rodent.rtype = MOUSE_PROTO_UNKNOWN;
@ -1111,6 +1144,45 @@ moused(void)
}
}
if (drift_terminate) {
if (flags != MOUSE_POSCHANGED || action.dz || action2.dz)
drift_last_activity = drift_current_tv;
else {
/* X or/and Y movement only - possibly drift */
timersub(&drift_current_tv,&drift_last_activity,&drift_tmp);
if (timercmp(&drift_tmp, &drift_after_tv, >)) {
timersub(&drift_current_tv, &drift_since, &drift_tmp);
if (timercmp(&drift_tmp, &drift_time_tv, <)) {
drift_last.x += action2.dx;
drift_last.y += action2.dy;
} else {
/* discard old accumulated steps (drift) */
if (timercmp(&drift_tmp, &drift_2time_tv, >))
drift_previous.x = drift_previous.y = 0;
else
drift_previous = drift_last;
drift_last.x = action2.dx;
drift_last.y = action2.dy;
drift_since = drift_current_tv;
}
if (abs(drift_last.x) + abs(drift_last.y)
> drift_distance) {
/* real movement, pass all accumulated steps */
action2.dx = drift_previous.x + drift_last.x;
action2.dy = drift_previous.y + drift_last.y;
/* and reset accumulators */
timerclear(&drift_since);
drift_last.x = drift_last.y = 0;
/* drift_previous will be cleared at next movement*/
drift_last_activity = drift_current_tv;
} else {
continue; /* don't pass current movement to
* console driver */
}
}
}
}
if (extioctl) {
/* Defer clicks until we aren't VirtualScroll'ing. */
if (scroll_state == SCROLL_NOTSCROLLING)
@ -1184,10 +1256,11 @@ cleanup(int sig)
static void
usage(void)
{
fprintf(stderr, "%s\n%s\n%s\n%s\n",
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
"usage: moused [-DRcdfs] [-I file] [-F rate] [-r resolution] [-S baudrate]",
" [-VH [-U threshold]] [-a X [,Y]] [-C threshold] [-m N=M] [-w N]",
" [-z N] [-t <mousetype>] [-l level] [-3 [-E timeout]] -p <port>",
" [-VH [-U threshold]] [-a X[,Y]] [-C threshold] [-m N=M] [-w N]",
" [-z N] [-t <mousetype>] [-l level] [-3 [-E timeout]]",
" [-T distance[,time[,after]]] -p <port>",
" moused [-d] -i <port|if|type|model|all> -p <port>");
exit(1);
}
@ -2373,6 +2446,7 @@ r_timestamp(mousestatus_t *act)
#endif
gettimeofday(&tv1, NULL);
drift_current_tv = tv1;
/* double click threshold */
tv2.tv_sec = rodent.clickthreshold/1000;