[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-input-evdev: Changes to 'upstream-unstable'



 .cvsignore       |   19 
 .gitignore       |   25 -
 ChangeLog        |   47 +
 Makefile.am      |   11 
 configure.ac     |    5 
 man/.cvsignore   |    2 
 man/.gitignore   |    3 
 man/evdev.man    |  323 +------------
 src/.cvsignore   |    6 
 src/.gitignore   |    6 
 src/Makefile.am  |    5 
 src/emuMB.c      |  334 +++++++++++++
 src/evdev.c      | 1330 ++++++++++++++++++++++++++++++++++++++-----------------
 src/evdev.h      |  323 ++-----------
 src/evdev_axes.c |  930 --------------------------------------
 src/evdev_btn.c  |  477 -------------------
 src/evdev_key.c  |  549 ----------------------
 17 files changed, 1441 insertions(+), 2954 deletions(-)

New commits:
commit b125b834f4ce4877204b9c8e98ad2641e2c7b082
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Sun Jun 22 17:52:58 2008 +0930

    evdev 2.0.1

diff --git a/configure.ac b/configure.ac
index c7df2a2..f7db989 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-input-evdev],
-        2.0.0,
+        2.0.1,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-input-evdev)
 

commit 05b20db8dbfb47bc370fe24e50ef563f1879be61
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Sat Jun 21 16:42:12 2008 +0930

    No need to finalize MB emulation after EvdevProbe anymore.
    
    Follow-up to 76800bfa75807e49398380b902f6c0f547cd4c0e.
    (cherry picked from commit 5a0ea39b79b27b7c3117661a21e7ab5eba3c9b24)

diff --git a/src/evdev.c b/src/evdev.c
index f029e8b..0078881 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1052,7 +1052,6 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
     /* parse the XKB options during kbd setup */
 
     if (EvdevProbe(pInfo)) {
-	EvdevMBEmuFinalize(pInfo);
 	close(pInfo->fd);
 	xf86DeleteInput(pInfo, 0);
         return NULL;

commit 43768d59da2c519dde5a8efaf0ff2b12b6c47fcc
Author: Simon Munton <simon@munton.demon.co.uk>
Date:   Sat Jun 21 10:19:07 2008 +0930

    Close file descriptor if EvdevProbe fails.
    
    Signed-off-by: Peter Hutterer <peter@cs.unisa.edu.au>
    (cherry picked from commit 373e13ae353d1e0022f8821adc528ebc5411d47d)

diff --git a/src/evdev.c b/src/evdev.c
index fa0545f..f029e8b 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1053,6 +1053,7 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
 
     if (EvdevProbe(pInfo)) {
 	EvdevMBEmuFinalize(pInfo);
+	close(pInfo->fd);
 	xf86DeleteInput(pInfo, 0);
         return NULL;
     }

commit 9c524f6963645bf42bbd41d4189d6319020a133d
Author: Keith Packard <keithp@keithp.com>
Date:   Fri Jun 20 18:20:55 2008 -0700

    Enable middle button emulation at DEVICE_ON instead of DEVICE_INIT.
    
    This ensures that the middle button emulation is re-enabled after VT switch,
    otherwise the block handler that deals with the timeouts would not get
    re-registered.
    
    Signed-off-by: Keith Packard <keithp@keithp.com>
    (cherry picked from commit 76800bfa75807e49398380b902f6c0f547cd4c0e)

diff --git a/src/evdev.c b/src/evdev.c
index 65b7185..fa0545f 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -835,6 +835,8 @@ EvdevProc(DeviceIntPtr device, int what)
             xf86Msg(X_WARNING, "%s: Grab failed (%s)\n", pInfo->name,
                     strerror(errno));
         xf86AddEnabledDevice(pInfo);
+	if (pEvdev->flags & EVDEV_BUTTON_EVENTS)
+	    EvdevMBEmuPreInit(pInfo);
 	device->public.on = TRUE;
 	break;
 	    
@@ -941,7 +943,6 @@ EvdevProbe(InputInfoPtr pInfo)
 
     if (TestBit(BTN_LEFT, key_bitmask)) {
         xf86Msg(X_INFO, "%s: Found mouse buttons\n", pInfo->name);
-	EvdevMBEmuPreInit(pInfo);
 	pEvdev->flags |= EVDEV_BUTTON_EVENTS;
 	has_buttons = TRUE;
     }

commit 04003a98a9ca1b4b0c32d319fab07ee7afc83c75
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Tue Jun 17 14:01:49 2008 +0930

    evdev 2.0.0

diff --git a/configure.ac b/configure.ac
index f366c9c..c7df2a2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-input-evdev],
-        1.99.4,
+        2.0.0,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-input-evdev)
 

