From c488987daf865663a4db5953874438cda9dff8db Mon Sep 17 00:00:00 2001 Message-Id: From: Yan Li Date: Fri, 3 Dec 2010 13:57:32 +0800 Subject: [PATCH] Add new option JumpyCursorThreshold v5 This option can filter out big value changes from some models of touchpad that lead to jumpy cursor (most notably the touchpad from Lenovo S10-3t, MeeGo Bug #4807). v1-v4 written by Alberto Milone: https://bugs.freedesktop.org/show_bug.cgi?id=21614 v5: ported to latest head by Yan Li. Signed-off-by: Yan Li --- include/synaptics-properties.h | 3 ++ man/synaptics.man | 16 +++++++++ src/properties.c | 9 +++++ src/synaptics.c | 68 ++++++++++++++++++++++++++++++++++++++- src/synapticsstr.h | 2 + tools/synclient.c | 1 + 6 files changed, 97 insertions(+), 2 deletions(-) diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h index 9c6a2ee..9183853 100644 --- a/include/synaptics-properties.h +++ b/include/synaptics-properties.h @@ -155,4 +155,7 @@ /* 32 bit, 4 values, left, right, top, bottom */ #define SYNAPTICS_PROP_AREA "Synaptics Area" +/* 32 bit */ +#define SYNAPTICS_PROP_JUMPYCURSOR_THRESHOLD "Synaptics Jumpy Cursor Threshold" + #endif /* _SYNAPTICS_PROPERTIES_H_ */ diff --git a/man/synaptics.man b/man/synaptics.man index 25f1115..5756f9c 100644 --- a/man/synaptics.man +++ b/man/synaptics.man @@ -561,6 +561,14 @@ coordinates are less than MaxTapMove units apart. A "touch" event happens when the Z value goes above FingerHigh, and an "untouch" event happens when the Z value goes below FingerLow. . +.TP +.BI "Option \*qJumpyCursorThreshold\*q \*q" integer \*q +Set the threshold above which movement events are ignored on single-touch touchpads. +. +The option is disabled by default and can be enabled by setting the +JumpyCursorThreshold option to any integer value other than zero. Property: "Synaptics +Jumpy Cursor Threshold" +. .LP The MaxDoubleTapTime parameter has the same function as the MaxTapTime parameter, but for the second, third, etc tap in a tap sequence. @@ -908,6 +916,14 @@ right button, two-finger detection, three-finger detection, pressure detection, .BI "Synaptics Pad Resolution" 32 bit unsigned, 2 values (read-only), vertical, horizontal in units/millimeter. +.TP 7 +.BI "Synaptics Jumpy Cursor Threshold" +The Synaptics Jumpy Cursor Threshold parameter is used to suppress movements (which +take place in 20 milliseconds or less) whose covered distance is greater than or +equal to the threshold on single-touch touchpads. This property is disabled by default. + +32 bit, 1 value. 0 disables the property. + .SH "NOTES" There is an example hal policy file in .I ${sourcecode}/fdi/11-x11-synaptics.fdi diff --git a/src/properties.c b/src/properties.c index ee9a5a6..16e9ef2 100644 --- a/src/properties.c +++ b/src/properties.c @@ -82,6 +82,7 @@ Atom prop_gestures = 0; Atom prop_capabilities = 0; Atom prop_resolution = 0; Atom prop_area = 0; +Atom prop_jumpycursor_threshold = 0; static Atom InitAtom(DeviceIntPtr dev, char *name, int format, int nvalues, int *values) @@ -278,6 +279,8 @@ InitDeviceProperties(LocalDevicePtr local) values[2] = para->area_top_edge; values[3] = para->area_bottom_edge; prop_area = InitAtom(local->dev, SYNAPTICS_PROP_AREA, 32, 4, values); + + prop_jumpycursor_threshold = InitAtom(local->dev, SYNAPTICS_PROP_JUMPYCURSOR_THRESHOLD, 32, 1, ¶->jumpycursor_threshold); } int @@ -649,6 +652,12 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, para->area_right_edge = area[1]; para->area_top_edge = area[2]; para->area_bottom_edge = area[3]; + } else if (property == prop_jumpycursor_threshold) + { + if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER) + return BadMatch; + + para->jumpycursor_threshold = *(INT32*)prop->data; } return Success; diff --git a/src/synaptics.c b/src/synaptics.c index 2e5f8ae..e8f3ec7 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -129,6 +129,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; + void InitDeviceProperties(LocalDevicePtr local); int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, BOOL checkonly); @@ -595,6 +598,7 @@ static void set_default_parameters(LocalDevicePtr local) pars->tap_and_drag_gesture = xf86SetBoolOption(opts, "TapAndDragGesture", TRUE); pars->resolution_horiz = xf86SetIntOption(opts, "HorizResolution", horizResolution); pars->resolution_vert = xf86SetIntOption(opts, "VertResolution", vertResolution); + pars->jumpycursor_threshold = xf86SetIntOption(opts, "JumpyCursorThreshold", 0); /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */ if (pars->top_edge > pars->bottom_edge) { @@ -1685,11 +1689,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; } @@ -1809,6 +1814,65 @@ ComputeDeltas(SynapticsPrivate *priv, const struct SynapticsHwState *hw, } priv->prevFingers = hw->numFingers; + /* Handle JumpyCursor here */ + if (dx || dy) { + /* Work around issues caused by two fingers on multi-touch + * models + */ + 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 single-touch + * models + */ + else { + /* If para->jumpycursor_threshold <= 0, quirks are not + * available + */ + if (para->jumpycursor_threshold <= 0) + 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) >= para->jumpycursor_threshold || abs(dy) >= para->jumpycursor_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; @@ -2534,7 +2598,7 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState *hw) /* generate a history of the absolute positions */ if (inside_active_area) - 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 5e4090e..eb470a6 100644 --- a/src/synapticsstr.h +++ b/src/synapticsstr.h @@ -44,6 +44,7 @@ typedef struct _SynapticsMoveHist { int x, y; + int num_fingers; int millis; } SynapticsMoveHistRec; @@ -160,6 +161,7 @@ typedef struct _SynapticsParameters unsigned int resolution_horiz; /* horizontal resolution of touchpad in units/mm */ unsigned int resolution_vert; /* vertical resolution of touchpad in units/mm */ int area_left_edge, area_right_edge, area_top_edge, area_bottom_edge; /* area coordinates absolute */ + int jumpycursor_threshold; /* jumpy cursor threshold */ } SynapticsParameters; diff --git a/tools/synclient.c b/tools/synclient.c index e7be499..eab722c 100644 --- a/tools/synclient.c +++ b/tools/synclient.c @@ -143,6 +143,7 @@ static struct Parameter params[] = { {"AreaRightEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 1}, {"AreaTopEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 2}, {"AreaBottomEdge", PT_INT, 0, 10000, SYNAPTICS_PROP_AREA, 32, 3}, + {"JumpyCursorThreshold", PT_INT, 0, 1000, SYNAPTICS_PROP_JUMPYCURSOR_THRESHOLD, 32, 0}, { NULL, 0, 0, 0, 0 } }; -- 1.7.2.3