Add 'virtual scrolling' support to moused(8). When holding down the middle

mouse button, motions are interpreted as scrolling.

Submitted by:	Jordan Sissel <psionic-AT-csh.rit.edu>
Approved by:	njl
This commit is contained in:
philip 2004-10-11 07:57:08 +00:00
parent fd6137c713
commit 10b896310b
2 changed files with 109 additions and 3 deletions

View File

@ -43,6 +43,7 @@
.Op Fl F Ar rate .Op Fl F Ar rate
.Op Fl r Ar resolution .Op Fl r Ar resolution
.Op Fl S Ar baudrate .Op Fl S Ar baudrate
.Op Fl V Op Fl U Ar distance
.Op Fl a Ar X Ns Op , Ns Ar Y .Op Fl a Ar X Ns Op , Ns Ar Y
.Op Fl C Ar threshold .Op Fl C Ar threshold
.Op Fl m Ar N=M .Op Fl m Ar N=M
@ -156,6 +157,12 @@ mode.
.It Fl S Ar baudrate .It Fl S Ar baudrate
Select the baudrate for the serial port (1200 to 9600). Select the baudrate for the serial port (1200 to 9600).
Not all serial mice support this option. Not all serial mice support this option.
.It Fl V
Enable ``Virtual Scrolling'', with this option set, holding the middle mouse
button down will cause motion to be interpreted as scrolling. Use the
.Fl U
option to set the distance the mouse must move before the scrolling mode is
activated.
.It Fl a Ar X Ns Op , Ns Ar Y .It Fl a Ar X Ns Op , Ns Ar Y
Accelerate or decelerate the mouse input. Accelerate or decelerate the mouse input.
This is a linear acceleration only. This is a linear acceleration only.

View File

@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
#define MAX_BUTTON2TIMEOUT 2000 /* 2 seconds */ #define MAX_BUTTON2TIMEOUT 2000 /* 2 seconds */
#define DFLT_CLICKTHRESHOLD 500 /* 0.5 second */ #define DFLT_CLICKTHRESHOLD 500 /* 0.5 second */
#define DFLT_BUTTON2TIMEOUT 100 /* 0.1 second */ #define DFLT_BUTTON2TIMEOUT 100 /* 0.1 second */
#define DFLT_SCROLLTHRESHOLD 3 /* 3 pixels */
/* Abort 3-button emulation delay after this many movement events. */ /* Abort 3-button emulation delay after this many movement events. */
#define BUTTON2_MAXMOVE 3 #define BUTTON2_MAXMOVE 3
@ -97,11 +98,12 @@ __FBSDID("$FreeBSD$");
#define ClearDTR 0x0004 #define ClearDTR 0x0004
#define ClearRTS 0x0008 #define ClearRTS 0x0008
#define NoPnP 0x0010 #define NoPnP 0x0010
#define VirtualScroll 0x0020
#define ID_NONE 0 #define ID_NONE 0
#define ID_PORT 1 #define ID_PORT 1
#define ID_IF 2 #define ID_IF 2
#define ID_TYPE 4 #define ID_TYPE 4
#define ID_MODEL 8 #define ID_MODEL 8
#define ID_ALL (ID_PORT | ID_IF | ID_TYPE | ID_MODEL) #define ID_ALL (ID_PORT | ID_IF | ID_TYPE | ID_MODEL)
@ -159,6 +161,13 @@ int identify = ID_NONE;
int extioctl = FALSE; int extioctl = FALSE;
char *pidfile = "/var/run/moused.pid"; char *pidfile = "/var/run/moused.pid";
#define SCROLL_NOTSCROLLING 0
#define SCROLL_PREPARE 1
#define SCROLL_SCROLLING 2
static int scroll_state;
static int scroll_movement;
/* local variables */ /* local variables */
/* interface (the table must be ordered by MOUSE_IF_XXX in mouse.h) */ /* interface (the table must be ordered by MOUSE_IF_XXX in mouse.h) */
@ -380,6 +389,7 @@ static struct rodentparam {
mousemode_t mode; /* protocol information */ mousemode_t mode; /* protocol information */
float accelx; /* Acceleration in the X axis */ float accelx; /* Acceleration in the X axis */
float accely; /* Acceleration in the Y axis */ float accely; /* Acceleration in the Y axis */
int scrollthreshold; /* Movement distance before virtual scrolling */
} rodent = { } rodent = {
.flags = 0, .flags = 0,
.portname = NULL, .portname = NULL,
@ -398,6 +408,7 @@ static struct rodentparam {
.button2timeout = DFLT_BUTTON2TIMEOUT, .button2timeout = DFLT_BUTTON2TIMEOUT,
.accelx = 1.0, .accelx = 1.0,
.accely = 1.0, .accely = 1.0,
.scrollthreshold = DFLT_SCROLLTHRESHOLD,
}; };
/* button status */ /* button status */
@ -509,7 +520,7 @@ main(int argc, char *argv[])
for (i = 0; i < MOUSE_MAXBUTTON; ++i) for (i = 0; i < MOUSE_MAXBUTTON; ++i)
mstate[i] = &bstate[i]; mstate[i] = &bstate[i];
while ((c = getopt(argc, argv, "3C:DE:F:I:PRS:a:cdfhi:l:m:p:r:st:w:z:")) != -1) while ((c = getopt(argc, argv, "3C:DE:F:I:PRS:VU:a:cdfhi:l:m:p:r:st:w:z:")) != -1)
switch(c) { switch(c) {
case '3': case '3':
@ -714,6 +725,17 @@ main(int argc, char *argv[])
warnx("no such mouse type `%s'", optarg); warnx("no such mouse type `%s'", optarg);
usage(); usage();
case 'V':
rodent.flags |= VirtualScroll;
break;
case 'U':
rodent.scrollthreshold = atoi(optarg);
if (rodent.scrollthreshold < 0) {
warnx("invalid argument `%s'", optarg);
usage();
}
break;
case 'h': case 'h':
case '?': case '?':
default: default:
@ -967,6 +989,50 @@ moused(void)
} }
if ((flags = r_protocol(b, &action0)) == 0) if ((flags = r_protocol(b, &action0)) == 0)
continue; continue;
if (rodent.flags & VirtualScroll) {
/* Allow middle button drags to scroll up and down */
if (action0.button == MOUSE_BUTTON2DOWN) {
if (scroll_state == SCROLL_NOTSCROLLING) {
scroll_state = SCROLL_PREPARE;
debug("PREPARING TO SCROLL");
}
debug("[BUTTON2] flags:%08x buttons:%08x obuttons:%08x",
action.flags, action.button, action.obutton);
} else {
debug("[NOTBUTTON2] flags:%08x buttons:%08x obuttons:%08x",
action.flags, action.button, action.obutton);
/* This isn't a middle button down... move along... */
if (scroll_state == SCROLL_SCROLLING) {
/*
* We were scrolling, someone let go of button 2.
* Now turn autoscroll off.
*/
scroll_state = SCROLL_NOTSCROLLING;
debug("DONE WITH SCROLLING / %d", scroll_state);
} else if (scroll_state == SCROLL_PREPARE) {
mousestatus_t newaction = action0;
/* We were preparing to scroll, but we never moved... */
r_timestamp(&action0);
r_statetrans(&action0, &newaction,
A(newaction.button & MOUSE_BUTTON1DOWN,
action0.button & MOUSE_BUTTON3DOWN));
/* Send middle down */
newaction.button = MOUSE_BUTTON2DOWN;
r_click(&newaction);
/* Send middle up */
r_timestamp(&newaction);
newaction.obutton = newaction.button;
newaction.button = action0.button;
r_click(&newaction);
}
}
}
r_timestamp(&action0); r_timestamp(&action0);
r_statetrans(&action0, &action, r_statetrans(&action0, &action,
A(action0.button & MOUSE_BUTTON1DOWN, A(action0.button & MOUSE_BUTTON1DOWN,
@ -984,8 +1050,41 @@ moused(void)
debug("activity : buttons 0x%08x dx %d dy %d dz %d", debug("activity : buttons 0x%08x dx %d dy %d dz %d",
action2.button, action2.dx, action2.dy, action2.dz); action2.button, action2.dx, action2.dy, action2.dz);
if (rodent.flags & VirtualScroll) {
/*
* If *only* the middle button is pressed AND we are moving
* the stick/trackpoint/nipple, scroll!
*/
if (scroll_state == SCROLL_PREPARE) {
/* Ok, Set we're really scrolling now.... */
if (action2.dy || action2.dx)
scroll_state = SCROLL_SCROLLING;
}
if (scroll_state == SCROLL_SCROLLING) {
scroll_movement += action2.dy;
debug("SCROLL: %d", scroll_movement);
if (scroll_movement < -rodent.scrollthreshold) {
/* Scroll down */
action2.dz = -1;
scroll_movement = 0;
}
else if (scroll_movement > rodent.scrollthreshold) {
/* Scroll up */
action2.dz = 1;
scroll_movement = 0;
}
/* Don't move while scrolling */
action2.dx = action2.dy = 0;
}
}
if (extioctl) { if (extioctl) {
r_click(&action2); /* Defer clicks until we aren't VirtualScroll'ing. */
if (scroll_state == SCROLL_NOTSCROLLING)
r_click(&action2);
if (action2.flags & MOUSE_POSCHANGED) { if (action2.flags & MOUSE_POSCHANGED) {
mouse.operation = MOUSE_MOTION_EVENT; mouse.operation = MOUSE_MOTION_EVENT;
mouse.u.data.buttons = action2.button; mouse.u.data.buttons = action2.button;