Hi all,

I have implemented a new feature for the mouse driver.
On the one side I like the copy and paste function with the middle mouse 
button in X11. On the other side I like the scrolling capability using the 
same middle mouse button and a trackpoint like it is built into most IBM 
notebooks. But with the current mouse driver it is not possible to have both.

I wanted to have both and just implemented this into the mouse driver. Using 
this patch there is a new mouse driver integer option called 
EmulateWheelTimeout.
If the EmulateWheel button is pressed and released within this timout the 
original button press/release event is emitted. If it is pressed longer than 
this timeout you can use use the mouse axis like usual with EmulateWheel for 
scrolling.

This is a very usefull feature for notebooks with trackpoints.

Attached is a patch to yesterdays cvs tree. Please apply!

Since I am not on any xfree list please cc me on reply.

   Many thanks in advance

       Mathias Fröhlich

-- 
Mathias Fröhlich, email: [EMAIL PROTECTED]
Index: programs/Xserver/hw/xfree86/input/mouse/mouse.c
===================================================================
RCS file: /cvs/xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c,v
retrieving revision 1.76
diff -u -r1.76 mouse.c
--- programs/Xserver/hw/xfree86/input/mouse/mouse.c	17 Sep 2003 03:46:32 -0000	1.76
+++ programs/Xserver/hw/xfree86/input/mouse/mouse.c	24 Sep 2003 20:23:24 -0000
@@ -186,6 +186,7 @@
     OPTION_EMULATE_WHEEL,
     OPTION_EMU_WHEEL_BUTTON,
     OPTION_EMU_WHEEL_INERTIA,
+    OPTION_EMU_WHEEL_TIMEOUT,
     OPTION_X_AXIS_MAPPING,
     OPTION_Y_AXIS_MAPPING,
     OPTION_AUTO_SOFT,
@@ -223,6 +224,7 @@
     { OPTION_EMULATE_WHEEL,	"EmulateWheel",	  OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_EMU_WHEEL_BUTTON,	"EmulateWheelButton", OPTV_INTEGER, {0}, FALSE },
     { OPTION_EMU_WHEEL_INERTIA,	"EmulateWheelInertia", OPTV_INTEGER, {0}, FALSE },
+    { OPTION_EMU_WHEEL_TIMEOUT,	"EmulateWheelTimeout", OPTV_INTEGER, {0}, FALSE },
     { OPTION_X_AXIS_MAPPING,	"XAxisMapping",	  OPTV_STRING,	{0}, FALSE },
     { OPTION_Y_AXIS_MAPPING,	"YAxisMapping",	  OPTV_STRING,	{0}, FALSE },
     { OPTION_AUTO_SOFT,		"AutoSoft",	  OPTV_BOOLEAN, {0}, FALSE },
@@ -581,7 +583,7 @@
 			pInfo->name, wheelButton);
 	    wheelButton = 4;
 	}
-	pMse->wheelButtonMask = 1 << (wheelButton - 1);
+	pMse->wheelButton = wheelButton;
 	
 	pMse->wheelInertia = xf86SetIntOption(pInfo->options,
 					"EmulateWheelInertia", 10);
@@ -590,6 +592,8 @@
 			pInfo->name, pMse->wheelInertia);
 	    pMse->wheelInertia = 50;
 	}
+	pMse->wheelButtonTimeout = xf86SetIntOption(pInfo->options,
+					"EmulateWheelButtonTimeout", 200);
 
 	pMse->negativeX = MSE_NOAXISMAP;
 	pMse->positiveX = MSE_NOAXISMAP;
@@ -1631,6 +1635,7 @@
 	pMse->lastButtons = 0;
 	pMse->emulateState = 0;
 	pMse->emulate3Pending = FALSE;
+	pMse->wheelButtonExpires = GetTimeInMillis ();
 	device->public.on = TRUE;
 	FlushButtons(pMse);
 	if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft)
@@ -1961,6 +1966,8 @@
     int truebuttons, emulateButtons;
     int id, change;
     int emuWheelDelta, emuWheelButton, emuWheelButtonMask;
+    int wheelButtonMask;
+    int ms;
 
     pMse = pInfo->private;
 
@@ -1970,64 +1977,102 @@
     else
 	buttons = reverseBits(reverseMap, buttons);
 
