[PATCH 17/18] Add three-finger gesture support

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


Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 include/synaptics-properties.h |    3 +
 src/properties.c               |   15 ++++++
 src/synaptics.c                |   98 +++++++++++++++++++++++++++++++++++++++-
 src/synapticsstr.h             |   17 +++++++-
 tools/synclient.c              |    2 +
 5 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/include/synaptics-properties.h b/include/synaptics-properties.h
index f6fbfac..c31c53c 100644
--- a/include/synaptics-properties.h
+++ b/include/synaptics-properties.h
@@ -182,4 +182,7 @@
 /* 32 bit */
 #define SYNAPTICS_PROP_ORIENTATION "Synaptics Orientation"
 
+/* 32 bit, 2 values */
+#define SYNAPTICS_PROP_THREEFINGER_DELTA "Synaptics Three-Finger Delta"
+
 #endif /* _SYNAPTICS_PROPERTIES_H_ */
diff --git a/src/properties.c b/src/properties.c
index 7278560..9977b28 100644
--- a/src/properties.c
+++ b/src/properties.c
@@ -91,6 +91,7 @@ Atom prop_led_double_tap        = 0;
 Atom prop_multi_touch_pinch     = 0;
 Atom prop_gesture_mode_notify   = 0;
 Atom prop_gesture_mode          = 0;
+Atom prop_threefinger           = 0;
 
 static Atom
 InitAtom(DeviceIntPtr dev, char *name, int format, int nvalues, int *values)
@@ -306,6 +307,10 @@ InitDeviceProperties(InputInfoPtr pInfo)
 
     values[0] = 0;
     prop_gesture_mode = InitAtom(local->dev, SYNAPTICS_PROP_GESTURE_MODE, 32, 1, values);
+
+    values[0] =  para->threefinger_delta_horiz;
+    values[1] =  para->threefinger_delta_vert;
+    prop_threefinger = InitAtom(local->dev, SYNAPTICS_PROP_THREEFINGER_DELTA, 32, 2, values);
 }
 
 int
@@ -730,6 +735,15 @@ SetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
             if (priv->proto_ops && priv->proto_ops->UpdateLED)
                 priv->proto_ops->UpdateLED(local);
         }
+    } else if (property == prop_threefinger)
+    {
+        INT32 *delta;
+        if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
+            return BadMatch;
+
+        delta = (INT32*)prop->data;
+	para->threefinger_delta_horiz = delta[0];
+	para->threefinger_delta_vert = delta[1];
     }
 
     return Success;
@@ -757,6 +771,7 @@ void SynapticsSetGestureModeProperty(DeviceIntPtr dev, int mode)
 	[GESTURE_HSCROLL] = 11,
 	[GESTURE_VSCROLL] = 12,
 	[GESTURE_CIRCULAR] = 13,
+	[GESTURE_3FINGER] = 15,
     };
 
     if (!prop_gesture_mode || !para->gesture_mode_notify)
diff --git a/src/synaptics.c b/src/synaptics.c
index 71a5134..747bdb9 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -612,6 +612,9 @@ static void set_default_parameters(InputInfoPtr pInfo)
     pars->multi_touch_pinch_dist = xf86SetIntOption(opts, "MultiTouchPinchDelta", pinchDelta);
     pars->gesture_mode_notify = xf86SetBoolOption(opts, "GestureModeNotify", TRUE);
 
