[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