#
# This patch is from http://www.postnuklear.de/xorg-patches/
#
# Description: This is a patch for the evtouch input driver (
#              http://stz-softwaretechnik.com/~ke/touchscreen/evtouch.html).
# Changes (for full description see ChangeLog file after patching (-: ):
#   o Changed code to compile a working driver for both XInput ABI 0.x and 2.0 (Xorg 1.4.0)
#   o changed rotation (due to segfault on xorg + fbdev)
#   o drag support
#   o tap "tolerance"
#   o added generic ts-adc touchscreen device to udev rules file
#
# Feel free to send comments, critics, suggestions to harryrat@postnuklear.de
# To apply simply change into the toplevel directory of the source to be modified and enter:
# patch -p1 < <PATH_TO_PATCH>
# 
# All patches are available under the GNU GPL, I hope they might be useful for you (-:
# - Harald Radke  
#
Index: xserver-xorg-input-evtouch/69-touchscreen.rules
===================================================================
--- xserver-xorg-input-evtouch.orig/69-touchscreen.rules	2008-02-02 21:49:20.783972805 +0900
+++ xserver-xorg-input-evtouch/69-touchscreen.rules	2008-02-02 21:49:39.730979724 +0900
@@ -7,8 +7,11 @@
 # Name can be found in /proc/bus/input/devices ('cat /proc/bus/input/devices')
 #
 
-# These are the touchscreens supported by kernel's "usbtouchscreen" module
+# Generic ts-adc touchscreen modules
+KERNEL=="event*", SUBSYSTEM=="input", ATTRS{name}=="ts-adc", SYMLINK+="input/evtouch_event"
+
 
+# These are the touchscreens supported by kernel's "usbtouchscreen" module
 # eGalax Inc. USB TouchController)
 KERNEL=="event*", SUBSYSTEM=="input", ATTRS{idVendor}=="3823", ATTRS{idProduct}=="0001", SYMLINK+="input/evtouch_event"
 # eGalax Inc. USB TouchController)
