[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