[PATCH evdev] Support smooth scrolling on wheel emulation
Max Schwarz
Max at x-quadraht.de
Sun Oct 2 07:30:58 PDT 2011
This adds support for the new smooth-scrolling valuator system to
the wheel emulation code.
Caveats:
- Enabling wheel emulation at runtime does not work if the device
does not provide the necessary axes already.
- Horizontal scrolling is always reported on the REL_HWHEEL axis,
ignoring a REL_DIAL axis present in hardware.
Signed-off-by: Max Schwarz <Max at x-quadraht.de>
---
Hi Peter,
here's a tentative patch for evdev for smooth wheel emulation. It applies on
your smooth-scrolling branch.
Note: Without this patch (i.e. using the old button interface) wheel emulation
direction is flipped, because scroll.increment is set to -1. That would be a
regression, so please wait with merging smooth-scrolling until that's
resolved.
Best regards,
Max
src/emuWheel.c | 19 ++++++++++++++++++-
src/evdev.c | 34 +++++++++++++++++++++++++++-------
src/evdev.h | 4 +++-
3 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/src/emuWheel.c b/src/emuWheel.c
index ae894fa..0439a5b 100644
--- a/src/emuWheel.c
+++ b/src/emuWheel.c
@@ -167,9 +167,13 @@ static int
EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value)
{
EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
+ int rc = 0;
+#ifndef HAVE_SMOOTH_SCROLLING
int button;
int inertia;
- int rc = 0;
+#else
+ double v;
+#endif
/* if this axis has not been configured, just eat the motion */
if (!axis->up_button)
@@ -177,6 +181,7 @@ EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr
axis, int value)
axis->traveled_distance += value;
+#ifndef HAVE_SMOOTH_SCROLLING
if (axis->traveled_distance < 0) {
button = axis->up_button;
inertia = -pEvdev->emulateWheel.inertia;
@@ -192,6 +197,14 @@ EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr
axis, int value)
rc++;
}
return rc;
+#else
+ /* Inject relative valuator delta */
+ v = -((double)axis->traveled_distance) / pEvdev->emulateWheel.inertia;
+ EvdevInjectRelativeMotion(pEvdev, axis->code, v);
+ axis->traveled_distance = 0;
+ xf86IDrvMsg(pInfo, X_ERROR, "rel motion: %f\n", v);
+ return 1;
+#endif
}
/* Handle button mapping here to avoid code duplication,
@@ -322,6 +335,10 @@ EvdevWheelEmuPreInit(InputInfoPtr pInfo)
pEvdev->emulateWheel.X.traveled_distance = 0;
pEvdev->emulateWheel.Y.traveled_distance = 0;
+ /* Used to inject smooth scrolling events */
+ pEvdev->emulateWheel.X.code = REL_HWHEEL;
+ pEvdev->emulateWheel.Y.code = REL_WHEEL;
+
xf86IDrvMsg(pInfo, X_CONFIG,
"EmulateWheelButton: %d, "
"EmulateWheelInertia: %d, "
diff --git a/src/evdev.c b/src/evdev.c
index 2281206..9559758 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -362,7 +362,7 @@ EvdevProcessValuators(InputInfoPtr pInfo)
{
int tmp;
EvdevPtr pEvdev = pInfo->private;
- int *delta = pEvdev->delta;
+ double *delta = pEvdev->delta;
/* convert to relative motion for touchpads */
if (pEvdev->abs_queued && (pEvdev->flags & EVDEV_RELATIVE_MODE)) {
@@ -413,7 +413,7 @@ EvdevProcessValuators(InputInfoPtr pInfo)
{
int map = pEvdev->axis_map[i];
if (pEvdev->delta[i] && map != -1)
- valuator_mask_set(pEvdev->vals, map, pEvdev->delta[i]);
+ valuator_mask_set_double(pEvdev->vals, map, pEvdev-
>delta[i]);
}
}
/*
@@ -586,7 +586,6 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct
input_event *ev)
{
int value;
EvdevPtr pEvdev = pInfo->private;
- int map;
/* Get the signed value, earlier kernels had this as unsigned */
value = ev->value;
@@ -618,15 +617,25 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo,
struct input_event *ev)
if (EvdevWheelEmuFilterMotion(pInfo, ev))
return;
- pEvdev->rel_queued = 1;
- pEvdev->delta[ev->code] += value;
- map = pEvdev->axis_map[ev->code];
- valuator_mask_set(pEvdev->vals, map, value);
+ EvdevInjectRelativeMotion(pEvdev, ev->code, value);
break;
}
}
/**
+ * Inject a relative motion on a valuator axis.
+ **/
+void
+EvdevInjectRelativeMotion(EvdevPtr pEvdev, int axis_code, double delta)
+{
+ int map = pEvdev->axis_map[axis_code];
+
+ pEvdev->rel_queued = 1;
+ pEvdev->delta[axis_code] += delta;
+ valuator_mask_set_double(pEvdev->vals, map, delta);
+}
+
+/**
* Take the absolute motion input event and process it accordingly.
*/
static void
@@ -896,6 +905,7 @@ EvdevReadInput(InputInfoPtr pInfo)
}
#define TestBit(bit, array) ((array[(bit) / LONG_BITS]) & (1L << ((bit) %
LONG_BITS)))
+#define evdev_SetBit(bit, array) ((array[(bit) / LONG_BITS]) |= (1L << ((bit)
% LONG_BITS)))
static void
EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
@@ -1099,6 +1109,16 @@ EvdevAddRelValuatorClass(DeviceIntPtr device)
if (!TestBit(EV_REL, pEvdev->bitmask))
goto out;
+#ifdef HAVE_SMOOTH_SCROLLING
+ /* If wheel emulation is enabled, we need to report virtual axes */
+ if (pEvdev->emulateWheel.enabled) {
+ if(pEvdev->emulateWheel.X.up_button)
+ evdev_SetBit(REL_HWHEEL, pEvdev->rel_bitmask);
+ if(pEvdev->emulateWheel.Y.up_button)
+ evdev_SetBit(REL_WHEEL, pEvdev->rel_bitmask);
+ }
+#endif
+
num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX));
if (num_axes < 1)
goto out;
diff --git a/src/evdev.h b/src/evdev.h
index b2e2f42..d15f823 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -101,6 +101,7 @@ typedef struct {
int up_button;
int down_button;
int traveled_distance;
+ int code; /* REL_WHEEL or REL_HWHEEL */
} WheelAxis, *WheelAxisPtr;
/* Event queue used to defer keyboard/button events until EV_SYN time. */
@@ -135,7 +136,7 @@ typedef struct {
BOOL invert_x;
BOOL invert_y;
- int delta[REL_CNT];
+ double delta[REL_CNT];
unsigned int abs_queued, rel_queued, prox_queued;
/* XKB stuff has to be per-device rather than per-driver */
@@ -223,6 +224,7 @@ void EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int
num_v, int first_v,
void EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
int v[MAX_VALUATORS]);
unsigned int EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code);
+void EvdevInjectRelativeMotion(EvdevPtr pEvdev, int axis_code, double delta);
/* Middle Button emulation */
int EvdevMBEmuTimer(InputInfoPtr);
--
1.7.4.1
More information about the xorg-devel
mailing list