[PATCH] mouse wheel acceleration

Simon Thum simon.thum at gmx.de
Sun Sep 5 10:28:09 PDT 2010


Hi Albert,

the code looks good to me in general. Besides some technicalities,
there may be a larger problem: There is an effort to support wheels with
higher precision (github.com/x-quadraht/pscroll). Whether that
particular solution will make it or not, it would be cool to handle
wheel acceleration in one place. I don't think the scheme mechanism is
especially suitable here, IMO one can achieve a much higher degree of
code sharing.

>      {0, ACCEL_PROP_CONSTANT_DECELERATION},
>      {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
>      {0, ACCEL_PROP_VELOCITY_SCALING},
> +    {0, WHEELACCEL_PROP_SPEEDMULT},
> +    {0, WHEELACCEL_PROP_MAXSPEED},
I would argue the terms are too inconsistent with pointer acceleration.
IMO your speed multipier is actually an acceleration factor. Maxspeed
seems to actually be a maximum speed gain, but that's negligible.

> +    dev->button = NULL; /* reset it initially. some functions in InitWheelVelocityData rely on that */
This is probably superfluous, as dev is cleared on allocation.

> +/* Wheel acceleration: maximum button press multiplier */
> +#define MAX_WHEELBTN_MULTIPLIER	100
> +
...
> +     * Evtl. additional events for wheel acceleration, MAX_WHEELBTN_MULTIPLIER * 2 (up + down)
>       * One possible device changed event
>       */
> -    return 3;
> +    return 1 + 1 + MAX_WHEELBTN_MULTIPLIER * 2 + 1;
Returning a high number here will increase memory consumption. This is a
bit unfortunate, but I'm unsure what you could do about it.



> +/********************************
> + *  acceleration proc
> + *******************************/
> +
> +
> +void
> +ProcessWheelAccel(
> +    DeviceIntPtr dev,
> +    int button,
> +    int* add_num_button_presses,
> +    int evtime)
> +{
> +    DeviceWheelVelocityPtr velocitydata =
> +	(DeviceWheelVelocityPtr) dev->button->wheelAccelScheme.accelData;
> +    int axeIndex = 0;
> +    int delta = 0;
> +    float dt;
> +    *add_num_button_presses = 0;
> +
> +    if (!add_num_button_presses || !velocitydata)
> +        return;
> +
> +    switch(button) {
> +	case 4: axeIndex = 0; delta = -1; break;
> +	case 5: axeIndex = 0; delta = 1; break;
> +	case 6: axeIndex = 1; delta = -1; break;
> +	case 7: axeIndex = 1; delta = 1; break;
> +	default: /* unknown wheel button number */ return;
> +    }
> +
> +    if(velocitydata->lastWheelEvent[axeIndex].delta != delta)
> +	/* we scrolled in a different direction than before -> dont accel */
> +	goto finish;
> +
> +    if(evtime < velocitydata->lastWheelEvent[axeIndex].time)
> +	/* this should not happen */
> +	goto finish;
> +
> +    dt = evtime - velocitydata->lastWheelEvent[axeIndex].time;
> +    *add_num_button_presses = (int) (velocitydata->speed_mult / dt);
> +    if(*add_num_button_presses > velocitydata->max_speed)
> +	*add_num_button_presses = velocitydata->max_speed;
> +
> +finish:
> +    velocitydata->lastWheelEvent[axeIndex].delta = delta;
> +    velocitydata->lastWheelEvent[axeIndex].time = evtime;    
> +}
Most of that is done in the ptrveloc equivalent as well. You could
instantiate a PointerVelocityRec using InitVelocityData (the structure
is a bit tied to pointer accel but I'm cleaning that up.) and go like:

switch(button) {
	case 4: x =  0; y = -1; break;
	case 5: x =  0; y =  1; break;
	case 6: x = -1; y =  0; break;
	case 7: x =  1; y =  0; break;
	default: /* unknown wheel button number */ return;
}
ProcessVelocityData2D(ptr, x, y, timestamp);

Besides having a time-tested algorithm, you could adapt to a smooth
wheel vs. button-based wheel by simply adjusting the PtrVelocityRec
and some boilerplate code. I'm probably fine with any patches which make
the accel stuff less pointer-specific. Plus, you get profiles more or
less for free.

Cheers,

Simon


> +
> diff --git a/hw/xfree86/loader/sdksyms.sh b/hw/xfree86/loader/sdksyms.sh
> index eea0240..fbe4663 100755
> --- a/hw/xfree86/loader/sdksyms.sh
> +++ b/hw/xfree86/loader/sdksyms.sh
> @@ -296,6 +296,7 @@ cat > sdksyms.c << EOF
>  #include "property.h"
>  #include "propertyst.h"
>  #include "ptrveloc.h"
> +#include "wheelveloc.h"
>  #include "region.h"
>  #include "regionstr.h"
>  #include "registry.h"
> diff --git a/include/input.h b/include/input.h
> index 4a845be..e3bc7f8 100644
> --- a/include/input.h
> +++ b/include/input.h
> @@ -146,6 +146,13 @@ typedef void (*PointerAccelSchemeProc)(
>      int* /*valuators*/,
>      int /*evtime*/);
>  
> +/* wheel acceleration handling */
> +typedef void (*WheelAccelSchemeProc)(
> +    DeviceIntPtr /*pDev*/,
> +    int /*button*/,
> +    int* /*add_num_button_presses*/,
> +    int /*evtime*/);
> +
>  typedef void (*DeviceCallbackProc)(
>                DeviceIntPtr /*pDev*/);
>  
> diff --git a/include/inputstr.h b/include/inputstr.h
> index 15184d0..3de7519 100644
> --- a/include/inputstr.h
> +++ b/include/inputstr.h
> @@ -241,6 +241,12 @@ typedef struct _ValuatorClassRec {
>      ValuatorAccelerationRec	accelScheme;
>  } ValuatorClassRec, *ValuatorClassPtr;
>  
> +typedef struct _WheelAccelerationRec {
> +    WheelAccelSchemeProc        AccelSchemeProc;
> +    void                       *accelData; /* at disposal of AccelScheme */
> +    DeviceCallbackProc          AccelCleanupProc;
> +} WheelAccelerationRec, *WheelAccelerationPtr;
> +
>  typedef struct _ButtonClassRec {
>      int			sourceid;
>      CARD8		numButtons;
> @@ -256,6 +262,7 @@ typedef struct _ButtonClassRec {
>      CARD8		map[MAP_LENGTH];
>      union _XkbAction    *xkb_acts;
>      Atom		labels[MAX_BUTTONS];
> +    WheelAccelerationRec	wheelAccelScheme;
>  } ButtonClassRec, *ButtonClassPtr;
>  
>  typedef struct _FocusClassRec {
> diff --git a/include/wheelveloc.h b/include/wheelveloc.h
> new file mode 100644
> index 0000000..13c6146
> --- /dev/null
> +++ b/include/wheelveloc.h
> @@ -0,0 +1,61 @@
> +/*
> + *
> + * Copyright © 2010 Albert Zeyer		albert . zeyer @ rwth - aachen . de
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef WHEELVELOCITY_H
> +#define WHEELVELOCITY_H
> +
> +#include <input.h> /* DeviceIntPtr */
> +
> +/**
> + * a motion history, with just enough information to
> + * calc mean velocity
> + */
> +typedef struct _WheelTracker {
> +    int delta;	/* accumulated delta */
> +    int time;	/* time of creation */
> +} WheelTrackerRec, *WheelTrackerPtr;
> +
> +/**
> + * Contains all data needed to implement wheel ballistics
> + */
> +typedef struct _DeviceWheelVelocityRec {
> +    WheelTrackerRec lastWheelEvent[2]; /* 2 for both Z and W axes */
> +    int     add_num_button_presses;
> +    float   speed_mult;      /* config: speed multiplier */
> +    int	    max_speed;       /* config: max speed */
> +} DeviceWheelVelocityRec, *DeviceWheelVelocityPtr;
> +
> +
> +extern _X_EXPORT void
> +InitWheelVelocityData(DeviceIntPtr dev, DeviceWheelVelocityPtr vel);
> +
> +extern _X_INTERNAL void
> +CleanupWheelAccel(DeviceIntPtr dev);
> +
> +extern _X_INTERNAL void
> +ProcessWheelAccel(DeviceIntPtr dev, int button,
> +	          int* add_num_button_presses, int evtime);
> +
> +
> +#endif  /* POINTERVELOCITY_H */
> diff --git a/include/xserver-properties.h b/include/xserver-properties.h
> index 626d0ad..fc0fe56 100644
> --- a/include/xserver-properties.h
> +++ b/include/xserver-properties.h
> @@ -45,6 +45,11 @@
>  /* FLOAT, format 32 */
>  #define ACCEL_PROP_VELOCITY_SCALING "Device Accel Velocity Scaling"
>  
> +/* Wheel acceleration properties */
> +/* FLOAT, format 32*/
> +#define WHEELACCEL_PROP_SPEEDMULT "Device Wheel Accel Speed Multiplier"
> +/* INTEGER of any format. 0 - no acceleration */
> +#define WHEELACCEL_PROP_MAXSPEED "Device Wheel Accel Max Speed"
>  
>  /* Axis labels */
>  #define AXIS_LABEL_PROP "Axis Labels"
> 
> 
> 
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel



More information about the xorg-devel mailing list