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