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. */