542d25d
From deab888bb3bb2a56963da50ff551bd66fbd858a1 Mon Sep 17 00:00:00 2001
542d25d
From: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
Date: Tue, 29 Jun 2010 13:49:27 +1000
542d25d
Subject: [PATCH 1/5] xkb: Mark switch case fallthrough with comment.
542d25d
542d25d
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
---
542d25d
 xkb/xkbActions.c |    2 ++
542d25d
 1 files changed, 2 insertions(+), 0 deletions(-)
542d25d
542d25d
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
542d25d
index 4c7bce2..6a7f36d 100644
542d25d
--- a/xkb/xkbActions.c
542d25d
+++ b/xkb/xkbActions.c
542d25d
@@ -625,6 +625,8 @@ _XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
542d25d
 		    break;
542d25d
 		}
542d25d
 		xkbi->lockedPtrButtons&= ~(1<
542d25d
+
542d25d
+		/* fallthrough */
542d25d
 	    case XkbSA_PtrBtn:
542d25d
 		XkbDDXFakeDeviceButton(xkbi->device, 0, button);
542d25d
 		break;
542d25d
-- 
542d25d
1.7.1
542d25d
542d25d
From 50b6311dbd2594acc36d6856fdde8623459f1374 Mon Sep 17 00:00:00 2001
542d25d
From: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
Date: Tue, 29 Jun 2010 12:12:53 +1000
542d25d
Subject: [PATCH 2/5] xkb: merge lockedPtrButtons state from all attached SDs.
542d25d
MIME-Version: 1.0
542d25d
Content-Type: text/plain; charset=UTF-8
542d25d
Content-Transfer-Encoding: 8bit
542d25d
542d25d
Problem:
542d25d
lockedPtrButtons keeps the state of the buttons locked by a PointerKeys button
542d25d
press. Unconditionally clearing the bits may cause stuck buttons in this
542d25d
sequence of events:
542d25d
542d25d
1. type Shift + NumLock to enable PointerKeys
542d25d
2. type 0/Ins on keypad to emulate Button 1 press
542d25d
        → button1 press event to client
542d25d
3. press and release button 1 on physical mouse
542d25d
        → button1 release event to client
542d25d
542d25d
Button 1 on the MD is now stuck and cannot be released.
542d25d
542d25d
Cause:
542d25d
XKB PointerKeys button events are posted through the XTEST pointer device.
542d25d
Once a press is generated, the XTEST device's button is down. The DIX merges
542d25d
the button state of all attached SDs, hence the MD will have a button down
542d25d
while the XTEST device has a button down.
542d25d
542d25d
PointerKey button events are only generated on the master device to avoid
542d25d
duplicate events (see XkbFakeDeviceButton()). If the MD has the
542d25d
lockedPtrButtons bit cleared by a release event on a physical device, no
542d25d
such event is generated when a keyboard device triggers the PointerKey
542d25d
ButtonRelease trigger. Since the event - if generated - is posted through
542d25d
the XTEST pointer device, lack of a generated ButtonRelease event on the
542d25d
XTEST pointer device means the button is never released, resulting in the
542d25d
stuck button observed above.
542d25d
542d25d
Solution:
542d25d
This patch merges the MD's lockedPtrButtons with the one of all attached
542d25d
slave devices on release events. Thus, as long as one attached keyboard has
542d25d
a lockedPtrButtons bit set, this bit is kept in the MD. Once a PointerKey
542d25d
button is released on all keyboards, the matching release event is emulated
542d25d
from the MD through the XTEST pointer device, thus also releasing the button
542d25d
in the DIX.
542d25d
542d25d
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
---
542d25d
 include/xkbsrv.h |    3 +++
542d25d
 xkb/xkbAccessX.c |   18 +++++++++++++++++-
542d25d
 xkb/xkbActions.c |    8 ++++++++
542d25d
 xkb/xkbUtils.c   |   26 ++++++++++++++++++++++++++
542d25d
 4 files changed, 54 insertions(+), 1 deletions(-)
542d25d
542d25d
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
542d25d
index c0cd501..f0db0e4 100644
542d25d
--- a/include/xkbsrv.h
542d25d
+++ b/include/xkbsrv.h
542d25d
@@ -933,6 +933,9 @@ extern int XkbGetEffectiveGroup(
542d25d
         XkbStatePtr             /* xkbstate */,
542d25d
         CARD8                   /* keycode */);
542d25d
 
542d25d
+extern void XkbMergeLockedPtrBtns(
542d25d
+        DeviceIntPtr            /* master */);
542d25d
+
542d25d
 #include "xkbfile.h"
542d25d
 #include "xkbrules.h"
542d25d
 
542d25d
diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
542d25d
index be1dcee..e3fdc06 100644
542d25d
--- a/xkb/xkbAccessX.c
542d25d
+++ b/xkb/xkbAccessX.c
542d25d
@@ -707,8 +707,24 @@ DeviceEvent     *event = &ev->device_event;
542d25d
 	    changed |= XkbPointerButtonMask;
542d25d
     }
542d25d
     else if (event->type == ET_ButtonRelease) {
542d25d
-	if (xkbi)
542d25d
+	if (xkbi) {
542d25d
 	    xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7));
