diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2014-09-16 08:52:56 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2014-12-22 08:53:06 +1000 |
commit | c3c68e3cbb04f869d075adaba5fa7fa2ef85a9d8 (patch) | |
tree | ee85728a4544a4756dc8d269e10b2d07e8a78066 | |
parent | c3df19df672754a950b66de53bcce0a1d898e7bf (diff) |
Limit the movement to 20 mm per event
Touchpads are limited by a fixed sampling rate (usually 80Hz). Some finger
changes may happen too fast for this sampling rate, resulting in two distinct
event sequences:
* finger 1 up and finger 2 down in the same EV_SYN frame. Synaptics sees one
finger down before and after and the changed coordinates
* finger 1 up and finger 2 down _between_ two EV_SYN frames. Synaptics sees one
touchpoint move from f1 position to f2 position.
That move causes a large cursor jump. The former could be solved (with
difficulty) by adding fake EV_SYN handling after releasing touchpoints but
that won't fix the latter case.
So as a solution for now limit the finger movement to 20mm per event.
Tests on a T440 and an x220 showed that this is just above what a reasonable
finger movement would trigger. If a movement is greater than that limit, reset
it to 0/0.
On devices without resolution, use 0.25 of the touchpad's diagonal instead.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
(cherry picked from commit 41b2312c006fca1f24e1a366174d3203a63fa04a)
-rw-r--r-- | src/synaptics.c | 33 | ||||
-rw-r--r-- | src/synapticsstr.h | 2 |
2 files changed, 35 insertions, 0 deletions
diff --git a/src/synaptics.c b/src/synaptics.c index e5cc927..bb10548 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -756,6 +756,23 @@ set_default_parameters(InputInfoPtr pInfo) pars->resolution_vert = 1; } + /* Touchpad sampling rate is too low to detect all movements. + A user may lift one finger and put another one down within the same + EV_SYN or even between samplings so the driver doesn't notice at all. + + We limit the movement to 20 mm within one event, that is more than + recordings showed is needed (17mm on a T440). + */ + if (pars->resolution_horiz > 1 && + pars->resolution_vert > 1) + pars->maxDeltaMM = 20; + else { + /* on devices without resolution set the vector length to 0.25 of + the touchpad diagonal */ + pars->maxDeltaMM = diag * 0.25; + } + + /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */ if (pars->top_edge > pars->bottom_edge) { int tmp = pars->top_edge; @@ -2217,6 +2234,13 @@ get_delta(SynapticsPrivate *priv, const struct SynapticsHwState *hw, *dy = integral; } +/* Vector length, but not sqrt'ed, we only need it for comparison */ +static inline double +vlenpow2(double x, double y) +{ + return x * x + y * y; +} + /** * Compute relative motion ('deltas') including edge motion. */ @@ -2226,6 +2250,7 @@ ComputeDeltas(SynapticsPrivate * priv, const struct SynapticsHwState *hw, { enum MovingState moving_state; double dx, dy; + double vlen; int delay = 1000000000; dx = dy = 0; @@ -2271,6 +2296,14 @@ ComputeDeltas(SynapticsPrivate * priv, const struct SynapticsHwState *hw, out: priv->prevFingers = hw->numFingers; + vlen = vlenpow2(dx/priv->synpara.resolution_horiz, + dy/priv->synpara.resolution_vert); + + if (vlen > priv->synpara.maxDeltaMM * priv->synpara.maxDeltaMM) { + dx = 0; + dy = 0; + } + *dxP = dx; *dyP = dy; diff --git a/src/synapticsstr.h b/src/synapticsstr.h index 4bd32ac..75f52d5 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -226,6 +226,8 @@ typedef struct _SynapticsParameters { int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */ int softbutton_areas[4][4]; /* soft button area coordinates, 0 => right, 1 => middle , 2 => secondary right, 3 => secondary middle button */ int hyst_x, hyst_y; /* x and y width of hysteresis box */ + + int maxDeltaMM; /* maximum delta movement (vector length) in mm */ } SynapticsParameters; struct _SynapticsPrivateRec { |