Commit 41b2312c authored by Peter Hutterer's avatar Peter Hutterer

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's avatarPeter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: default avatarHans de Goede <hdegoede@redhat.com>
parent 049611bd
......@@ -780,6 +780,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;
......@@ -2229,6 +2246,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.
*/
......@@ -2238,6 +2262,7 @@ ComputeDeltas(SynapticsPrivate * priv, const struct SynapticsHwState *hw,
{
enum MovingState moving_state;
double dx, dy;
double vlen;
int delay = 1000000000;
dx = dy = 0;
......@@ -2283,6 +2308,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;
......
......@@ -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 {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment