I have finished the rewrite of gestures and attached patch.  Its also
been pushed to bamboo branch of xf86-input-wacom.  Comments welcome.
Also, I need to debug Zoom gestures to figure out what about
emitKeysym is crashing my Fedora Xorg 1.7 server.  And I also need to
bring the variables back out to xsetwacom again.

Below is text from commit message:


1 and 2 finger gesture have a lot of overlapping and
interacting logic so combine into single function.

Most decisions on gesture types are not made at a time window
defined by wcmGestureTapTime instead of based on distance alone.

Added a new Tap gesture to  click left/right button on touchpads.

Comment out Zoom calls to emitKeysym because its crashing my
X server.

Split scroll speed control into horizontal/vertical values to
align with  xf86-input-synaptics user interface.  Also speed
is now based on exact distance traveled instead of distance of
midpoints.

Chris

On Sat, Jan 30, 2010 at 7:28 PM, Chris Bagwell <[email protected]> wrote:
> Hi all,
>
> I wanted to let you know the status of Bamboo P&T and
> xf86-input-wacom; especially related to making use of patches that
> Jason Child has produced.
>
> I've ported most all the patch set except for a part related to
> reconnecting the tablet and setting some new variables using
> xsetwacom.  They have been uploaded to sourceforge.  You can play with
> them using:
>
> git clone 
> git://linuxwacom.git.sourceforge.net/gitroot/linuxwacom/xf86-input-wacom
> git checkout -b bamboo remotes/origin/bamboo
>
> To get full use of this, you'll need to use latest kernel driver from
> linuxwacom-0.8.5-9 and also apply all the kernel patches to it from
> Jason Childs' latest patchset on mailing list.
>
> With this combination of software, I can get single finger touch and
> single finger double tap gestures working.  I can also get two finger
> scrolling gestures working.  There are a few issues/bugs I can tell
> but quite usable overall.
>
> Chris
>
From 202b9c7ab30ea355468ec00e21376fb75880481f Mon Sep 17 00:00:00 2001
From: Chris Bagwell <[email protected]>
Date: Thu, 4 Feb 2010 23:22:36 -0600
Subject: [PATCH] Rewrite gestures by combining 1 and 2 finger logic

1 and 2 finger gesture have a lot of overlapping and
interacting logic so combine into single function.

Most decisions on gesture types are not made at a time window
defined by wcmGestureTapTime instead of based on distance alone.

Added a new Tap gesture to left/right click mouse on touchpads.

Comment out Zoom calls to emitKeysym because its crashing my
X server.

Split scroll speed control into horizontal/vertical values to
align with  xf86-input-synaptics user interface.  Also speed
is now based on exact distance traveled instead of distance of
midpoints.

Signed-off-by: Chris Bagwell <[email protected]>
---
 src/wcmCommon.c         |  110 +-------------
 src/wcmConfig.c         |   10 +-
 src/wcmTouchFilter.c    |  385 ++++++++++++++++++++++++++++++++---------------
 src/wcmValidateDevice.c |   36 +----
 src/xf86WacomDefs.h     |   12 +-
 5 files changed, 285 insertions(+), 268 deletions(-)

diff --git a/src/wcmCommon.c b/src/wcmCommon.c
index 37c88a1..febb34a 100644
--- a/src/wcmCommon.c
+++ b/src/wcmCommon.c
@@ -35,7 +35,7 @@ extern void xf86WcmInitialCoordinates(LocalDevicePtr local, int axes);
 extern void xf86WcmVirtualTabletSize(LocalDevicePtr local);
 extern void xf86WcmVirtualTabletPadding(LocalDevicePtr local);
 extern void wcmTilt2R(WacomDeviceStatePtr ds);