542d25d
+
542d25d
+            /* Merge this MD's lockedPtrButtons with the one of all
542d25d
+             * attached slave devices.
542d25d
+             * The DIX uses a merged button state for MDs, not
542d25d
+             * releasing buttons until the last SD has released
542d25d
+             * thenm. If we unconditionally clear the
542d25d
+             * lockedPtrButtons bit on the MD, a PointerKeys button
542d25d
+             * release on the SD keyboard won't generate the required fake button
542d25d
+             * event on the XTEST pointer, thus never processing the
542d25d
+             * button event in the DIX and the XTEST pointer's
542d25d
+             * buttons stay down - result is a stuck button.
542d25d
+             */
542d25d
+	    if (IsMaster(dev))
542d25d
+                XkbMergeLockedPtrBtns(dev);
542d25d
+	}
542d25d
+
542d25d
 	changed |= XkbPointerButtonMask;
542d25d
     }
542d25d
 
542d25d
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
542d25d
index 6a7f36d..ab52b6a 100644
542d25d
--- a/xkb/xkbActions.c
542d25d
+++ b/xkb/xkbActions.c
542d25d
@@ -626,6 +626,14 @@ _XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
542d25d
 		}
542d25d
 		xkbi->lockedPtrButtons&= ~(1<
542d25d
 
542d25d
+		if (IsMaster(xkbi->device))
542d25d
+		{
542d25d
+		    XkbMergeLockedPtrBtns(xkbi->device);
542d25d
+                    /* One SD still has lock set, don't post event */
542d25d
+		    if ((xkbi->lockedPtrButtons & (1 << button)) != 0)
542d25d
+			break;
542d25d
+		}
542d25d
+
542d25d
 		/* fallthrough */
542d25d
 	    case XkbSA_PtrBtn:
542d25d
 		XkbDDXFakeDeviceButton(xkbi->device, 0, button);
542d25d
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
542d25d
index b1e0e55..d7d1935 100644
542d25d
--- a/xkb/xkbUtils.c
542d25d
+++ b/xkb/xkbUtils.c
542d25d
@@ -2190,3 +2190,29 @@ XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode)
542d25d
 
542d25d
     return effectiveGroup;
542d25d
 }
542d25d
+
542d25d
+/* Merge the lockedPtrButtons from all attached SDs for the given master
542d25d
+ * device into the MD's state.
542d25d
+ */
542d25d
+void
542d25d
+XkbMergeLockedPtrBtns(DeviceIntPtr master)
542d25d
+{
542d25d
+    DeviceIntPtr d = inputInfo.devices;
542d25d
+    XkbSrvInfoPtr xkbi = NULL;
542d25d
+
542d25d
+    if (!IsMaster(master))
542d25d
+        return;
542d25d
+
542d25d
+    if (!master->key)
542d25d
+        return;
542d25d
+
542d25d
+    xkbi = master->key->xkbInfo;
542d25d
+    xkbi->lockedPtrButtons = 0;
542d25d
+
542d25d
+    for (; d; d = d->next) {
542d25d
+        if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key)
542d25d
+            continue;
542d25d
+
542d25d
+        xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons;
542d25d
+    }
542d25d
+}
542d25d
-- 
542d25d
1.7.1
542d25d
542d25d
From 4a4224f5d786035af88c251a9ee177217e8f77fd Mon Sep 17 00:00:00 2001
542d25d
From: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
Date: Wed, 14 Apr 2010 10:54:29 +1000
542d25d
Subject: [PATCH 3/5] xkb: rename XkbFakeDeviceButton and XkbFakeDeviceMotion, move into xkbActions.c
542d25d
542d25d
The name XkbDDXFakeDeviceButton and XkbDDXFakeDeviceMotion is somewhat
542d25d
misleading, there's no DDX involved in the game at all anymore.
542d25d
542d25d
This removes XkbFakeDeviceMotion and XkbFakeDeviceButton from the API where
542d25d
it arguably shouldn't have been in the first place.
542d25d
542d25d
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
Reviewed-by: Daniel Stone <daniel@fooishbar.org>
542d25d
Reviewed-by: Dan Nicholson <dbn.lists@gmail.com>
542d25d
---
542d25d
 include/xkbsrv.h |   13 -------
542d25d
 xkb/Makefile.am  |    4 +--
542d25d
 xkb/ddxDevBtn.c  |   69 --------------------------------------
542d25d
 xkb/ddxFakeMtn.c |   64 -----------------------------------
542d25d
 xkb/xkbActions.c |   97 ++++++++++++++++++++++++++++++++++++++++++++++-------
542d25d
 5 files changed, 85 insertions(+), 162 deletions(-)
542d25d
 delete mode 100644 xkb/ddxDevBtn.c
542d25d
 delete mode 100644 xkb/ddxFakeMtn.c
542d25d
542d25d
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
542d25d
index f0db0e4..d1cbd1a 100644
542d25d
--- a/include/xkbsrv.h
542d25d
+++ b/include/xkbsrv.h
542d25d
@@ -768,19 +768,6 @@ extern _X_EXPORT void XkbDDXUpdateDeviceIndicators(
542d25d
 	CARD32			/* newState */
542d25d
 );
542d25d
 