commit 0443fb430f2481c1f0d0d83730a9145b5794f559
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Tue Jun 17 13:59:15 2008 +0930

    Shut up compiler warning "implicit declaration of function 'xf86Msg'"

diff --git a/src/emuMB.c b/src/emuMB.c
index f24a721..5def36b 100644
--- a/src/emuMB.c
+++ b/src/emuMB.c
@@ -34,6 +34,8 @@
 #include "config.h"
 #endif
 
+#include <xf86.h>
+
 #include "evdev.h"
 
 enum {

commit 998f52010f92dc79f2ace6048a2f3fd600a97582
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Thu Jun 12 11:23:10 2008 +0930

    Finalize MB emulation if EvdevProbe fails.
    
    This avoids segfaults when HAL is restarted behind our backs. Also, only init
    MB emulation when the device actually has a button.

diff --git a/src/evdev.c b/src/evdev.c
index 4d20b76..65b7185 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -941,6 +941,7 @@ EvdevProbe(InputInfoPtr pInfo)
 
     if (TestBit(BTN_LEFT, key_bitmask)) {
         xf86Msg(X_INFO, "%s: Found mouse buttons\n", pInfo->name);
+	EvdevMBEmuPreInit(pInfo);
 	pEvdev->flags |= EVDEV_BUTTON_EVENTS;
 	has_buttons = TRUE;
     }
@@ -1025,8 +1026,6 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
      */
     pEvdev->tool = 1;
 
-    EvdevMBEmuPreInit(pInfo);
-
     device = xf86CheckStrOption(dev->commonOptions, "Path", NULL);
     if (!device)
 	device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
@@ -1052,6 +1051,7 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
     /* parse the XKB options during kbd setup */
 
     if (EvdevProbe(pInfo)) {
+	EvdevMBEmuFinalize(pInfo);
 	xf86DeleteInput(pInfo, 0);
         return NULL;
     }

commit de07c04f5c2874b8e407913c3121e715e46653d2
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Wed Jun 11 11:24:07 2008 +0930

    evdev 1.99.4
    
    1.99.3 had a nasty bug, so here's a quick update.

diff --git a/configure.ac b/configure.ac
index 1b2f2fb..f366c9c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-input-evdev],
-        1.99.3,
+        1.99.4,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-input-evdev)
 

commit 01355b9d4b3ed92da42f90fb69384eb22cdcb3d9
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Wed Jun 11 11:19:04 2008 +0930

    If Emulate3Buttons is specified in the config, don't auto-deactivate it.
    
    Default setting is still "on" until middle button is pressed.  If the options
    is however explicitly stated in the config file, it takes the value from the
    config file, no matter if a middle button is present.

diff --git a/src/emuMB.c b/src/emuMB.c
index b2974b7..f24a721 100644
--- a/src/emuMB.c
+++ b/src/emuMB.c
@@ -36,6 +36,12 @@
 
 #include "evdev.h"
 