-extern void xf86WcmFingerTapToClick(WacomCommonPtr common, WacomDevicePtr priv);
+extern int xf86WcmTouchFilter(WacomCommonPtr common, WacomDevicePtr priv, unsigned int channel);
 
 /*****************************************************************************
  * Static functions
@@ -1218,108 +1218,14 @@ void wcmEvent(WacomCommonPtr common, unsigned int channel,
 		} 
 	}
 
-	/* process second finger data if exists
-	 * and both touch and geature are enabled */
-	if ((ds.device_type == TOUCH_ID) &&
-			common->wcmTouch && common->wcmGesture)
-	{
-		WacomChannelPtr pOtherChannel;
-		WacomDeviceState dsOther;
-
-		/* Get the other channel state */
-		if (channel)
-			pOtherChannel = common->wcmChannel;
-		else
-			pOtherChannel = common->wcmChannel + 1;
-		dsOther = pOtherChannel->valid.state;
-
-		/* Exit gesture mode when both fingers are out. */
-		if (!ds.proximity && !dsOther.proximity)
-		{
-			common->wcmGestureMode = 0;
-
-			/* send a touch out-prox event here
-			 * in case the FF was out before the SF */
-			channel = 0;
-		}
-		else
-		{
-			/* don't move the cursor if in gesture mode
-			 * wait for second finger data to process gestures */
-			if (!channel && common->wcmGestureMode)
-				goto ret;
-
-			/* process gesture */
-			if (channel)
-			{
-				xf86WcmFingerTapToClick(common, priv);
-				goto ret;
-			}
-		}
-	}
-
-	/* process single finger events 
-	 * if touch is in Relative mode then allow single click
-	 * to work regardless of gesture on/off state.
-	 * Also ensure that we don't try to process single clicks
-	 * when in an active gesture mode.
-	 */
-	if (ds.device_type == TOUCH_ID && common->wcmTouch && 
-	     (common->wcmCapacityDefault && !(priv->flags & ABSOLUTE_FLAG) && !common->wcmGestureMode))
-	{
-		WacomDeviceState* pds = &common->wcmTouchpadState;
-
-		if (ds.proximity)
-		{
-			switch (common->wcmTouchpadMode)
-			{
-				case 0:
-					common->wcmTouchpadMode = 1;
-					common->wcmTouchpadState = ds;
-					common->wcmTouchpadState.sample = (int)GetTimeInMillis();
-					break;
-				case 1:
-					if (GetTimeInMillis() - pds->sample <= 200) {
-						int xd = ds.x - pds->x;
-						int yd = ds.y - pds->y;
-
-						if (xd*xd + yd*yd > 10*10)
-							common->wcmTouchpadMode = 2;
-					} else {
-						/* left button down */
-						xf86PostButtonEvent(priv->local->dev,FALSE,1,TRUE,0,0);
-						common->wcmTouchpadMode = 3;
-					}
-					break;
-			}
-		} else {
-			switch (common->wcmTouchpadMode)
-			{
-				case 1:
-					if (GetTimeInMillis() - pds->sample <= 200)
-					{
-						/* left button down */
-						xf86PostButtonEvent(priv->local->dev,FALSE,1,TRUE,0,0);
-						/* left button up */
-						xf86PostButtonEvent(priv->local->dev,FALSE,1,FALSE,0,0);
-					}
-					break;
-				case 3:
-					/* left button up */
-					xf86PostButtonEvent(priv->local->dev,FALSE,1,FALSE,0,0);
-			}
-			common->wcmTouchpadMode = 0;
-		}
-		if (common->wcmTouchpadMode == 1 || common->wcmTouchpadMode == 2)
-			ds.buttons &= ~1;
-	}
+	if (ds.device_type == TOUCH_ID && common->wcmTouch &&
+	    common->wcmGesture)
+		/* Consume gesture if requested */
+		if (xf86WcmTouchFilter(common, priv, channel))
+			goto ret;
 
-	/* everything else falls here,
-	 * dispatch unless this is destined for a touch device
-	 * and touch is disabled.
-	 */
-	if (ds.device_type != TOUCH_ID || common->wcmTouch)
-		commonDispatchDevice(common,channel,pChannel, suppress);
+	/* everything else falls here */
+	commonDispatchDevice(common,channel,pChannel,suppress);
 ret:
 	resetSampleCounter(pChannel);
 }
diff --git a/src/wcmConfig.c b/src/wcmConfig.c
index 8358f46..7beaf3f 100644
--- a/src/wcmConfig.c
+++ b/src/wcmConfig.c
@@ -134,11 +134,11 @@ static int xf86WcmAllocate(LocalDevicePtr local, char* type_name, int flag)
 	common->wcmDevCls = &gWacomUSBDevice; /* device-specific functions */
 	common->wcmTPCButton = 
 		common->wcmTPCButtonDefault; /* set Tablet PC button on/off */
-	common->wcmRightClickDistance = 300; /* max finger spacing */
-	common->wcmZoomPinchDistance = 350; /* max to start gesture */
-	common->wcmActivateDistance = 50;  /* min to start any gesture */
-	common->wcmScrollActivateDistance = 50; /* min to start scroll */
-	common->wcmGestureTapTime = 150;   /* min time to start gesture */
+	common->wcmGestureTapDistance = 50;/* max distance to start gesture */
+	common->wcmGestureTapTime = 200;   /* min time to start gesture */
+	common->wcmGestureVertDelta = 50;  /* Vert scroll event distance */
+	common->wcmGestureHorzDelta = 50;  /* Horz scroll event distance */
+	common->wcmGestureZoomDelta = 20;  /* Pinch Zoom event distance */
 	common->wcmCapacity = -1;          /* Capacity is disabled */
 	common->wcmCapacityDefault = -1;   /* default to -1 when capacity isn't supported */
 					   /* 3 when capacity is supported */
