[PATCH v3 16/23] Revise palm check logic

Daniel Stone daniel at fooishbar.org
Thu Jun 23 15:12:51 PDT 2011


From: Derek Foreman <derek.foreman at collabora.co.uk>

Make the palm-check logic more stable and reliable, and make sure that
any palms are blocked for the duration of their presses.

Signed-off-by: Derek Foreman <derek.foreman at collabora.co.uk>
Reviewed-by: Daniel Stone <daniel at fooishbar.org>
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/synaptics.c    |   54 +++++++++++++++++++++++++++------------------------
 src/synapticsstr.h |    3 +-
 2 files changed, 30 insertions(+), 27 deletions(-)

v3: Only trigger on sufficient width and pressure, not just either.

diff --git a/src/synaptics.c b/src/synaptics.c
index 0ce8024..0b15056 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -1358,12 +1358,16 @@ SynapticsDetectFinger(SynapticsPrivate *priv, struct SynapticsHwState *hw)
     enum FingerState finger;
 
     /* finger detection thru pressure and threshold */
+    if (hw->z < para->finger_low)
+        return FS_UNTOUCHED;
+
+    if (priv->finger_state == FS_BLOCKED)
+        return FS_BLOCKED;
+
     if (hw->z > para->finger_press && priv->finger_state < FS_PRESSED)
         finger = FS_PRESSED;
-    else if (hw->z > para->finger_high && priv->finger_state < FS_TOUCHED)
+    else if (hw->z > para->finger_high && priv->finger_state == FS_UNTOUCHED)
         finger = FS_TOUCHED;
-    else if (hw->z < para->finger_low &&  priv->finger_state > FS_UNTOUCHED)
-        finger = FS_UNTOUCHED;
     else
 	finger = priv->finger_state;
 
@@ -1371,17 +1375,16 @@ SynapticsDetectFinger(SynapticsPrivate *priv, struct SynapticsHwState *hw)
 	return finger;
 
     /* palm detection */
-    if (finger) {
-	if ((hw->z > para->palm_min_z) && (hw->fingerWidth > para->palm_min_width))
-	    priv->palm = TRUE;
-    } else {
-	priv->palm = FALSE;
-    }
-    if (hw->x == 0)
+
+    if ((hw->z > para->palm_min_z) && (hw->fingerWidth > para->palm_min_width))
+        return FS_BLOCKED;
+
+    if (hw->x == 0 || priv->finger_state == FS_UNTOUCHED)
 	priv->avg_width = 0;
     else
 	priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2;