-    /* Intercept wheel emulation. */
-    if (pMse->emulateWheel && (buttons & pMse->wheelButtonMask)) {
-	/* Y axis movement */
-	if (pMse->negativeY != MSE_NOAXISMAP) {
-	    pMse->wheelYDistance += dy;
-	    if (pMse->wheelYDistance < 0) {
-		emuWheelDelta = -pMse->wheelInertia;
-		emuWheelButton = pMse->negativeY;
+    if (pMse->emulateWheel) {
+	/* Emulate wheel button handling */
+	wheelButtonMask = 1 << (pMse->wheelButton - 1);
+
+	if (pMse->protocolID == PROT_MMHIT)
+	    change = buttons ^ reverseBits(hitachMap, pMse->lastButtons);
+	else
+	    change = buttons ^ reverseBits(reverseMap, pMse->lastButtons);
+
+	if (change & wheelButtonMask) {
+	    if (buttons & wheelButtonMask) {
+		/* Start timeout handling */
+		pMse->wheelButtonExpires = GetTimeInMillis () + pMse->wheelButtonTimeout;
+		ms = - pMse->wheelButtonTimeout;  
 	    } else {
-		emuWheelDelta = pMse->wheelInertia;
-		emuWheelButton = pMse->positiveY;
-	    }
-	    emuWheelButtonMask = 1 << (emuWheelButton - 1);
-	    while (abs(pMse->wheelYDistance) > pMse->wheelInertia) {
-		pMse->wheelYDistance -= emuWheelDelta;
+		ms = pMse->wheelButtonExpires - GetTimeInMillis ();
 
-		/*
-		 * Synthesize the press and release, but not when the button
-		 * to be synthesized is already pressed "for real".
-		 */
-		if (!(emuWheelButtonMask & buttons) ||
-		    (emuWheelButtonMask & pMse->wheelButtonMask)) {
-		    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 1, 0, 0);
-		    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 0, 0, 0);
+		if (0 < ms) {
+		    /*
+		     * If the button is released early enough emit the button
+		     * press/release events
+		     */
+		    xf86PostButtonEvent(pInfo->dev, 0, pMse->wheelButton, 1, 0, 0);
+		    xf86PostButtonEvent(pInfo->dev, 0, pMse->wheelButton, 0, 0, 0);
 		}
 	    }
-	}
+	} else
+	    ms = pMse->wheelButtonExpires - GetTimeInMillis ();
 
-	/* X axis movement */
-	if (pMse->negativeX != MSE_NOAXISMAP) {
-	    pMse->wheelXDistance += dx;
-	    if (pMse->wheelXDistance < 0) {
-		emuWheelDelta = -pMse->wheelInertia;
-		emuWheelButton = pMse->negativeX;
-	    } else {
-		emuWheelDelta = pMse->wheelInertia;
-		emuWheelButton = pMse->positiveX;
-	    }
-	    emuWheelButtonMask = 1 << (emuWheelButton - 1);
-	    while (abs(pMse->wheelXDistance) > pMse->wheelInertia) {
-		pMse->wheelXDistance -= emuWheelDelta;
+	/* Intercept wheel emulation. */
+	if (buttons & wheelButtonMask) {
+	    if (ms <= 0) {
+		/* Y axis movement */
+		if (pMse->negativeY != MSE_NOAXISMAP) {
+		    pMse->wheelYDistance += dy;
+		    if (pMse->wheelYDistance < 0) {
+			emuWheelDelta = -pMse->wheelInertia;
+			emuWheelButton = pMse->negativeY;
+		    } else {
+			emuWheelDelta = pMse->wheelInertia;
+			emuWheelButton = pMse->positiveY;
+		    }
+		    emuWheelButtonMask = 1 << (emuWheelButton - 1);
+		    while (abs(pMse->wheelYDistance) > pMse->wheelInertia) {
+			pMse->wheelYDistance -= emuWheelDelta;
+
+			/*
+			 * Synthesize the press and release, but not when
+			 * the button to be synthesized is already pressed
+			 * "for real".
+			 */
+			if (!(emuWheelButtonMask & buttons) ||
+			    (emuWheelButtonMask & wheelButtonMask)) {
+			    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 1, 0, 0);
+			    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 0, 0, 0);
+			}
+		    }
+		}
 
-		/*
-		 * Synthesize the press and release, but not when the button
-		 * to be synthesized is already pressed "for real".
-		 */
-		if (!(emuWheelButtonMask & buttons) ||
-		    (emuWheelButtonMask & pMse->wheelButtonMask)) {
-		    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 1, 0, 0);
-		    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 0, 0, 0);
+		/* X axis movement */
+		if (pMse->negativeX != MSE_NOAXISMAP) {
+		    pMse->wheelXDistance += dx;
+		    if (pMse->wheelXDistance < 0) {
+			emuWheelDelta = -pMse->wheelInertia;
+			emuWheelButton = pMse->negativeX;
+		    } else {
+			emuWheelDelta = pMse->wheelInertia;
+			emuWheelButton = pMse->positiveX;
+		    }
+		    emuWheelButtonMask = 1 << (emuWheelButton - 1);
+		    while (abs(pMse->wheelXDistance) > pMse->wheelInertia) {
+			pMse->wheelXDistance -= emuWheelDelta;
+
+			/*
+			 * Synthesize the press and release, but not when
+			 * the button to be synthesized is already pressed
+			 * "for real".
+			 */
+			if (!(emuWheelButtonMask & buttons) ||
+			    (emuWheelButtonMask & wheelButtonMask)) {
+			    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 1, 0, 0);
+			    xf86PostButtonEvent(pInfo->dev, 0, emuWheelButton, 0, 0, 0);
+			}
+		    }
 		}
 	    }
-	}
 
