diff --git a/src/eventcomm.c b/src/eventcomm.c index ae853f2..8738c3c 100644 --- a/src/eventcomm.c +++ b/src/eventcomm.c @@ -162,7 +162,10 @@ event_query_info(LocalDevicePtr local) for(model_lookup = model_lookup_table; model_lookup->vendor; model_lookup++) { if(model_lookup->vendor == id[ID_VENDOR] && (model_lookup->product == id[ID_PRODUCT] || model_lookup->product == PRODUCT_ANY)) + { priv->model = model_lookup->model; + priv->model_version = id[ID_VERSION]; + } } } diff --git a/src/synaptics.c b/src/synaptics.c index dc833c5..65c1477 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 old_time_millis = 0; +Bool was_time_skipped = FALSE; + #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3 void InitDeviceProperties(LocalDevicePtr local); int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, @@ -1609,11 +1612,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; } @@ -1762,11 +1766,77 @@ 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) )) { + dx = dy = 0; + } + old_time_millis = hw->millis; + } + /* Work around issues caused by two fingers on Synaptics + * models which cannot detect two or more fingers + */ + else { + int threshold; + switch (priv->model_version) { + case 0x01b1:/* Dell Mini 10v, Hp Mini 1000 MI */ + threshold = 90; + break; + case 0x23b3:/* Unknown project */ + threshold = 50; + break; + default: + goto post_quirks; + + } + + int elapsed_time = hw->millis - HIST(0).millis; + + /* Ignore deltas as they couldn't possibly happen in so little time */ + if (elapsed_time <= 20 && (abs(dx) >= threshold || abs(dy) >= threshold)) { + dx = dy = 0.0; + was_time_skipped = 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 the deltas + * are wrong. + * Let's ignore the deltas and append the skipped event to priv->move_hist + * otherwise the next deltas will be wrong too. + */ + else if (old_time_millis > 0 && (HIST(0).millis != old_time_millis)) { + dx = dy = 0.0; + was_time_skipped = TRUE; + } + /* Something went wrong and an event was previously skipped, hence these deltas + * are wrong. + * Let's ignore the deltas and set was_time_skipped to FALSE as the next deltas + * should be good. + */ + else { + if (was_time_skipped) { + dx = 0.0; + dy = 0.0; + } + was_time_skipped = FALSE; + } + + old_time_millis = hw->millis; + } + + } +post_quirks: + *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 f2bf7d4..f64f55e 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; @@ -241,6 +242,7 @@ typedef struct _SynapticsPrivateRec Bool has_pressure; /* device reports pressure */ enum TouchpadModel model; /* The detected model */ + short model_version; /* The version reported by ID_VERSION */ /* edges_forces is set to RIGHT_EDGE | LEFT_EDGE | ... when the matching * edge is specified in the xorg.conf. When the edges are auto-adjusted,