542d25d
-extern _X_EXPORT void XkbDDXFakePointerMotion(
542d25d
-	DeviceIntPtr	/* dev */,
542d25d
- 	unsigned int	/* flags */,
542d25d
-	int		/* x */,
542d25d
-	int		/* y */
542d25d
-);
542d25d
-
542d25d
-extern _X_EXPORT void XkbDDXFakeDeviceButton(
542d25d
-	DeviceIntPtr	/* dev */,
542d25d
-	Bool		/* press */,
542d25d
-	int		/* button */
542d25d
-);
542d25d
-
542d25d
 extern _X_EXPORT int XkbDDXTerminateServer(
542d25d
 	DeviceIntPtr	/* dev */,
542d25d
 	KeyCode		/* key */,
542d25d
diff --git a/xkb/Makefile.am b/xkb/Makefile.am
542d25d
index e54ce59..fb3ccbf 100644
542d25d
--- a/xkb/Makefile.am
542d25d
+++ b/xkb/Makefile.am
542d25d
@@ -5,11 +5,9 @@ AM_CFLAGS = $(DIX_CFLAGS)
542d25d
 DDX_SRCS = \
542d25d
         ddxBeep.c \
542d25d
         ddxCtrls.c \
542d25d
-        ddxFakeMtn.c \
542d25d
         ddxLEDs.c \
542d25d
         ddxLoad.c \
542d25d
-        ddxList.c \
542d25d
-        ddxDevBtn.c
542d25d
+        ddxList.c
542d25d
 
542d25d
 DIX_SRCS = \
542d25d
         xkb.c \
542d25d
diff --git a/xkb/ddxDevBtn.c b/xkb/ddxDevBtn.c
542d25d
deleted file mode 100644
542d25d
index b8a1255..0000000
542d25d
--- a/xkb/ddxDevBtn.c
542d25d
+++ /dev/null
542d25d
@@ -1,69 +0,0 @@
542d25d
-/************************************************************
542d25d
-Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
542d25d
-
542d25d
-Permission to use, copy, modify, and distribute this
542d25d
-software and its documentation for any purpose and without
542d25d
-fee is hereby granted, provided that the above copyright
542d25d
-notice appear in all copies and that both that copyright
542d25d
-notice and this permission notice appear in supporting
542d25d
-documentation, and that the name of Silicon Graphics not be 
542d25d
-used in advertising or publicity pertaining to distribution 
542d25d
-of the software without specific prior written permission.
542d25d
-Silicon Graphics makes no representation about the suitability 
542d25d
-of this software for any purpose. It is provided "as is"
542d25d
-without any express or implied warranty.
542d25d
-
542d25d
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
542d25d
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
542d25d
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
542d25d
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
542d25d
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
542d25d
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
542d25d
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
542d25d
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
542d25d
-
542d25d
-********************************************************/
542d25d
-
542d25d
-#ifdef HAVE_DIX_CONFIG_H
542d25d
-#include <dix-config.h>
542d25d
-#endif
542d25d
-
542d25d
-#include "inputstr.h"
542d25d
-#include <xkbsrv.h>
542d25d
-#include "mi.h"
542d25d
-
542d25d
-void
542d25d
-XkbDDXFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
542d25d
-{
542d25d
-    EventListPtr        events;
542d25d
-    int                 nevents, i;
542d25d
-    DeviceIntPtr        ptr;
542d25d
-
542d25d
-    /* If dev is a slave device, and the SD is attached, do nothing. If we'd
542d25d
-     * post through the attached master pointer we'd get duplicate events.
542d25d
-     *
542d25d
-     * if dev is a master keyboard, post through the XTEST device
542d25d
-     *
542d25d
-     * if dev is a floating slave, post through the device itself.
542d25d
-     */
542d25d
-
542d25d
-    if (IsMaster(dev))
542d25d
-        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
542d25d
-    else if (!dev->u.master)
542d25d
-        ptr = dev;
542d25d
-    else
542d25d
-        return;
542d25d
-
542d25d
-    events = InitEventList(GetMaximumEventsNum());
542d25d
-    OsBlockSignals();
542d25d
-    nevents = GetPointerEvents(events, ptr,
542d25d
-                               press ? ButtonPress : ButtonRelease, button,
542d25d
-                               0 /* flags */, 0 /* first */,
542d25d
-                               0 /* num_val */, NULL);
542d25d
-    OsReleaseSignals();
542d25d
-
542d25d
-    for (i = 0; i < nevents; i++)
542d25d
-        mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
542d25d
-
542d25d
-    FreeEventList(events, GetMaximumEventsNum());
542d25d
-}
542d25d
diff --git a/xkb/ddxFakeMtn.c b/xkb/ddxFakeMtn.c
542d25d
deleted file mode 100644
542d25d
index b383716..0000000
542d25d
--- a/xkb/ddxFakeMtn.c
542d25d
+++ /dev/null
542d25d
@@ -1,64 +0,0 @@
542d25d
-/************************************************************
542d25d
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
542d25d
-
542d25d
-Permission to use, copy, modify, and distribute this
542d25d
-software and its documentation for any purpose and without
542d25d
-fee is hereby granted, provided that the above copyright
542d25d
-notice appear in all copies and that both that copyright
542d25d
-notice and this permission notice appear in supporting
542d25d
-documentation, and that the name of Silicon Graphics not be 
542d25d
-used in advertising or publicity pertaining to distribution 
542d25d
-of the software without specific prior written permission.
542d25d
-Silicon Graphics makes no representation about the suitability 
542d25d
-of this software for any purpose. It is provided "as is"
542d25d
-without any express or implied warranty.
542d25d
-
542d25d
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
542d25d
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
542d25d
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
542d25d
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
542d25d
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
542d25d
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
542d25d
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
542d25d
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
542d25d
-
542d25d
-********************************************************/
542d25d
-
542d25d
-#ifdef HAVE_DIX_CONFIG_H
542d25d
-#include <dix-config.h>
542d25d
-#endif
542d25d
-
542d25d
-#include "inputstr.h"
542d25d
-#include <xkbsrv.h>
542d25d
-#include "mi.h"
542d25d
-
542d25d
-void
542d25d
-XkbDDXFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
542d25d
-{
542d25d
-    EventListPtr        events;
542d25d
-    int                 nevents, i;
542d25d
-    DeviceIntPtr        ptr;
542d25d
-    int                 gpe_flags = 0;
542d25d
-
542d25d
-    if (!dev->u.master)
542d25d
-        ptr = dev;
542d25d
-    else
542d25d
-        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
542d25d
-
542d25d
-    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
542d25d
-        gpe_flags = POINTER_ABSOLUTE;
542d25d
-    else
542d25d
-        gpe_flags = POINTER_RELATIVE;
542d25d
-
542d25d
-    events = InitEventList(GetMaximumEventsNum());
542d25d
-    OsBlockSignals();
542d25d
-    nevents = GetPointerEvents(events, ptr,
542d25d
-                               MotionNotify, 0,
542d25d
-                               gpe_flags, 0, 2, (int[]){x, y});
542d25d
-    OsReleaseSignals();
542d25d
-
542d25d
-    for (i = 0; i < nevents; i++)
542d25d
-        mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
542d25d
-
542d25d
-    FreeEventList(events, GetMaximumEventsNum());
542d25d
-}
542d25d
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
542d25d
index ab52b6a..2817e39 100644
542d25d
--- a/xkb/xkbActions.c
542d25d
+++ b/xkb/xkbActions.c
542d25d
@@ -40,11 +40,15 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
542d25d
 #include <xkbsrv.h>
542d25d
 #include "xkb.h"
542d25d
 #include <ctype.h>
542d25d
+#include "mi.h"
542d25d
 #define EXTENSION_EVENT_BASE 64
542d25d
 
542d25d
 static int xkbDevicePrivateKeyIndex;
542d25d
 DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex;
542d25d
 
542d25d
+static void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
542d25d
+static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y);
542d25d
+
542d25d
 void
