[PATCH 27/27] Input: Add smooth-scrolling support to GetPointerEvents

Daniel Stone daniel at fooishbar.org
Fri Jun 3 08:00:03 PDT 2011


For scroll wheel support, we used to send buttons 4/5 and 6/7 for
horizontal/vertical positive/negative scroll events.  For touchpads, we
really want more fine-grained scroll values.  GetPointerEvents now
accepts both old-school scroll button presses, and new-style scroll axis
events, while emitting both types of events to support both old and new
clients.

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
---
 dix/getevents.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/dix/getevents.c b/dix/getevents.c
index c1ebbb2..f8be73c 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -2,6 +2,7 @@
  * Copyright © 2006 Nokia Corporation
  * Copyright © 2006-2007 Daniel Stone
  * Copyright © 2008 Red Hat, Inc.
+ * Copyright © 2011 The Chromium OS Authors
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -60,11 +61,13 @@
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XI2.h>
 #include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI2.h>
 #include <pixman.h>
 #include "exglobals.h"
 #include "exevents.h"
 #include "extnsionst.h"
 #include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
+#include "xserver-properties.h"
 
 /* Number of motion history events to store. */
 #define MOTION_HISTORY_SIZE 256
@@ -622,8 +625,10 @@ GetMaximumEventsNum(void) {
     /* One raw event
      * One device event
      * One possible device changed event
+     * Lots of possible separate scroll events (horiz + vert)
+     * Lots of possible separate raw scroll event (horiz + vert)
      */
-    return 3;
+    return 51;
 }
 
 
@@ -1199,7 +1204,12 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
                   int flags, const ValuatorMask *mask_in)
 {
     CARD32 ms = GetTimeInMillis();
-    int num_events = 0;
+    int num_events = 0, nev_tmp;
+    int i;
+    ValuatorMask mask;
+    Atom h_scroll_label = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
+    Atom v_scroll_label = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
+    int h_scroll_axis = -1, v_scroll_axis = -1;
 
     /* refuse events from disabled devices */
     if (!pDev->enabled)
@@ -1210,8 +1220,98 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
 
     events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT,
                               &num_events);
-    num_events += _GetPointerEvents(events, pDev, type, buttons, ms, flags,
-                                    mask_in);
+
+    valuator_mask_copy(&mask, mask_in);
+
+    /* Find the vertical and horizontal scroll axes, if any. */
+    for (i = 0; i < pDev->valuator->numAxes; i++)
+    {
+        if (h_scroll_label && pDev->valuator->axes[i].label == h_scroll_label)
+            h_scroll_axis = i;
+        else if (v_scroll_label &&
+                 pDev->valuator->axes[i].label == v_scroll_label)
+            v_scroll_axis = i;
+    }
+
+    /* Turn a scroll button press into a smooth-scrolling event. */
+    if (type == ButtonPress &&
+        ((v_scroll_axis != -1 && (buttons == 4 || buttons == 5)) ||
+         (h_scroll_axis != -1 && (buttons == 6 || buttons == 7))))
+    {
+        double val;
+
+        type = MotionNotify;
+        buttons = 0;
+        if (buttons == 4)
+        {
+            val = valuator_mask_get_double(&mask, v_scroll_axis) + 1.0;
+            valuator_mask_set_double(&mask, v_scroll_axis, val);
+        }
+        else if (buttons == 5)
+        {
+            val = valuator_mask_get_double(&mask, v_scroll_axis) - 1.0;
+            valuator_mask_set_double(&mask, v_scroll_axis, val);
+        }
+        else if (buttons == 6)
+        {
+            val = valuator_mask_get_double(&mask, v_scroll_axis) + 1.0;
+            valuator_mask_set_double(&mask, h_scroll_axis, val);
+        }
+        else if (buttons == 7)
+        {
+            val = valuator_mask_get_double(&mask, v_scroll_axis) - 1.0;
+            valuator_mask_set_double(&mask, h_scroll_axis, val);
+        }
+    }
+
+    /* Return the original event set, plus potential legacy scrolling events. */
+    nev_tmp = _GetPointerEvents(events, pDev, type, buttons, ms, flags,
+                                &mask);
+    events += nev_tmp;
+    num_events += nev_tmp;
+
+    while (((v_scroll_axis != -1 &&
+             fabs(pDev->last.valuators[v_scroll_axis]) >= 1.0) ||
+            (h_scroll_axis != -1 &&
+             fabs(pDev->last.valuators[h_scroll_axis]) >= 1.0)) &&
+           (num_events + 4) < GetMaximumEventsNum())
+    {
+        int b = 0;
+
+        if (v_scroll_axis != -1 && pDev->last.valuators[v_scroll_axis] <= -1.0)
+        {
+            pDev->last.valuators[v_scroll_axis] += 1.0;
+            b = 4;
+        }
+        else if (v_scroll_axis != -1 &&
+                 pDev->last.valuators[v_scroll_axis] >= 1.0)
+        {
+            pDev->last.valuators[v_scroll_axis] -= 1.0;
+            b = 5;
+        }
+        else if (h_scroll_axis != -1 &&
+                 pDev->last.valuators[h_scroll_axis] <= -1.0)
+        {
+            pDev->last.valuators[h_scroll_axis] += 1.0;
+            b = 6;
+        }
+        else if (h_scroll_axis != -1 &&
+                 pDev->last.valuators[h_scroll_axis] >= 1.0)
+        {
+            pDev->last.valuators[h_scroll_axis] -= 1.0;
+            b = 7;
+        }
+
+        nev_tmp = _GetPointerEvents(events, pDev, ButtonPress, b, ms,
+                                    POINTER_EMULATED, NULL);
+        events += nev_tmp;
+        num_events += nev_tmp;
+        nev_tmp = _GetPointerEvents(events, pDev, ButtonRelease, b, ms,
+                                    POINTER_EMULATED, NULL);
+        events += nev_tmp;
+        num_events += nev_tmp;
+    }
+
     return num_events;
 }
 
-- 
1.7.5.3



More information about the xorg-devel mailing list