| From: Chung-yih Wang <cywang@chromium.org> |
| Date: Wed, 14 Nov 2012 15:42:36 +0800 |
| Subject: [PATCH] Accelerate emulated wheel events |
| |
| Use the Chromium OS Mouse Wheel acceleration for Emulated Wheel |
| events. This acceleration replaces the simpler "accumulated inertia |
| mapped to number of button clicks" approach. |
| |
| The main motivation of this change is to send Emulated Wheel events to |
| Chrome using the scroll valuators instead of legacy button events. |
| --- |
| src/emuWheel.c | 48 +++++++++--------------------------------------- |
| src/evdev.c | 20 +++++++++++++++++++- |
| src/evdev.h | 4 ++++ |
| 3 files changed, 32 insertions(+), 40 deletions(-) |
| |
| diff --git a/src/emuWheel.c b/src/emuWheel.c |
| index db989c5..dae4031 100644 |
| --- a/src/emuWheel.c |
| +++ b/src/emuWheel.c |
| @@ -50,9 +50,6 @@ static Atom prop_wheel_inertia = 0; |
| static Atom prop_wheel_timeout = 0; |
| static Atom prop_wheel_button = 0; |
| |
| -/* Local Funciton Prototypes */ |
| -static int EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value); |
| - |
| /* Filter mouse button events */ |
| BOOL |
| EvdevWheelEmuFilterButton(InputInfoPtr pInfo, unsigned int button, int value) |
| @@ -148,8 +145,15 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv) |
| */ |
| if (pAxis) |
| { |
| - if (EvdevWheelEmuInertia(pInfo, pAxis, value)) |
| - pOtherAxis->traveled_distance = 0; |
| + if (pAxis->up_button) { |
| + /* |
| + * Try to emit an emulated wheel event. For REL_Y, up is - |
| + * and down is + but, for REL_WHEEL, up is + and down is -. |
| + */ |
| + pEv->code = (pEv->code == REL_Y) ? REL_WHEEL : REL_HWHEEL; |
| + pEv->value *= (pEv->code == REL_WHEEL) ? -1 : 1; |
| + EvdevProcessRelativeMotionEvent(pInfo, pEv); |
| + } |
| } |
| |
| /* Eat motion events while emulateWheel button pressed. */ |
| @@ -159,40 +163,6 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv) |
| return FALSE; |
| } |
| |
| -/* 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 rc; |
| - |
| - axis->traveled_distance += value; |
| - |
| - if (axis->traveled_distance < 0) { |
| - button = axis->up_button; |
| - inertia = -pEvdev->emulateWheel.inertia; |
| - } else { |
| - button = axis->down_button; |
| - inertia = pEvdev->emulateWheel.inertia; |
| - } |
| - |
| - /* Produce button press events for wheel motion */ |
| - 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, |
| returns true if a button mapping was found. */ |
| static BOOL |
| diff --git a/src/evdev.c b/src/evdev.c |
| index 986519c..f2cba5e 100644 |
| --- a/src/evdev.c |
| +++ b/src/evdev.c |
| @@ -131,6 +131,7 @@ static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab); |
| static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]); |
| static int EvdevOpenDevice(InputInfoPtr pInfo); |
| static void EvdevCloseDevice(InputInfoPtr pInfo); |
| +static void EvdevForceWheel(InputInfoPtr pInfo); |
| |
| static int EvdevInjectEvent(InputInfoPtr pInfo, uint16_t type, |
| uint16_t code, int32_t value); |
| @@ -787,6 +788,8 @@ EvdevAccelWheel(InputInfoPtr pInfo, struct input_event *ev) |
| |
| /* If start_time == end_time, compute click_speed using dt = 1 second */ |
| dt = (end_time - start_time) ?: 1.0; |
| + if (pEvdev->emulateWheel.enabled) |
| + dt *= pEvdev->emulateWheel.inertia; |
| click_speed = ev->value / dt; |
| |
| wheel->value = ev->value; |
| @@ -812,7 +815,7 @@ EvdevAccelWheel(InputInfoPtr pInfo, struct input_event *ev) |
| /** |
| * Take the relative motion input event and process it accordingly. |
| */ |
| -static void |
| +void |
| EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) |
| { |
| int value; |
| @@ -2052,6 +2055,8 @@ EvdevAddRelValuatorClass(DeviceIntPtr device) |
| if (!EvdevBitIsSet(pEvdev->bitmask, EV_REL)) |
| goto out; |
| |
| + EvdevForceWheel(pInfo); |
| + |
| num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX)); |
| if (num_axes < 1) |
| goto out; |
| @@ -2589,6 +2594,19 @@ EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab) |
| } |
| |
| /** |
| + * Some devices require REL_WHEEL and REL_HWHEEL axes to emulate wheel |
| + * activities. |
| + */ |
| +static void |
| +EvdevForceWheel(InputInfoPtr pInfo) |
| +{ |
| + EvdevPtr pEvdev = pInfo->private; |
| + |
| + EvdevSetBit(pEvdev->rel_bitmask, REL_WHEEL); |
| + EvdevSetBit(pEvdev->rel_bitmask, REL_HWHEEL); |
| +} |
| + |
| +/** |
| * Some devices only have other axes (e.g. wheels), but we |
| * still need x/y for these. The server relies on devices having |
| * x/y as axes 0/1 and core/XI 1.x clients expect it too (#44655) |
| diff --git a/src/evdev.h b/src/evdev.h |
| index 7b7ca8d..38beb98 100644 |
| --- a/src/evdev.h |
| +++ b/src/evdev.h |
| @@ -314,6 +314,10 @@ void EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int num_v, int first_v, |
| int v[MAX_VALUATORS]); |
| unsigned int EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code); |
| |
| +/* Event processing functions */ |
| +void EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, |
| + struct input_event *ev); |
| + |
| /* Middle Button emulation */ |
| int EvdevMBEmuTimer(InputInfoPtr); |
| BOOL EvdevMBEmuFilterEvent(InputInfoPtr, int, BOOL); |
| -- |
| 1.8.4.1 |
| |