[PATCH 14/18] Add gesture-mode notification via input properties

Takashi Iwai tiwai at suse.de
Fri Oct 8 10:22:38 PDT 2010


Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 include/synaptics-properties.h |    6 +++
 src/properties.c               |   33 +++++++++++++++++++
 src/synaptics.c                |   68 +++++++++++++++++++++++++++++++++-------
 src/synapticsstr.h             |   11 ++++++
 tools/synclient.c              |    1 +
 5 files changed, 107 insertions(+), 12 deletions(-)

diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h
index 7112bc0..5d440be 100644
--- a/include/synaptics-properties.h
+++ b/include/synaptics-properties.h
@@ -173,4 +173,10 @@
 /* 32 bit, 2 values, start, delta (0 disable) */
 #define SYNAPTICS_PROP_MULTI_TOUCH_PINCH "Synaptics Multi-Touch Pinch"
 
+/* 8 bit (BOOL) */
+#define SYNAPTICS_PROP_GESTURE_MODE_NOTIFY "Gesture Mode Notify"
+
+/* 32bit, read-only */
+#define SYNAPTICS_PROP_GESTURE_MODE "Current Gesture Mode"
+
 #endif /* _SYNAPTICS_PROPERTIES_H_ */
diff --git a/src/properties.c b/src/properties.c
index 0f679dd..7788a13 100644
--- a/src/properties.c
+++ b/src/properties.c
@@ -88,6 +88,8 @@ Atom prop_led                   = 0;
 Atom prop_led_status            = 0;
 Atom prop_led_double_tap        = 0;
 Atom prop_multi_touch_pinch     = 0;
+Atom prop_gesture_mode_notify   = 0;
+Atom prop_gesture_mode          = 0;
 
 static Atom
 InitAtom(DeviceIntPtr dev, char *name, int format, int nvalues, int *values)
@@ -296,6 +298,11 @@ InitDeviceProperties(InputInfoPtr pInfo)
     values[0] =  para->multi_touch_pinch_start;
     values[1] =  para->multi_touch_pinch_dist;
     prop_multi_touch_pinch = InitAtom(local->dev, SYNAPTICS_PROP_MULTI_TOUCH_PINCH, 32, 2, values);
+
+    prop_gesture_mode_notify = InitAtom(local->dev, SYNAPTICS_PROP_GESTURE_MODE_NOTIFY, 8, 1, &para->gesture_mode_notify);
+
+    values[0] = 0;
+    prop_gesture_mode = InitAtom(local->dev, SYNAPTICS_PROP_GESTURE_MODE, 32, 1, values);
 }
 
 int
@@ -542,7 +549,13 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
         dist = (INT32*)prop->data;
 	para->multi_touch_pinch_start = dist[0];
 	para->multi_touch_pinch_dist = dist[1];
+    } else if (property == prop_gesture_mode_notify)
+    {
+        INT32 *dist;
+        if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
+            return BadMatch;
 
+        para->gesture_mode_notify = *(CARD8*)prop->data;
     } else if (property == prop_gestures)
     {
         BOOL *gestures;
@@ -724,3 +737,23 @@ void SynapticsToggleOffProperty(DeviceIntPtr dev, Bool off)
         XIChangeDeviceProperty(dev, prop_off, XA_INTEGER, 8,
                                PropModeReplace, 1, &val, FALSE);
 }
+
+void SynapticsSetGestureModeProperty(DeviceIntPtr dev, int mode)
+{
+    LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+    SynapticsPrivate *priv = (SynapticsPrivate *) local->private;
+    SynapticsParameters *para = &priv->synpara;
+    static int gesture_mode_vals[] = {
+	[GESTURE_NONE] = 0,
+	[GESTURE_PINCH] = 10,
+	[GESTURE_HSCROLL] = 11,
+	[GESTURE_VSCROLL] = 12,
+	[GESTURE_CIRCULAR] = 13,
+    };
+
+    if (!prop_gesture_mode || !para->gesture_mode_notify)
+	    return;
+    mode = gesture_mode_vals[mode];
+    XIChangeDeviceProperty(dev, prop_gesture_mode, XA_INTEGER, 32,
+			   PropModeReplace, 1, &mode, TRUE);
+}
diff --git a/src/synaptics.c b/src/synaptics.c
index 5ec853a..2f264f0 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -143,6 +143,7 @@ void InitDeviceProperties(InputInfoPtr pInfo);
 int SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
                 BOOL checkonly);
 void SynapticsToggleOffProperty(DeviceIntPtr dev, Bool off);