-    if (finger && !priv->finger_state) {
+
+    if (finger != FS_UNTOUCHED && priv->finger_state == FS_UNTOUCHED) {
 	int safe_width = MAX(hw->fingerWidth, priv->avg_width);
 
 	if (hw->numFingers > 1 ||	/* more than one finger -> not a palm */
@@ -1398,9 +1401,6 @@ SynapticsDetectFinger(SynapticsPrivate *priv, struct SynapticsHwState *hw)
     }
     priv->prev_z = hw->z;
 
-    if (priv->palm)
-	finger = FS_UNTOUCHED;
-
     return finger;
 }
 
@@ -1542,12 +1542,12 @@ HandleTapProcessing(SynapticsPrivate *priv, struct SynapticsHwState *hw,
     edge_type edge;
     int delay = 1000000000;
 
-    if (priv->palm)
+    if (priv->finger_state == FS_BLOCKED)
 	return delay;
 
-    touch = finger && !priv->finger_state;
-    release = !finger && priv->finger_state;
-    move = (finger &&
+    touch = finger >= FS_TOUCHED && priv->finger_state == FS_UNTOUCHED;
+    release = finger == FS_UNTOUCHED && priv->finger_state >= FS_TOUCHED;
+    move = (finger >= FS_TOUCHED &&
 	     (priv->tap_max_fingers <= ((priv->horiz_scroll_twofinger_on || priv->vert_scroll_twofinger_on)? 2 : 1)) &&
 	     ((abs(hw->x - priv->touch_on.x) >= para->tap_move) ||
 	     (abs(hw->y - priv->touch_on.y) >= para->tap_move)));
@@ -1984,7 +1984,7 @@ ComputeDeltas(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
 	}
     }
 
-    if (!inside_area || !moving_state || priv->palm ||
+    if (!inside_area || !moving_state || priv->finger_state == FS_BLOCKED ||
 	priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
 	priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
 	priv->circ_scroll_on || priv->prevFingers != hw->numFingers)
@@ -2107,7 +2107,7 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 
     sd->left = sd->right = sd->up = sd->down = 0;
 
-    if (priv->synpara.touchpad_off == 2) {
+    if ((priv->synpara.touchpad_off == 2) || (priv->finger_state == FS_BLOCKED)) {
 	stop_coasting(priv);
 	priv->circ_scroll_on = FALSE;
 	priv->vert_scroll_edge_on = FALSE;
@@ -2118,7 +2118,7 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
     }
 
     /* scroll detection */
-    if (finger && !priv->finger_state) {
+    if (finger && priv->finger_state == FS_UNTOUCHED) {
 	stop_coasting(priv);
 	if (para->circular_scrolling) {
 	    if ((para->circular_trigger == 0 && edge) ||
@@ -2156,7 +2156,7 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 		}
 	    }
 	}
-	if (finger && !priv->finger_state) {
+	if (finger && priv->finger_state == FS_UNTOUCHED) {
 	    if (!priv->vert_scroll_twofinger_on && !priv->horiz_scroll_twofinger_on) {
 		if ((para->scroll_edge_vert) && (para->scroll_dist_vert != 0) &&
 		    (edge & RIGHT_EDGE)) {
@@ -2589,7 +2589,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now,
 {
     SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
     SynapticsParameters *para = &priv->synpara;
-    int finger;
+    enum FingerState finger;
     int dx, dy, buttons, id;
     edge_type edge = NO_EDGE;
     int change;
@@ -2643,7 +2643,10 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now,
     /* no edge or finger detection outside of area */
     if (inside_active_area) {
 	edge = edge_detection(priv, hw->x, hw->y);
-	finger = SynapticsDetectFinger(priv, hw);
+	if (!from_timer)
+	    finger = SynapticsDetectFinger(priv, hw);
+	else
+	    finger = priv->finger_state;
     }
 
     /* tap and drag detection. Needs to be performed even if the finger is in
@@ -2655,7 +2658,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now,
     if (inside_active_area)
     {
 	/* Don't bother about scrolling in the dead area of the touchpad. */
-	timeleft = HandleScrolling(priv, hw, edge, finger, &scroll);
+	timeleft = HandleScrolling(priv, hw, edge, (finger >= FS_TOUCHED),
+				   &scroll);
 	if (timeleft > 0)
 	    delay = MIN(delay, timeleft);
 
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
index 67ca27b..596ea54 100644
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -52,6 +52,7 @@ typedef struct _SynapticsMoveHist
 } SynapticsMoveHistRec;
 
 enum FingerState {              /* Note! The order matters. Compared with < operator. */
+    FS_BLOCKED = -1,
     FS_UNTOUCHED = 0, /* this is 0 so it's the initialized value. */
     FS_TOUCHED = 1,
     FS_PRESSED = 2,
@@ -233,8 +234,6 @@ typedef struct _SynapticsPrivateRec
     int repeatButtons;			/* buttons for repeat */
     int nextRepeat;			/* Time when to trigger next auto repeat event */
     int lastButtons;			/* last state of the buttons */
-    int palm;				/* Set to true when palm detected, reset to false when
-					   palm/finger contact disappears */
     int prev_z;				/* previous z value, for palm detection */
     int prevFingers;			/* previous numFingers, for transition detection */
     int avg_width;			/* weighted average of previous fingerWidth values */
-- 
1.7.5.4



More information about the xorg-devel mailing list