542d25d
 xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
542d25d
                    pointer data)
542d25d
@@ -479,7 +483,7 @@ int		dx,dy;
542d25d
 	dx= xkbi->mouseKeysDX;
542d25d
 	dy= xkbi->mouseKeysDY;
542d25d
     }
542d25d
-    XkbDDXFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy);
542d25d
+    XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy);
542d25d
     return xkbi->desc->ctrls->mk_interval;
542d25d
 }
542d25d
 
542d25d
@@ -507,7 +511,7 @@ Bool	accel;
542d25d
 	accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0);
542d25d
 	x= XkbPtrActionX(&pAction->ptr);
542d25d
 	y= XkbPtrActionY(&pAction->ptr);
542d25d
-	XkbDDXFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y);
542d25d
+	XkbFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y);
542d25d
 	AccessXCancelRepeatKey(xkbi,keycode);
542d25d
 	xkbi->mouseKeysAccel= accel&&
542d25d
 		(xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask);
542d25d
@@ -554,7 +558,7 @@ _XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
542d25d
 			((pAction->btn.flags&XkbSA_LockNoLock)==0)) {
542d25d
 		    xkbi->lockedPtrButtons|= (1<
542d25d
 		    AccessXCancelRepeatKey(xkbi,keycode);
542d25d
-		    XkbDDXFakeDeviceButton(xkbi->device, 1, button);
542d25d
+		    XkbFakeDeviceButton(xkbi->device, 1, button);
542d25d
 		    filter->upAction.type= XkbSA_NoAction;
542d25d
 		}
542d25d
 		break;
542d25d
@@ -565,12 +569,12 @@ _XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
542d25d
 		    if (pAction->btn.count>0) {
542d25d
 			nClicks= pAction->btn.count;
542d25d
 			for (i=0;i
542d25d
-			    XkbDDXFakeDeviceButton(xkbi->device, 1, button);
542d25d
-			    XkbDDXFakeDeviceButton(xkbi->device, 0, button);
542d25d
+			    XkbFakeDeviceButton(xkbi->device, 1, button);
542d25d
+			    XkbFakeDeviceButton(xkbi->device, 0, button);
542d25d
 			}
542d25d
 			filter->upAction.type= XkbSA_NoAction;
542d25d
 		    }
542d25d
-		    else XkbDDXFakeDeviceButton(xkbi->device, 1, button);
542d25d
+		    else XkbFakeDeviceButton(xkbi->device, 1, button);
542d25d
 		}
542d25d
 		break;
542d25d
 	    case XkbSA_SetPtrDflt:
542d25d
@@ -636,7 +640,7 @@ _XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
542d25d
 
542d25d
 		/* fallthrough */
542d25d
 	    case XkbSA_PtrBtn:
542d25d
-		XkbDDXFakeDeviceButton(xkbi->device, 0, button);
542d25d
+		XkbFakeDeviceButton(xkbi->device, 0, button);
542d25d
 		break;
542d25d
 	}
542d25d
 	filter->active = 0;
542d25d
@@ -974,7 +978,7 @@ int		button;
542d25d
 		if ((pAction->devbtn.flags&XkbSA_LockNoLock)||
542d25d
 		    BitIsOn(dev->button->down, button))
542d25d
 		    return 0;
542d25d
-		XkbDDXFakeDeviceButton(dev,TRUE,button);
542d25d
+		XkbFakeDeviceButton(dev,TRUE,button);
542d25d
 		filter->upAction.type= XkbSA_NoAction;
542d25d
 		break;
542d25d
 	    case XkbSA_DeviceBtn:
542d25d
@@ -982,12 +986,12 @@ int		button;
542d25d
 		    int nClicks,i;
542d25d
 		    nClicks= pAction->btn.count;
542d25d
 		    for (i=0;i
542d25d
-			XkbDDXFakeDeviceButton(dev,TRUE,button);
542d25d
-			XkbDDXFakeDeviceButton(dev,FALSE,button);
542d25d
+			XkbFakeDeviceButton(dev,TRUE,button);
542d25d
+			XkbFakeDeviceButton(dev,FALSE,button);
542d25d
 		    }
