[Xorg] [PATCH] allow EmulateWheel to generate normal clicks too

Andrew Pimlott andrew at pimlott.net
Sun Aug 15 01:55:00 PDT 2004


I just got hooked on the EmulateWheel feature, for which I use
EmulateWheelButton 2.  But I also like having a third button, and I
believe it's possible to have the best of both:  If I press button 2 and
release it without moving the mouse, it's a button 2 press; otherwise,
it's an emulated wheel.

This doesn't work for everyone.  It requires you to press and release a
button without moving the mouse, which may be hard with a normal mouse,
but easy with a trackball or trackpoint.  And it requires you not to
press button 2 to scroll, then change your mind and release without
moving the mouse.  But I have found I never do this anyway, so the
behavior I've implemented works great.

I have put this behavior under the option EmulateWheelClickToo, which
defaults to off.

The patch is fairly straightforward, except someone should check my
addition to the man page, because I just aped what I saw.

Andrew


--- hw/xfree86/os-support/xf86OSmouse.h.orig	2004-08-15 00:24:15.000000000 -0700
+++ hw/xfree86/os-support/xf86OSmouse.h	2004-08-15 01:02:04.000000000 -0700
@@ -150,6 +150,8 @@
     Bool		emulateWheel;
     int			wheelInertia;
     int			wheelButtonMask;
+    Bool		wheelButtonClick;
+    Bool		wheelButtonMoved;
     int			negativeX;	/* Button values.  Unlike the Z and */
     int			positiveX;	/* W equivalents, these are button  */
     int			negativeY;	/* values rather than button masks. */
--- hw/xfree86/input/mouse/mouse.c.orig	2004-08-15 00:07:41.000000000 -0700
+++ hw/xfree86/input/mouse/mouse.c	2004-08-15 01:15:47.000000000 -0700
@@ -185,6 +185,7 @@
     OPTION_RESOLUTION,
     OPTION_EMULATE_WHEEL,
     OPTION_EMU_WHEEL_BUTTON,
+    OPTION_EMU_WHEEL_CLICK,
     OPTION_EMU_WHEEL_INERTIA,
     OPTION_X_AXIS_MAPPING,
     OPTION_Y_AXIS_MAPPING,
@@ -222,6 +223,7 @@
     { OPTION_RESOLUTION,	"Resolution",	  OPTV_INTEGER,	{0}, FALSE },
     { OPTION_EMULATE_WHEEL,	"EmulateWheel",	  OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_EMU_WHEEL_BUTTON,	"EmulateWheelButton", OPTV_INTEGER, {0}, FALSE },
+    { OPTION_EMU_WHEEL_CLICK,	"EmulateWheelClickToo", OPTV_BOOLEAN, {0}, FALSE },
     { OPTION_EMU_WHEEL_INERTIA,	"EmulateWheelInertia", OPTV_INTEGER, {0}, FALSE },
     { OPTION_X_AXIS_MAPPING,	"XAxisMapping",	  OPTV_STRING,	{0}, FALSE },
     { OPTION_Y_AXIS_MAPPING,	"YAxisMapping",	  OPTV_STRING,	{0}, FALSE },
@@ -619,6 +621,9 @@
 	}
 	pMse->wheelButtonMask = 1 << (wheelButton - 1);
 	
+        pMse->wheelButtonClick = xf86SetBoolOption(pInfo->options,
+                                        "EmulateWheelClickToo", FALSE);
+
 	pMse->wheelInertia = xf86SetIntOption(pInfo->options,
 					"EmulateWheelInertia", 10);
 	if (pMse->wheelInertia <= 0) {
@@ -689,8 +694,9 @@
 		    pInfo->name, pMse->negativeY, pMse->positiveY);
 	}
 	xf86Msg(X_CONFIG, "%s: EmulateWheel, EmulateWheelButton: %d, "
-			  "EmulateWheelInertia: %d\n",
-		pInfo->name, wheelButton, pMse->wheelInertia);
+			  "EmulateWheelClickToo: %d, EmulateWheelInertia: %d\n",
+		pInfo->name, wheelButton, pMse->wheelInertia,
+                pMse->wheelButtonClick);
     }
     if (origButtons != pMse->buttons)
 	from = X_CONFIG;
@@ -1992,6 +1998,8 @@
 
     /* Intercept wheel emulation. */
     if (pMse->emulateWheel && (buttons & pMse->wheelButtonMask)) {
+        pMse->wheelButtonMoved = pMse->wheelButtonMoved || dx || dy;
+
 	/* Y axis movement */
 	if (pMse->negativeY != MSE_NOAXISMAP) {
 	    pMse->wheelYDistance += dy;
@@ -2044,10 +2052,9 @@
 	    }
 	}
 
-	/* Absorb the mouse movement and the wheel button press. */
+	/* Absorb the mouse movement. */
 	dx = 0;
 	dy = 0;
-	buttons &= ~pMse->wheelButtonMask;
     }
 
     if (dx || dy)
@@ -2060,6 +2067,31 @@
 	else
 	    change = buttons ^ reverseBits(reverseMap, pMse->lastButtons);
 
+        /* We generally swallow wheelButtonMask events, except when a wheel
+         * button is released, and we haven't moved the mouse since a wheel
+         * button was pressed, and EmulateWheelClickToo is set. */
+
+        if (pMse->emulateWheel && change & pMse->wheelButtonMask) {
+            int wheelChange = change & pMse->wheelButtonMask;
+
+            while (wheelChange) {
+                id = ffs(wheelChange);
+                wheelChange &= ~(1 << (id - 1));
+                if (pMse->wheelButtonClick &&
+                    ! (buttons & (1 << (id - 1))) &&  /* released */
+                    ! pMse->wheelButtonMoved) {
+                        xf86PostButtonEvent(pInfo->dev, 0, id, 1, 0, 0);
+                        xf86PostButtonEvent(pInfo->dev, 0, id, 0, 0, 0);
+                }
+            }
+
+            if (! (buttons & pMse->wheelButtonMask))
+                pMse->wheelButtonMoved = 0;
+
+            buttons &= ~pMse->wheelButtonMask;
+            change  &= ~pMse->wheelButtonMask;
+        }
+
 	/*
 	 * adjust buttons state for drag locks!
 	 * if there is drag locks
--- hw/xfree86/input/mouse/mouse.man.orig	2004-08-15 01:04:07.000000000 -0700
+++ hw/xfree86/input/mouse/mouse.man	2004-08-15 01:16:00.000000000 -0700
@@ -112,6 +112,12 @@
 .B YAxisMapping
 settings.  Default: 4.
 .TP 7
+.BI "Option \*qEmulateWheelClickToo\*q \*q" boolean \*q
+Causes
+.B EmulateWheelButton 
+to generate normal clicks when the mouse isn't moved between press and
+release.  Default: off
+.TP 7
 .BI "Option \*qEmulateWheelInertia\*q \*q" integer \*q
 Specifies how far (in pixels) the pointer must move to generate button
 press/release events in wheel emulation mode.  Default: 50.





More information about the xorg mailing list