+enum {
+    MBEMU_DISABLED = 0,
+    MBEMU_ENABLED,
+    MBEMU_AUTO
+};
+
 /*
  * Lets create a simple finite-state machine for 3 button emulation:
  *
@@ -288,9 +294,17 @@ void
 EvdevMBEmuPreInit(InputInfoPtr pInfo)
 {
     EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
+    pEvdev->emulateMB.enabled = MBEMU_AUTO;
+
+    if (xf86FindOption(pInfo->options, "Emulate3Buttons"))
+    {
+        pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
+                                                      "Emulate3Buttons",
+                                                      MBEMU_ENABLED);
+        xf86Msg(X_INFO, "%s: Forcing middle mouse button emulation.\n",
+                        pInfo->name);
+    }
 
-    pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
-                                                  "Emulate3Buttons", TRUE);
     pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
                                                  "Emulate3Timeout", 50);
     RegisterBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
@@ -313,5 +327,6 @@ void
 EvdevMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
 {
     EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
-    pEvdev->emulateMB.enabled = enable;
+    if (pEvdev->emulateMB.enabled == MBEMU_AUTO)
+        pEvdev->emulateMB.enabled = enable;
 }

commit 9591dc1f6cc89208805b120eabd055e8dabd3e40
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Wed Jun 11 10:36:00 2008 +0930

    Remove wakeup handlers when device is closed.
    
    Less SIGABRTs are less exciting, but sometimes boredom is what we want.

diff --git a/src/emuMB.c b/src/emuMB.c
index 2855632..b2974b7 100644
--- a/src/emuMB.c
+++ b/src/emuMB.c
@@ -299,6 +299,15 @@ EvdevMBEmuPreInit(InputInfoPtr pInfo)
 
 }
 
+void
+EvdevMBEmuFinalize(InputInfoPtr pInfo)
+{
+    RemoveBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
+                                  EvdevMBEmuWakeupHandler,
+                                  (pointer)pInfo);
+
+}
+
 /* Enable/disable middle mouse button emulation. */
 void
 EvdevMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
diff --git a/src/evdev.c b/src/evdev.c
index 05eb760..4d20b76 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -843,6 +843,7 @@ EvdevProc(DeviceIntPtr device, int what)
             xf86Msg(X_WARNING, "%s: Release failed (%s)\n", pInfo->name,
                     strerror(errno));
         xf86RemoveEnabledDevice(pInfo);
+        EvdevMBEmuFinalize(pInfo);
 	device->public.on = FALSE;
 	break;
 
diff --git a/src/evdev.h b/src/evdev.h
index 9b88e16..cad1eed 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -75,6 +75,7 @@ BOOL EvdevMBEmuFilterEvent(InputInfoPtr, int, BOOL);
 void EvdevMBEmuWakeupHandler(pointer, int, pointer);
 void EvdevMBEmuBlockHandler(pointer, struct timeval**, pointer);
 void EvdevMBEmuPreInit(InputInfoPtr);
+void EvdevMBEmuFinalize(InputInfoPtr);
 void EvdevMBEmuEnable(InputInfoPtr, BOOL);
 
 #endif

commit 08ba40b2532bd61b60c9cf994b21300f596f7ebd
Author: Adam Jackson <ajax@redhat.com>
Date:   Tue Jun 10 17:35:33 2008 -0400

    evdev 1.99.3

diff --git a/configure.ac b/configure.ac
index b2da490..1b2f2fb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,7 +22,7 @@
 
 AC_PREREQ(2.57)
 AC_INIT([xf86-input-evdev],
-        1.99.2,
+        1.99.3,
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         xf86-input-evdev)
 

commit 39dc453691804648f34dbd856bd7e66cfdc59d66
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Tue Jun 10 22:48:01 2008 +0930

    Disable middle mouse button emulation when a real middle MB event is detected.
    
    Devices may report middle mouse buttons even if they don't have one (PS/2
    devices just don't know any better), so we can't be sure until we see the
    event.

diff --git a/man/evdev.man b/man/evdev.man
index b8807f0..f438f78 100644
--- a/man/evdev.man
+++ b/man/evdev.man
@@ -60,8 +60,8 @@ one of \*qPath\*q or \*qDevice\*q must be given.
 .BI "Option \*qEmulate3Buttons\*q \*q" boolean \*q
 Enable/disable the emulation of the third (middle) mouse button for mice
 which only have two physical buttons.  The third button is emulated by
-pressing both buttons simultaneously.  Default: on, unless the device reports
-the presence of a physical button 3.
+pressing both buttons simultaneously.  Default: on, until a middle mouse
+button event is registered.
 .TP 7
 .BI "Option \*qEmulate3Timeout\*q \*q" integer \*q
 Sets the timeout (in milliseconds) that the driver waits before deciding
diff --git a/src/evdev.c b/src/evdev.c
index 27d75dc..05eb760 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -226,6 +226,7 @@ EvdevReadInput(InputInfoPtr pInfo)
                     xf86PostButtonEvent(pInfo->dev, 0, 3, value, 0, 0);
                 break;
             case BTN_MIDDLE:
+                EvdevMBEmuEnable(pInfo, FALSE);
                 xf86PostButtonEvent(pInfo->dev, 0, 2, value, 0, 0);
                 break;
 