542d25d
 		    filter->upAction.type= XkbSA_NoAction;
542d25d
 		}
542d25d
-		else XkbDDXFakeDeviceButton(dev,TRUE,button);
542d25d
+		else XkbFakeDeviceButton(dev,TRUE,button);
542d25d
 		break;
542d25d
 	}
542d25d
     }
542d25d
@@ -1006,10 +1010,10 @@ int		button;
542d25d
 		if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)||
542d25d
 		    !BitIsOn(dev->button->down, button))
542d25d
 		    return 0;
542d25d
-		XkbDDXFakeDeviceButton(dev,FALSE,button);
542d25d
+		XkbFakeDeviceButton(dev,FALSE,button);
542d25d
 		break;
542d25d
 	    case XkbSA_DeviceBtn:
542d25d
-		XkbDDXFakeDeviceButton(dev,FALSE,button);
542d25d
+		XkbFakeDeviceButton(dev,FALSE,button);
542d25d
 		break;
542d25d
 	}
542d25d
 	filter->active = 0;
542d25d
@@ -1326,3 +1330,70 @@ xkbStateNotify	sn;
542d25d
     return;
542d25d
 }
542d25d
 
542d25d
+static void
542d25d
+XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
542d25d
+{
542d25d
+    EventListPtr        events;
542d25d
+    int                 nevents, i;
542d25d
+    DeviceIntPtr        ptr;
542d25d
+    int                 gpe_flags = 0;
542d25d
+
542d25d
+    if (!dev->u.master)
542d25d
+        ptr = dev;
542d25d
+    else
542d25d
+        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
542d25d
+
542d25d
+    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
542d25d
+        gpe_flags = POINTER_ABSOLUTE;
542d25d
+    else
542d25d
+        gpe_flags = POINTER_RELATIVE;
542d25d
+
542d25d
+    events = InitEventList(GetMaximumEventsNum());
542d25d
+    OsBlockSignals();
542d25d
+    nevents = GetPointerEvents(events, ptr,
542d25d
+                               MotionNotify, 0,
542d25d
+                               gpe_flags, 0, 2, (int[]){x, y});
542d25d
+    OsReleaseSignals();
542d25d
+
542d25d
+    for (i = 0; i < nevents; i++)
542d25d
+        mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
542d25d
+
542d25d
+    FreeEventList(events, GetMaximumEventsNum());
542d25d
+}
542d25d
+
542d25d
+static void
542d25d
+XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
542d25d
+{
542d25d
+    EventListPtr        events;
542d25d
+    int                 nevents, i;
542d25d
+    DeviceIntPtr        ptr;
542d25d
+
542d25d
+    /* If dev is a slave device, and the SD is attached, do nothing. If we'd
542d25d
+     * post through the attached master pointer we'd get duplicate events.
542d25d
+     *
542d25d
+     * if dev is a master keyboard, post through the XTEST device
542d25d
+     *
542d25d
+     * if dev is a floating slave, post through the device itself.
542d25d
+     */
542d25d
+
542d25d
+    if (IsMaster(dev))
542d25d
+        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
542d25d
+    else if (!dev->u.master)
542d25d
+        ptr = dev;
542d25d
+    else
542d25d
+        return;
542d25d
+
542d25d
+    events = InitEventList(GetMaximumEventsNum());
542d25d
+    OsBlockSignals();
542d25d
+    nevents = GetPointerEvents(events, ptr,
542d25d
+                               press ? ButtonPress : ButtonRelease, button,
542d25d
+                               0 /* flags */, 0 /* first */,
542d25d
+                               0 /* num_val */, NULL);
542d25d
+    OsReleaseSignals();
542d25d
+
542d25d
+
542d25d
+    for (i = 0; i < nevents; i++)
542d25d
+        mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
542d25d
+
542d25d
+    FreeEventList(events, GetMaximumEventsNum());
542d25d
+}
542d25d
-- 
542d25d
1.7.1
542d25d
542d25d
From dcb46252f959893f1934232698e2ae26390a8a5b Mon Sep 17 00:00:00 2001
542d25d
From: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
Date: Tue, 29 Jun 2010 15:24:51 +1000
542d25d
Subject: [PATCH 4/5] xkb: emulate PointerKeys events only on the master device.
542d25d
542d25d
This patch replicates the behaviour for button events. Only generate a
542d25d
PointerKeys motion event on the master device, not on the slave device.
542d25d
Fixes the current issue of PointerKey motion events generating key events as
542d25d
well.
542d25d
542d25d
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
---
542d25d
 xkb/xkbActions.c |    9 ++++-----
542d25d
 1 files changed, 4 insertions(+), 5 deletions(-)
