[PATCH v2 28/28] Input: Add smooth-scrolling support to GetPointerEvents
Daniel Stone
daniel at fooishbar.org
Thu Jun 9 10:17:36 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/devices.c | 8 ++++
dix/getevents.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++--
include/inputstr.h | 2 +
3 files changed, 114 insertions(+), 4 deletions(-)
v2: Cache horiz/vert scroll axes in DeviceIntRec, rather than scanning for
them on every GPE. Changed an ungodly series of if branches testing
for legacy button events to a much cleaner switch. More incisive comments.
Removed duplicate XI2.h include.
Outstanding gotchas: We don't send x/y with the button events, and the
scroll delta currently accumulates until it hits a magnitude of 1.0.
Probably need to clean up the button -> axis -> button conversion
further.
diff --git a/dix/devices.c b/dix/devices.c
index 0ccf252..3801913 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1261,6 +1261,8 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
{
int i;
ValuatorClassPtr valc;
+ Atom h_scroll_label = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
+ Atom v_scroll_label = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
if (!dev)
return FALSE;
@@ -1281,6 +1283,8 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
valc->motion = NULL;
valc->first_motion = 0;
valc->last_motion = 0;
+ valc->h_scroll_axis = -1;
+ valc->v_scroll_axis = -1;
valc->numMotionEvents = numMotionEvents;
valc->motionHintWindow = NullWindow;
@@ -1295,6 +1299,10 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
for (i=0; i<numAxes; i++) {
InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS,
0, 0, 0, mode);
+ if (labels[i] == h_scroll_label)
+ valc->h_scroll_axis = i;
+ else if (labels[i] == v_scroll_label)
+ valc->v_scroll_axis = i;
valc->axisVal[i]=0;
}
diff --git a/dix/getevents.c b/dix/getevents.c
index 03c7938..8788ac6 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 Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -65,6 +66,7 @@
#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 +624,10 @@ GetMaximumEventsNum(void) {
/* One raw event
* One device event
* One possible device changed event
+ * Lots of possible separate button scroll events (horiz + vert)
+ * Lots of possible separate raw button scroll events (horiz + vert)
*/
- return 3;
+ return 51;
}
@@ -1208,7 +1212,10 @@ 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 h_scroll_axis = pDev->valuator->h_scroll_axis;
+ int v_scroll_axis = pDev->valuator->v_scroll_axis;
+ ValuatorMask mask;
/* refuse events from disabled devices */
if (!pDev->enabled)
@@ -1219,8 +1226,101 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT,
&num_events);
- num_events += fill_pointer_events(events, pDev, type, buttons, ms, flags,
- mask_in);
+
+ valuator_mask_copy(&mask, mask_in);
+
+ /* Turn a scroll button press into a smooth-scrolling event if necessary. */
+ if (type == ButtonPress)
+ {
+ double val, adj;
+ int axis;
+
+ switch (buttons) {
+ case 4:
+ adj = 1.0;
+ axis = v_scroll_axis;
+ break;
+ case 5:
+ adj = -1.0;
+ axis = v_scroll_axis;
+ break;
+ case 6:
+ adj = 1.0;
+ axis = h_scroll_axis;
+ break;
+ case 7:
+ adj = -1.0;
+ axis = h_scroll_axis;
+ break;
+ default:
+ adj = 0.0;
+ axis = -1;
+ break;
+ }
+
+ if (adj != 0.0 && axis != -1)
+ {
+ val = valuator_mask_get_double(&mask, axis) + adj;
+ valuator_mask_set_double(&mask, axis, val);
+ type = MotionNotify;
+ buttons = 0;
+ }
+ }
+
+ /* First fill out the original event set, with smooth-scrolling axes. */
+ nev_tmp = fill_pointer_events(events, pDev, type, buttons, ms, flags,
+ &mask);
+ events += nev_tmp;
+ num_events += nev_tmp;
+
+ /* Now turn the smooth-scrolling axes back into emulated button presses
+ * for legacy clients. */
+ 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))
+ {
+ int b = 0;
+
+ /* fill_pointer_events() generates four events: one normal and one raw
+ * event each for the emulated button press and release both. */
+ if (num_events + 4 >= GetMaximumEventsNum())
+ break;
+
+ 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 = fill_pointer_events(events, pDev, ButtonPress, b, ms,
+ POINTER_EMULATED, NULL);
+ events += nev_tmp;
+ num_events += nev_tmp;
+ nev_tmp = fill_pointer_events(events, pDev, ButtonRelease, b, ms,
+ POINTER_EMULATED, NULL);
+ events += nev_tmp;
+ num_events += nev_tmp;
+ }
+
return num_events;
}
diff --git a/include/inputstr.h b/include/inputstr.h
index 11d69e7..d905fff 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -283,6 +283,8 @@ typedef struct _ValuatorClassRec {
unsigned short numAxes;
double *axisVal; /* always absolute, but device-coord system */
ValuatorAccelerationRec accelScheme;
+ int h_scroll_axis; /* horiz smooth-scrolling axis */
+ int v_scroll_axis; /* vert smooth-scrolling axis */
} ValuatorClassRec;
typedef struct _ButtonClassRec {
--
1.7.5.3
More information about the xorg-devel
mailing list