@@ -943,12 +944,6 @@ EvdevProbe(InputInfoPtr pInfo)
 	has_buttons = TRUE;
     }
 
-    if (TestBit(BTN_MIDDLE, key_bitmask)) {
-        xf86Msg(X_INFO, "%s: Found middle button. Disabling emulation.\n",
-                pInfo->name);
-        EvdevMBEmuEnable(pInfo, FALSE);
-    }
-
     for (i = 0; i < BTN_MISC; i++)
         if (TestBit(i, key_bitmask))
             break;

commit e8887435ac065ec3071b2d8bf0895e8cb196ec3d
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Tue Jun 10 15:55:40 2008 +0930

    Enable middle-mouse button emulation.
    
    Ported from xf86-input-mouse, with a few cleanups.

diff --git a/man/evdev.man b/man/evdev.man
index dbe94f4..b8807f0 100644
--- a/man/evdev.man
+++ b/man/evdev.man
@@ -10,6 +10,8 @@ evdev \- Generic Linux input driver
 .B  "  Driver \*qevdev\*q"
 .BI "  Option \*qDevice\*q   \*q" devpath \*q
 .BI "  Option \*qPath\*q     \*q" path \*q
+.BI "  Option \*qEmulate3Buttons\*q     \*q" True \*q
+.BI "  Option \*qEmulate3Timeout\*q     \*q" 50 \*q
 \ \ ...
 .B EndSection
 .fi
@@ -54,6 +56,17 @@ generally be of the form \*q/dev/input/by-path/xyz\*q, where xyz includes the
 name of the device. The mapping from device node to hardware is
 system-dependent. This option has precedence over the \*qDevice\*q option but
 one of \*qPath\*q or \*qDevice\*q must be given.
+.TP 7
+.BI "Option \*qEmulate3Buttons\*q \*q" boolean \*q
+Enable/disable the emulation of the third (middle) mouse button for mice
+which only have two physical buttons.  The third button is emulated by
+pressing both buttons simultaneously.  Default: on, unless the device reports
+the presence of a physical button 3.
+.TP 7
+.BI "Option \*qEmulate3Timeout\*q \*q" integer \*q
+Sets the timeout (in milliseconds) that the driver waits before deciding
+if two buttons where pressed "simultaneously" when 3 button emulation is
+enabled.  Default: 50.
 .SH AUTHORS
 Kristian Høgsberg.
 .SH "SEE ALSO"
diff --git a/src/Makefile.am b/src/Makefile.am
index 2221bbc..d0b9b63 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,4 +28,6 @@
 @DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
 @DRIVER_NAME@_drv_ladir = @inputdir@
 
