Package: xserver-xorg-input-tslib
Version: 0.0.4-5
Severity: wishlist

Hello,

This is a patch and feature request for xf86-input-tslib.
It emulates right-click by a tap and hold gesture.

Sebastian Ohl is the patch author and he agreed that I paste the patch
to Debian's BTS [1].

Kind regards
 Wen-Yen Chuang (caleb)

[1] http://bugs.debian.org/xf86-input-tslib

Sebastian Ohl wrote:
> on the openmoko phone we have only two buttons so
> using one for rightclick isn't a good option (everyone wants the key
> for himself *g*). so the second try was the tap and hold solution.

> after some looking into the code i developed a patch that makes it
> possible to emulate this feature by a tap and hold gesture. the
> solution to realize this feature in the input driver has big
> advantages over doing this in every framework (i.e. gtk or qt) over
> and over again. i would love to see it included in the next revision
> of your packages, so everyone can use its advantages.


--- xf86-input-tslib-0.0.4/src/tslib.c	2007-10-19 10:59:29.000000000 +0000
+++ xf86-input-tslib-0.0.4.b3/src/tslib.c	2008-08-16 22:42:55.000000000 +0000
@@ -50,6 +50,8 @@
 #include <mipointer.h>
 
 #include <tslib.h>
+#include <sys/time.h>
+#include <time.h>
 
 #ifdef XFree86LOADER
 #include <xf86Module.h>
@@ -57,21 +59,28 @@
 
 #define TSLIB_DEV_DEFAULT "/dev/event0"
 
-#define MAXBUTTONS 1
+#define MAXBUTTONS 2
+#define TIME23RDBUTTON 0.5
+#define MOVEMENT23RDBUTTON 4
 
 #define DEFAULT_HEIGHT		240
 #define DEFAULT_WIDTH		320
 
 enum { TSLIB_ROTATE_NONE=0, TSLIB_ROTATE_CW=270, TSLIB_ROTATE_UD=180, TSLIB_ROTATE_CCW=90 };
 
+enum button_state { BUTTON_NOT_PRESSED = 0, BUTTON_1_PRESSED = 1, BUTTON_3_CLICK = 3, BUTTON_3_CLICKED=4 };
+
 struct ts_priv {
 	XISBuffer *buffer;
 	struct tsdev *ts;
-	int lastx,lasty,lastp;
+	int lastx,lasty;
 	int screen_num;
 	int rotate;
 	int height;
 	int width;
+	enum button_state state;
+	struct timeval button_down_start;
+	int button_down_x,button_down_y;
 };
 
 static const char *DEFAULTS[] = {
@@ -118,12 +127,25 @@
 	return TRUE;
 }
 
+struct timeval TimevalDiff(struct timeval a, struct timeval b)
+{
+	struct timeval t;
+	t.tv_sec = a.tv_sec-b.tv_sec;
+	t.tv_usec = a.tv_usec - b.tv_usec;
+	if (t.tv_usec < 0) {
+		t.tv_sec--;
+		t.tv_usec += 1000000;
+	}
+	return t;
+}
+
 static void ReadInput (LocalDevicePtr local)
 {
 	struct ts_priv *priv = (struct ts_priv *) (local->private);
 	struct ts_sample samp;
 	int ret;
 	int x,y;
+	struct timeval now;
 
 	ret = ts_read(priv->ts, &samp, 1);
 
@@ -134,6 +156,9 @@
 
 //	ErrorF("%ld.%06ld: %6d %6d %6d\n", samp.tv.tv_sec, samp.tv.tv_usec, samp.x, samp.y, samp.pressure);
 
+	gettimeofday(&now, NULL);
+	struct timeval pressureTime = TimevalDiff(now,priv->button_down_start);
+
 	if(samp.pressure) {
 		int tmp_x = samp.x;
 		
@@ -161,18 +186,78 @@
 
 		xf86PostMotionEvent (local->dev, TRUE, 0, 2,
 				x, y);
+	} 
 
+	/* button pressed state machine
+ 	 * if pressed than press button 1, start timer and remember the tab position
+	 * if pressed longer than TIME23RDBUTTON and it is not moved more than MOVEMENT23RDBUTTON release button 1 and click button 3
+	 * if still pressed do nothing until the pressure is released
+	 */
+	//ErrorF("%d\t",priv->state);
+	switch (priv->state) {
+		case BUTTON_NOT_PRESSED :
+			if (samp.pressure) {
+				priv->button_down_start = now;
+				priv->button_down_y = samp.y;
+				priv->button_down_x = samp.x;
+				priv->state = BUTTON_1_PRESSED;
+				//ErrorF("b1 down");
+				xf86PostButtonEvent(local->dev, TRUE,
+					priv->state, TRUE, 0, 2,
+					priv->lastx,
+					priv->lasty);
+			}
+			break;
+		case BUTTON_1_PRESSED :
+			if (samp.pressure) {	
+				//ErrorF("%d %d ",pressureTime.tv_sec,pressureTime.tv_usec);
+				if ((((double)pressureTime.tv_sec)+(((double)pressureTime.tv_usec)*1e-6) > TIME23RDBUTTON) &&
+				   (abs(priv->lastx-priv->button_down_x) < MOVEMENT23RDBUTTON &&
+				    abs(priv->lasty-priv->button_down_y) < MOVEMENT23RDBUTTON))
+				{
+					//ErrorF("b1 up");
+					xf86PostButtonEvent(local->dev, TRUE,
+						priv->state, FALSE, 0, 2,
+						priv->lastx,
+						priv->lasty);
+					priv->state = BUTTON_3_CLICK;
+					//ErrorF("b3 down");
+					xf86PostButtonEvent(local->dev, TRUE,
+						priv->state, TRUE, 0, 2,
+						priv->lastx,
+						priv->lasty);
+				} 
+				if (abs(priv->lastx-priv->button_down_x) > MOVEMENT23RDBUTTON ||
+				    abs(priv->lasty-priv->button_down_y) > MOVEMENT23RDBUTTON) {
+					priv->button_down_start = now;
+					priv->button_down_y = samp.y;
+					priv->button_down_x = samp.x;
+					//ErrorF("b1 state reset");
+				}
+			} else {
+				//ErrorF("b1 up");
+				xf86PostButtonEvent(local->dev, TRUE,
+					priv->state, FALSE, 0, 2,
+					priv->lastx,
+					priv->lasty);
+				priv->state = BUTTON_NOT_PRESSED;
+			}
+			break;
+		case BUTTON_3_CLICK :
+			//ErrorF("b3 up");
+			xf86PostButtonEvent(local->dev, TRUE,
+				priv->state, FALSE, 0, 2,
+				priv->lastx,
+				priv->lasty);
+			priv->state = BUTTON_3_CLICKED;
+			break;
+		case BUTTON_3_CLICKED :
+			if (!samp.pressure) {
+				//ErrorF("b3 free");
+				priv->state = BUTTON_NOT_PRESSED;
+			}
+			break;
 	}
-
-	if(priv->lastp != samp.pressure) {
-		priv->lastp = samp.pressure;
-
-		xf86PostButtonEvent(local->dev, TRUE,
-			1, !!samp.pressure, 0, 2,
-			priv->lastx,
-			priv->lasty);
-	}
-
 }
 
 /*
@@ -361,6 +446,8 @@
 
 	pInfo->fd = ts_fd(priv->ts);
 
+	priv->state = BUTTON_NOT_PRESSED;
+		
 	/* Mark the device configured */
 	pInfo->flags |= XI86_CONFIGURED;
 

Reply via email to