[PATCH 09/15] Add four new motion filters

Peter Hutterer peter.hutterer at who-t.net
Mon Jun 13 22:22:25 PDT 2011


On Thu, Jun 09, 2011 at 08:57:30PM +0100, Daniel Stone wrote:
> From: Derek Foreman <derek.foreman at collabora.co.uk>
> 
> Attempt to decrease the possibility of errant motion as much as possible
> by adding three new configurable filters, disabled by default:
>     - Synaptics Max Jerk: maximum change in acceleration before the
>       packet is declared errant (xorg.conf MaxJerk)
>     - Synaptics Max Accel: maximum acceleration the pointer can have
>       before being declared errant (xorg.conf MaxAccel)
>     - Synaptics Max Error: maximum error from a best-fit prediction of
>       the next position before being declared errant (xorg.conf MaxError)
>     - Synaptics Max Distance: maximum distance a finger can move in a
>       single report before being declared errant (xorg.conf MaxDistance)
> 

woo! more configuration options! :)

> Signed-off-by: Derek Foreman <derek.foreman at collabora.co.uk>
> Reviewed-by: Daniel Stone <daniel at fooishbar.org>
> ---
>  include/synaptics-properties.h |   12 ++++++++++
>  man/synaptics.man              |   23 ++++++++++++++++++++
>  src/properties.c               |   46 +++++++++++++++++++++++++++++++++++++++-
>  src/synaptics.c                |   44 ++++++++++++++++++++++++++++++++++++++
>  src/synapticsstr.h             |    6 +++++
>  5 files changed, 130 insertions(+), 1 deletions(-)
> 
> diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h
> index 77a1806..3e54fbb 100644
> --- a/include/synaptics-properties.h
> +++ b/include/synaptics-properties.h
> @@ -158,4 +158,16 @@
>  /* 32 Bit Integer, 2 values, horizontal hysteresis, vertical hysteresis */
>  #define SYNAPTICS_PROP_NOISE_CANCELLATION "Synaptics Noise Cancellation"
>  
> +/* FLOAT */
> +#define SYNAPTICS_PROP_MAX_DISTANCE "Synaptics Max Distance"
> +
> +/* FLOAT */
> +#define SYNAPTICS_PROP_MAX_JERK "Synaptics Max Jerk"
> +
> +/* FLOAT */
> +#define SYNAPTICS_PROP_MAX_ACCEL "Synaptics Max Accel"
> +
> +/* FLOAT */
> +#define SYNAPTICS_PROP_MAX_ERROR "Synaptics Max Error"

any reason these 4 couldn't be accumulated? they are related enough to
justify it, imo.

"Synaptics Acceleration Filters" or something more appropriate

