Bug 3547

Summary: [PATCH] RFE: Generate MouseUp event on EmulateWheel button release
Product: xorg Reporter: Daniel Stone <daniel>
Component: Input/MouseAssignee: Xorg Project Team <xorg-team>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: high CC: erik.andren, heilong, mat
Version: unspecifiedKeywords: patch
Hardware: x86 (IA32)   
OS: Windows (All)   
Whiteboard:
i915 platform: i915 features:

Description FreeDesktop Bugzilla Database Corruption Fix User 2005-06-16 04:11:02 UTC
I've got a thinkpad with trackpoint, and am using EmulateWheel to (middle-button
as EmulateButton) to get horizontal/vertical scrolling. There is the same
feature on windoze, only there the middle button not only works as a
EmulateWheel button, but it also generates click events. I think an option
should be added so that the EmulateButton will generate click events on MouseUp
apart from scrolling events.
It's very inconvenient that I can't use my trackpoint middle button to open tabs
in background in mozilla, while I could do that in windoze.
Comment 1 FreeDesktop Bugzilla Database Corruption Fix User 2005-06-16 04:27:56 UTC
I believe the windoze drivers logic is the following - if the middle button is
pressed and released without changing the cursor position, then the click event
is generated. It could be implemented by keeping a counter of scrolling events
emitted, setting it to zero when an EmulateButton is pressed, incrementing it
each time any movement (and, thus, scrolling events) occurs, and generating a
normal EmulateButton click event if this counter is zero upon EmulateButton unpress.
Comment 2 FreeDesktop Bugzilla Database Corruption Fix User 2005-06-16 04:45:42 UTC
I've just found out that there's already a patch for this, made in Aug 2004! Why
isn't it included in the release yet?

http://lists.freedesktop.org/pipermail/xorg/2004-August/002404.html

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

    * Previous message: [Xorg] composite / kde
    * Next message: [Xorg] [PATCH] allow EmulateWheel to generate normal clicks too
    * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

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.


Comment 3 Alan Coopersmith 2005-10-04 00:17:30 UTC
Original reporter e-mail and comments lost in bugzilla disk death.
xorg-team archives show:

           Summary: RFE: Generate MouseUp event on EmulateWheel button
                    release
           Product: xorg
           Version: unspecified
          Platform: PC
        OS/Version: Windows XP
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Input/Mouse
        AssignedTo: xorg-team at lists.x.org
        ReportedBy: heilong at bluebottle.com


I've got a thinkpad with trackpoint, and am using EmulateWheel to (middle-button
as EmulateButton) to get horizontal/vertical scrolling. There is the same
feature on windoze, only there the middle button not only works as a
EmulateWheel button, but it also generates click events. I think an option
should be added so that the EmulateButton will generate click events on MouseUp
apart from scrolling events.
It's very inconvenient that I can't use my trackpoint middle button to open tabs
in background in mozilla, while I could do that in windoze.          
     
------- Additional Comments From heilong at bluebottle.com  2005-06-16 04:27 -------
I believe the windoze drivers logic is the following - if the middle button is
pressed and released without changing the cursor position, then the click event
is generated. It could be implemented by keeping a counter of scrolling events
emitted, setting it to zero when an EmulateButton is pressed, incrementing it
each time any movement (and, thus, scrolling events) occurs, and generating a
normal EmulateButton click event if this counter is zero upon EmulateButton
unpress.          
     
------- Additional Comments From heilong at bluebottle.com  2005-06-16 04:45 -------
I've just found out that there's already a patch for this, made in Aug 2004! Why
isn't it included in the release yet?

http://lists.freedesktop.org/pipermail/xorg/2004-August/002404.html

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

    * Previous message: [Xorg] composite / kde
    * Next message: [Xorg] [PATCH] allow EmulateWheel to generate normal clicks too
    * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

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.
Comment 4 Erik Andren 2006-04-18 05:09:00 UTC
Added patch keyword
Comment 5 Daniel Stone 2006-06-03 02:37:47 UTC
matthias, does this look alright to you?
Comment 6 Gene Pavlovsky 2006-06-04 01:01:51 UTC
eh, latest x.org's emulatewheel works exactly as needed
Comment 7 Daniel Stone 2006-06-04 11:06:27 UTC
even better

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.