542d25d
542d25d
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
542d25d
index 2817e39..391c375 100644
542d25d
--- a/xkb/xkbActions.c
542d25d
+++ b/xkb/xkbActions.c
542d25d
@@ -496,9 +496,6 @@ _XkbFilterPointerMove(	XkbSrvInfoPtr	xkbi,
542d25d
 int	x,y;
542d25d
 Bool	accel;
542d25d
 
542d25d
-    if (xkbi->device == inputInfo.keyboard)
542d25d
-        return 0;
542d25d
-
542d25d
     if (filter->keycode==0) {		/* initial press */
542d25d
 	filter->keycode = keycode;
542d25d
 	filter->active = 1;
542d25d
@@ -1338,10 +1335,12 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
542d25d
     DeviceIntPtr        ptr;
542d25d
     int                 gpe_flags = 0;
542d25d
 
542d25d
-    if (!dev->u.master)
542d25d
+    if (IsMaster(dev))
542d25d
+        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
542d25d
+    else if (!dev->u.master)
542d25d
         ptr = dev;
542d25d
     else
542d25d
-        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
542d25d
+        return;
542d25d
 
542d25d
     if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
542d25d
         gpe_flags = POINTER_ABSOLUTE;
542d25d
-- 
542d25d
1.7.1
542d25d
542d25d
From 40941fb2e9ae763add7b74850e8a0471ac754db6 Mon Sep 17 00:00:00 2001
542d25d
From: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
Date: Thu, 1 Jul 2010 12:44:57 +1000
542d25d
Subject: [PATCH 5/5] xkb: release XTEST pointer buttons on physical releases. (#28808)
542d25d
542d25d
If a button release event is posted for the MD pointer, post a release event
542d25d
through the matching XTEST device. This way, a client who posts a button
542d25d
press through the XTEST extension cannot inadvertedly lock the button.
542d25d
542d25d
This behaviour is required for historical reasons, until server 1.7 the core
542d25d
pointer would release a button press on physical events, regardless of the
542d25d
XTEST state. Clients seem to rely on this behaviour, causing seemingly stuck
542d25d
grabs.
542d25d
542d25d
The merged behaviour is kept for multiple keyboard PointerKey events, if two
542d25d
physical keyboards hold the button down as a result of PointerKey actions,
542d25d
the button is not released until the last keyboard releases the button.
542d25d
542d25d
X.Org Bug 28808 <http://bugs.freedesktop.org/show_bug.cgi?id=28808>
542d25d
542d25d
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
542d25d
---
542d25d
 include/xkbsrv.h |    6 ++++++
542d25d
 xkb/xkbAccessX.c |   23 ++++++++++-------------
542d25d
 xkb/xkbActions.c |    4 ++--
542d25d
 3 files changed, 18 insertions(+), 15 deletions(-)
542d25d
542d25d
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
542d25d
index d1cbd1a..a96ca56 100644
542d25d
--- a/include/xkbsrv.h
542d25d
+++ b/include/xkbsrv.h
542d25d
@@ -923,6 +923,12 @@ extern int XkbGetEffectiveGroup(
542d25d
 extern void XkbMergeLockedPtrBtns(
542d25d
         DeviceIntPtr            /* master */);
542d25d
 
542d25d
+extern void XkbFakeDeviceButton(
542d25d
+        DeviceIntPtr            /* dev */,
542d25d
+        int                     /* press */,
542d25d
+        int                     /* button */);
542d25d
+
542d25d
+
542d25d
 #include "xkbfile.h"
542d25d
 #include "xkbrules.h"
542d25d
 
542d25d
diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
542d25d
index e3fdc06..d3f9652 100644
542d25d
--- a/xkb/xkbAccessX.c
542d25d
+++ b/xkb/xkbAccessX.c
542d25d
@@ -710,19 +710,16 @@ DeviceEvent     *event = &ev->device_event;
542d25d
 	if (xkbi) {
542d25d
 	    xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7));
542d25d
 
542d25d
-            /* Merge this MD's lockedPtrButtons with the one of all
542d25d
-             * attached slave devices.
542d25d
-             * The DIX uses a merged button state for MDs, not
542d25d
-             * releasing buttons until the last SD has released
542d25d
-             * thenm. If we unconditionally clear the
542d25d
-             * lockedPtrButtons bit on the MD, a PointerKeys button
542d25d
-             * release on the SD keyboard won't generate the required fake button
542d25d
-             * event on the XTEST pointer, thus never processing the
542d25d
-             * button event in the DIX and the XTEST pointer's
542d25d
-             * buttons stay down - result is a stuck button.
542d25d
-             */
542d25d
-	    if (IsMaster(dev))
542d25d
-                XkbMergeLockedPtrBtns(dev);
542d25d
+            if (IsMaster(dev))
542d25d
+            {
542d25d
+                DeviceIntPtr source;
542d25d
+                int rc;
542d25d
+                rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess);
542d25d
+                if (rc != Success)
542d25d
+                    ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid);
542d25d
+                else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER)))
542d25d
+                    XkbFakeDeviceButton(dev, FALSE, event->detail.key);
542d25d
+            }
542d25d
 	}
542d25d
 
542d25d
 	changed |= XkbPointerButtonMask;
542d25d
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
542d25d
index 391c375..5d40199 100644
542d25d
--- a/xkb/xkbActions.c
542d25d
+++ b/xkb/xkbActions.c
542d25d
@@ -46,7 +46,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
542d25d
 static int xkbDevicePrivateKeyIndex;
542d25d
 DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex;
542d25d
 
542d25d
-static void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
542d25d
+void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
542d25d
 static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y);
542d25d
 
542d25d
 void
542d25d
@@ -1360,7 +1360,7 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
542d25d
     FreeEventList(events, GetMaximumEventsNum());
542d25d
 }
542d25d
 
542d25d
-static void
542d25d
+void
542d25d
 XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