Index: xserver-xorg-input-evtouch/ChangeLog
===================================================================
--- xserver-xorg-input-evtouch.orig/ChangeLog	2008-02-02 21:49:20.795972782 +0900
+++ xserver-xorg-input-evtouch/ChangeLog	2008-02-02 21:49:39.730979724 +0900
@@ -1,3 +1,61 @@
+0.8.7-HR *** Note this is not an official release but an "unauthorized
+	 *** fix version by me (Harald Radke - harryrat@postnuklear.de)
+	-> Changed code to compile a working driver for  both 
+	  XInput ABI 0.x and 2.0 (Xorg 1.4.0)
+	  (test compile for 0.x still needs to be done)
+	  - evtouch.c: 
+            * capsulated xf86Post*Events and xf86InputSetScreen 
+	      in functions where depending on the XINPUT ABI conversion
+	      is done or xf86 functions are directly called
+	    * xf86InitValuatorAxisStruct and xf86AlwaysCore() depending
+	      on ABI done
+	  - libtouch.h: passing xf86PostButtonEvent capsulation function
+	    to init function (same as in evtouch.c) to do proper button
+	    triggering
+	-> Rotation:
+	  - added support for Option "Rotate" "UD" (upside down) 
+	     in evtouch input section of xorg.conf
+	  - due to Segfault with (at least) fbdev video device, only
+	    evtouch "Rotate" option is taken into calculations for coords,
+	    meaning to get proper touchscreen behaviour on rotated X screens.
+	    same Rotate option as in video device section of xorg.conf has
+            to be set in the evtouch section
+	-> Drag support:
+	  Option "<STATE>_drag" "<BUTTON_ID>" has been added. When set,
+	  the handle_<STATE>() function triggers BUTTON_DOWN for Button <BUTTON_ID>
+	  before changing into S_MOVE state. Note that actually only
+	  Option "touched_drag" "<BUTTON_ID>" is implemented, rest is dummy
+	  (and doesn't make too much sense I guess) (-;
+	-> tap "tolerance":
+	   introduce move_limit to evtouch.c as it is in libtouch.c, using it
+	   to discard ABS_X/Y position changes if they are inside move_limit
+	   around cur_x/y. this way pointer hopping can be avoided as well as
+           proper touched_drag established
+         - changes of cur_x/y are reported on EV_SYN in evtouch.c ReadInput() instead
+           on EV_ABS
+	-> added generic ts-adc touchscreen device to udev rules file	   
+
+	=>  Example for a Loox720 PDA setup in input section of xorg.conf:
+		Section "InputDevice"
+		 Identifier "touchscreen"
+		 Driver "evtouch"
+		 Option "Device" "/dev/input/evtouch_event"
+		 Option "MinX" "434"
+		 Option "MinY" "333"
+		 Option "MaxX" "3643"
+		 Option "MaxY" "3804"
+		 Option "SwapX" "true"
+		 Option "longtouched_action" "down"
+		 Option "longtouched_button" "3"
+		 Option "maybetapped_action" "click"
+		 Option "maybetapped_button" "1"
+		 Option "touched_drag" "1"
+		 Option "oneandahalftap_button" "0"
+		 Option "TapTimer" "30"
+		 Option "LongtouchTimer"  "500"
+		 Option "MoveLimit"  "18"
+		EndSection
+
 0.8.7
 	- Added Elo Touchscreen to udev-rules (Stephen Webb)
 	- Added "fix" for AMD64-crashes on touch (Martin Letenay)
Index: xserver-xorg-input-evtouch/evtouch.c
===================================================================
--- xserver-xorg-input-evtouch.orig/evtouch.c	2008-02-02 21:49:20.811973497 +0900
+++ xserver-xorg-input-evtouch/evtouch.c	2008-02-02 21:49:39.734971242 +0900
@@ -182,6 +182,20 @@ static const char *default_options[] =
 static int
 ControlProc(LocalDevicePtr device, xDeviceCtl *ctrl);
 
+static void 
+PostMotionEvent(LocalDevicePtr local);
+
+static void 
+PostProximityEvent(LocalDevicePtr local,int is_in);
+
+static void 
+PostButtonEvent(LocalDevicePtr local, int button,
+		    	 int is_down, int x,int y);
+
+static void 
+InputSetScreen(LocalDevicePtr local);
+
+
 /*****************************************************************************
  *        Function Definitions
  ****************************************************************************/
@@ -197,11 +211,10 @@ emulate3Timer(OsTimerPtr timer, CARD32 n
         LocalDevicePtr local = (LocalDevicePtr)_local;
         EVTouchPrivatePtr priv = (EVTouchPrivatePtr) local->private;
 
+
         sigstate = xf86BlockSIGIO();
 
-        xf86PostMotionEvent(local->dev, TRUE, 0, 2, 
-                            priv->cur_x, 
-                            priv->cur_y);
+        PostMotionEvent(local);
 
         /* 
          * Emit a button press -- release is handled in EVTouchLBRBEvent
@@ -209,31 +222,21 @@ emulate3Timer(OsTimerPtr timer, CARD32 n
         if ( ( priv->touch_flags & LB_STAT ) &&
              !( priv->touch_flags & RB_STAT ) ) {
                 DBGOUT(2, "EVTouch: Left Press\n");
-                xf86PostButtonEvent (local->dev, TRUE,
-                                     1, 1, 0, 2, 
-                                     priv->cur_x, 
-                                     priv->cur_y);
+                PostButtonEvent (local, 1, 1,priv->cur_x,priv->cur_y);
         }
 
         if ( ( priv->touch_flags & RB_STAT ) &&
              !( priv->touch_flags & LB_STAT ) ) {
                 DBGOUT(2, "EVTouch: Right Press\n");
-                xf86PostButtonEvent (local->dev, TRUE,
-                                     3, 1, 0, 2, 
-                                     priv->cur_x, 
-                                     priv->cur_y);
-        }
-
+                PostButtonEvent (local, 3, 1,priv->cur_x,priv->cur_y);
+	}
         /*
           Handling "middle" button press
         */
         if ( ( priv->touch_flags & RB_STAT ) &&
              ( priv->touch_flags & LB_STAT ) ) {
                 DBGOUT(2, "EVTouch: Middle Press\n");
-                xf86PostButtonEvent (local->dev, TRUE,
-                                     2, 1, 0, 2, 
-                                     priv->cur_x, 
-                                     priv->cur_y);
+                PostButtonEvent (local, 2, 1,priv->cur_x,priv->cur_y);
         }
 
         priv->emulate3_timer_expired = TRUE;
@@ -246,6 +249,7 @@ static void DoBtnAction(EVTouchPrivatePt
 {
         int btn = 0;
         LocalDevicePtr local = priv->local;
+
         DBGOUT(2, "EVTouch: %s btn_count=%d\n", __FUNCTION__, priv->btn_count);
 
         for (btn = 0; btn < priv->btn_count; btn++) {
@@ -262,12 +266,7 @@ static void DoBtnAction(EVTouchPrivatePt
                         DBGOUT(2, "EVTouch: %s btn = %d action = %d\n", 
                                __FUNCTION__, btn, 
                                priv->btn_actions[btn].action);
-
-                        xf86PostButtonEvent (local->dev, TRUE, btn, 
-                                             priv->btn_actions[btn].action, 
-                                             0, 2,
-                                             priv->cur_x,
-                                             priv->cur_y);
+			PostButtonEvent (local, btn, priv->btn_actions[btn].action,priv->cur_x,priv->cur_y);                        
 
                         priv->btn_actions[btn].do_it  = 0;
                         priv->btn_actions[btn].action = 0;
@@ -292,39 +291,32 @@ void EVTouchProcessAbs(EVTouchPrivatePtr
         ev = &priv->ev;
 
         if ( (ev->code == ABS_X) || (ev->code == ABS_Z) ) {
+ 		if ((priv->cur_x - ev->value < priv->move_limit)
+                        && (priv->cur_x - ev->value > -priv->move_limit))
+                        return;
                 priv->cur_x = ev->value;
-		libtouchSetXPos(priv->libtouch, priv->cur_x);
+//		libtouchSetXPos(priv->libtouch, priv->cur_x);
 	}
 
         if ( (ev->code == ABS_Y) || (ev->code == ABS_RX) ) {
+		if ((priv->cur_y - ev->value < priv->move_limit)
+                        && (priv->cur_y - ev->value > -priv->move_limit))
+                        return;
                 priv->cur_y = ev->value;
-		libtouchSetYPos(priv->libtouch, priv->cur_y);
+//		libtouchSetYPos(priv->libtouch, priv->cur_y);
 	}
 
 	if (ev->code == ABS_WHEEL) {
 		LocalDevicePtr local = priv->local;
-
 		if (ev->value > 0) {
 			for (; ev->value > 0; ev->value--) {
-				xf86PostButtonEvent (local->dev, TRUE,
-						     4, 1, 0, 2, 
-						     priv->cur_x, 
-						     priv->cur_y);
-				xf86PostButtonEvent (local->dev, TRUE,
-						     4, 0, 0, 2, 
-						     priv->cur_x, 
-						     priv->cur_y);
+				PostButtonEvent (local, 4,1,priv->cur_x,priv->cur_y);
+				PostButtonEvent (local, 4,0,priv->cur_x,priv->cur_y);
 			}
 		} else if (ev->value < 0) {
 			for (ev->value = -ev->value; ev->value > 0; ev->value--) {
-				xf86PostButtonEvent (local->dev, TRUE,
-						     5, 1, 0, 2, 
-						     priv->cur_x, 
-						     priv->cur_y);
-				xf86PostButtonEvent (local->dev, TRUE,
-						     5, 0, 0, 2, 
-						     priv->cur_x, 
-						     priv->cur_y);
+				PostButtonEvent (local, 5,1,priv->cur_x,priv->cur_y);
+				PostButtonEvent (local, 5,0,priv->cur_x,priv->cur_y);
 			}
 		}			
 	}
@@ -451,10 +443,7 @@ void EVTouchProcessKey(EVTouchPrivatePtr
         default:
                 return;
         }
-        xf86PostButtonEvent(local->dev, TRUE,
-                            btn, ev->value, 0, 2, 
-                            priv->cur_x, 
-                            priv->cur_y);
+	PostButtonEvent (local, btn, ev->value,priv->cur_x,priv->cur_y);
 #endif
 
         return;
@@ -492,8 +481,8 @@ DeviceOn (DeviceIntPtr dev)
 
         priv->buffer = XisbNew(local->fd, 64);
 
-        DBG (9, XisbTrace (priv->buffer, 1));
-
+// breaks compilation
+//        DBG (9, XisbTrace (priv->buffer, 1));
 
         if (!priv->buffer) 
         {
@@ -637,8 +626,19 @@ DeviceInit (DeviceIntPtr dev)
                 ErrorF ("Unable to allocate EVTouch touchscreen ValuatorClassDeviceStruct\n");
                 return !Success;
         }
-
-        xf86InitValuatorAxisStruct(dev, 0, priv->min_x, priv->max_x,
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 2
+        xf86InitValuatorAxisStruct(dev, 0, 0, priv->screen_width,
+                                   1024,
+                                   EV_AXIS_MIN_RES /* min_res */ ,
+                                   EV_AXIS_MAX_RES /* max_res */ );
+        xf86InitValuatorDefaults(dev, 0);
+        xf86InitValuatorAxisStruct(dev, 1, 0, priv->screen_height,
+                                   1024,
+                                   EV_AXIS_MIN_RES /* min_res */ ,
+                                   EV_AXIS_MAX_RES /* max_res */ );
+        xf86InitValuatorDefaults(dev, 1);
+#else
+	xf86InitValuatorAxisStruct(dev, 0, priv->min_x, priv->max_x,
                                    1024,
                                    EV_AXIS_MIN_RES /* min_res */ ,
                                    EV_AXIS_MAX_RES /* max_res */ );
@@ -648,7 +648,7 @@ DeviceInit (DeviceIntPtr dev)
                                    EV_AXIS_MIN_RES /* min_res */ ,
                                    EV_AXIS_MAX_RES /* max_res */ );
         xf86InitValuatorDefaults(dev, 1);
-
+#endif
         /* Initial position of pointer on screen: Centered */
         priv->cur_x=(priv->max_x - priv->min_x)/2;
         priv->cur_y=(priv->max_y - priv->min_y)/2;
@@ -777,14 +777,8 @@ static void ReadInput (LocalDevicePtr lo
 		DBGOUT(2, "EVTouch: %s type:%0.2x code: 0x%0.4x value:%d\n",
 			__FUNCTION__, ev->type, ev->code, ev->value);
 
-                xf86XInputSetScreen(local, 
-                                    priv->screen_num, 
-                                    priv->cur_x, 
-                                    priv->cur_y);
-                        
-                xf86PostProximityEvent(local->dev, 1, 0, 2,
-                                       priv->cur_x,
-                                       priv->cur_y);
+		InputSetScreen(local);
+		PostProximityEvent (local,1);
 
                 switch (ev->type) {
                 case EV_ABS:
@@ -794,9 +788,7 @@ static void ReadInput (LocalDevicePtr lo
                         EVTouchProcessRel(priv);
                         break;
 		case EV_KEY:
-                        xf86PostMotionEvent (local->dev, TRUE, 0, 2, 
-                                             priv->cur_x,
-                                             priv->cur_y);
+			PostMotionEvent (local);
 
 			if (priv->ev.code == BTN_TOUCH) {
 				if (priv->ev.value == 1) {
@@ -811,9 +803,8 @@ static void ReadInput (LocalDevicePtr lo
                         EVTouchProcessKey(priv);
 			break;
 		case EV_SYN:
-                        xf86PostMotionEvent (local->dev, TRUE, 0, 2, 
-                                             priv->cur_x,
-                                             priv->cur_y);
+			libtouchSetPos(priv->libtouch, priv->cur_x,priv->cur_y);
+			PostMotionEvent (local);
 
 			if ( priv->touch_flags & TOUCHED )
 				libtouchTriggerSM(priv->libtouch, PEN_TOUCHED);
@@ -902,7 +893,9 @@ ConvertProc ( LocalDevicePtr local,
 
         EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private);  
 	ScrnInfoPtr pScrn = xf86Screens[priv->screen_num];
-	Rotation rotation = RRGetRotation(pScrn->pScreen);
+
+// X Segfaults
+//	Rotation rotation = RRGetRotation(pScrn->pScreen);
 
         DBGOUT(2, "EVTouch: FIRST: v0=%d   v1=%d\n", v0, v1);
 
@@ -921,15 +914,17 @@ ConvertProc ( LocalDevicePtr local,
                 max_x = priv->max_x - priv->min_x;
                 max_y = priv->max_y - priv->min_y;
 
-                if (priv->rotate == EV_ROTATE_NONE) {
+
+//                if (priv->rotate == EV_ROTATE_NONE) {
                         screen_width  = pScrn->currentMode->HDisplay;
                         screen_height = pScrn->currentMode->VDisplay;
+/* Swapping is done below in Coords! Leave those to be able to calc correct mapping
                 } else {
                         screen_width  = pScrn->currentMode->VDisplay;
                         screen_height = pScrn->currentMode->HDisplay;
                 }
 
-
+*/
                 if (xc < (max_x / 2)) {
                         /*
                           left
@@ -1042,45 +1037,57 @@ ConvertProc ( LocalDevicePtr local,
 
                 int tmp = 0;
                 /* rotation mixes x and y up a bit */
-                if (priv->rotate == EV_ROTATE_CW) {
+		switch(priv->rotate) {
+		case EV_ROTATE_CW:
                         tmp = xc;
                         xc = yc;
                         yc = screen_width - tmp;
-                } else if (priv->rotate == EV_ROTATE_CCW) {
+		break;
+                case EV_ROTATE_CCW:
                         tmp = xc;
                         xc = screen_height - yc;
                         yc = tmp;
+		break;
+		case EV_ROTATE_UD:
+			xc = screen_width - xc;
+			yc = screen_height - yc;
+		break;
+		default:
+		break;
                 }
 
-		switch (rotation) {
-			case RR_Rotate_0:
+/* X Segfaults on rotation setting
+                switch (rotation) {
+                        case RR_Rotate_0:
                                 v0 = xc;
                                 v1 = yc;
-				break;
-			case RR_Rotate_180:
-				v0 = screen_width - xc;
-				v1 = screen_height - yc;
-				break;
-			case RR_Rotate_90:
+                                break;
+                        case RR_Rotate_180:
+                                v0 = screen_width - xc;
+                                v1 = screen_height - yc;
+                                break;
+                        case RR_Rotate_90:
                                 tmp = xc;
-				v0  = screen_height - yc;
+                                v0  = screen_height - yc;
                                 v1  = tmp;
-				break;
-			case RR_Rotate_270:
+                                break;
+                        case RR_Rotate_270:
                                 tmp = xc;
-				v0 = yc;
-				v1 = screen_width - tmp;
-				break;
-			default:
-				break;
-		}
+                                v0 = yc;
+                                v1 = screen_width - tmp;
+                                break;
+                        default:
+                                break;
+                }
+
+
+*/
         }
 
         DBGOUT(2, "EVTouch: FINAL: v0=%d   v1=%d\n", v0, v1);
 
-        *x = v0;
-        *y = v1;
-
+        *x = xc;
+        *y = yc;
         return (TRUE);
 }
 
@@ -1133,8 +1140,9 @@ EVTouchPreInit(InputDriverPtr drv, IDevP
 
         xf86OptionListReport(local->options);
 
+
 	priv->libtouch = xcalloc(1, sizeof(LibTouchRec));
-	libtouchInit(priv->libtouch, local);
+	libtouchInit(priv->libtouch, local,PostButtonEvent);
 
         priv->screen_num    = xf86SetIntOption(local->options, "ScreenNumber", 0 );
 
@@ -1164,9 +1172,9 @@ EVTouchPreInit(InputDriverPtr drv, IDevP
         timeo = xf86SetIntOption(local->options, "LongtouchTimer", 160);
         libtouchSetLongtouchTimeo(priv->libtouch, timeo);
 
-        libtouchSetMoveLimit(priv->libtouch, 
-                             xf86SetIntOption( local->options, 
-                                               "MoveLimit", 180 ));
+	priv->move_limit = xf86SetIntOption( local->options,
+                                               "MoveLimit", 180 );
+        libtouchSetMoveLimit(priv->libtouch, priv->move_limit);
 
         priv->rotate     = EV_ROTATE_NONE;
         s = xf86FindOptionValue(local->options, "Rotate");
@@ -1175,7 +1183,11 @@ EVTouchPreInit(InputDriverPtr drv, IDevP
                         priv->rotate = EV_ROTATE_CW;                           
                 } else if (xf86NameCmp(s, "CCW") == 0 ) {
                         priv->rotate = EV_ROTATE_CCW;
-                } 
+                }  else if (xf86NameCmp(s, "UD") == 0 ) {
+                        priv->rotate = EV_ROTATE_UD;
+                }
+
+ 
         }
 
         if (priv->rotate == EV_ROTATE_NONE) {
@@ -1207,9 +1219,10 @@ EVTouchPreInit(InputDriverPtr drv, IDevP
                     priv->diff[i][0], priv->diff[i][1]);
         }
         
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 0
         xf86AlwaysCore(local, TRUE);
+#endif
         priv->touch_flags = 0;
-
         local->history_size = xf86SetIntOption( local->options, "HistorySize", 0 );
 
         /* prepare to process touch packets */
@@ -1232,6 +1245,7 @@ EVTouchPreInit(InputDriverPtr drv, IDevP
 
         xf86CloseSerial(local->fd);
         local->fd = -1;
+
         return (local);
 }
 
@@ -1243,3 +1257,58 @@ EVTouchPtrCtrl(DeviceIntPtr device, PtrC
      Ho Hum.
   */
 }
+
+
+static void
+PostMotionEvent(LocalDevicePtr local) {
+int cur_x, cur_y;
+EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private);
+
+ cur_x = priv->cur_x;
+ cur_y = priv->cur_y;
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 2
+ ConvertProc(local,0,2,priv->cur_x,priv->cur_y,0,0,0,0,&cur_x,&cur_y);
+#endif
+
+xf86PostMotionEvent (local->dev, TRUE, 0, 2, cur_x, cur_y);
+}
+
+static void
+PostProximityEvent(LocalDevicePtr local, int is_in) {
+int cur_x, cur_y;
+EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private);
+
+ cur_x = priv->cur_x;
+ cur_y = priv->cur_y;
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 2
+ ConvertProc(local,0,2,priv->cur_x,priv->cur_y,0,0,0,0,&cur_x,&cur_y);
+#endif
+
+xf86PostProximityEvent(local->dev, is_in, 0, 2, cur_x,cur_y);
+}
+
+static void
+PostButtonEvent(LocalDevicePtr local, int button, int is_down,int x, int y) {
+EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private);
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 2
+ ConvertProc(local,0,2,x,y,0,0,0,0,&x,&y);
+#endif
+
+xf86PostButtonEvent (local->dev, TRUE, button, is_down, 0, 2, x, y);
+}
+
+
+static void InputSetScreen(LocalDevicePtr local) {
+int cur_x, cur_y;
+EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private);
+
+ cur_x = priv->cur_x;
+ cur_y = priv->cur_y;
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) == 2
+ ConvertProc(local,0,2,priv->cur_x,priv->cur_y,0,0,0,0,&cur_x,&cur_y);
+#endif
+
+xf86XInputSetScreen(local,priv->screen_num,cur_x,cur_y);
+}
+
Index: xserver-xorg-input-evtouch/evtouch.h
===================================================================
--- xserver-xorg-input-evtouch.orig/evtouch.h	2008-02-02 21:49:20.823984091 +0900
+++ xserver-xorg-input-evtouch/evtouch.h	2008-02-02 21:49:39.734971242 +0900
@@ -42,6 +42,7 @@
 #define EV_ROTATE_NONE 0
 #define EV_ROTATE_CW   1
 #define EV_ROTATE_CCW  2
+#define EV_ROTATE_UD  3
 
 #define EV_AXIS_MIN_RES       0
 #define EV_AXIS_MAX_RES       1024
@@ -80,6 +81,7 @@ typedef struct _EVTouchPrivateRec
         int max_rel_y;  /* Maximum y                    */
 
         int drag_timer;
+	int move_limit;
         Bool emulate3;
         int emulate3_timeout;
         OsTimerPtr emulate3_timer;
@@ -138,6 +140,7 @@ typedef struct _EVTouchPrivateRec
 
         LibTouchRecPtr libtouch;
         LocalDevicePtr local;
+
 } EVTouchPrivateRec, *EVTouchPrivatePtr;
 
 
Index: xserver-xorg-input-evtouch/libtouch.c
===================================================================
--- xserver-xorg-input-evtouch.orig/libtouch.c	2008-02-02 21:49:36.899983517 +0900
+++ xserver-xorg-input-evtouch/libtouch.c	2008-02-02 21:49:39.734971242 +0900
@@ -52,6 +52,7 @@ typedef struct state {
         int  (*handle_state)(LibTouchRecPtr priv);
         void (*action)(LibTouchRecPtr priv, int btn, int x, int y);
         int btn;
+	int drag_btn;
 } state_t;
 
 
@@ -68,16 +69,14 @@ typedef enum states {
 static void btn_down_action(LibTouchRecPtr priv, int btn, int x, int y)
 {
         DBG(4, ErrorF("LibTouch: Issuing Button %d down\n", btn));
-        xf86PostButtonEvent(priv->local->dev, TRUE,
-                            btn, 1, 0, 2, x, y);
+        priv->post_button_proc(priv->local,btn, 1,x,y);
         priv->pressed_btn_stat |= 1 << btn;
 }
 
 static void btn_up_action(LibTouchRecPtr priv, int btn, int x, int y)
 {
         DBG(4, ErrorF("LibTouch: Issuing Button %d up\n", btn));
-        xf86PostButtonEvent(priv->local->dev, TRUE,
-                            btn, 0, 0, 2, x, y);
+        priv->post_button_proc(priv->local,btn, 0,x,y);
         priv->pressed_btn_stat &= ~(1 << btn);
 }
 
@@ -103,13 +102,13 @@ static int handle_oneandahalftap(LibTouc
 static void dump_configuration();
 
 state_t state_ar[] = {
-        {enter_untouched, handle_untouched, NULL, 0},
-        {enter_touched, handle_touched, NULL, 0},
-        {enter_longtouched, handle_longtouched, btn_down_action, 1},
-        {enter_moving, handle_moving, NULL, 0},
-        {enter_maybetap, handle_maybetap, btn_click_action, 1},
-        {enter_oneandahalftap, handle_oneandahalftap, btn_down_action, 3},
-        {NULL, NULL, NULL, -1},
+        {enter_untouched, handle_untouched, NULL, 0,-1},
+        {enter_touched, handle_touched, NULL, 0,-1},
+        {enter_longtouched, handle_longtouched, btn_down_action, 1,-1},
+        {enter_moving, handle_moving, NULL, 0,-1},
+        {enter_maybetap, handle_maybetap, btn_click_action, 1,-1},
+        {enter_oneandahalftap, handle_oneandahalftap, btn_down_action, 3,-1},
+        {NULL, NULL, NULL, -1,-1},
 };
 
 char *state_str[] = {
@@ -142,6 +141,16 @@ char *state_button_str[] = {
           NULL,
 };
 
+char *state_drag_str[] = {
+          "untouched_drag",
+          "touched_drag",
+          "longtouched_drag",
+          "moving_drag",
+          "maybetapped_drag",
+          "oneandahalftap_drag",
+          NULL,
+};
+
 char *action_str[] = {
         "down",
         "up",
@@ -177,13 +186,13 @@ void libtouchSetMoveLimit(LibTouchRecPtr
 }
 
 
-void libtouchInit(LibTouchRecPtr libtouch, LocalDevicePtr local)
+void libtouchInit(LibTouchRecPtr libtouch, LocalDevicePtr local,pointer post_button_proc)
 {
         int state_action_idx = 0;
         int state_button_idx = 0;
+        int state_drag_idx = 0;
         int action_idx = 0;
         int btn;
-
         char *str;
 
         xf86memset(libtouch, 0, sizeof(LibTouchRec));
@@ -193,6 +202,7 @@ void libtouchInit(LibTouchRecPtr libtouc
         libtouch->local = local;
         libtouch->move_limit = 30;
 
+	libtouch->post_button_proc = post_button_proc;
         /*
           Actions: up, down, click
 
@@ -228,6 +238,11 @@ void libtouchInit(LibTouchRecPtr libtouc
                 }
         }
 
+	/* parse dragging for the states, that is which button sent to be as down, when in state and about to change to MOVING state */
+        for (state_drag_idx = 0; state_drag_str[state_drag_idx] != NULL; state_drag_idx++) {
+                btn = xf86SetIntOption(local->options, state_drag_str[state_drag_idx], -1);
+                if (btn != -1) state_ar[state_drag_idx].drag_btn = btn;
+        }
 
         dump_configuration();
 }
@@ -359,10 +374,7 @@ static void enter_untouched(LibTouchRecP
         for (i = 0; i < bit_size; i++)
                 if (priv->pressed_btn_stat & (1 << i)) {
                         DBG(4, ErrorF("LibTouch: Issuing Button-release %d\n", i));
-                        xf86PostButtonEvent(priv->local->dev, TRUE,
-                                            i, 0, 0, 2,
-                                            priv->cur_x, 
-                                            priv->cur_y);
+			priv->post_button_proc(priv->local,i, 0,priv->cur_x,priv->cur_y);
                 }
 
         priv->pressed_btn_stat = 0;
@@ -445,6 +457,10 @@ static int handle_touched(LibTouchRecPtr
                 if (priv->cur_x != priv->old_x) {
                         dx = delta(priv->touch_x, priv->cur_x);
                         if (dx > priv->move_limit) {
+				if((state_ar[S_TOUCHED].drag_btn != -1) && (priv->touch_time != priv->now)){
+					libtouchSetTime(priv, GetTimeInMillis());
+					btn_down_action(priv, state_ar[S_TOUCHED].drag_btn, priv->cur_x,priv->cur_y);
+				}
                                 return S_MOVING;
                         }
                 }
@@ -454,7 +470,10 @@ static int handle_touched(LibTouchRecPtr
                 if (priv->cur_y != priv->old_y) {
                         dy = delta(priv->touch_y, priv->cur_y);
                         if (dy > priv->move_limit) {
-                                return S_MOVING;
+				if((state_ar[S_TOUCHED].drag_btn != -1) && (priv->touch_time != priv->now)){
+					libtouchSetTime(priv, GetTimeInMillis());
+					btn_down_action(priv, state_ar[S_TOUCHED].drag_btn, priv->cur_x,priv->cur_y);
+}                                return S_MOVING;
                         }
                 }
         }
@@ -500,7 +519,7 @@ static int handle_longtouched(LibTouchRe
         } else  {
                 if (priv->cur_x != priv->old_x) {
                         dx = delta(priv->touch_x, priv->cur_x);
-                        if (dx > priv->move_limit) 
+                        if (dx > priv->move_limit)
                                 rc = S_MOVING;
                 }
 
Index: xserver-xorg-input-evtouch/libtouch.h
===================================================================
--- xserver-xorg-input-evtouch.orig/libtouch.h	2008-02-02 21:49:36.899983517 +0900
+++ xserver-xorg-input-evtouch/libtouch.h	2008-02-02 21:49:39.734971242 +0900
@@ -50,6 +50,7 @@ typedef struct _libtouch {
         CARD32 past;
         CARD32 now;
         LocalDevicePtr local;
+        void                (*post_button_proc)(LocalDevicePtr local,int button, int is_down,int x,int y);
 } LibTouchRec, *LibTouchRecPtr;
 
 void libtouchSetDebugLevel(int level);
@@ -59,7 +60,7 @@ void libtouchSetOneandahalftapTimeo(LibT
 void libtouchSetTime(LibTouchRecPtr libtouch, CARD32 now);
 void libtouchSetMoveLimit(LibTouchRecPtr libtouch, int move_limit);
 
-void libtouchInit(LibTouchRecPtr libtouch, LocalDevicePtr local);
+void libtouchInit(LibTouchRecPtr libtouch, LocalDevicePtr local,pointer post_button_proc);
 
 void libtouchSetPos(LibTouchRecPtr libtouch, int x, int y);
 void libtouchTriggerSM(LibTouchRecPtr libtouch, LibTouchState_t touch);
