[PATCH v2 28/28] Input: Add smooth-scrolling support to GetPointerEvents
Peter Hutterer
peter.hutterer at who-t.net
Wed Jun 22 20:35:59 PDT 2011
On Thu, Jun 09, 2011 at 06:17:36PM +0100, Daniel Stone wrote:
> 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;
> }
every time I see 95 lines being added to one function something in me diese
a little.
you don't seem to be accessing anything but v_scroll_axis and h_scroll_axis
from the local stack anyway, why not make the while loop a:
int emulate_scroll_button_events(events, device, hscroll, vscroll)
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net> for the lot though
(well, the unreviewed ones)
Cheers,
Peter
>
> 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