542d25d
 {
542d25d
     EventListPtr        events;
542d25d
-- 
542d25d
1.7.1
542d25d
Peter Hutterer 8be23b2
From 7273832bcdc6f43e9a5a8fdbb56844466efb710a Mon Sep 17 00:00:00 2001
Peter Hutterer 8be23b2
From: Peter Hutterer <peter.hutterer@who-t.net>
Peter Hutterer 8be23b2
Date: Fri, 23 Jul 2010 11:46:30 +1000
Peter Hutterer 8be23b2
Subject: [PATCH 1/3] xkb: post-fix PointerKeys button events with a DeviceChangedEvent.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
commit 14327858391ebe929b806efb53ad79e789361883
Peter Hutterer 8be23b2
    xkb: release XTEST pointer buttons on physical releases. (#28808)
Peter Hutterer 8be23b2
revealed a bug with the XTEST/PointerKeys interaction.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Events resulting from PointerKeys are injected into the event processing
Peter Hutterer 8be23b2
stream, not appended to the event queue. The events generated for the fake
Peter Hutterer 8be23b2
button press include a DeviceChangedEvent (DCE), a raw button event and the
Peter Hutterer 8be23b2
button event itself. The DCE causes the master to switch classes to the
Peter Hutterer 8be23b2
attached XTEST pointer device.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Once the fake button is processed, normal event processing continues with
Peter Hutterer 8be23b2
events in the EQ. The master still contains the XTEST classes, causing some
Peter Hutterer 8be23b2
events to be dropped if e.g. the number of valuators of the event in the
Peter Hutterer 8be23b2
queue exceeds the XTEST device's number of valuators.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Example: the EQ contains the following events, processed one-by-one, left to
Peter Hutterer 8be23b2
right.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
[DCE (dev)][Btn down][Btn up][Motion][Motion][...]
Peter Hutterer 8be23b2
                  ^ XkbFakeDeviceButton injects [DCE (XTEST)][Btn up]
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Thus the event sequence processed looks like this:
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
[DCE (dev)][Btn down][Btn up][DCE (XTEST)][Btn up][Motion][Motion][...]
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
The first DCE causes the master to switch to the device. The button up event
Peter Hutterer 8be23b2
injects a DCE to the XTEST device, causing the following Motion events to be
Peter Hutterer 8be23b2
processed with the master still being on XTEST classes.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
This patch post-fixes the injected event sequence with a DCE to restore the
Peter Hutterer 8be23b2
classes of the original slave device, resulting in an event sequence like
Peter Hutterer 8be23b2
this:
Peter Hutterer 8be23b2
[DCE (dev)][Btn down][Btn up][DCE (XTEST)][Btn up][DCE (dev)][Motion][Motion]
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Note that this is a simplified description. The event sequence injected by
Peter Hutterer 8be23b2
the PointerKeys code is injected for the master device only and the matching
Peter Hutterer 8be23b2
slave device that caused the injection has already finished processing on
Peter Hutterer 8be23b2
the slave. Furthermore, the injection happens as part of the the XKB layer,
Peter Hutterer 8be23b2
before the unwrapping of the processInputProc takes us into the DIX where
Peter Hutterer 8be23b2
the DCE is actually handled.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Bug reproducible with a device that reports more than 2 valuators. Simply
Peter Hutterer 8be23b2
cause button releases on the device and wait for a "too many valuators"
Peter Hutterer 8be23b2
warning message.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Peter Hutterer 8be23b2
---
Peter Hutterer 8be23b2
 xkb/xkbActions.c |   26 +++++++++++++++++++-------
Peter Hutterer 8be23b2
 1 files changed, 19 insertions(+), 7 deletions(-)
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
Peter Hutterer 8be23b2
index 5d40199..2afd46d 100644
Peter Hutterer 8be23b2
--- a/xkb/xkbActions.c
Peter Hutterer 8be23b2
+++ b/xkb/xkbActions.c
Peter Hutterer 8be23b2
@@ -1365,34 +1365,46 @@ XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
Peter Hutterer 8be23b2
 {
Peter Hutterer 8be23b2
     EventListPtr        events;
Peter Hutterer 8be23b2
     int                 nevents, i;
Peter Hutterer 8be23b2
-    DeviceIntPtr        ptr;
Peter Hutterer 8be23b2
+    DeviceIntPtr        ptr, mpointer, lastSlave;
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
     /* If dev is a slave device, and the SD is attached, do nothing. If we'd
Peter Hutterer 8be23b2
      * post through the attached master pointer we'd get duplicate events.
Peter Hutterer 8be23b2
      *
Peter Hutterer 8be23b2
      * if dev is a master keyboard, post through the XTEST device
Peter Hutterer 8be23b2
-     *
Peter Hutterer 8be23b2
      * if dev is a floating slave, post through the device itself.
Peter Hutterer 8be23b2
+     *
Peter Hutterer 8be23b2
+     * The event is injected into the event processing, not the EQ. Thus,
Peter Hutterer 8be23b2
+     * ensure that we restore the master after the event sequence to the
Peter Hutterer 8be23b2
+     * original set of classes. Otherwise, the master remains on the XTEST
Peter Hutterer 8be23b2
+     * classes and drops events that don't fit into the XTEST layout (e.g.
Peter Hutterer 8be23b2
+     * events with more than 2 valuators).
Peter Hutterer 8be23b2
+     * To do so, we remember the lastSlave that posted through the master
Peter Hutterer 8be23b2
+     * and add a DeviceChangedEvent to the end of the list.
Peter Hutterer 8be23b2
      */
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
-    if (IsMaster(dev))
Peter Hutterer 8be23b2
-        ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
Peter Hutterer 8be23b2
-    else if (!dev->u.master)
Peter Hutterer 8be23b2
+    if (IsMaster(dev)) {
Peter Hutterer 8be23b2
+        mpointer = GetMaster(dev, MASTER_POINTER);
Peter Hutterer 8be23b2
+        lastSlave = mpointer->u.lastSlave;
Peter Hutterer 8be23b2
+        ptr = GetXTestDevice(mpointer);
Peter Hutterer 8be23b2
+    } else if (!dev->u.master)
Peter Hutterer 8be23b2
         ptr = dev;
Peter Hutterer 8be23b2
     else
Peter Hutterer 8be23b2
         return;
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
-    events = InitEventList(GetMaximumEventsNum());
Peter Hutterer 8be23b2
+    events = InitEventList(GetMaximumEventsNum() + 1);
Peter Hutterer 8be23b2
     OsBlockSignals();
Peter Hutterer 8be23b2
     nevents = GetPointerEvents(events, ptr,
Peter Hutterer 8be23b2
                                press ? ButtonPress : ButtonRelease, button,
Peter Hutterer 8be23b2
                                0 /* flags */, 0 /* first */,
Peter Hutterer 8be23b2
                                0 /* num_val */, NULL);
Peter Hutterer 8be23b2
+    if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
Peter Hutterer 8be23b2
+        CreateClassesChangedEvent(&events[nevents++], mpointer,
Peter Hutterer 8be23b2
+                                  lastSlave, DEVCHANGE_POINTER_EVENT);
Peter Hutterer 8be23b2
     OsReleaseSignals();
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
     for (i = 0; i < nevents; i++)
Peter Hutterer 8be23b2
         mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
-    FreeEventList(events, GetMaximumEventsNum());
Peter Hutterer 8be23b2
+    FreeEventList(events, GetMaximumEventsNum() + 1);
Peter Hutterer 8be23b2
 }
Peter Hutterer 8be23b2
-- 
Peter Hutterer 8be23b2
1.7.2
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
From 817e031a996a5f5aa16fc789d7e570cc589d96cb Mon Sep 17 00:00:00 2001
Peter Hutterer 8be23b2
From: Peter Hutterer <peter.hutterer@who-t.net>
Peter Hutterer 8be23b2
Date: Wed, 28 Jul 2010 14:24:59 +1000
Peter Hutterer 8be23b2
Subject: [PATCH 3/3] Xi: reset the unused classes pointer after copying
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
After copying the unused_classes into the device, reset the original
Peter Hutterer 8be23b2
pointer. Otherwise we have two pointers pointing to the same field and both
Peter Hutterer 8be23b2
get freed on device removal.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Some classes already have this behaviour since 51c8fd69.
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Peter Hutterer 8be23b2
---
Peter Hutterer 8be23b2
 Xi/exevents.c |    6 ++++++
Peter Hutterer 8be23b2
 1 files changed, 6 insertions(+), 0 deletions(-)
Peter Hutterer 8be23b2
Peter Hutterer 8be23b2
diff --git a/Xi/exevents.c b/Xi/exevents.c
Peter Hutterer 8be23b2
index 566b0ef..a6160dd 100644
Peter Hutterer 8be23b2
--- a/Xi/exevents.c
Peter Hutterer 8be23b2
+++ b/Xi/exevents.c
Peter Hutterer 8be23b2
@@ -227,6 +227,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
Peter Hutterer 8be23b2
             classes = dixLookupPrivate(&to->devPrivates,
Peter Hutterer 8be23b2
                                        UnusedClassesPrivateKey);
Peter Hutterer 8be23b2
             to->intfeed = classes->intfeed;
Peter Hutterer 8be23b2
+            classes->intfeed = NULL;
Peter Hutterer 8be23b2
         }
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
         i = &to->intfeed;
Peter Hutterer 8be23b2
@@ -263,6 +264,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
Peter Hutterer 8be23b2
             classes = dixLookupPrivate(&to->devPrivates,
Peter Hutterer 8be23b2
                                        UnusedClassesPrivateKey);
Peter Hutterer 8be23b2
             to->stringfeed = classes->stringfeed;
Peter Hutterer 8be23b2
+            classes->stringfeed = NULL;
Peter Hutterer 8be23b2
         }
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
         s = &to->stringfeed;