+    pars->threefinger_delta_horiz = xf86SetIntOption(opts, "HorizThreeFingerDelta", 750);
+    pars->threefinger_delta_vert = xf86SetIntOption(opts, "VertThreeFingerDelta", 750);
+
     /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
     if (pars->top_edge > pars->bottom_edge) {
 	int tmp = pars->top_edge;
@@ -827,6 +830,26 @@ static void setup_zoom_actions(LocalDevicePtr local)
 	action = "Control+Button5";
     priv->zoom_out_num_actions =
 	SynapticsParseActionStr(local, action, priv->zoom_out_action, MAX_ACTIONS);
+    action = xf86FindOptionValue(local->options, "ThreeFingerLeftAction");
+    if (!action)
+	action = "Alt+Left";
+    priv->threefinger_left_num_actions =
+	SynapticsParseActionStr(local, action, priv->threefinger_left_action, MAX_ACTIONS);
+    action = xf86FindOptionValue(local->options, "ThreeFingerRightAction");
+    if (!action)
+	action = "Alt+Right";
+    priv->threefinger_right_num_actions =
+	SynapticsParseActionStr(local, action, priv->threefinger_right_action, MAX_ACTIONS);
+    action = xf86FindOptionValue(local->options, "ThreeFingerUpAction");
+    if (!action)
+	action = "Control+Tab";
+    priv->threefinger_up_num_actions =
+	SynapticsParseActionStr(local, action, priv->threefinger_up_action, MAX_ACTIONS);
+    action = xf86FindOptionValue(local->options, "ThreeFingerDownAction");
+    if (!action)
+	action = "Control+Shift+Tab";
+    priv->threefinger_down_num_actions =
+	SynapticsParseActionStr(local, action, priv->threefinger_down_action, MAX_ACTIONS);
 }
 
 /*
@@ -2538,6 +2561,76 @@ handle_multi_touch_pinch(SynapticsPrivate *priv, struct SynapticsHwState *hw,
 }
 
 static void
+handle_three_finger_action(SynapticsPrivate *priv, struct SynapticsHwState *hw,
+			   int *xdelta, int *ydelta)
+{
+    SynapticsParameters *para = &priv->synpara;
+
+    *xdelta = *ydelta = 0;
+
+    if (hw->numFingers < 3)
+	return;
+
+    if (priv->multi_touch_mode != MULTI_TOUCH_MODE_3FINGER) {
+	if (priv->multi_touch_mode == MULTI_TOUCH_MODE_START ||
+	    priv->multi_touch_mode >= MULTI_TOUCH_MODE_GESTURE) {
+	    priv->multi_touch_mode = MULTI_TOUCH_MODE_3FINGER;
+	    priv->gesture_mode = GESTURE_3FINGER;
+	    priv->threefinger_x = hw->x;
+	    priv->threefinger_y = hw->y;
+	}
+	return;
+    }
+
+    if (para->threefinger_delta_horiz) {
+	int delta = hw->x - priv->threefinger_x;
+	int n = fabs(delta) / para->threefinger_delta_horiz;
+	if (n > 0) {
+	    if (delta < 0) {
+		priv->threefinger_x -= para->threefinger_delta_horiz * n;
+		*xdelta = -1;
+	    } else {
+		priv->threefinger_x += para->threefinger_delta_horiz * n;
+		*xdelta = 1;
+	    }
+	}
+    }
+    if (para->threefinger_delta_vert) {
+	int delta = hw->y - priv->threefinger_y;
+	int n = fabs(delta) / para->threefinger_delta_vert;
+	if (n > 0) {
+	    if (delta < 0) {
+		priv->threefinger_y -= para->threefinger_delta_vert * n;
+		*ydelta = -1;
+	    } else {
+		priv->threefinger_y += para->threefinger_delta_vert * n;
+		*ydelta = 1;
+	    }
+	}
+    }
+}
+
+static void send_threefinger_event(LocalDevicePtr local, int xd, int yd)
+{
+    SynapticsPrivate *priv = (SynapticsPrivate *) (local->private);
+
+    if (xd < 0) {
+	SynapticsSendAction(local, priv->threefinger_left_num_actions,
+			    priv->threefinger_left_action);
+    } else if (xd > 0) {
+	SynapticsSendAction(local, priv->threefinger_right_num_actions,
+			    priv->threefinger_right_action);
+    }
+    if (yd < 0) {
+	SynapticsSendAction(local, priv->threefinger_up_num_actions,
+			    priv->threefinger_up_action);
+    } else if (yd > 0) {
+	SynapticsSendAction(local, priv->threefinger_down_num_actions,
+			    priv->threefinger_down_action);
+    }
+}
+
+static void
 handle_clickfinger(SynapticsParameters *para, struct SynapticsHwState *hw)
 {
     int action = 0;
@@ -2873,6 +2966,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw)
     Bool inside_active_area;
     int zoom_in = 0, zoom_out = 0;
     int prev_gesture_mode;
+    int threefinger_xd = 0, threefinger_yd = 0;
 
     prev_gesture_mode = priv->gesture_mode;
 
@@ -2943,6 +3037,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw)
 
 	handle_multi_touch_pinch(priv, hw, &zoom_in, &zoom_out);
 
+	handle_three_finger_action(priv, hw, &threefinger_xd, &threefinger_yd);
+
 	/*
 	 * Compensate for unequal x/y resolution. This needs to be done after
 	 * calculations that require unadjusted coordinates, for example edge
@@ -3009,7 +3105,7 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw)
     }
 
     send_zoom_event(local, zoom_in, zoom_out);
-
+    send_threefinger_event(local, threefinger_xd, threefinger_yd);
 
     /* Process scroll events only if coordinates are
      * in the Synaptics Area
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
index e972a42..440521a 100644
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -169,6 +169,8 @@ typedef struct _SynapticsParameters
     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 */
+    int threefinger_delta_horiz;
+    int threefinger_delta_vert;
 } SynapticsParameters;
 
 
@@ -180,6 +182,7 @@ enum MultiTouchMode {
     MULTI_TOUCH_MODE_PINCH,
     MULTI_TOUCH_MODE_GESTURE = MULTI_TOUCH_MODE_PINCH,
     MULTI_TOUCH_MODE_SCROLL,
+    MULTI_TOUCH_MODE_3FINGER,
 };
 
 enum GestureMode {
@@ -187,7 +190,8 @@ enum GestureMode {
     GESTURE_PINCH,
     GESTURE_HSCROLL,
     GESTURE_VSCROLL,
-    GESTURE_CIRCULAR
+    GESTURE_CIRCULAR,
+    GESTURE_3FINGER
 };
 
 #define MAX_ACTIONS	4
@@ -290,6 +294,17 @@ typedef struct _SynapticsPrivateRec
     int zoom_out_action[MAX_ACTIONS];
 
     enum TouchpadModel model;          /* The detected model */
+
+    int threefinger_x, threefinger_y;
+    int threefinger_left_num_actions;
+    int threefinger_left_action[MAX_ACTIONS];
+    int threefinger_right_num_actions;
+    int threefinger_right_action[MAX_ACTIONS];
+    int threefinger_up_num_actions;
+    int threefinger_up_action[MAX_ACTIONS];
+    int threefinger_down_num_actions;
+    int threefinger_down_action[MAX_ACTIONS];
+
 } SynapticsPrivate;
 
 
diff --git a/tools/synclient.c b/tools/synclient.c
index c08d30c..247d65d 100644
--- a/tools/synclient.c
+++ b/tools/synclient.c
@@ -151,6 +151,8 @@ static struct Parameter params[] = {
     {"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},
+    {"HorizThreeFingerDelta", PT_INT,    0, 4000,  SYNAPTICS_PROP_THREEFINGER_DELTA,	32,	0},
+    {"VertThreeFingerDelta",  PT_INT,    0, 4000,  SYNAPTICS_PROP_THREEFINGER_DELTA,	32,	1},
     { NULL, 0, 0, 0, 0 }
 };
 
-- 
1.7.3.1



More information about the xorg-devel mailing list