From 3b40645a10a119529610405c8ef0373cf4eabd7c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 17 Aug 2009 09:41:11 +1000 Subject: [PATCH] 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 --- src/emuWheel.c | 28 +++++++++++++++++++++------- 1 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/emuWheel.c b/src/emuWheel.c index 9bff731..e5adcc6 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; @@ -119,19 +119,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; @@ -140,17 +149,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; @@ -166,7 +178,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, -- 1.6.3.rc1.2.g0164.dirty