-@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c
+@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
+                               @DRIVER_NAME@.h \
+                               emuMB.c
diff --git a/src/emuMB.c b/src/emuMB.c
new file mode 100644
index 0000000..2855632
--- /dev/null
+++ b/src/emuMB.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
+ * Copyright 1993 by David Dawes <dawes@xfree86.org>
+ * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
+ * Copyright 1994-2002 by The XFree86 Project, Inc.
+ * Copyright 2002 by Paul Elliott
+ * (Ported from xf86-input-mouse, above copyrights taken from there)
+ * Copyright © 2008 University of South Australia
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.  Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/* Middle mouse button emulation code. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "evdev.h"
+
+/*
+ * Lets create a simple finite-state machine for 3 button emulation:
+ *
+ * We track buttons 1 and 3 (left and right).  There are 11 states:
+ *   0 ground           - initial state
+ *   1 delayed left     - left pressed, waiting for right
+ *   2 delayed right    - right pressed, waiting for left
+ *   3 pressed middle   - right and left pressed, emulated middle sent
+ *   4 pressed left     - left pressed and sent
+ *   5 pressed right    - right pressed and sent
+ *   6 released left    - left released after emulated middle
+ *   7 released right   - right released after emulated middle
+ *   8 repressed left   - left pressed after released left
+ *   9 repressed right  - right pressed after released right
+ *  10 pressed both     - both pressed, not emulating middle
+ *
+ * At each state, we need handlers for the following events
+ *   0: no buttons down
+ *   1: left button down
+ *   2: right button down
+ *   3: both buttons down
+ *   4: emulate3Timeout passed without a button change
+ * Note that button events are not deltas, they are the set of buttons being
+ * pressed now.  It's possible (ie, mouse hardware does it) to go from (eg)
+ * left down to right down without anything in between, so all cases must be
+ * handled.
+ *
+ * a handler consists of three values:
+ *   0: action1
+ *   1: action2
+ *   2: new emulation state
+ *
+ * action > 0: ButtonPress
+ * action = 0: nothing
+ * action < 0: ButtonRelease
+ *
+ * The comment preceeding each section is the current emulation state.
+ * The comments to the right are of the form
+ *      <button state> (<events>) -> <new emulation state>
+ * which should be read as
+ *      If the buttons are in <button state>, generate <events> then go to
+ *      <new emulation state>.
+ */
+static signed char stateTab[11][5][3] = {
+/* 0 ground */
+  {
+    {  0,  0,  0 },   /* nothing -> ground (no change) */
+    {  0,  0,  1 },   /* left -> delayed left */
+    {  0,  0,  2 },   /* right -> delayed right */
+    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  0,  0, -1 }    /* timeout N/A */
+  },
+/* 1 delayed left */
+  {
+    {  1, -1,  0 },   /* nothing (left event) -> ground */
+    {  0,  0,  1 },   /* left -> delayed left (no change) */
+    {  1, -1,  2 },   /* right (left event) -> delayed right */
+    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  1,  0,  4 },   /* timeout (left press) -> pressed left */
+  },
+/* 2 delayed right */
+  {
+    {  3, -3,  0 },   /* nothing (right event) -> ground */
+    {  3, -3,  1 },   /* left (right event) -> delayed left (no change) */
+    {  0,  0,  2 },   /* right -> delayed right (no change) */
+    {  2,  0,  3 },   /* left & right (middle press) -> pressed middle */
+    {  3,  0,  5 },   /* timeout (right press) -> pressed right */
+  },
+/* 3 pressed middle */
+  {
+    { -2,  0,  0 },   /* nothing (middle release) -> ground */
+    {  0,  0,  7 },   /* left -> released right */
+    {  0,  0,  6 },   /* right -> released left */
+    {  0,  0,  3 },   /* left & right -> pressed middle (no change) */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 4 pressed left */
+  {
+    { -1,  0,  0 },   /* nothing (left release) -> ground */
+    {  0,  0,  4 },   /* left -> pressed left (no change) */
+    { -1,  0,  2 },   /* right (left release) -> delayed right */
+    {  3,  0, 10 },   /* left & right (right press) -> pressed both */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 5 pressed right */
+  {
+    { -3,  0,  0 },   /* nothing (right release) -> ground */
+    { -3,  0,  1 },   /* left (right release) -> delayed left */
+    {  0,  0,  5 },   /* right -> pressed right (no change) */
+    {  1,  0, 10 },   /* left & right (left press) -> pressed both */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 6 released left */
+  {
+    { -2,  0,  0 },   /* nothing (middle release) -> ground */
+    { -2,  0,  1 },   /* left (middle release) -> delayed left */
+    {  0,  0,  6 },   /* right -> released left (no change) */
+    {  1,  0,  8 },   /* left & right (left press) -> repressed left */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 7 released right */
+  {
+    { -2,  0,  0 },   /* nothing (middle release) -> ground */
+    {  0,  0,  7 },   /* left -> released right (no change) */
+    { -2,  0,  2 },   /* right (middle release) -> delayed right */
+    {  3,  0,  9 },   /* left & right (right press) -> repressed right */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 8 repressed left */
+  {
+    { -2, -1,  0 },   /* nothing (middle release, left release) -> ground */
+    { -2,  0,  4 },   /* left (middle release) -> pressed left */
+    { -1,  0,  6 },   /* right (left release) -> released left */
+    {  0,  0,  8 },   /* left & right -> repressed left (no change) */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 9 repressed right */
+  {
+    { -2, -3,  0 },   /* nothing (middle release, right release) -> ground */
+    { -3,  0,  7 },   /* left (right release) -> released right */
+    { -2,  0,  5 },   /* right (middle release) -> pressed right */
+    {  0,  0,  9 },   /* left & right -> repressed right (no change) */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+/* 10 pressed both */
+  {
+    { -1, -3,  0 },   /* nothing (left release, right release) -> ground */
+    { -3,  0,  4 },   /* left (right release) -> pressed left */
+    { -1,  0,  5 },   /* right (left release) -> pressed right */
+    {  0,  0, 10 },   /* left & right -> pressed both (no change) */
+    {  0,  0, -1 },   /* timeout N/A */
+  },
+};
+
+
+int
+EvdevMBEmuTimer(InputInfoPtr pInfo)
+{
+    EvdevPtr pEvdev = pInfo->private;
+    int	sigstate;
+    int id;
+
+    sigstate = xf86BlockSIGIO ();
+
+    pEvdev->emulateMB.pending = FALSE;
+    if ((id = stateTab[pEvdev->emulateMB.state][4][0]) != 0) {
+        xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
+        pEvdev->emulateMB.state =
+            stateTab[pEvdev->emulateMB.state][4][2];
+    } else {
+        ErrorF("Got unexpected buttonTimer in state %d\n",
+                pEvdev->emulateMB.state);
+    }
+
+    xf86UnblockSIGIO (sigstate);
+    return 0;
+}
+
+
+/**
+ * Emulate a middle button on button press.
+ *
+ * @param code Evdev event code (BTN_LEFT or BTN_RIGHT)
+ * @param press TRUE if press, FALSE if release.
+ *
+ * @return TRUE if event was swallowed by middle mouse button emulation, FALSE
+ * otherwise.
+ */
+BOOL
+EvdevMBEmuFilterEvent(InputInfoPtr pInfo, int code, BOOL press)
+{
+    EvdevPtr pEvdev = pInfo->private;
+    int id;
+    int *btstate;
+    int ret = FALSE;
+
+    if (!pEvdev->emulateMB.enabled)
+        return ret;
+
+    /* don't care about other buttons */
+    if (code != BTN_LEFT && code != BTN_RIGHT)
+        return ret;
+
+    btstate = &pEvdev->emulateMB.buttonstate;
+    if (press)
+        *btstate |= (code == BTN_LEFT) ? 0x1 : 0x2;
+    else
+        *btstate &= (code == BTN_LEFT) ? ~0x1 : ~0x2;
+
+    if ((id = stateTab[pEvdev->emulateMB.state][*btstate][0]) != 0)
+    {
+        xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
+        ret = TRUE;
+    }
+    if ((id = stateTab[pEvdev->emulateMB.state][*btstate][1]) != 0)
+    {
+        xf86PostButtonEvent(pInfo->dev, 0, abs(id), (id >= 0), 0, 0);
+        ret = TRUE;
+    }
+
+    pEvdev->emulateMB.state =
+        stateTab[pEvdev->emulateMB.state][*btstate][2];
+
+    if (stateTab[pEvdev->emulateMB.state][4][0] != 0) {
+        pEvdev->emulateMB.expires = GetTimeInMillis () + pEvdev->emulateMB.timeout;
+        pEvdev->emulateMB.pending = TRUE;
+        ret = TRUE;
+    } else {
+        pEvdev->emulateMB.pending = FALSE;
+    }
+
+    return ret;
+}
+
+
+void EvdevMBEmuWakeupHandler(pointer data,
+                             int i,
+                             pointer LastSelectMask)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)data;
+    EvdevPtr     pEvdev = (EvdevPtr)pInfo->private;
+    int ms;
+
+    if (pEvdev->emulateMB.pending)
+    {
+        ms = pEvdev->emulateMB.expires - GetTimeInMillis();
+        if (ms <= 0)
+            EvdevMBEmuTimer(pInfo);
+    }
+}
+
+void EvdevMBEmuBlockHandler(pointer data,
+                            struct timeval **waitTime,
+                            pointer LastSelectMask)
+{
+    InputInfoPtr    pInfo = (InputInfoPtr) data;
+    EvdevPtr        pEvdev= (EvdevPtr) pInfo->private;
+    int             ms;
+
+    if (pEvdev->emulateMB.pending)
+    {
+        ms = pEvdev->emulateMB.expires - GetTimeInMillis ();
+        if (ms <= 0)
+            ms = 0;
+        AdjustWaitForDelay (waitTime, ms);
+    }
+}
+
+void
+EvdevMBEmuPreInit(InputInfoPtr pInfo)
+{
+    EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
+
+    pEvdev->emulateMB.enabled = xf86SetBoolOption(pInfo->options,
+                                                  "Emulate3Buttons", TRUE);
+    pEvdev->emulateMB.timeout = xf86SetIntOption(pInfo->options,
+                                                 "Emulate3Timeout", 50);
+    RegisterBlockAndWakeupHandlers (EvdevMBEmuBlockHandler,
+                                    EvdevMBEmuWakeupHandler,
+                                    (pointer)pInfo);
+
+}
+
+/* Enable/disable middle mouse button emulation. */
+void
+EvdevMBEmuEnable(InputInfoPtr pInfo, BOOL enable)
+{
+    EvdevPtr pEvdev = (EvdevPtr)pInfo->private;
+    pEvdev->emulateMB.enabled = enable;
+}
diff --git a/src/evdev.c b/src/evdev.c
index 2f093c4..27d75dc 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -33,7 +33,6 @@
 #include <X11/XF86keysym.h>
 #include <X11/extensions/XIproto.h>
 
-#include <linux/input.h>
 #include <unistd.h>
 
 #include <misc.h>
@@ -44,10 +43,7 @@
 #include <exevents.h>
 #include <mipointer.h>
 
-#if defined(XKB)
-/* XXX VERY WRONG.  this is a client side header. */
-#include <X11/extensions/XKBstr.h>
-#endif
+#include "evdev.h"
 
 #include <xf86Module.h>
 
@@ -91,25 +87,6 @@
 #define MODEFLAG	8
 #define COMPOSEFLAG	16
 
-typedef struct {
-    int kernel24;
-    int screen;
-    int min_x, min_y, max_x, max_y;
-    int abs_x, abs_y, old_x, old_y;
-    int flags;
-    int tool;
-
-    /* XKB stuff has to be per-device rather than per-driver */
-    int noXkb;
-#ifdef XKB
-    char                    *xkb_rules;
-    char                    *xkb_model;
-    char                    *xkb_layout;
-    char                    *xkb_variant;
-    char                    *xkb_options;
-    XkbComponentNamesRec    xkbnames;
-#endif
-} EvdevRec, *EvdevPtr;
 
 static const char *evdevDefaults[] = {
     "XkbRules",     "base",
@@ -241,10 +218,12 @@ EvdevReadInput(InputInfoPtr pInfo)
             switch (ev.code) {
 	    /* swap here, pretend we're an X-conformant device. */
             case BTN_LEFT:
-                xf86PostButtonEvent(pInfo->dev, 0, 1, value, 0, 0);
+                if (!EvdevMBEmuFilterEvent(pInfo, ev.code, value))
+                    xf86PostButtonEvent(pInfo->dev, 0, 1, value, 0, 0);
                 break;
             case BTN_RIGHT:
-                xf86PostButtonEvent(pInfo->dev, 0, 3, value, 0, 0);
+                if (!EvdevMBEmuFilterEvent(pInfo, ev.code, value))
+                    xf86PostButtonEvent(pInfo->dev, 0, 3, value, 0, 0);
                 break;
             case BTN_MIDDLE:
                 xf86PostButtonEvent(pInfo->dev, 0, 2, value, 0, 0);
@@ -964,6 +943,12 @@ EvdevProbe(InputInfoPtr pInfo)
 	has_buttons = TRUE;
     }
 
+    if (TestBit(BTN_MIDDLE, key_bitmask)) {
+        xf86Msg(X_INFO, "%s: Found middle button. Disabling emulation.\n",
+                pInfo->name);
+        EvdevMBEmuEnable(pInfo, FALSE);
+    }
+
     for (i = 0; i < BTN_MISC; i++)
         if (TestBit(i, key_bitmask))
             break;
@@ -1044,6 +1029,8 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
      */
     pEvdev->tool = 1;
 
+    EvdevMBEmuPreInit(pInfo);
+
     device = xf86CheckStrOption(dev->commonOptions, "Path", NULL);
     if (!device)
 	device = xf86CheckStrOption(dev->commonOptions, "Device", NULL);
@@ -1052,7 +1039,7 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
 	xf86DeleteInput(pInfo, 0);
         return NULL;
     }
-	
+
     xf86Msg(deviceFrom, "%s: Device: \"%s\"\n", pInfo->name, device);
     do {
         pInfo->fd = open(device, O_RDWR, 0);
diff --git a/src/evdev.h b/src/evdev.h
new file mode 100644
index 0000000..9b88e16
--- /dev/null
+++ b/src/evdev.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2004-2008 Red Hat, Inc.
+ * Copyright © 2008 University of South Australia
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat
+ * not be used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.  Red
+ * Hat makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors:
+ *	Kristian Høgsberg (krh@redhat.com)
+ *	Adam Jackson (ajax@redhat.com)
+ *	Peter Hutterer (peter@cs.unisa.edu.au)
+ */
+
+#ifndef EVDEV_H
+#define EVDEV_H
+
+#include <linux/input.h>
+
+#include <xf86Xinput.h>
+#include <xf86_OSproc.h>
+
+#if defined(XKB)
+/* XXX VERY WRONG.  this is a client side header. */
+#include <X11/extensions/XKBstr.h>
+#endif
+
+typedef struct {
+    int kernel24;
+    int screen;
+    int min_x, min_y, max_x, max_y;
+    int abs_x, abs_y, old_x, old_y;
+    int flags;
+    int tool;
+
+    /* XKB stuff has to be per-device rather than per-driver */
+    int noXkb;
+#ifdef XKB
+    char                    *xkb_rules;
+    char                    *xkb_model;
+    char                    *xkb_layout;
+    char                    *xkb_variant;
+    char                    *xkb_options;
+    XkbComponentNamesRec    xkbnames;
+#endif
+    /* Middle mouse button emulation */
+    struct {
+        BOOL                enabled;
+        BOOL                pending;     /* timer waiting? */
+        int                 buttonstate; /* phys. button state */
+        int                 state;       /* state machine (see bt3emu.c) */
+        Time                expires;     /* time of expiry */
+        Time                timeout;
+    } emulateMB;
+} EvdevRec, *EvdevPtr;
+
+/* Middle Button emulation */
+int  EvdevMBEmuTimer(InputInfoPtr);
+BOOL EvdevMBEmuFilterEvent(InputInfoPtr, int, BOOL);
+void EvdevMBEmuWakeupHandler(pointer, int, pointer);
+void EvdevMBEmuBlockHandler(pointer, struct timeval**, pointer);
+void EvdevMBEmuPreInit(InputInfoPtr);
+void EvdevMBEmuEnable(InputInfoPtr, BOOL);
+
+#endif

commit b0f6987ee6b133e28f3af18da62cfb5ca79fbe07
Author: Peter Hutterer <peter@cs.unisa.edu.au>
Date:   Tue Jun 10 22:41:43 2008 +0930

    Plug a memory leak, we allocated pEvdev twice, dropping the first memory area.

diff --git a/src/evdev.c b/src/evdev.c
index bd01316..2f093c4 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1029,10 +1029,6 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
     pInfo->always_core_feedback = 0;
     pInfo->conf_idev = dev;
 
-    if (!(pEvdev = xcalloc(sizeof(*pEvdev), 1)))
-        return pInfo;
-    pInfo->private = pEvdev;
-
     if (!(pEvdev = xcalloc(sizeof(EvdevRec), 1)))
         return pInfo;
 

commit fec73e1418a4da1b64496faca27b06fef0aa5206
Author: Sven Wegener <swegener@gentoo.org>
Date:   Sat Jun 7 13:01:22 2008 +0200

    evdev: Port b4a5a204 "Fix pointer crossing screen bug." to current master branch
    
    The commit b4a5a204 fixed an issue, where we can't move the pointer to
    other screens and this happens in current master branch again. This commit
    ports the old commit to the current master branch.
    
    Signed-off-by: Sven Wegener <swegener@gentoo.org>
    Signed-off-by: Peter Hutterer <peter@cs.unisa.edu.au>

diff --git a/src/evdev.c b/src/evdev.c
index b146d41..bd01316 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -767,11 +767,11 @@ EvdevAddRelClass(DeviceIntPtr device)
         return !Success;
 
     /* X valuator */
-    xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1);
+    xf86InitValuatorAxisStruct(device, 0, -1, -1, 1, 0, 1);
     xf86InitValuatorDefaults(device, 0);
 
     /* Y valuator */
-    xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1);
+    xf86InitValuatorAxisStruct(device, 1, -1, -1, 1, 0, 1);
     xf86InitValuatorDefaults(device, 1);
     xf86MotionHistoryAllocate(pInfo);


Reply to: