[PATCH evdev 1/2] Fix axis initialization for devices with abs x/y and rel scrollwheels

Peter Hutterer peter.hutterer at who-t.net
Wed Aug 13 20:54:55 PDT 2014


The Xen Virtual Pointer device has ABS_X, ABS_Y and REL_WHEEL. If smooth
scrolling is detected, the current code would first initialize relative axes
for scrolling and immediately overwrite those axes when the abs valuators are
written out.

This patch fixes the default case only, in the case of a device setting the
two Ignore*Axis options both to "off", the axes are still overwritten. The
wheels will work, other axes only if the same number of abs axes exists. And
it keeps the current memory leak too, but it's marked with a FIXME now.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev.c | 82 +++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 44 insertions(+), 38 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 5a39d8b..045d780 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1221,7 +1221,7 @@ is_blacklisted_axis(int axis)
 
 
 static int
-EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes)
+EvdevAddAbsValuatorClass(DeviceIntPtr device, int num_scroll_axes)
 {
     InputInfoPtr pInfo;
     EvdevPtr pEvdev;
@@ -1283,16 +1283,9 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes)
 
 #endif
 
+
 #ifdef HAVE_SMOOTH_SCROLLING
-    if (want_scroll_axes && libevdev_has_event_type(pEvdev->dev, EV_REL))
-    {
-        if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL))
-            num_axes++;
-        if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL))
-            num_axes++;
-        if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL))
-            num_axes++;
-    }
+    num_axes += num_scroll_axes;
 #endif
 
     if (num_axes + num_mt_axes > MAX_VALUATORS) {
@@ -1397,7 +1390,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes)
     }
 
 #ifdef HAVE_SMOOTH_SCROLLING
-    if (want_scroll_axes)
+    if (num_scroll_axes > 0)
     {
         mapping++; /* continue from abs axis mapping */
 
@@ -1507,7 +1500,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device, int want_scroll_axes)
 #endif
 
 #ifdef HAVE_SMOOTH_SCROLLING
-    if (want_scroll_axes)
+    if (num_scroll_axes)
     {
         int idx;
         if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL))
@@ -1642,7 +1635,7 @@ EvdevSetScrollValuators(DeviceIntPtr device)
 }
 
 static int
-EvdevAddRelValuatorClass(DeviceIntPtr device)
+EvdevAddRelValuatorClass(DeviceIntPtr device, int num_scroll_axes)
 {
     InputInfoPtr pInfo;
     EvdevPtr pEvdev;
@@ -1655,24 +1648,22 @@ EvdevAddRelValuatorClass(DeviceIntPtr device)
     if (!libevdev_has_event_type(pEvdev->dev, EV_REL))
         goto out;
 
-    for (i = 0; i < REL_MAX; i++)
+    for (i = 0; i < REL_MAX; i++) {
+        if (i == REL_WHEEL || i == REL_HWHEEL || i == REL_DIAL)
+            continue;
+
         if (libevdev_has_event_code(pEvdev->dev, EV_REL, i))
             num_axes++;
-    if (num_axes < 1)
-        goto out;
+    }
 
-#ifndef HAVE_SMOOTH_SCROLLING
-    /* Wheels are special, we post them as button events. So let's ignore them
-     * in the axes list too */
-    if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL))
-        num_axes--;
-    if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL))
-        num_axes--;
-    if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL))
-        num_axes--;
+    /* If we have only relative scroll axes, then we punt axis init to
+       EvdevInitAbsValuators if possible */
+    if (num_axes < 1 &&
+        (num_scroll_axes == 0 || pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
+            goto out;
 
-    if (num_axes <= 0)
-        goto out;
+#ifdef HAVE_SMOOTH_SCROLLING
+    num_axes += num_scroll_axes;
 #endif
 
     if (num_axes > MAX_VALUATORS) {
@@ -1811,20 +1802,36 @@ EvdevInitButtonMapping(InputInfoPtr pInfo)
 
 }
 
+static int
+EvdevCountScrollAxes(EvdevPtr pEvdev)
+{
+    int num_scroll_axes = 0;
+
+#ifdef HAVE_SMOOTH_SCROLLING
+    if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_WHEEL))
+        num_scroll_axes++;
+    if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_HWHEEL))
+        num_scroll_axes++;
+    if (libevdev_has_event_code(pEvdev->dev, EV_REL, REL_DIAL))
+        num_scroll_axes++;
+#endif
+
+    return num_scroll_axes;
+}
+
 static void
 EvdevInitAnyValuators(DeviceIntPtr device, EvdevPtr pEvdev)
 {
     InputInfoPtr pInfo = device->public.devicePrivate;
-    int rel_success = FALSE;
+    int num_scroll_axes = EvdevCountScrollAxes(pEvdev);
 
     if (pEvdev->flags & EVDEV_RELATIVE_EVENTS &&
-        EvdevAddRelValuatorClass(device) == Success)
-    {
-        rel_success = TRUE;
+        EvdevAddRelValuatorClass(device, num_scroll_axes) == Success)
         xf86IDrvMsg(pInfo, X_INFO, "initialized for relative axes.\n");
-    }
+    /* FIXME: EvdevAddAbsValuatorClass overwrites the valuators initialized
+       in EvdevAddRelValuatorClass and leaks the latter's memory */
     if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS &&
-        EvdevAddAbsValuatorClass(device, !rel_success) == Success)
+        EvdevAddAbsValuatorClass(device, num_scroll_axes) == Success)
         xf86IDrvMsg(pInfo, X_INFO, "initialized for absolute axes.\n");
 }
 
@@ -1832,8 +1839,9 @@ static void
 EvdevInitAbsValuators(DeviceIntPtr device, EvdevPtr pEvdev)
 {
     InputInfoPtr pInfo = device->public.devicePrivate;
+    int num_scroll_axes = EvdevCountScrollAxes(pEvdev);
 
-    if (EvdevAddAbsValuatorClass(device, TRUE) == Success) {
+    if (EvdevAddAbsValuatorClass(device, num_scroll_axes) == Success) {
         xf86IDrvMsg(pInfo, X_INFO,"initialized for absolute axes.\n");
     } else {
         xf86IDrvMsg(pInfo, X_ERROR,"failed to initialize for absolute axes.\n");
@@ -1846,8 +1854,9 @@ EvdevInitRelValuators(DeviceIntPtr device, EvdevPtr pEvdev)
 {
     InputInfoPtr pInfo = device->public.devicePrivate;
     int has_abs_axes = pEvdev->flags & EVDEV_ABSOLUTE_EVENTS;
+    int num_scroll_axes = EvdevCountScrollAxes(pEvdev);
 
-    if (EvdevAddRelValuatorClass(device) == Success) {
+    if (EvdevAddRelValuatorClass(device, num_scroll_axes) == Success) {
 
         xf86IDrvMsg(pInfo, X_INFO,"initialized for relative axes.\n");
 
@@ -2274,9 +2283,6 @@ EvdevProbe(InputInfoPtr pInfo)
 #endif
                 EvdevForceXY(pInfo, Absolute);
         }
-
-
-
     }
 
     for (i = 0; i < BTN_MISC; i++) {
-- 
1.9.3



More information about the xorg-devel mailing list