[PATCH evdev, v2] Support smooth scrolling on wheel emulation
Peter Hutterer
peter.hutterer at who-t.net
Tue Oct 4 20:28:22 PDT 2011
On Tue, Oct 04, 2011 at 09:53:56PM +0200, Max Schwarz wrote:
> 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.
you could make the support compiled in, but not compiled _out_. so even if
you HAVE_SMOOTH_SCROLLING, the old bits are ready to go when enabled.
if no smooth scrolling axis is otherwise present on the device, just post
button events as previously.
> - Horizontal scrolling is always reported on the REL_HWHEEL axis,
> ignoring a REL_DIAL axis present in hardware.
REL_DIAL is set up as vertical axis by default anyway.
>
> Signed-off-by: Max Schwarz <Max at x-quadraht.de>
> ---
> Resend, my E-Mail client ate the patch...
>
> 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);
this should be removed in the final version
> + 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)
Can we use the server's BitIsOn (inputstr.h), SetBit, etc here instead of
relying on our own macros with name conflicts?
Cheers,
Peter
> % 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