[PATCH evdev, v2] Support smooth scrolling on wheel emulation

Peter Hutterer peter.hutterer at who-t.net
Tue Oct 4 17:48:35 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.
>  - Horizontal scrolling is always reported on the REL_HWHEEL axis,
>    ignoring a REL_DIAL axis present in hardware.
> 
> Signed-off-by: Max Schwarz <Max at x-quadraht.de>
> ---
> Resend, my E-Mail client ate the patch...

and it did so again, please re-send as attachment. or alternatively teach
your client not to wrap lines when sending patches.

Cheers,
  Peter
> 
>  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);
> +    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) 
> % 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