--- mouse.c.orig 2006-05-06 22:40:59.000000000 +0200 +++ mouse.c 2006-05-06 22:51:57.000000000 +0200 @@ -1,3 +1,4 @@ +/* /var/tmp/portage/xorg-x11-6.8.2-r6/work/xc/programs/Xserver/hw/xfree86/input/mouse */ /* $XdotOrg: xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c,v 1.3 2004/07/24 17:35:39 herrb Exp $ */ /* $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c,v 1.79 2003/11/03 05:11:48 tsi Exp $ */ /* @@ -187,6 +188,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, @@ -226,6 +228,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 }, @@ -588,7 +591,7 @@ pInfo->name, wheelButton); wheelButton = 4; } - pMse->wheelButtonMask = 1 << (wheelButton - 1); + pMse->wheelButton = wheelButton; pMse->wheelInertia = xf86SetIntOption(pInfo->options, "EmulateWheelInertia", 10); @@ -597,6 +600,8 @@ pInfo->name, pMse->wheelInertia); pMse->wheelInertia = 50; } + pMse->wheelButtonTimeout = xf86SetIntOption(pInfo->options, + "EmulateWheelButtonTimeout", 200); pMse->negativeX = MSE_NOAXISMAP; pMse->positiveX = MSE_NOAXISMAP; @@ -1697,6 +1702,7 @@ pMse->lastButtons = 0; pMse->emulateState = 0; pMse->emulate3Pending = FALSE; + pMse->wheelButtonExpires = GetTimeInMillis (); device->public.on = TRUE; FlushButtons(pMse); if (pMse->emulate3Buttons || pMse->emulate3ButtonsSoft) @@ -2027,6 +2033,8 @@ int truebuttons, emulateButtons; int id, change; int emuWheelDelta, emuWheelButton, emuWheelButtonMask; + int wheelButtonMask; + int ms; pMse = pInfo->private; @@ -2036,64 +2044,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)