diff --git a/src/wcmTouchFilter.c b/src/wcmTouchFilter.c
index d3a253b..12fa95b 100644
--- a/src/wcmTouchFilter.c
+++ b/src/wcmTouchFilter.c
@@ -24,21 +24,23 @@
 #include <math.h>
 
 /* Defines for 2FC Gesture */
-#define WACOM_DOWN_TIME_IN_MS       800
-#define WACOM_TIME_BETWEEN_IN_MS    400
 #define WACOM_HORIZ_ALLOWED           1
 #define WACOM_VERT_ALLOWED            2
 
-#define GESTURE_TAP_MODE              1
-#define GESTURE_SCROLL_MODE           2
-#define GESTURE_ZOOM_MODE             4
+#define GESTURE_NO_MODE               0
+#define GESTURE_DETECT_MODE           1
+#define GESTURE_PASSTHRU_MODE         3
+#define GESTURE_SCROLL_HORZ_MODE      7 
+#define GESTURE_SCROLL_VERT_MODE      8
+#define GESTURE_ZOOM_MODE             9
 
 #define WCM_SCROLL_UP                 5	/* vertical up */
 #define WCM_SCROLL_DOWN               4	/* vertical down */
 #define WCM_SCROLL_LEFT               6	/* horizontal left */
 #define WCM_SCROLL_RIGHT              7	/* horizontal right */
 
-void xf86WcmFingerTapToClick(WacomCommonPtr common, WacomDevicePtr priv);
+int xf86WcmTouchFilter(WacomCommonPtr common, WacomDevicePtr priv,
+		       unsigned int channel);
 
 extern void wcmRotateCoordinates(LocalDevicePtr local, int* x, int* y);
 extern void emitKeysym (DeviceIntPtr keydev, int keysym, int state);
@@ -54,6 +56,11 @@ static double touchDistance(WacomDeviceState ds0, WacomDeviceState ds1)
 	return distance;
 }
 