Peter Hutterer 8be23b2
@@ -299,6 +301,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
Peter Hutterer 8be23b2
             classes = dixLookupPrivate(&to->devPrivates,
Peter Hutterer 8be23b2
                                        UnusedClassesPrivateKey);
Peter Hutterer 8be23b2
             to->bell = classes->bell;
Peter Hutterer 8be23b2
+            classes->bell = NULL;
Peter Hutterer 8be23b2
         }
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
         b = &to->bell;
Peter Hutterer 8be23b2
@@ -336,6 +339,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
Peter Hutterer 8be23b2
             classes = dixLookupPrivate(&to->devPrivates,
Peter Hutterer 8be23b2
                                        UnusedClassesPrivateKey);
Peter Hutterer 8be23b2
             to->leds = classes->leds;
Peter Hutterer 8be23b2
+            classes->leds = NULL;
Peter Hutterer 8be23b2
         }
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
         l = &to->leds;
Peter Hutterer 8be23b2
@@ -387,6 +391,7 @@ DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
Peter Hutterer 8be23b2
             to->kbdfeed = classes->kbdfeed;
Peter Hutterer 8be23b2
             if (!to->kbdfeed)
Peter Hutterer 8be23b2
                 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
Peter Hutterer 8be23b2
+            classes->kbdfeed = NULL;
Peter Hutterer 8be23b2
         }
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
         k = &to->kbdfeed;
Peter Hutterer 8be23b2
@@ -517,6 +522,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
Peter Hutterer 8be23b2
             classes = dixLookupPrivate(&to->devPrivates,
Peter Hutterer 8be23b2
                                        UnusedClassesPrivateKey);
Peter Hutterer 8be23b2
             to->ptrfeed = classes->ptrfeed;
Peter Hutterer 8be23b2
+            classes->ptrfeed = NULL;
Peter Hutterer 8be23b2
         }
Peter Hutterer 8be23b2
 
Peter Hutterer 8be23b2
         p = &to->ptrfeed;
Peter Hutterer 8be23b2
-- 
Peter Hutterer 8be23b2
1.7.2
Peter Hutterer 8be23b2