+void SynapticsSetGestureModeProperty(DeviceIntPtr dev, int val);
 
 InputDriverRec SYNAPTICS = {
     1,
@@ -608,6 +609,7 @@ static void set_default_parameters(InputInfoPtr pInfo)
     pars->led_double_tap = xf86SetBoolOption(opts, "LEDDoubleTap", TRUE);
     pars->multi_touch_pinch_start = xf86SetIntOption(opts, "MultiTouchPinchStart", pinchStart);
     pars->multi_touch_pinch_dist = xf86SetIntOption(opts, "MultiTouchPinchDelta", pinchDelta);
+    pars->gesture_mode_notify = xf86SetBoolOption(opts, "GestureModeNotify", TRUE);
 
     /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
     if (pars->top_edge > pars->bottom_edge) {
@@ -1191,7 +1193,7 @@ handle_toggle_led(LocalDevicePtr local, struct SynapticsHwState *hw, int finger)
             para->touchpad_off = !para->touchpad_off;
             if (priv->proto_ops && priv->proto_ops->UpdateLED)
                 priv->proto_ops->UpdateLED(local);
-	    priv->prop_change_pending = 1;
+	    priv->prop_change_pending |= 1;
             priv->led_tapped = FALSE;
         }
     } else
@@ -1322,6 +1324,7 @@ handle_clickpad(LocalDevicePtr local, struct SynapticsHwState *hw)
 	    if (in_multi_button)
 		get_clickpad_button(priv, hw, hw->multi_touch_x);
 	    priv->multi_touch_mode = MULTI_TOUCH_MODE_DRAG;
+	    priv->gesture_mode = GESTURE_NONE;
 	}
     } else {
 	/* button being released, reset dragging if necessary */
@@ -1489,10 +1492,11 @@ timerFunc(OsTimerPtr timer, CARD32 now, pointer arg)
     delay = HandleState(pInfo, &hw);
 
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
-    if (priv->prop_change_pending & 1) {
+    if (priv->prop_change_pending & 1)
 	SynapticsToggleOffProperty(local->dev, para->touchpad_off);
-	priv->prop_change_pending = 0;
-    }
+    if (priv->prop_change_pending & 2)
+	SynapticsSetGestureModeProperty(local->dev, priv->gesture_mode);
+    priv->prop_change_pending = 0;
 #endif
 
     /*
@@ -2173,6 +2177,44 @@ multi_touch_distance(struct SynapticsHwState *hw)
     return sqrt(SQR(hw->x - hw->multi_touch_x) + SQR(hw->y - hw->multi_touch_y));
 }
 
+static void
+update_scroll_gesture_mode(SynapticsPrivate *priv, struct ScrollData *sd)
+{
+    switch (priv->gesture_mode) {
+    case GESTURE_CIRCULAR:
+	if (!priv->circ_scroll_on)
+	    priv->gesture_mode = GESTURE_NONE;
+	break;
+    case GESTURE_HSCROLL:
+	if (!(priv->horiz_scroll_edge_on || priv->horiz_scroll_twofinger_on))
+	    priv->gesture_mode = GESTURE_NONE;
+	break;
+    case GESTURE_VSCROLL:
+	if (!(priv->vert_scroll_edge_on || priv->vert_scroll_twofinger_on))
+	    priv->gesture_mode = GESTURE_NONE;
+	break;
+    default:
+	break;
+    }
+    if (priv->circ_scroll_on) {
+	if (sd->left || sd->right || sd->up || sd->down)
+	    priv->gesture_mode = GESTURE_CIRCULAR;
+    } else {
+	if ((priv->horiz_scroll_edge_on || priv->horiz_scroll_twofinger_on) &&
+	    (sd->left || sd->right)) {
+	    if (priv->multi_touch_mode == MULTI_TOUCH_MODE_START)
+		priv->multi_touch_mode = MULTI_TOUCH_MODE_SCROLL;
+	    priv->gesture_mode = GESTURE_HSCROLL;
+	}
+	if ((priv->vert_scroll_edge_on || priv->vert_scroll_twofinger_on) &&
+	    (sd->down || sd->up)) {
+	    if (priv->multi_touch_mode == MULTI_TOUCH_MODE_START)
+		priv->multi_touch_mode = MULTI_TOUCH_MODE_SCROLL;
+	    priv->gesture_mode = GESTURE_VSCROLL;
+	}
+    }
+}
+
 static int
 HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 		edge_type edge, Bool finger, struct ScrollData *sd)
@@ -2189,6 +2231,7 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 	priv->horiz_scroll_edge_on = FALSE;
 	priv->vert_scroll_twofinger_on = FALSE;
 	priv->horiz_scroll_twofinger_on = FALSE;
+	priv->gesture_mode = GESTURE_NONE;
 	return delay;
     }
 
@@ -2354,14 +2397,10 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 	    while (hw->y - priv->scroll_y > delta) {
 		sd->down++;
 		priv->scroll_y += delta;
-		if (priv->multi_touch_mode == MULTI_TOUCH_MODE_START)
-		    priv->multi_touch_mode = MULTI_TOUCH_MODE_SCROLL;
 	    }
 	    while (hw->y - priv->scroll_y < -delta) {
 		sd->up++;
 		priv->scroll_y -= delta;
-		if (priv->multi_touch_mode == MULTI_TOUCH_MODE_START)
-		    priv->multi_touch_mode = MULTI_TOUCH_MODE_SCROLL;
 	    }
 	}
     }
@@ -2372,14 +2411,10 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 	    while (hw->x - priv->scroll_x > delta) {
 		sd->right++;
 		priv->scroll_x += delta;
-		if (priv->multi_touch_mode == MULTI_TOUCH_MODE_START)
-		    priv->multi_touch_mode = MULTI_TOUCH_MODE_SCROLL;
 	    }
 	    while (hw->x - priv->scroll_x < -delta) {
 		sd->left++;
 		priv->scroll_x -= delta;
-		if (priv->multi_touch_mode == MULTI_TOUCH_MODE_START)
-		    priv->multi_touch_mode = MULTI_TOUCH_MODE_SCROLL;
 	    }
 	}
     }
@@ -2450,6 +2485,8 @@ HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 	}
     }
 
+    update_scroll_gesture_mode(priv, sd);
+
     return delay;
 }
 
@@ -2481,6 +2518,7 @@ handle_multi_touch_pinch(SynapticsPrivate *priv, struct SynapticsHwState *hw,
     if (abs_diff > para->multi_touch_pinch_start) {
 	if (priv->multi_touch_mode != MULTI_TOUCH_MODE_PINCH) {
 	    priv->multi_touch_mode = MULTI_TOUCH_MODE_PINCH;
+	    priv->gesture_mode = GESTURE_PINCH;
 	    priv->vert_scroll_twofinger_on = FALSE;
 	    priv->horiz_scroll_twofinger_on = FALSE;
 	}
@@ -2801,6 +2839,9 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw)
     int timeleft;
     Bool inside_active_area;
     int zoom_in = 0, zoom_out = 0;
+    int prev_gesture_mode;
+
+    prev_gesture_mode = priv->gesture_mode;
 
     update_multi_touch(priv, hw);
 
@@ -2957,6 +2998,9 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw)
     if (inside_active_area)
 	store_history(priv, hw->x, hw->y, hw->millis);
 
+    if (prev_gesture_mode != priv->gesture_mode)
+	priv->prop_change_pending |= 2;
+
     return delay;
 }
 
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
index 31756cb..285c8f3 100644
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -167,6 +167,7 @@ typedef struct _SynapticsParameters
     Bool led_double_tap;		    /* double-tap period in ms for touchpad LED control */
     int multi_touch_pinch_start;            /* multi-touch pinch sthard threshold distance */
     int multi_touch_pinch_dist;             /* multi-touch pinch delta threshold distance */
+    Bool gesture_mode_notify;               /* Notify gesture mode via property */
 } SynapticsParameters;
 
 