+/* When in auto-detect mode, find when fingers are moving in a line
+ * that is of width wcmGestureTapDistance and return its direction.
+ * When a direction is specified, return TRUE only when moving
+ * in line of wcmGestureTapDistance width.
+ */
 static Bool pointsInLine(WacomCommonPtr common, WacomDeviceState ds0, 
 			 WacomDeviceState ds1, int *direction)
 {
@@ -61,12 +68,12 @@ static Bool pointsInLine(WacomCommonPtr common, WacomDeviceState ds0,
 
 	if (*direction == 0)
 	{
-		if (abs(ds0.x - ds1.x) < common->wcmScrollActivateDistance)
+		if (abs(ds0.x - ds1.x) < common->wcmGestureTapDistance)
 		{
 			*direction = WACOM_VERT_ALLOWED;
 			ret = TRUE;
 		}
-		else if (abs(ds0.y - ds1.y) < common->wcmScrollActivateDistance)
+		else if (abs(ds0.y - ds1.y) < common->wcmGestureTapDistance)
 		{
 			*direction = WACOM_HORIZ_ALLOWED;
 			ret = TRUE;
@@ -74,12 +81,12 @@ static Bool pointsInLine(WacomCommonPtr common, WacomDeviceState ds0,
 	}
 	else if (*direction == WACOM_HORIZ_ALLOWED)
 	{
-		if (abs(ds0.y - ds1.y) < common->wcmScrollActivateDistance)
+		if (abs(ds0.y - ds1.y) < common->wcmGestureTapDistance)
 			ret = TRUE;
 	}
 	else if (*direction == WACOM_VERT_ALLOWED)
 	{
-		if (abs(ds0.x - ds1.x) < common->wcmScrollActivateDistance)
+		if (abs(ds0.x - ds1.x) < common->wcmGestureTapDistance)
 			ret = TRUE;
 	}
 	return ret;
@@ -89,133 +96,256 @@ static Bool pointsInLineAfter(WacomCommonPtr common, int p1, int p2)
 {
 	Bool ret = FALSE;
 
-	if (abs(p1 - p2) < common->wcmScrollActivateDistance)
+	if (abs(p1 - p2) < common->wcmGestureTapDistance)
 		ret = TRUE;
 
 	return ret;
 }
 
-static void xf86WcmSwitchLeftClick(WacomDevicePtr priv)
-{
-	WacomCommonPtr common = priv->common;
-
-	if (common->wcmGestureMode)
-	{
-		/* send button one up */
-		xf86PostButtonEvent(priv->local->dev,FALSE,1,FALSE,0,0);
-		priv->oldButtons = 0;
-	}
-}
-
-/*****************************************************************************
- *   translate second finger tap to right click
- ****************************************************************************/
-
-void xf86WcmFingerTapToClick(WacomCommonPtr common, WacomDevicePtr priv)
+/* Filters out events related to following gestures and replaces with
+ * specified action:
+ *
+ * Single and Double Finger Taps - Left and Right button click
+ * Double Finger Scroll - Scroll Button Events
+ * Double Finger Pinch Zoom - Zoom Finger Events
+ * Single and Double Finger Touches - Left and Right Button Clicks
+ *
+ * In addition, Touch gestures let standard X/Y data to be processed
+ * as normal.
+ */
+int xf86WcmTouchFilter(WacomCommonPtr common, WacomDevicePtr priv, 
+		       unsigned int channel)
 {
 	WacomChannelPtr firstChannel = common->wcmChannel;
 	WacomChannelPtr secondChannel = common->wcmChannel + 1;
-	WacomDeviceState ds[2] = { firstChannel->valid.states[0],
-				   secondChannel->valid.states[0] };
+	WacomDeviceState ds[2] = { firstChannel->valid.state,
+				   secondChannel->valid.state };
 	WacomDeviceState dsLast[2] = { firstChannel->valid.states[1],
-					secondChannel->valid.states[1] };
-	int direction = 0;
-
-	DBG(10, priv, "mode = %d, "
-	    "ds[0].x = %d, ds[0].y = %d, ds[1].x = %d, ds[1].y = %d, "
-	    "ds[0].sample = %d, ds[1].sample = %d, "
-	    "dsLast[0].sample = %d, dsLast[1].sample = %d, "
-	    "ds[1].proximity = %s, dsLast[1].proximity = %s\n",
-	    common->wcmGestureMode, 
-	    ds[0].x, ds[0].y, ds[1].x, ds[1].y,
-	    ds[0].sample, ds[1].sample,
-	    dsLast[0].sample, dsLast[1].sample,
-	    ds[1].proximity ? "true" : "false", 
-	    dsLast[1].proximity ? "true" : "false");
-
-	/* skip initial second finger event */
-	if (!dsLast[1].proximity)
-		goto skipGesture;
+		secondChannel->valid.states[1] };
 
 	if (!IsTouch(priv))
 	{
 		/* this should never happen */
 		xf86Msg(X_ERROR, "WACOM: No touch device found for %s \n", common->wcmDevice);
-		goto skipGesture;
+		return TRUE;
 	}
 
-	/* process second finger tap if matched */
-	if ((dsLast[0].sample < dsLast[1].sample) && 
-	    ((GetTimeInMillis() - dsLast[1].sample) <= common->wcmGestureTapTime))
+	DBG(10, priv, "channel = %d, mode = %d, "
+	    "ds[0].x = %d, ds[0].y = %d, ds[1].x = %d, ds[1].y = %d, "
+	    "ds[0].sample = %d, ds[1].sample = %d, "
+	    "wcmGestureState[0].sample = %d, wcmGestureState[1].sample = %d, "
+	    "wcmGestureFingers = %d ds[0].proximity = %s, ds[1].proximity = %s\n",
+	    channel,
+	    common->wcmGestureMode, 
+	    ds[0].x, ds[0].y, ds[1].x, ds[1].y,
+	    ds[0].sample, ds[1].sample,
+	    common->wcmGestureState[0].sample, 
+	    common->wcmGestureState[1].sample,
+	    common->wcmGestureFingers,
+	    ds[0].proximity ? "true" : "false", 
+	    ds[1].proximity ? "true" : "false");
+
+	/* Detect when both fingers are removed */
+	if (!ds[0].proximity && !ds[1].proximity)
 	{
-		/* send right click when second finger taps within WACOM_TAP_TIMEms
-		 * and both fingers stay within WACOM_DIST */
-		if (!ds[1].proximity && dsLast[1].proximity)
+		if (common->wcmGestureMode == GESTURE_DETECT_MODE)
 		{
-			if (touchDistance(ds[0], dsLast[1]) <= common->wcmRightClickDistance)
+			/* In relative mode, we met condition
+			 * to send button down. */
+			if (!(priv->flags & ABSOLUTE_FLAG))
 			{
-				/* send left up before sending right down */
-				if (!common->wcmGestureMode)
-				{
-					common->wcmGestureMode = GESTURE_TAP_MODE;
-					xf86WcmSwitchLeftClick(priv);
-				}
-
-				/* right button down */
-				xf86PostButtonEvent(priv->local->dev,FALSE,3,TRUE,0,0);
-				/* right button up */
-				xf86PostButtonEvent(priv->local->dev,FALSE,3,FALSE,0,0);
-			} else	if (common->wcmGestureMode == GESTURE_TAP_MODE) {
-				common->wcmGestureMode = 0;
+				/* left for single finger
+				 * right for double finger
+				 */
+				if (common->wcmGestureFingers == 1)
+					common->wcmGestureButtonDown = 1;
+				else
+					common->wcmGestureButtonDown = 3;
+
+				xf86PostButtonEvent(priv->local->dev,
+						    priv->flags&ABSOLUTE_FLAG,
+						    common->wcmGestureButtonDown,
+						    1,0,0);
+				xf86PostButtonEvent(priv->local->dev,
+						    priv->flags&ABSOLUTE_FLAG,
+						    common->wcmGestureButtonDown,
+						    0,0,0);
+				common->wcmGestureButtonDown = 0;
 			}
+			common->wcmGestureMode = 0;
+			return TRUE;
 		}
-	}
-	/* process complex two finger gestures */
-	if ((common->wcmGestureTapTime > 
-	     (GetTimeInMillis() - dsLast[0].sample)) &&
-	    (common->wcmGestureTapTime > 
-	     (GetTimeInMillis() - dsLast[1].sample)))
-	{
-
-		/* FIXME: Crashes X when emitting Ctrl-Up/Ctrl-Down */
-		if (0 && touchDistance(ds[0], ds[1]) >= common->wcmZoomPinchDistance &&
-		    common->wcmGestureMode != GESTURE_TAP_MODE &&
-		    common->wcmGestureMode != GESTURE_SCROLL_MODE)
+		else if (common->wcmGestureMode == GESTURE_PASSTHRU_MODE)
 		{
-			/* fingers moved apart more than WACOM_APART_IN_POINT
-			 * zoom mode is entered */
-			if (!common->wcmGestureMode)
+			if (common->wcmGestureButtonDown)
 			{
-				common->wcmGestureMode = GESTURE_ZOOM_MODE;
-				xf86WcmSwitchLeftClick(priv);
+				xf86PostButtonEvent(priv->local->dev,
+						    priv->flags&ABSOLUTE_FLAG,
+						    common->wcmGestureButtonDown,
+						    0,0,0);
+				common->wcmGestureButtonDown = 0;
 			}
-			xf86WcmFingerZoom(priv);
+			common->wcmGestureMode = 0;
+			return channel;
 		}
-
-		if ( pointsInLine(common, ds[0], dsLast[0], &direction) &&
-		     pointsInLine(common, ds[1], dsLast[1], &direction) &&
-		     common->wcmGestureMode != GESTURE_ZOOM_MODE &&
-		     common->wcmGestureMode != GESTURE_TAP_MODE)
+		else
 		{
-			/* send scroll event when both fingers move in
-			 * the same direction */
-			if (!common->wcmGestureMode)
-			{
-				common->wcmGestureMode = GESTURE_SCROLL_MODE;
-				xf86WcmSwitchLeftClick(priv);
-			}
-			xf86WcmFingerScroll(priv);
+			common->wcmGestureMode = 0;
+			return TRUE;
 		}
 	}
 
-skipGesture:
-	/* keep the initial states for both fingers */
-	if ( !(common->wcmGestureMode && (GESTURE_SCROLL_MODE | GESTURE_ZOOM_MODE))
-			&& ds[0].proximity && ds[1].proximity)
+	/* Process one and two finger gestures at same time.
+	 * Commit to gesture at wcmGestureTapTime time.
+	 */
+	switch (common->wcmGestureMode)
 	{
-		common->wcmGestureState[0] = ds[0];
-		common->wcmGestureState[1] = ds[1];
+		case GESTURE_NO_MODE:
+			/* Transition into single finger gesture
+			 * mode and store its related state.
+			 */
+			common->wcmGestureMode = GESTURE_DETECT_MODE;
+			common->wcmGestureState[0] = ds[0];
+			/* Consume and return because we always need
+			 * at least two samples to do next step.
+			 */
+			return TRUE;
+		case GESTURE_DETECT_MODE:
+			{
+				int dist = touchDistance(ds[0], common->wcmGestureState[0]);
+
+				if (ds[1].proximity)
+					common->wcmGestureFingers = 2;
+				else
+					common->wcmGestureFingers = 1;
+
+				/* As long as less then 200ms and didn't
+				 * move to much, then consume
+				 * until we know enough to determine tap 
+				 * vs. touch.
+				 */
+				if ((GetTimeInMillis() - common->wcmGestureState[0].sample) <= common->wcmGestureTapTime && 
+				    (dist <= common->wcmGestureTapDistance))
+					return TRUE;
+
+				/* Process no movement case first. */
+				if (dist <= common->wcmGestureTapDistance)
+				{
+
+					common->wcmGestureMode = GESTURE_PASSTHRU_MODE;
+
+					/* For touchscreens, perform a left
+					 * button press.
+					 */
+					/* FIXME: If we are going to
+					 * support Touchscreen button
+					 * presses right here then it
+					 * looks like duplicate of 
+					 * (CapacityDefault >= 0)
+					 * logic in commonDispatchDevice.
+					 * I do not know that code
+					 * good enough yet to know were
+					 * logic needs to live.
+					 */
+					if (priv->flags & ABSOLUTE_FLAG)
+					{
+						if (common->wcmGestureFingers == 1) 
+							common->wcmGestureButtonDown = 1;
+						else
+							common->wcmGestureButtonDown = 3;
+
+						/* left button down */
+						xf86PostButtonEvent(priv->local->dev,
+								    priv->flags&ABSOLUTE_FLAG,
+								    common->wcmGestureButtonDown,
+								    1,0,0);
+						return TRUE;
+					}
+				}
+				else if (common->wcmGestureFingers == 2)
+				{
+					int direction = 0;
+
+					/* Detect if first finger is moving
+					 * in a line and then verify
+					 * finger two is following same
+					 * line.
+					 */
+					if (pointsInLine(common, ds[0], 
+							 dsLast[0],
+							 &direction) &&
+					    pointsInLine(common, ds[1], 
+							 dsLast[1],
+							 &direction))
+					{
+						if (direction == WACOM_HORIZ_ALLOWED)
+							common->wcmGestureMode = GESTURE_SCROLL_HORZ_MODE;
+						else
+							common->wcmGestureMode = GESTURE_SCROLL_VERT_MODE;
+						xf86WcmFingerScroll(priv);
+						return TRUE;
+					}
+					else if (abs(touchDistance(common->wcmGestureState[0], common->wcmGestureState[1]) - touchDistance(ds[0], ds[1])) > common->wcmGestureZoomDelta)
+					{
+						common->wcmGestureMode = GESTURE_ZOOM_MODE;
+						xf86WcmFingerZoom(priv);
+					}
+					else
+						common->wcmGestureMode = GESTURE_PASSTHRU_MODE;
+				}
+				else
+					common->wcmGestureMode = GESTURE_PASSTHRU_MODE;
+			}
+			break;
+		case GESTURE_PASSTHRU_MODE:
+			/* Only let channel 0 events processed normally. */
+			return channel;
+
+		case GESTURE_SCROLL_HORZ_MODE:
+		case GESTURE_SCROLL_VERT_MODE:
+			{
+				int direction = 0;
+
+				/* Since both fingers will be moving with
+				 * this gesture, only process first finger
+				 * data to prevent double-sends of
+				 * scroll events.
+				 * Go ahead and look for invalid range
+				 * and abort gesture in that case.
+				 */
+				if (channel)
+				{
+					if (!(pointsInLine(common, ds[1], dsLast[1], 
+							   &direction)))
+						/* Come out of scroll mode */
+						common->wcmGestureMode = GESTURE_PASSTHRU_MODE;
+					return TRUE;
+				}
+
+				/* Since second figure was validated in
+				 * its own context, just check validity
+				 * first figure now.
+				 */
+				if (pointsInLine(common, ds[0], dsLast[0], 
+						 &direction))
+					xf86WcmFingerScroll(priv);
+				else
+					/* Come out of scroll mode */
+					common->wcmGestureMode = GESTURE_PASSTHRU_MODE;
+				return TRUE;
+			}
+			break;
+		case GESTURE_ZOOM_MODE:
+			xf86WcmFingerZoom(priv);
+
+			return TRUE;
+
+		default:
+			/* Should not happen */
+			common->wcmGestureMode = GESTURE_NO_MODE;
+			return TRUE;
 	}
+	return FALSE;
 }
 
 static void xf86WcmSendScrollEvent(WacomDevicePtr priv, int dist,
@@ -224,6 +354,12 @@ static void xf86WcmSendScrollEvent(WacomDevicePtr priv, int dist,
 	WacomCommonPtr common = priv->common;
 	int i = 0;
 	int button = (dist > 0) ? up :dn;
+	int dist_threshold;
+
+	if (common->wcmGestureMode == GESTURE_SCROLL_VERT_MODE)
+		dist_threshold = common->wcmGestureVertDelta;
+	else
+		dist_threshold = common->wcmGestureHorzDelta;
 
 	/* Make sure at least one event happens even if
          * distances is negligible.
@@ -231,11 +367,13 @@ static void xf86WcmSendScrollEvent(WacomDevicePtr priv, int dist,
 
 	do {
 		/* button down */
-		xf86PostButtonEvent(priv->local->dev, FALSE, button, TRUE, 0, 0);
+		xf86PostButtonEvent(priv->local->dev, priv->flags&ABSOLUTE_FLAG,
+				    button, 1, 0, 0);
 		/* button up */
-		xf86PostButtonEvent(priv->local->dev, FALSE, button, FALSE, 0, 0);
+		xf86PostButtonEvent(priv->local->dev, priv->flags&ABSOLUTE_FLAG,
+				    button, 0, 0, 0);
 		i++;
-	} while (i < (int)(((double)abs(dist)/(double)common->wcmActivateDistance) + 0.5));
+	} while (i < (int)(((double)abs(dist)/(double)dist_threshold) + 0.5));
 }
 
 static void xf86WcmFingerScroll(WacomDevicePtr priv)
@@ -278,11 +416,9 @@ static void xf86WcmFingerScroll(WacomDevicePtr priv)
 	midPoint_new = (((double)filterd.x[0] + (double)filterd.x[1]) / 2.);
 	if (pointsInLineAfter(common, midPoint_old, midPoint_new))
 	{
-		midPoint_old = (((double)filterd.y[2] + (double)filterd.y[3]) / 2.);
-		midPoint_new = (((double)filterd.y[0] + (double)filterd.y[1]) / 2.);
-		dist = midPoint_old - midPoint_new;
+		dist = filterd.y[2] - filterd.y[0];
 
-		if (abs(dist) > common->wcmScrollActivateDistance)
+		if (abs(dist) > common->wcmGestureVertDelta)
 		{
 			gesture = 1;
 			xf86WcmSendScrollEvent(priv,  dist,
@@ -296,11 +432,9 @@ static void xf86WcmFingerScroll(WacomDevicePtr priv)
 			midPoint_new = (((double)filterd.y[0] + (double)filterd.y[1]) / 2.);
 			if (pointsInLineAfter(common, midPoint_old, midPoint_new))
 			{
-				midPoint_old = (((double)filterd.x[2] + (double)filterd.x[3]) / 2.);
-				midPoint_new = (((double)filterd.x[0] + (double)filterd.x[1]) / 2.);
-				dist = midPoint_old - midPoint_new;
+				dist = filterd.x[2] - filterd.x[0];
 
-				if (abs(dist) > common->wcmScrollActivateDistance)
+				if (abs(dist) > common->wcmGestureHorzDelta)
 				{
 					gesture = 1;
 					xf86WcmSendScrollEvent(priv, dist,
@@ -322,8 +456,8 @@ static void xf86WcmFingerZoom(WacomDevicePtr priv)
 	WacomCommonPtr common = priv->common;
 	WacomChannelPtr firstChannel = common->wcmChannel;
 	WacomChannelPtr secondChannel = common->wcmChannel + 1;
-	WacomDeviceState ds[2] = { firstChannel->valid.states[0],
-		secondChannel->valid.states[0] };
+	WacomDeviceState ds[2] = { firstChannel->valid.state,
+		secondChannel->valid.state };
 	int i = 0;
 	int direction;
 	int dist = touchDistance(common->wcmGestureState[0],
@@ -332,18 +466,21 @@ static void xf86WcmFingerZoom(WacomDevicePtr priv)
 	DBG(10, priv, "\n");
 
 	dist = touchDistance(ds[0], ds[1]) - dist;
-	direction = (dist > 0) ? XK_plus : XK_minus;
 
 	/* zooming? */
-	if (abs(dist) > common->wcmActivateDistance)
+	if (abs(dist) > common->wcmGestureZoomDelta)
 	{
-		for (i=0; i<(int)(((double)abs(dist)/
-				(double)common->wcmActivateDistance) + 0.5); i++)
+		direction = (dist > 0) ? XK_plus : XK_minus;
+
+		for (i=0; i<=(int)(((double)abs(dist)/
+				(double)common->wcmGestureZoomDelta) + 0.5); i++)
 		{
+			/*
 			emitKeysym (priv->local->dev, XK_Control_L, TRUE);
 			emitKeysym (priv->local->dev, direction, TRUE);
-			emitKeysym (priv->local->dev, direction, FALSE);
+			emitKeysym (priv->local->dev, direction, FALSE); 
 			emitKeysym (priv->local->dev, XK_Control_L, FALSE);
+			*/
 		}
 
 		/* reset initial states */
diff --git a/src/wcmValidateDevice.c b/src/wcmValidateDevice.c
index ca13b46..18d2a66 100644
--- a/src/wcmValidateDevice.c
+++ b/src/wcmValidateDevice.c
@@ -642,38 +642,12 @@ int wcmParseOptions(LocalDevicePtr local, unsigned long* keys)
 		common->wcmGestureDefault = 1;
 	}
 
-	/* Set Bamboo P&T Defaults for gesture size and timeouts.
-	 * Other hardware uses initialized defaults.
-	 */
-	if (common->tablet_id >= 0xd0 && common->tablet_id <= 0xd3) {
-		common->wcmRightClickDistance = 100;
-		common->wcmZoomPinchDistance = 350;
-		common->wcmActivateDistance = 20;
-		common->wcmScrollActivateDistance = 20;
-		common->wcmGestureTapTime = 150;
-	}
-
-	/* Set maximum distance allowed for right click touch gesture */
-	common->wcmRightClickDistance = 
-		xf86SetIntOption(local->options, "RightClickDistance",
-				 common->wcmRightClickDistance);
-
-	/* Set minimum distance allowed for zoom touch gesture */
-	common->wcmZoomPinchDistance = 
-		xf86SetIntOption(local->options, "ZoomPinchDistance",
-				 common->wcmZoomPinchDistance);
-
-	/* Set minimum motion required before sending on a scroll gesture */
-	common->wcmActivateDistance = 
-		xf86SetIntOption(local->options, "ActivateDistance",
-				 common->wcmActivateDistance);
-
-	/* Set min parallel motion required before entering scroll gesture */
-	common->wcmScrollActivateDistance = 
-		xf86SetIntOption(local->options, "ScrollActivateDistance",
-				 common->wcmScrollActivateDistance);
+	/* Set maximum distance to start a tap gesture */
+	common->wcmGestureTapDistance = 
+		xf86SetIntOption(local->options, "GestureTapDistance",
+				 common->wcmGestureTapDistance);
 
-	/* Set minimum time between events required to start a gesture */
+	/* Set maximum time allowed to start a gesture */
 	common->wcmGestureTapTime = 
 		xf86SetIntOption(local->options, "GestureTapTime",
 				 common->wcmGestureTapTime);
diff --git a/src/xf86WacomDefs.h b/src/xf86WacomDefs.h
index 21458db..509c32b 100644
--- a/src/xf86WacomDefs.h
+++ b/src/xf86WacomDefs.h
@@ -427,17 +427,17 @@ struct _WacomCommonRec
 	int wcmTouch;	             /* disable/enable touch event */
 	int wcmTPCButtonDefault;     /* Tablet PC button default */
 	int wcmTouchDefault;	     /* default to disable when not supported */
-	int wcmTouchpadMode;         /* in touchpad mdoe? */
-	WacomDeviceState wcmTouchpadState; /* initial state in touchpad mode */
 	int wcmGesture;	     	     /* disable/enable touch gesture */
 	int wcmGestureDefault;       /* default touch gesture to disable when not supported */
 	int wcmGestureMode;	     /* data is in Gesture Mode? */
 	WacomDeviceState wcmGestureState[MAX_FINGERS]; /* inital state when in gesture mode */
-	int wcmRightClickDistance;   /* maximum finger spacing for gesture */
-	int wcmZoomPinchDistance;    /* minimum to start zoom guesture */
-	int wcmActivateDistance;     /* minimum motion to start any gestures */
-	int wcmScrollActivateDistance; /* minimum to start scroll gesture */
+	int wcmGestureTapDistance;   /* maximum distance to start gesture */
 	int wcmGestureTapTime;       /* minimum time to start a gesture */
+	int wcmGestureButtonDown;    /* button down from last gesture */
+	int wcmGestureFingers;       /* Fingers in proximity at gesture start */
+	int wcmGestureVertDelta;     /* Vertical scroll event distance  */
+	int wcmGestureHorzDelta;     /* Horizonatl scroll event distance */
+	int wcmGestureZoomDelta;     /* Pinch Zoom event distance */
 	int wcmCapacity;	     /* disable/enable capacity */
 	int wcmCapacityDefault;      /* default to -1 when capacity isn't supported/disabled */
 				     /* 3 when capacity is supported */
-- 
1.6.6

------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
Linuxwacom-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to