-	/* Absorb the mouse movement and the wheel button press. */
-	dx = 0;
-	dy = 0;
-	buttons &= ~pMse->wheelButtonMask;
+	    /* Absorb the mouse movement while the wheel button is pressed. */
+	    dx = 0;
+	    dy = 0;
+	}
+	/*
+	 * Button events for the wheel button are only emitted through
+	 * the timeout code.
+	 */
+	buttons &= ~wheelButtonMask;
     }
 
     if (dx || dy)
Index: programs/Xserver/hw/xfree86/input/mouse/mouse.man
===================================================================
RCS file: /cvs/xc/programs/Xserver/hw/xfree86/input/mouse/mouse.man,v
retrieving revision 1.7
diff -u -r1.7 mouse.man
--- programs/Xserver/hw/xfree86/input/mouse/mouse.man	29 May 2003 21:48:10 -0000	1.7
+++ programs/Xserver/hw/xfree86/input/mouse/mouse.man	24 Sep 2003 20:23:25 -0000
@@ -116,6 +116,14 @@
 Specifies how far (in pixels) the pointer must move to generate button
 press/release events in wheel emulation mode.  Default: 50.
 .TP 7
+.BI "Option \*qEmulateWheelTimeout\*q \*q" integer \*q
+Specifies the time in milliseconds the
+.BR EmulateWheelButton
+must be pressed before wheel emulation is started. If the
+.BR EmulateWheelButton
+is released before this timeout, the original button press/release event
+is sent.  Default: 200.
+.TP 7
 .BI "Option \*qXAxisMapping\*q \*q" "N1 N2" \*q
 Specifies which buttons are mapped to motion in the X direction in wheel
 emulation mode.  Button number
Index: programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h
===================================================================
RCS file: /cvs/xc/programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h,v
retrieving revision 1.22
diff -u -r1.22 xf86OSmouse.h
--- programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h	24 Aug 2003 19:58:06 -0000	1.22
+++ programs/Xserver/hw/xfree86/os-support/xf86OSmouse.h	24 Sep 2003 20:23:26 -0000
@@ -162,6 +162,7 @@
     Bool		emulate3Buttons;
     Bool		emulate3ButtonsSoft;
     int			emulate3Timeout;/* Timeout for 3 button emulation */
+    int			wheelButtonTimeout;/* Timeout for the wheel button emulation */
     Bool		chordMiddle;
     Bool                flipXY;
     int                 invX;
@@ -189,7 +190,8 @@
     CARD32		emulate3Expires;/* time to fire emulation code */
     Bool		emulateWheel;
     int			wheelInertia;
-    int			wheelButtonMask;
+    int			wheelButton;
+    CARD32		wheelButtonExpires;
     int			negativeX;	/* Button values.  Unlike the Z and */
     int			positiveX;	/* W equivalents, these are button  */
     int			negativeY;	/* values rather than button masks. */

Reply via email to