[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