diff --git a/src/synaptics.c b/src/synaptics.c index d95aa30..c6c6104 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -121,6 +121,9 @@ static void ReadDevDimensions(LocalDevicePtr); static void ScaleCoordinates(SynapticsPrivate *priv, struct SynapticsHwState *hw); static void CalculateScalingCoeffs(SynapticsPrivate *priv); +int oldTimeMillis =0; +Bool wasTimeSkipped = FALSE; + #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3 void InitDeviceProperties(LocalDevicePtr local); int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, @@ -1577,11 +1580,12 @@ HandleTapProcessing(SynapticsPrivate *priv, struct SynapticsHwState *hw, #define HIST(a) (priv->move_hist[((priv->hist_index - (a) + SYNAPTICS_MOVE_HISTORY) % SYNAPTICS_MOVE_HISTORY)]) static void -store_history(SynapticsPrivate *priv, int x, int y, unsigned int millis) +store_history(SynapticsPrivate *priv, int x, int y, int num_fingers, unsigned int millis) { int idx = (priv->hist_index + 1) % SYNAPTICS_MOVE_HISTORY; priv->move_hist[idx].x = x; priv->move_hist[idx].y = y; + priv->move_hist[idx].num_fingers = num_fingers; priv->move_hist[idx].millis = millis; priv->hist_index = idx; } @@ -1730,11 +1734,72 @@ ComputeDeltas(SynapticsPrivate *priv, struct SynapticsHwState *hw, dy += hw->guest_dy; } + /* Quirks for Synaptics touchpads */ + if ((dx || dy) && (priv->model == MODEL_SYNAPTICS)) { + /* Work around issues caused by two fingers on Synaptics + * models which can detect two or more fingers + */ + if (priv->has_double) { + if ((hw->numFingers < 2) && + ((HIST(0).num_fingers >= 2) || (HIST(1).num_fingers >= 2) || + (HIST(2).num_fingers >= 2) || (HIST(3).num_fingers >= 2) )) { + xf86Msg(X_INFO, "Ignoring touchpad deltas because previous fingers were: 0=%d, 1=%d, 2=%d, 3=%d\n", + HIST(0).num_fingers, HIST(1).num_fingers, HIST(2).num_fingers, HIST(3).num_fingers); + dx = dy = 0; + } + oldTimeMillis = hw->millis; + } + /* Work around issues caused by two fingers on Synaptics + * models which cannot detect two or more fingers + */ + else { + int oldMillis = priv->move_hist[priv->hist_index].millis; + int oldX = priv->move_hist[priv->hist_index].x; + int oldY = priv->move_hist[priv->hist_index].y; + int elapsed_time = hw->millis - oldMillis; + int dX = abs(abs(hw->x) - abs(oldX)); + int dY = abs(abs(hw->y) - abs(oldY)); + double threshold = 90.0; + + /* Ignore deltas as they couldn't possibly happen in so little time */ + if (elapsed_time <= 20 && (abs(dx) >= threshold || abs(dy) >= threshold)) { + dx = 0.0; + dy = 0.0; + wasTimeSkipped = FALSE; + } + /* A comparison between the timestamp in priv->move_hist and hw->millis shows + * that something went wrong and that an event was skipped, hence these + * deltas are wrong. + * Let's ignore the deltas and set wasTimeSkipped to TRUE as the next deltas + * will be wrong too. + */ + else if (oldTimeMillis > 0 && (oldMillis != oldTimeMillis)) { + dx = 0.0; + dy = 0.0; + wasTimeSkipped = TRUE; + } + /* Something went wrong and an event was previously skipped, hence these deltas + * are wrong. + * Let's ignore the deltas and set wasTimeSkipped to FALSE as the next deltas + * should be good. + */ + else { + if (wasTimeSkipped) { + dx = 0.0; + dy = 0.0; + } + wasTimeSkipped = FALSE; + } + oldTimeMillis = hw->millis; + } + + } + *dxP = dx; *dyP = dy; /* generate a history of the absolute positions */ - store_history(priv, hw->x, hw->y, hw->millis); + store_history(priv, hw->x, hw->y, hw->numFingers, hw->millis); return delay; } diff --git a/src/synapticsstr.h b/src/synapticsstr.h index 8348e72..0db97f7 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -33,6 +33,7 @@ typedef struct _SynapticsMoveHist { int x, y; + int num_fingers; int millis; } SynapticsMoveHistRec;