@@ -180,6 +181,14 @@ enum MultiTouchMode {
     MULTI_TOUCH_MODE_SCROLL,
 };
 
+enum GestureMode {
+    GESTURE_NONE,
+    GESTURE_PINCH,
+    GESTURE_HSCROLL,
+    GESTURE_VSCROLL,
+    GESTURE_CIRCULAR
+};
+
 #define MAX_ACTIONS	4
 enum { ACTION_BUTTON = 1, ACTION_KEY, ACTION_KEYMOD };
 
@@ -272,6 +281,8 @@ typedef struct _SynapticsPrivateRec
     int multi_touch_distance;
     int prev_multi_touch_distance;
 
+    enum GestureMode gesture_mode;
+
     int zoom_in_num_actions;
     int zoom_in_action[MAX_ACTIONS];
     int zoom_out_num_actions;
diff --git a/tools/synclient.c b/tools/synclient.c
index ab737dc..68faa13 100644
--- a/tools/synclient.c
+++ b/tools/synclient.c
@@ -149,6 +149,7 @@ static struct Parameter params[] = {
     {"LEDDoubleTap",          PT_BOOL,   0, 1,     SYNAPTICS_PROP_LED_DOUBLE_TAP,	8,	0},
     {"MultiTouchPinchStart",  PT_INT,    0, 1000,  SYNAPTICS_PROP_MULTI_TOUCH_PINCH,	32,	0},
     {"MultiTouchPinchDelta",  PT_INT,    0, 4000,  SYNAPTICS_PROP_MULTI_TOUCH_PINCH,	32,	1},
+    {"GestureModeNotify",     PT_BOOL,   0, 1,     SYNAPTICS_PROP_GESTURE_MODE_NOTIFY,	8,	0},
     { NULL, 0, 0, 0, 0 }
 };
 
-- 
1.7.3.1



More information about the xorg-devel mailing list