> +
>  #endif /* _SYNAPTICS_PROPERTIES_H_ */
> diff --git a/man/synaptics.man b/man/synaptics.man
> index cb5f4c6..5b365e6 100644
> --- a/man/synaptics.man
> +++ b/man/synaptics.man
> @@ -510,6 +510,29 @@ AreaBottomEdge option to any integer value other than zero. If supported by the
>  server (version 1.9 and later), the edge may be specified in percent of
>  the total height of the touchpad. Property: "Synaptics Area"
>  .
> +.TP
> +.BI "Option \*qMaxAccel\*q \*q" integer \*q
> +If acceleration increases beyond the specified value, ignore the packet that
> +provoked it, assuming that it is erroneous. Property: "Synaptics Max Accel"
> +.
> +.TP
> +.BI "Option \*qMaxDistance\*q \*q" integer \*q
> +Ignore any single packet containing movement greater than the specified value
> +in pixels, assuming that it is erroneous. Property: "Synaptics Max Distance"
> +.
> +.TP
> +.BI "Option \*qMaxError\*q \*q" integer \*q
> +Ignore any single packet containing movement where the error from a best-fit
> +line determining the expected pointer position from historical values is larger
> +than the specified value, assuming that it is erroneous.
> +Property: "Synaptics Max Error"
> +.
> +.TP
> +.BI "Option \*qMaxJerk\*q \*q" integer \*q
> +If the derivative of acceleration increases beyond the specified value, ignore
> +the packet that provoked it, assuming that it is erroneous.
> +Property: "Synaptics Max Jerk"
> +.
>  
>  .SH CONFIGURATION DETAILS
>  .SS Area handling
> diff --git a/src/properties.c b/src/properties.c
> index 8370c0b..ad4c026 100644
> --- a/src/properties.c
> +++ b/src/properties.c
> @@ -94,6 +94,10 @@ Atom prop_area                  = 0;
>  Atom prop_noise_cancellation    = 0;
>  Atom prop_product_id            = 0;
>  Atom prop_device_node           = 0;
> +Atom prop_max_distance          = 0;
> +Atom prop_max_jerk              = 0;
> +Atom prop_max_accel             = 0;
> +Atom prop_max_error             = 0;
>  
>  static Atom
>  InitAtom(DeviceIntPtr dev, char *name, int format, int nvalues, int *values)
> @@ -313,6 +317,17 @@ InitDeviceProperties(InputInfoPtr pInfo)
>          XISetDevicePropertyDeletable(pInfo->dev, prop_device_node, FALSE);
>      }
>  
> +    fvalues[0] = para->max_distance;
> +    prop_max_distance = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_MAX_DISTANCE, 1, fvalues);
> +
> +    fvalues[0] = para->max_jerk;
> +    prop_max_jerk = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_MAX_JERK, 1, fvalues);
> +
> +    fvalues[0] = para->max_accel;
> +    prop_max_accel = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_MAX_ACCEL, 1, fvalues);
> +
> +    fvalues[0] = para->max_error;
> +    prop_max_error = InitFloatAtom(pInfo->dev, SYNAPTICS_PROP_MAX_ERROR, 1, fvalues);
>  }
>  
>  int
> @@ -694,8 +709,37 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
>              return BadValue;
>          para->hyst_x = hyst[0];
>          para->hyst_y = hyst[1];
> -    } else if (property == prop_product_id || property == prop_device_node)
> +    } else if (property == prop_product_id || property == prop_device_node) {
>          return BadValue; /* read-only */
> +    } else if (property == prop_max_distance) {
> +        float max_distance;
> +        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
> +            return BadMatch;
> +
> +        max_distance = *(float*)prop->data;
> +        para->max_distance = max_distance;
> +    } else if (property == prop_max_jerk) {
> +        float max_jerk;
> +        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
> +            return BadMatch;
> +
> +        max_jerk = *(float*)prop->data;
> +        para->max_jerk = max_jerk;
> +    } else if (property == prop_max_accel) {
> +        float max_accel;
> +        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
> +            return BadMatch;
> +
> +        max_accel = *(float*)prop->data;
> +        para->max_accel = max_accel;
> +    } else if (property == prop_max_error) {
> +        float max_error;
> +        if (prop->size != 1 || prop->format != 32 || prop->type != float_type)
> +            return BadMatch;
> +
> +        max_error = *(float*)prop->data;
> +        para->max_error = max_error;
> +    }
>  
>      return Success;
>  }
> diff --git a/src/synaptics.c b/src/synaptics.c
> index 560f166..4c408d9 100644
> --- a/src/synaptics.c
> +++ b/src/synaptics.c
> @@ -573,6 +573,11 @@ static void set_default_parameters(InputInfoPtr pInfo)
>      pars->resolution_horiz = xf86SetIntOption(opts, "HorizResolution", horizResolution);
>      pars->resolution_vert = xf86SetIntOption(opts, "VertResolution", vertResolution);
>  
> +    pars->max_jerk = xf86SetRealOption(opts, "MaxJerk", 0.0);
> +    pars->max_distance = xf86SetRealOption(opts, "MaxDistance", 0.0);
> +    pars->max_accel = xf86SetRealOption(opts, "MaxAccel", 0.0);
> +    pars->max_error = xf86SetRealOption(opts, "MaxError", 0.0);
> +
>      /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
>      if (pars->top_edge > pars->bottom_edge) {
>  	int tmp = pars->top_edge;
> @@ -1801,6 +1806,33 @@ static void regress(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
>      double yb1n = 0, xb1n = 0, b1d = 0, xb1, yb1;
>      double dista, distb, distc, vela, velb, velc, acca, accb, jerk;
>  
> +    if (pars->max_distance &&
for consistency with the checks a few lines below, this should state > 0 as well

> +        hypot(hw->x - HIST(0).x, hw->y - HIST(0).y) > pars->max_distance)
> +        goto filtered;
> +
> +    if (pars->max_accel > 0 || pars->max_jerk > 0) {
> +        if (priv->count_packet_finger < 3) {
> +            *dx = 0;
> +            *dy = 0;
> +            return;
> +        }
> +

for the poor buggers that may have to debug this one day, a comment on
what's actually done here would be awesome. I've spent too much time on
wikipedia's math sites lately, trying to figure out what a piece of code was
supposed to do.

Cheers,
  Peter

> +        dista = hypot(HIST(0).x - hw->x, HIST(0).y - hw->y);
> +        distb = hypot(HIST_DELTA(1, 0, x), HIST_DELTA(1, 0, y));
> +        distc = hypot(HIST_DELTA(2, 1, x), HIST_DELTA(2, 1, y));
> +        vela = dista / (HIST(0).millis - hw->millis);
> +        velb = distb / HIST_DELTA(1, 0, millis);
> +        velc = distc / HIST_DELTA(2, 1, millis);
> +        acca = (vela - velb) / (HIST(1).millis - hw->millis);
> +        if (pars->max_accel > 0 && fabs(acca) > pars->max_accel)
> +            goto filtered;
> +
> +        accb = (velc - velb) / HIST_DELTA(2, 0, millis);
> +        jerk = (acca - accb) / (HIST(2).millis - hw->millis);
> +        if (pars->max_jerk > 0 && fabs(jerk) > pars->max_jerk)
> +            goto filtered;
> +    }
> +
>      if (priv->count_packet_finger == 1) {
>          *dx = hw->x - HIST(0).x;
>          *dy = hw->y - HIST(0).y;
> @@ -1826,6 +1858,18 @@ static void regress(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
>      xb1 = xb1n/b1d;
>      yb1 = yb1n/b1d;
>  
> +    if (pars->max_error > 0) {
> +        double X, Y, e, xb0, yb0;
> +
> +        xb0 = xm - xb1*tm;
> +        yb0 = ym - yb1*tm;
> +        X = xb1*(hw->millis - HIST(0).millis) + xb0;
> +        Y = yb1*(hw->millis - HIST(0).millis) + yb0;
> +        e = hypot(hw->x - X, hw->y - Y);
> +        if (e > pars->max_error)
> +            goto filtered;
> +    }
> +
>      *dx = xb1 * (hw->millis - start_time);
>      *dy = yb1 * (hw->millis - start_time);
>      return;
> diff --git a/src/synapticsstr.h b/src/synapticsstr.h
> index a496212..73893cf 100644
> --- a/src/synapticsstr.h
> +++ b/src/synapticsstr.h
> @@ -163,6 +163,12 @@ typedef struct _SynapticsParameters
>      Bool tap_and_drag_gesture;		    /* Switches the tap-and-drag gesture on/off */
>      unsigned int resolution_horiz;          /* horizontal resolution of touchpad in units/mm */
>      unsigned int resolution_vert;           /* vertical resolution of touchpad in units/mm */
> +
> +    double max_distance;                    /* maximum distance in a single report for valid input */
> +    double max_jerk;                        /* maximum jerk for valid input */
> +    double max_accel;                       /* maximum acceleration for valid input */
> +    double max_error;                       /* maximum deviation from estimated position for valid input */
> +
>      int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */
>      int hyst_x, hyst_y;                     /* x and y width of hysteresis box */
>  } SynapticsParameters;
> -- 
> 1.7.5.3
> 
> _______________________________________________
> 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