mirror of
https://github.com/X11Libre/xf86-input-synaptics.git
synced 2026-03-24 09:44:40 +00:00
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 41b2312c00)
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user