aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2009-08-17 09:41:11 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2009-08-18 13:07:13 +1000
commit2e5f68754fd5bc4e6b7fa5b95bdd30e2bb4e57fb (patch)
treef47cc3e630eb791465486c91469baa7d583b4b17
parentman: fix documentation for EVDEV_PROP_WHEEL_BUTTON (diff)
downloadxf86-input-evdev-2e5f68754fd5bc4e6b7fa5b95bdd30e2bb4e57fb.tar.gz
xf86-input-evdev-2e5f68754fd5bc4e6b7fa5b95bdd30e2bb4e57fb.tar.bz2
xf86-input-evdev-2e5f68754fd5bc4e6b7fa5b95bdd30e2bb4e57fb.zip
Restrict wheel emulation to a single axis at a time.
Wheel emulation works for both horizontal and vertical axes. Thus, if a device doesn't move in perfect straight line, scroll events build up on the respective other axis. In some clients, scroll wheel events have specific meanings other than scrolling (e.g. mplayer). In these clients, erroneous scrolling events come at a high cost. Thus, if a scroll wheel event is generated for one axis, reset the inertia of the other axis to 0, avoiding the buildup of these erroneous scrolling events. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r--src/emuWheel.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/src/emuWheel.c b/src/emuWheel.c
index 421477e..cc23f1d 100644
--- a/src/emuWheel.c
+++ b/src/emuWheel.c
@@ -54,7 +54,7 @@ static Atom prop_wheel_button = 0;
/* Local Funciton Prototypes */
static BOOL EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char *axis_name);
-static void EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value);
+static int EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value);
/* Filter mouse button events */
BOOL
@@ -98,7 +98,7 @@ BOOL
EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
- WheelAxisPtr pAxis = NULL;
+ WheelAxisPtr pAxis = NULL, pOtherAxis = NULL;
int value = pEv->value;
int ms;
@@ -117,19 +117,28 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
switch(pEv->code) {
case REL_X:
pAxis = &(pEvdev->emulateWheel.X);
+ pOtherAxis = &(pEvdev->emulateWheel.Y);
break;
case REL_Y:
pAxis = &(pEvdev->emulateWheel.Y);
+ pOtherAxis = &(pEvdev->emulateWheel.X);
break;
default:
break;
}
- /* If we found REL_X or REL_Y, emulate a mouse wheel */
+ /* If we found REL_X or REL_Y, emulate a mouse wheel.
+ Reset the inertia of the other axis when a scroll event was sent
+ to avoid the buildup of erroneous scroll events if the user
+ doesn't move in a perfectly straight line.
+ */
if (pAxis)
- EvdevWheelEmuInertia(pInfo, pAxis, value);
+ {
+ if (EvdevWheelEmuInertia(pInfo, pAxis, value))
+ pOtherAxis->traveled_distance = 0;
+ }
/* Eat motion events while emulateWheel button pressed. */
return TRUE;
@@ -138,17 +147,20 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
return FALSE;
}
-/* Simulate inertia for our emulated mouse wheel */
-static void
+/* Simulate inertia for our emulated mouse wheel.
+ Returns the number of wheel events generated.
+ */
+static int
EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
int button;
int inertia;
+ int rc = 0;
/* if this axis has not been configured, just eat the motion */
if (!axis->up_button)
- return;
+ return rc;
axis->traveled_distance += value;
@@ -164,7 +176,9 @@ EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value)
while(abs(axis->traveled_distance) > pEvdev->emulateWheel.inertia) {
axis->traveled_distance -= inertia;
EvdevQueueButtonClicks(pInfo, button, 1);
+ rc++;
}
+ return rc;
}
/* Handle button mapping here to avoid code duplication,