xserver: Branch 'mpx' - 20 commits

Peter Hutterer whot at kemper.freedesktop.org
Wed May 23 00:36:53 PDT 2007


 Xext/Makefile.am               |    6 
 Xext/geext.c                   |  383 +++++++++++++++++++++++++
 Xext/geext.h                   |   63 ++++
 Xext/geint.h                   |   60 +++
 Xext/security.c                |    7 
 Xi/Makefile.am                 |    8 
 Xi/chpkpair.c                  |   29 +
 Xi/chpkpair.h                  |    5 
 Xi/exevents.c                  |   15 
 Xi/exglobals.h                 |    2 
 Xi/extgrbdev.c                 |  252 ++++++++++++++++
 Xi/extgrbdev.h                 |   46 +++
 Xi/extinit.c                   |   86 ++++-
 Xi/fakedevdata.c               |  128 ++++++++
 Xi/fakedevdata.h               |   42 ++
 Xi/grabdev.c                   |    7 
 Xi/ungrdev.c                   |    2 
 Xi/xiselev.c                   |   78 +++++
 Xi/xiselev.h                   |   44 ++
 dix/devices.c                  |  105 +++---
 dix/events.c                   |  616 ++++++++++++++++++++++++++++-------------
 dix/getevents.c                |  137 +++++++--
 dix/main.c                     |   10 
 dix/window.c                   |   17 +
 hw/xfree86/common/xf86DGA.c    |    4 
 hw/xfree86/common/xf86Events.c |   20 -
 hw/xfree86/common/xf86Priv.h   |    3 
 hw/xfree86/common/xf86Xinput.c |   24 -
 hw/xfree86/loader/xf86sym.c    |   13 
 include/dix.h                  |   21 +
 include/input.h                |   24 +
 include/inputstr.h             |   20 +
 include/misc.h                 |    1 
 include/windowstr.h            |   13 
 mi/mieq.c                      |   97 ++++--
 mi/miinitext.c                 |    6 
 mi/mipointer.c                 |   10 
 os/utils.c                     |    2 
 xkb/xkbEvents.c                |    5 
 39 files changed, 2026 insertions(+), 385 deletions(-)

New commits:
diff-tree d0e8f474099dea40bbea555427772724ccb787d1 (from 167e1773de0fb566559d4362ff929eedcdb6d055)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 21 13:06:21 2007 +0930

    Change GrabDevice's parameter name back to "coreGrab".
    Was changed during a global search/replace for
    5c680e94938c16e04a4349715cf11796b80400db.
    
    Otherwise people like me introduce bugs (e.g. in
    333bab4b235801efd2b2de5b60df5b0c44048d3e)

diff --git a/dix/events.c b/dix/events.c
index 13c817a..402e3b3 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4695,7 +4695,7 @@ int
 GrabDevice(ClientPtr client, DeviceIntPtr dev, 
            unsigned this_mode, unsigned other_mode, Window grabWindow, 
            unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status,
-           Bool deviceGrab)
+           Bool coreGrab)
 {
     WindowPtr pWin;
     GrabPtr grab;
@@ -4749,7 +4749,7 @@ GrabDevice(ClientPtr client, DeviceIntPt
 	tempGrab.eventMask = mask;
 	tempGrab.device = dev;
         tempGrab.cursor = NULL;
-        tempGrab.coreGrab = (deviceGrab) ? FALSE : TRUE;
+        tempGrab.coreGrab = coreGrab;
         tempGrab.genericMasks = NULL;
 
 	(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
diff-tree 167e1773de0fb566559d4362ff929eedcdb6d055 (from 0b4db74922299df785e6273fdb1bf65c38d36070)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 21 10:45:10 2007 +0930

    Remove unused include "gestr.h"

diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
index 3575601..8ae2053 100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@ -46,7 +46,6 @@ from the author.
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include <X11/extensions/Xge.h>
-#include "gestr.h"
 #include "extnsionst.h"
 #include "extinit.h"	/* LookupDeviceIntRec */
 #include "exevents.h"
diff-tree 0b4db74922299df785e6273fdb1bf65c38d36070 (from 333bab4b235801efd2b2de5b60df5b0c44048d3e)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 17 18:00:07 2007 +0930

    Squish the flags into the upper bits of the mode field for EnterLeave events.
    This way we have enough space for the detail field.

diff --git a/dix/events.c b/dix/events.c
index b36e4a4..13c817a 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3940,11 +3940,14 @@ EnterLeaveEvent(
                                         NullGrab, 0);
     }
 
+    /* we don't have enough bytes, so we squash flags and mode into 
+       one byte, and use the last byte for the deviceid. */
     devEnterLeave = (deviceEnterNotify*)&event;
     devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify :
         DeviceLeaveNotify;
     devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify :
         DeviceLeaveNotify;
+    devEnterLeave->mode |= (event.u.enterLeave.flags << 4);
     devEnterLeave->deviceid = mouse->id;
     mskidx = mouse->id;
     inputMasks = wOtherInputMasks(pWin);
diff-tree 333bab4b235801efd2b2de5b60df5b0c44048d3e (from bc334286b060bc8d0c829b18acebadf24fbdaf19)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 17 17:59:02 2007 +0930

    Clean up, correct some comments.
    Send event type down with the RawEvents.

diff --git a/Xext/geext.c b/Xext/geext.c
index fed74dc..f0801cb 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -246,11 +246,10 @@ GEExtensionInit(void)
 /*                interface for extensions                  */
 /************************************************************/
 
-/* Register extension with GE. 
- * Requires the event swap function as parameter. The function will be called
- * each time an event is sent to a client with different byte order.
- * Returns extension offset. This offset is to be used in all generic events
- * sent to the client.
+/* Register an extension with GE. The given swap function will be called each
+ * time an event is sent to a client with different byte order.
+ * @param extension The extensions major opcode 
+ * @param ev_swap the event swap function.  
  */
 void GERegisterExtension(
         int extension, 
@@ -266,7 +265,8 @@ void GERegisterExtension(
 
 
 /* Sets type and extension field for a generic event. This is just an
- * auxiliary function, extensions could do it manually too. */
+ * auxiliary function, extensions could do it manually too. 
+ */ 
 void GEInitEvent(xGenericEvent* ev, int extension)
 {
     ev->type = GenericEvent;
diff --git a/Xext/geext.h b/Xext/geext.h
index 53aa21c..7a73e81 100644
--- a/Xext/geext.h
+++ b/Xext/geext.h
@@ -51,7 +51,6 @@ from the author.
     (((pWin)->optional) ? (pWin)->optional->geMasks->geClients : NULL)
 
 /* Interface for other extensions */
-Mask GENextMask(int extension);
 void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask);
 void GERegisterExtension(
         int extension,
diff --git a/Xi/exglobals.h b/Xi/exglobals.h
index 8fcd907..8cbccf2 100644
--- a/Xi/exglobals.h
+++ b/Xi/exglobals.h
@@ -52,7 +52,6 @@ extern Mask DeviceButtonMotionMask;
 extern Mask DevicePresenceNotifyMask;
 extern Mask DeviceEnterWindowMask;
 extern Mask DeviceLeaveWindowMask;
-extern Mask PointerKeyboardPairingChangedNotifyMask;
 extern Mask PropagateMask[];
 
 extern int DeviceValuator;
@@ -73,7 +72,6 @@ extern int ChangeDeviceNotify;
 extern int DevicePresenceNotify;
 extern int DeviceEnterNotify;
 extern int DeviceLeaveNotify;
-extern int PointerKeyboardPairingChangedNotify;
 
 extern int RT_INPUTCLIENT;
 
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 0888730..99518e1 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -134,6 +134,10 @@ Mask ExtValidMasks[EMASKSIZE];
 Mask ExtExclusiveMasks[EMASKSIZE];
 
 
+/**
+ * Filters for various generic events. 
+ * Evtype is index, mask is value at index.
+ */
 static Mask xi_filters[3] = {
     XI_PointerKeyboardPairingChangedMask,
     XI_RandomStringMask,
@@ -213,9 +217,6 @@ int DevicePresenceNotify;
 int DeviceEnterNotify;
 int DeviceLeaveNotify;
 
-/* GE events */
-int PointerKeyboardPairingChangedNotify;
-
 int RT_INPUTCLIENT;
 
 /*****************************************************************
@@ -828,10 +829,6 @@ FixExtensionEvents(ExtensionEntry * extE
     DeviceEnterNotify = DevicePresenceNotify + 1;
     DeviceLeaveNotify = DeviceEnterNotify + 1;
 
-    /* GE Events */
-    PointerKeyboardPairingChangedNotify =
-        XI_PointerKeyboardPairingChangedNotify;
-
     event_base[KeyClass] = DeviceKeyPress;
     event_base[ButtonClass] = DeviceButtonPress;
     event_base[ValuatorClass] = DeviceMotionNotify;
diff --git a/dix/events.c b/dix/events.c
index 463bf7c..b36e4a4 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1523,10 +1523,6 @@ DeactivateKeyboardGrab(DeviceIntPtr keyb
     ComputeFreezes();
 }
 
-/* 
- * Core flag decides whether to work on the deviceGrab or deviceGrab sync
- * fields.
- */
 void
 AllowSome(ClientPtr client, 
           TimeStamp time, 
@@ -1538,7 +1534,7 @@ AllowSome(ClientPtr client, 
     TimeStamp grabTime;
     DeviceIntPtr dev;
     GrabInfoPtr devgrabinfo, 
-                grabinfo = (core) ? &thisDev->deviceGrab : &thisDev->deviceGrab;
+                grabinfo = &thisDev->deviceGrab;
 
     thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
     thisSynced = FALSE;
@@ -1547,7 +1543,7 @@ AllowSome(ClientPtr client, 
     grabTime = grabinfo->grabTime;
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-        devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
+        devgrabinfo = &dev->deviceGrab;
 
 	if (dev == thisDev)
 	    continue;
@@ -1593,7 +1589,7 @@ AllowSome(ClientPtr client, 
 	    {
 		for (dev = inputInfo.devices; dev; dev = dev->next)
 		{
-                    devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
+                    devgrabinfo = &dev->deviceGrab;
 		    if (devgrabinfo->grab 
                             && SameClient(devgrabinfo->grab, client))
 			devgrabinfo->sync.state = THAWED;
@@ -1609,7 +1605,7 @@ AllowSome(ClientPtr client, 
 	    {
 		for (dev = inputInfo.devices; dev; dev = dev->next)
 		{
-                    devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
+                    devgrabinfo = &dev->deviceGrab;
 		    if (devgrabinfo->grab 
                             && SameClient(devgrabinfo->grab, client))
 			devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
@@ -1902,7 +1898,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev,
         if (type == GenericEvent)
         {
             GEClientPtr pClient;
-            /* FIXME: We don't do more than one GenericEvent at a time yet. */
+            /* We don't do more than one GenericEvent at a time. */
             if (count > 1)
             {
                 ErrorF("Do not send more than one GenericEvent at a time!\n");
@@ -3013,8 +3009,7 @@ CheckPassiveGrabsOnWindow(
 				tempGrab.modifiersDetail.exact&(~0x1f00);
 	    }
 #endif
-            grabinfo = (xE->u.u.type & EXTENSION_EVENT_BASE) ? 
-                &device->deviceGrab : &device->deviceGrab;
+            grabinfo = &device->deviceGrab;
 	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
  
 	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
@@ -4703,7 +4698,7 @@ GrabDevice(ClientPtr client, DeviceIntPt
     GrabPtr grab;
     TimeStamp time;
     int rc;
-    GrabInfoPtr grabInfo = (deviceGrab) ? &dev->deviceGrab : &dev->deviceGrab;
+    GrabInfoPtr grabInfo = &dev->deviceGrab;
 
     UpdateCurrentTime();
     if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
@@ -4751,7 +4746,7 @@ GrabDevice(ClientPtr client, DeviceIntPt
 	tempGrab.eventMask = mask;
 	tempGrab.device = dev;
         tempGrab.cursor = NULL;
-        tempGrab.coreGrab = deviceGrab;
+        tempGrab.coreGrab = (deviceGrab) ? FALSE : TRUE;
         tempGrab.genericMasks = NULL;
 
 	(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
diff --git a/dix/getevents.c b/dix/getevents.c
index 4f7993f..4d1fbb7 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -603,6 +603,7 @@ GetPointerEvents(EventList *events, Devi
     ev->evtype = XI_RawDeviceEvent;
     ev->extension = IReqCode;
     ev->length = (num_valuators > 4) ? (num_valuators - 4) : 0;
+    ev->event_type = type;
     ev->buttons = buttons;
     ev->num_valuators = num_valuators;
     ev->first_valuator = first_valuator;
diff-tree bc334286b060bc8d0c829b18acebadf24fbdaf19 (from a8c56372ba8aa36bac09877c478ff53ea5358df7)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 17 10:36:46 2007 +0930

    Init device axis with -1,-1 minimum values.
    
    This is needed to be able to cross to screens located east/north of the
    current active screen.

diff --git a/dix/devices.c b/dix/devices.c
index ac35fe6..4672b2a 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1011,7 +1011,7 @@ InitValuatorClassDeviceStruct(DeviceIntP
         AllocateMotionHistory(dev);
 
     for (i=0; i<numAxes; i++) {
-        InitValuatorAxisStruct(dev, i, 0, -1, 0, 0, 0);
+        InitValuatorAxisStruct(dev, i, -1, -1, 0, 0, 0);
 	valc->axisVal[i]=0;
     }
     return TRUE;
diff-tree a8c56372ba8aa36bac09877c478ff53ea5358df7 (from 81fc6a128b64ad412064405ed45db0175398e3f0)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 15 10:24:22 2007 +0930

    Revert "Allow events to grabWindows event if the device is not grabbed."
    
    This reverts commit 339b73e710a0920608a3fbcb20b406f0f6c4e0f6.
    Allowing those events can lead to race conditions.
    
    Conflicts:
    
    	dix/events.c

diff --git a/dix/events.c b/dix/events.c
index 30deeb6..463bf7c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1881,7 +1881,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev,
 	    return 0;
         
         if (!(type & EXTENSION_EVENT_BASE) && 
-            IsInterferingGrab(wClient(pWin), pWin, pDev, pEvents))
+            IsInterferingGrab(wClient(pWin), pDev, pEvents))
                 return 0;
 
 	if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
@@ -1946,7 +1946,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev,
             {
                 /* core event? check for grab interference */
                 if (!(type & EXTENSION_EVENT_BASE) &&
-                        IsInterferingGrab(rClient(other), pWin, pDev, pEvents))
+                        IsInterferingGrab(rClient(other), pDev, pEvents))
                     continue;
 
                 if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
@@ -5666,19 +5666,15 @@ PickKeyboard(ClientPtr client)
 /* A client that has one or more core grabs does not get core events from
  * devices it does not have a grab on. Legacy applications behave bad
  * otherwise because they are not used to it and the events interfere.
- * The one exception is: if we're about to send an event to a window that is
- * specified as grab window, we still do it. This makes popup menus
- * half-useable for WMs that don't set the ClientPointer.
  * Only applies for core events.
  *
  * Return true if a core event from the device would interfere and should not
  * be delivered.
  */
 Bool 
-IsInterferingGrab(ClientPtr client, WindowPtr win, DeviceIntPtr dev, xEvent* event)
+IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
 {
-    DeviceIntPtr it;
-    Bool mayInterfere = FALSE;
+    DeviceIntPtr it = inputInfo.devices;
 
     if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
         return FALSE;
@@ -5697,31 +5693,19 @@ IsInterferingGrab(ClientPtr client, Wind
             return FALSE;
     }
 
-    it = inputInfo.devices;
     while(it)
     {
         if (it != dev)
         {
             if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client))
             {
-                /* there's a client with a grab on some device. 
-                 * if we're delivering to the very same window that is
-                 * grabbed (or a child), we're good */
-                WindowPtr parent = win;
-                while(parent)
-                {
-                    if (it->deviceGrab.grab->window == parent)
-                        return FALSE;
-                    parent = parent->parent;
-                }
-
-                mayInterfere = TRUE;
+                return TRUE;
             }
         }
         it = it->next;
     }
 
-    return mayInterfere;
+    return FALSE;
 }
 
 /**
diff --git a/include/dix.h b/include/dix.h
index 736a93e..f0e2f2a 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -552,7 +552,6 @@ extern DeviceIntPtr PickKeyboard(
 
 extern Bool IsInterferingGrab(
         ClientPtr /* client */,
-        WindowPtr /* win */,
         DeviceIntPtr /* dev */,
         xEvent* /* events */);
 
diff-tree 81fc6a128b64ad412064405ed45db0175398e3f0 (from 5c680e94938c16e04a4349715cf11796b80400db)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 14 18:12:56 2007 +0930

    Add ungrab support to ExtendedGrabDeviceRequest handling.
    Polish the code a bit.

diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
index 0f0fd30..3575601 100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@ -45,12 +45,15 @@ from the author.
 #include "scrnintstr.h"	/* screen structure  */
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
+#include <X11/extensions/Xge.h>
 #include "gestr.h"
 #include "extnsionst.h"
 #include "extinit.h"	/* LookupDeviceIntRec */
 #include "exevents.h"
 #include "exglobals.h"
 
+#include "grabdev.h"    /* CreateMaskFromList */
+
 #include "extgrbdev.h"
 
 int 
@@ -68,9 +71,8 @@ SProcXExtendedGrabDevice(ClientPtr clien
     swapl(&stuff->time, n);
     swapl(&stuff->confine_to, n);
     swapl(&stuff->cursor, n);
-    swaps(&stuff->event_mask, n);
     swaps(&stuff->event_count, n);
-    swaps(&stuff->ge_event_count, n);
+    swaps(&stuff->generic_event_count, n);
 
     p = (long *)&stuff[1];
     for (i = 0; i < stuff->event_count; i++) {
@@ -78,7 +80,7 @@ SProcXExtendedGrabDevice(ClientPtr clien
 	p++;
     }
 
-    for (i = 0; i < stuff->ge_event_count; i++) {
+    for (i = 0; i < stuff->generic_event_count; i++) {
         p++; /* first 4 bytes are extension type and padding */
         swapl(p, n);
         p++;
@@ -93,7 +95,7 @@ ProcXExtendedGrabDevice(ClientPtr client
 {
     xExtendedGrabDeviceReply rep;
     DeviceIntPtr             dev;
-    int                      err, 
+    int                      err = Success, 
                              errval = 0,
                              i;
     WindowPtr                grab_window, 
@@ -101,14 +103,25 @@ ProcXExtendedGrabDevice(ClientPtr client
     CursorPtr                cursor = NULL;
     struct tmask             tmp[EMASKSIZE];
     TimeStamp                time;
-    XgeEventMask*            xgeMask;
+    XGenericEventMask*       xgeMask;
     GenericMaskPtr           gemasks = NULL;
 
     REQUEST(xExtendedGrabDeviceReq);
     REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq);
 
-    if (stuff->length != (sizeof(xExtendedGrabDeviceReq) >> 2) + 
-            stuff->event_count + 2 * stuff->ge_event_count)
+    if (stuff->ungrab)
+    {
+        REQUEST_SIZE_MATCH(xExtendedGrabDeviceReq);
+    }
+
+    rep.repType         = X_Reply;
+    rep.RepType         = X_ExtendedGrabDevice;
+    rep.sequenceNumber  = client->sequence;
+    rep.length          = 0;
+
+    if (!stuff->ungrab && /* other fields are undefined for ungrab */
+            (stuff->length != (sizeof(xExtendedGrabDeviceReq) >> 2) + 
+            stuff->event_count + 2 * stuff->generic_event_count))
     {
         errval = 0;
         err = BadLength;
@@ -122,6 +135,13 @@ ProcXExtendedGrabDevice(ClientPtr client
 	goto cleanup;
     }
 
+
+    if (stuff->ungrab)
+    {
+        ExtUngrabDevice(client, dev);
+        goto cleanup;
+    }
+
     err = dixLookupWindow(&grab_window, 
                           stuff->grab_window, 
                           client, 
@@ -159,11 +179,6 @@ ProcXExtendedGrabDevice(ClientPtr client
         }
     }
 
-    rep.repType         = X_Reply;
-    rep.RepType         = X_ExtendedGrabDevice;
-    rep.sequenceNumber  = client->sequence;
-    rep.length          = 0;
-
     if (CreateMaskFromList(client, 
                            (XEventClass*)&stuff[1],
                            stuff->event_count, 
@@ -174,10 +189,10 @@ ProcXExtendedGrabDevice(ClientPtr client
 
     time = ClientTimeToServerTime(stuff->time);
 
-    if (stuff->ge_event_count)
+    if (stuff->generic_event_count)
     {
         xgeMask = 
-            (XgeEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
+            (XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
 
         gemasks = xcalloc(1, sizeof(GenericMaskRec));
         gemasks->extension = xgeMask->extension;
@@ -185,7 +200,7 @@ ProcXExtendedGrabDevice(ClientPtr client
         gemasks->next = NULL;
         xgeMask++;
 
-        for (i = 1; i < stuff->ge_event_count; i++, xgeMask++)
+        for (i = 1; i < stuff->generic_event_count; i++, xgeMask++)
         {
             gemasks->next = xcalloc(1, sizeof(GenericMaskRec));
             gemasks = gemasks->next;
@@ -195,9 +210,9 @@ ProcXExtendedGrabDevice(ClientPtr client
         }
     }
 
-    ExtGrabDevice(client, dev, stuff->grabmode, stuff->device_mode, 
+    ExtGrabDevice(client, dev, stuff->device_mode, 
                   grab_window, confineTo, time, stuff->owner_events, 
-                  cursor, stuff->event_mask, tmp[stuff->deviceid].mask, 
+                  cursor, tmp[stuff->deviceid].mask, 
                   gemasks);
 
     if (err != Success) {
diff --git a/dix/events.c b/dix/events.c
index 1d9417d..30deeb6 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3161,11 +3161,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIn
     xEvent *dxE;
     SpritePtr pSprite = thisDev->spriteInfo->sprite;
 
-    if (xE->u.u.type & EXTENSION_EVENT_BASE || xE->u.u.type == GenericEvent)
-        grabinfo = &thisDev->deviceGrab;
-    else
-        grabinfo = &thisDev->deviceGrab;
-
+    grabinfo = &thisDev->deviceGrab;
     grab = grabinfo->grab;
 
     if (grab->ownerEvents)
@@ -5743,24 +5739,18 @@ SetGenericFilter(int extension, Mask* fi
 
 
 /**
- * Grab a device for core events, XI events or XGE events.
- * 
- * The latter also applies to generic events.
+ * Grab a device for XI events and XGE events.
  * grabmode is used to ungrab a device.
- * 
- *
  */
 _X_EXPORT int
 ExtGrabDevice(ClientPtr client, 
               DeviceIntPtr dev, 
-              int grabmode, 
               int device_mode,
               WindowPtr grabWindow, 
               WindowPtr confineTo, 
               TimeStamp ctime, 
               Bool ownerEvents, 
               CursorPtr cursor, 
-              Mask core_mask, 
               Mask xi_mask, 
               GenericMaskPtr ge_masks)
 {
@@ -5769,72 +5759,72 @@ ExtGrabDevice(ClientPtr client, 
 
     UpdateCurrentTime();
 
-    if (grabmode & DeviceOnlyGrab)
-    {
-        grabinfo = &dev->deviceGrab;
+    grabinfo = &dev->deviceGrab;
 
-        if (grabinfo->grab && !SameClient(grabinfo->grab, client))
-            return AlreadyGrabbed;
+    if (grabinfo->grab && !SameClient(grabinfo->grab, client))
+        return AlreadyGrabbed;
 
-        if (!grabWindow->realized)
-            return GrabNotViewable;
+    if (!grabWindow->realized)
+        return GrabNotViewable;
 
-        if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
+    if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
             (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER))
-            return GrabInvalidTime;
+        return GrabInvalidTime;
 
-        if (grabinfo->sync.frozen && grabinfo->sync.other &&
-                !SameClient(grabinfo->sync.other, client))
-            return GrabFrozen;
-
-        memset(&newGrab, 0, sizeof(GrabRec));
-        newGrab.window         = grabWindow;
-        newGrab.resource       = client->clientAsMask;
-        newGrab.ownerEvents    = ownerEvents;
-        newGrab.device         = dev;
-        newGrab.cursor         = cursor;
-        newGrab.confineTo      = confineTo;
-        newGrab.eventMask      = xi_mask;
-        newGrab.genericMasks   = NULL;
+    if (grabinfo->sync.frozen && grabinfo->sync.other &&
+            !SameClient(grabinfo->sync.other, client))
+        return GrabFrozen;
+
+    memset(&newGrab, 0, sizeof(GrabRec));
+    newGrab.window         = grabWindow;
+    newGrab.resource       = client->clientAsMask;
+    newGrab.ownerEvents    = ownerEvents;
+    newGrab.device         = dev;
+    newGrab.cursor         = cursor;
+    newGrab.confineTo      = confineTo;
+    newGrab.eventMask      = xi_mask;
+    newGrab.genericMasks   = NULL;
+
+    if (ge_masks)
+    {
+        GenericMaskPtr last;
+        newGrab.genericMasks  = xcalloc(1, sizeof(GenericMaskRec));
+        *newGrab.genericMasks = *ge_masks;
+        newGrab.genericMasks->next = NULL;
+        ge_masks = ge_masks->next;
+        last     = newGrab.genericMasks;
 
-        if (ge_masks)
+        while(ge_masks)
         {
-            GenericMaskPtr last;
-            newGrab.genericMasks  = xcalloc(1, sizeof(GenericMaskRec));
-            *newGrab.genericMasks = *ge_masks;
-            newGrab.genericMasks->next = NULL;
+            last->next = xcalloc(1, sizeof(GenericMaskRec));
+            last = last->next;
+            *last = *ge_masks;
             ge_masks = ge_masks->next;
-            last     = newGrab.genericMasks;
-
-            while(ge_masks)
-            {
-                last->next = xcalloc(1, sizeof(GenericMaskRec));
-                last = last->next;
-                *last = *ge_masks;
-                ge_masks = ge_masks->next;
-            }
         }
-
-        if (IsPointerDevice(dev))
-        {
-            newGrab.keyboardMode = GrabModeAsync;
-            newGrab.pointerMode  = device_mode;
-        } else
-        {
-            newGrab.keyboardMode = device_mode;
-            newGrab.pointerMode  = GrabModeAsync;
-        }
-
-        (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
     }
 
-    if (grabmode & UngrabAll)
+    if (IsPointerDevice(dev))
+    {
+        newGrab.keyboardMode = GrabModeAsync;
+        newGrab.pointerMode  = device_mode;
+    } else
     {
-        grabinfo = &dev->deviceGrab;
-        if (grabinfo->grab && SameClient(grabinfo->grab, client))
-            (*grabinfo->DeactivateGrab)(dev);
+        newGrab.keyboardMode = device_mode;
+        newGrab.pointerMode  = GrabModeAsync;
     }
 
+    (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
     return GrabSuccess;
 }
 
+
+_X_EXPORT int
+ExtUngrabDevice(ClientPtr client, DeviceIntPtr dev)
+{
+    GrabInfoPtr grabinfo = &dev->deviceGrab;
+    if (grabinfo->grab && SameClient(grabinfo->grab, client))
+        (*grabinfo->DeactivateGrab)(dev);
+    return GrabSuccess;
+}
+
+
diff --git a/include/dix.h b/include/dix.h
index 60a68ee..736a93e 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -699,15 +699,16 @@ extern void SetGenericFilter(int extensi
 
 extern int ExtGrabDevice(ClientPtr client,
                          DeviceIntPtr dev,
-                         int grabmode,
                          int device_mode,
                          WindowPtr grabWindow,
                          WindowPtr confineTo,
                          TimeStamp ctime,
                          Bool ownerEvents,
                          CursorPtr cursor, 
-                         Mask core_mask, 
                          Mask xi_mask,
                          GenericMaskPtr ge_masks);
 
+extern int ExtUngrabDevice(ClientPtr client,
+                         DeviceIntPtr dev);
+
 #endif /* DIX_H */
diff-tree 5c680e94938c16e04a4349715cf11796b80400db (from 4dc973f08c54294e06bc831bd2839fd3aa24ecfb)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 14 12:34:53 2007 +0930

    Remove double-grab option. We only want one grab per device.

diff --git a/Xext/security.c b/Xext/security.c
index 18ab496..715bc31 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -822,13 +822,10 @@ CALLBACK(SecurityCheckDeviceAccess)
     untrusted_got_event = FALSE;
     found_event_window = FALSE;
 
-    /* We can just use coreGrab as a comment a few lines above clearly states
-       "device security other than keyboard is not implemented yet". The core
-       kbd should never have a device grab set. */
-    if (dev->coreGrab.grab)
+    if (dev->deviceGrab.grab)
     {
 	untrusted_got_event =
-          (TRUSTLEVEL(rClient(dev->coreGrab.grab)) != XSecurityClientTrusted);
+        (TRUSTLEVEL(rClient(dev->deviceGrab.grab)) != XSecurityClientTrusted);
     }
     else
     {
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 2ecec96..98c2885 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -100,16 +100,14 @@ RegisterOtherDevice(DeviceIntPtr device)
 {
     device->public.processInputProc = ProcessOtherEvent;
     device->public.realInputProc = ProcessOtherEvent;
-    (device)->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
-    (device)->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
     if (DeviceIsPointerType(device))
     {
-        (device)->coreGrab.ActivateGrab = ActivatePointerGrab;
-        (device)->coreGrab.DeactivateGrab = DeactivatePointerGrab;
-    } else
+        (device)->deviceGrab.ActivateGrab = ActivatePointerGrab;
+        (device)->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
+    } else 
     {
-        (device)->coreGrab.ActivateGrab = ActivateKeyboardGrab;
-        (device)->coreGrab.DeactivateGrab = DeactivateKeyboardGrab;
+        (device)->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
+        (device)->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
     }
 }
 
diff --git a/Xi/ungrdev.c b/Xi/ungrdev.c
index b2b7169..e056ce6 100644
--- a/Xi/ungrdev.c
+++ b/Xi/ungrdev.c
@@ -111,7 +111,7 @@ ProcXUngrabDevice(ClientPtr client)
     time = ClientTimeToServerTime(stuff->time);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
 	(CompareTimeStamps(time, dev->deviceGrab.grabTime) != EARLIER) &&
-	(grab) && SameClient(grab, client))
+	(grab) && SameClient(grab, client) && !grab->coreGrab)
 	(*dev->deviceGrab.DeactivateGrab) (dev);
     return Success;
 }
diff --git a/dix/devices.c b/dix/devices.c
index d663649..ac35fe6 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -126,16 +126,6 @@ AddInputDevice(DeviceProc deviceProc, Bo
     dev->deviceProc = deviceProc;
     dev->startup = autoStart;
 
-    /* core grab defaults */
-    dev->coreGrab.sync.frozen = FALSE;
-    dev->coreGrab.sync.other = NullGrab;
-    dev->coreGrab.sync.state = NOT_GRABBED;
-    dev->coreGrab.sync.event = (xEvent *) NULL;
-    dev->coreGrab.sync.evcount = 0;
-    dev->coreGrab.grab = NullGrab;
-    dev->coreGrab.grabTime = currentTime;
-    dev->coreGrab.fromPassiveGrab = FALSE;
-
     /* device grab defaults */
     dev->deviceGrab.sync.frozen = FALSE;
     dev->deviceGrab.sync.other = NullGrab;
@@ -438,8 +428,8 @@ InitCoreDevices(void)
         dev->public.processInputProc = ProcessKeyboardEvent;
         dev->public.realInputProc = ProcessKeyboardEvent;
 #endif
-        dev->coreGrab.ActivateGrab = ActivateKeyboardGrab;
-        dev->coreGrab.DeactivateGrab = DeactivateKeyboardGrab;
+        dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
+        dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
         dev->coreEvents = FALSE;
         dev->spriteInfo->spriteOwner = FALSE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
@@ -464,8 +454,8 @@ InitCoreDevices(void)
         dev->public.processInputProc = ProcessPointerEvent;
         dev->public.realInputProc = ProcessPointerEvent;
 #endif
-        dev->coreGrab.ActivateGrab = ActivatePointerGrab;
-        dev->coreGrab.DeactivateGrab = DeactivatePointerGrab;
+        dev->deviceGrab.ActivateGrab = ActivatePointerGrab;
+        dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
         dev->coreEvents = FALSE;
         dev->spriteInfo->spriteOwner = TRUE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
@@ -663,7 +653,6 @@ CloseDevice(DeviceIntPtr dev)
     if (dev->devPrivates)
 	xfree(dev->devPrivates);
 
-    xfree(dev->coreGrab.sync.event);
     xfree(dev->deviceGrab.sync.event);
     xfree(dev->spriteInfo);
     xfree(dev);
@@ -2030,7 +2019,7 @@ ProcGetPointerControl(ClientPtr client)
 void
 MaybeStopHint(DeviceIntPtr dev, ClientPtr client)
 {
-    GrabPtr grab = dev->coreGrab.grab;
+    GrabPtr grab = dev->deviceGrab.grab;
 
     if ((grab && SameClient(grab, client) &&
 	 ((grab->eventMask & PointerMotionHintMask) ||
diff --git a/dix/events.c b/dix/events.c
index 415db6e..1d9417d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -539,7 +539,7 @@ XineramaCheckVirtualMotion(
 	pSprite->hot.pScreen = qe->pScreen;  /* should always be Screen 0 */
 	pSprite->hot.x = qe->event->u.keyButtonPointer.rootX;
 	pSprite->hot.y = qe->event->u.keyButtonPointer.rootY;
-	pWin = pDev->coreGrab.grab ? pDev->coreGrab.grab->confineTo :
+	pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo :
 					 NullWindow;
     }
     if (pWin)
@@ -862,7 +862,7 @@ CheckVirtualMotion(
 	pSprite->hot.pScreen = qe->pScreen;
 	pSprite->hot.x = qe->event->u.keyButtonPointer.rootX;
 	pSprite->hot.y = qe->event->u.keyButtonPointer.rootY;
-	pWin = pDev->coreGrab.grab ? pDev->coreGrab.grab->confineTo : NullWindow;
+	pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
     }
     if (pWin)
     {
@@ -991,7 +991,7 @@ static void
 PostNewCursor(DeviceIntPtr pDev)
 {
     WindowPtr win;
-    GrabPtr grab = pDev->coreGrab.grab;
+    GrabPtr grab = pDev->deviceGrab.grab;
     SpritePtr   pSprite = pDev->spriteInfo->sprite;
     CursorPtr   pCursor;
 
@@ -1197,7 +1197,7 @@ PlayReleasedEvents(void)
     prev = &syncEvents.pending;
     while ( (qe = *prev) )
     {
-	if (!qe->device->coreGrab.sync.frozen)
+	if (!qe->device->deviceGrab.sync.frozen)
 	{
 	    *prev = qe->next;
             pDev = qe->device;
@@ -1223,7 +1223,7 @@ PlayReleasedEvents(void)
 	    (*qe->device->public.processInputProc)(qe->event, qe->device,
 						   qe->evcount);
 	    xfree(qe);
-	    for (dev = inputInfo.devices; dev && dev->coreGrab.sync.frozen; dev = dev->next)
+	    for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
 		;
 	    if (!dev)
 		break;
@@ -1239,7 +1239,7 @@ PlayReleasedEvents(void)
 static void
 FreezeThaw(DeviceIntPtr dev, Bool frozen)
 {
-    dev->coreGrab.sync.frozen = frozen;
+    dev->deviceGrab.sync.frozen = frozen;
     if (frozen)
 	dev->public.processInputProc = dev->public.enqueueInputProc;
     else
@@ -1258,15 +1258,15 @@ ComputeFreezes(void)
     DeviceIntPtr dev;
 
     for (dev = inputInfo.devices; dev; dev = dev->next)
-	FreezeThaw(dev, dev->coreGrab.sync.other || 
-                (dev->coreGrab.sync.state >= FROZEN));
+	FreezeThaw(dev, dev->deviceGrab.sync.other || 
+                (dev->deviceGrab.sync.state >= FROZEN));
     if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
 	return;
     syncEvents.playingEvents = TRUE;
     if (replayDev)
     {
-	xE = replayDev->coreGrab.sync.event;
-	count = replayDev->coreGrab.sync.evcount;
+	xE = replayDev->deviceGrab.sync.event;
+	count = replayDev->deviceGrab.sync.evcount;
 	syncEvents.replayDev = (DeviceIntPtr)NULL;
 
         w = XYToWindow(replayDev, XE_KBPTR.rootX, XE_KBPTR.rootY);
@@ -1294,7 +1294,7 @@ ComputeFreezes(void)
 playmore:
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	if (!dev->coreGrab.sync.frozen)
+	if (!dev->deviceGrab.sync.frozen)
 	{
 	    PlayReleasedEvents();
 	    break;
@@ -1307,7 +1307,7 @@ playmore:
         {
             /* the following may have been skipped during replay, 
               so do it now */
-            if ((grab = dev->coreGrab.grab) && grab->confineTo)
+            if ((grab = dev->deviceGrab.grab) && grab->confineTo)
             {
                 if (grab->confineTo->drawable.pScreen !=
                         dev->spriteInfo->sprite->hotPhys.pScreen) 
@@ -1336,7 +1336,7 @@ ScreenRestructured (ScreenPtr pScreen)
 
         /* GrabDevice doesn't have a confineTo field, so we don't need to
          * worry about it. */
-        if ((grab = pDev->coreGrab.grab) && grab->confineTo)
+        if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
         {
             if (grab->confineTo->drawable.pScreen 
                     != pDev->spriteInfo->sprite->hotPhys.pScreen)
@@ -1354,31 +1354,31 @@ ScreenRestructured (ScreenPtr pScreen)
 void
 CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
 {
-    GrabPtr grab = thisDev->coreGrab.grab;
+    GrabPtr grab = thisDev->deviceGrab.grab;
     DeviceIntPtr dev;
 
     if (thisMode == GrabModeSync)
-	thisDev->coreGrab.sync.state = FROZEN_NO_EVENT;
+	thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
     else
     {	/* free both if same client owns both */
-	thisDev->coreGrab.sync.state = THAWED;
-	if (thisDev->coreGrab.sync.other &&
-	    (CLIENT_BITS(thisDev->coreGrab.sync.other->resource) ==
+	thisDev->deviceGrab.sync.state = THAWED;
+	if (thisDev->deviceGrab.sync.other &&
+	    (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
 	     CLIENT_BITS(grab->resource)))
-	    thisDev->coreGrab.sync.other = NullGrab;
+	    thisDev->deviceGrab.sync.other = NullGrab;
     }
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
 	if (dev != thisDev)
 	{
 	    if (otherMode == GrabModeSync)
-		dev->coreGrab.sync.other = grab;
+		dev->deviceGrab.sync.other = grab;
 	    else
 	    {	/* free both if same client owns both */
-		if (dev->coreGrab.sync.other &&
-		    (CLIENT_BITS(dev->coreGrab.sync.other->resource) ==
+		if (dev->deviceGrab.sync.other &&
+		    (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
 		     CLIENT_BITS(grab->resource)))
-		    dev->coreGrab.sync.other = NullGrab;
+		    dev->deviceGrab.sync.other = NullGrab;
 	    }
 	}
     }
@@ -1402,8 +1402,7 @@ void
 ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 
                     TimeStamp time, Bool autoGrab)
 {
-    GrabInfoPtr grabinfo = 
-        (grab->coreGrab) ? &mouse->coreGrab : &mouse->deviceGrab;
+    GrabInfoPtr grabinfo = &mouse->deviceGrab;
     WindowPtr oldWin = (grabinfo->grab) ? 
                         grabinfo->grab->window
                         : mouse->spriteInfo->sprite->win;
@@ -1440,17 +1439,17 @@ ActivatePointerGrab(DeviceIntPtr mouse, 
 void
 DeactivatePointerGrab(DeviceIntPtr mouse)
 {
-    GrabPtr grab = mouse->coreGrab.grab;
+    GrabPtr grab = mouse->deviceGrab.grab;
     DeviceIntPtr dev;
 
     mouse->valuator->motionHintWindow = NullWindow;
-    mouse->coreGrab.grab = NullGrab;
-    mouse->coreGrab.sync.state = NOT_GRABBED;
-    mouse->coreGrab.fromPassiveGrab = FALSE;
+    mouse->deviceGrab.grab = NullGrab;
+    mouse->deviceGrab.sync.state = NOT_GRABBED;
+    mouse->deviceGrab.fromPassiveGrab = FALSE;
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	if (dev->coreGrab.sync.other == grab)
-	    dev->coreGrab.sync.other = NullGrab;
+	if (dev->deviceGrab.sync.other == grab)
+	    dev->deviceGrab.sync.other = NullGrab;
     }
     DoEnterLeaveEvents(mouse, grab->window, 
                        mouse->spriteInfo->sprite->win, NotifyUngrab);
@@ -1470,8 +1469,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse
 void
 ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
 {
-    GrabInfoPtr grabinfo = 
-        (grab->coreGrab) ? &keybd->coreGrab : &keybd->deviceGrab;
+    GrabInfoPtr grabinfo = &keybd->deviceGrab;
     WindowPtr oldWin;
 
     if (grabinfo->grab)
@@ -1501,7 +1499,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd,
 void
 DeactivateKeyboardGrab(DeviceIntPtr keybd)
 {
-    GrabPtr grab = keybd->coreGrab.grab;
+    GrabPtr grab = keybd->deviceGrab.grab;
     DeviceIntPtr dev;
     WindowPtr focusWin = keybd->focus ? keybd->focus->win
                                            : keybd->spriteInfo->sprite->win;
@@ -1513,20 +1511,20 @@ DeactivateKeyboardGrab(DeviceIntPtr keyb
 	focusWin = inputInfo.keyboard->focus->win;
     if (keybd->valuator)
 	keybd->valuator->motionHintWindow = NullWindow;
-    keybd->coreGrab.grab = NullGrab;
-    keybd->coreGrab.sync.state = NOT_GRABBED;
-    keybd->coreGrab.fromPassiveGrab = FALSE;
+    keybd->deviceGrab.grab = NullGrab;
+    keybd->deviceGrab.sync.state = NOT_GRABBED;
+    keybd->deviceGrab.fromPassiveGrab = FALSE;
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	if (dev->coreGrab.sync.other == grab)
-	    dev->coreGrab.sync.other = NullGrab;
+	if (dev->deviceGrab.sync.other == grab)
+	    dev->deviceGrab.sync.other = NullGrab;
     }
     DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
     ComputeFreezes();
 }
 
 /* 
- * Core flag decides whether to work on the coreGrab or deviceGrab sync
+ * Core flag decides whether to work on the deviceGrab or deviceGrab sync
  * fields.
  */
 void
@@ -1540,7 +1538,7 @@ AllowSome(ClientPtr client, 
     TimeStamp grabTime;
     DeviceIntPtr dev;
     GrabInfoPtr devgrabinfo, 
-                grabinfo = (core) ? &thisDev->coreGrab : &thisDev->deviceGrab;
+                grabinfo = (core) ? &thisDev->deviceGrab : &thisDev->deviceGrab;
 
     thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
     thisSynced = FALSE;
@@ -1549,7 +1547,7 @@ AllowSome(ClientPtr client, 
     grabTime = grabinfo->grabTime;
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-        devgrabinfo = (core) ? &dev->coreGrab : &dev->deviceGrab;
+        devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
 
 	if (dev == thisDev)
 	    continue;
@@ -1595,7 +1593,7 @@ AllowSome(ClientPtr client, 
 	    {
 		for (dev = inputInfo.devices; dev; dev = dev->next)
 		{
-                    devgrabinfo = (core) ? &dev->coreGrab : &dev->deviceGrab;
+                    devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
 		    if (devgrabinfo->grab 
                             && SameClient(devgrabinfo->grab, client))
 			devgrabinfo->sync.state = THAWED;
@@ -1611,7 +1609,7 @@ AllowSome(ClientPtr client, 
 	    {
 		for (dev = inputInfo.devices; dev; dev = dev->next)
 		{
-                    devgrabinfo = (core) ? &dev->coreGrab : &dev->deviceGrab;
+                    devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
 		    if (devgrabinfo->grab 
                             && SameClient(devgrabinfo->grab, client))
 			devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
@@ -1640,7 +1638,7 @@ AllowSome(ClientPtr client, 
 		{
 		    if (dev == thisDev)
 			continue;
-                    devgrabinfo = (core) ? &dev->coreGrab : &dev->deviceGrab;
+                    devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
 		    if (devgrabinfo->grab 
                             && SameClient(devgrabinfo->grab, client))
 			devgrabinfo->sync.state = THAWED;
@@ -1718,9 +1716,9 @@ ReleaseActiveGrabs(ClientPtr client)
     	done = TRUE;
     	for (dev = inputInfo.devices; dev; dev = dev->next)
     	{
-	    if (dev->coreGrab.grab && SameClient(dev->coreGrab.grab, client))
+	    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
 	    {
-	    	(*dev->coreGrab.DeactivateGrab)(dev);
+	    	(*dev->deviceGrab.DeactivateGrab)(dev);
 	    	done = FALSE;
 	    }
 
@@ -1979,7 +1977,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev,
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
         tempGrab.coreGrab = True;
-	(*inputInfo.pointer->coreGrab.ActivateGrab)(pDev, &tempGrab,
+        tempGrab.genericMasks = NULL;
+	(*inputInfo.pointer->deviceGrab.ActivateGrab)(pDev, &tempGrab,
 					   currentTime, TRUE);
     }
     else if ((type == MotionNotify) && deliveries)
@@ -2522,7 +2521,7 @@ void ReinitializeRootWindow(WindowPtr wi
                 REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2,    xoff, yoff);
 
             /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
-            if ((grab = pDev->coreGrab.grab) && grab->confineTo) {
+            if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
                 if (grab->confineTo->drawable.pScreen 
                         != pSprite->hotPhys.pScreen)
                     pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
@@ -3015,7 +3014,7 @@ CheckPassiveGrabsOnWindow(
 	    }
 #endif
             grabinfo = (xE->u.u.type & EXTENSION_EVENT_BASE) ? 
-                &device->deviceGrab : &device->coreGrab;
+                &device->deviceGrab : &device->deviceGrab;
 	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
  
 	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
@@ -3165,7 +3164,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIn
     if (xE->u.u.type & EXTENSION_EVENT_BASE || xE->u.u.type == GenericEvent)
         grabinfo = &thisDev->deviceGrab;
     else
-        grabinfo = &thisDev->coreGrab;
+        grabinfo = &thisDev->deviceGrab;
 
     grab = grabinfo->grab;
 
@@ -3338,7 +3337,7 @@ drawable.id:0;
     if (xE->u.u.type & EXTENSION_EVENT_BASE)
         grabinfo = &keybd->deviceGrab;
     else
-        grabinfo = &keybd->coreGrab;
+        grabinfo = &keybd->deviceGrab;
 
     grab = grabinfo->grab;
 
@@ -3501,7 +3500,7 @@ CoreProcessPointerEvent (xEvent *xE, Dev
 ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 #endif
 {
-    GrabPtr	        grab = mouse->coreGrab.grab;
+    GrabPtr	        grab = mouse->deviceGrab.grab;
     Bool                deactivateGrab = FALSE;
     ButtonClassPtr      butc = mouse->button;
     SpritePtr           pSprite = mouse->spriteInfo->sprite;
@@ -3588,7 +3587,7 @@ ProcessPointerEvent (xEvent *xE, DeviceI
 	    if (xE->u.u.detail <= 5)
 		butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	    filters[MotionNotify] = Motion_Filter(butc);
-	    if (!butc->state && mouse->coreGrab.fromPassiveGrab)
+	    if (!butc->state && mouse->deviceGrab.fromPassiveGrab)
 		deactivateGrab = TRUE;
 	    break;
 	default: 
@@ -3603,7 +3602,7 @@ ProcessPointerEvent (xEvent *xE, DeviceI
 	DeliverDeviceEvents(pSprite->win, xE, NullGrab, NullWindow,
 			    mouse, count);
     if (deactivateGrab)
-        (*mouse->coreGrab.DeactivateGrab)(mouse);
+        (*mouse->deviceGrab.DeactivateGrab)(mouse);
 }
 
 #define AtMostOneClient \
@@ -3757,7 +3756,7 @@ maskSet: 
     if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
 	(mask & PointerMotionHintMask) &&
 	!(check & PointerMotionHintMask) &&
-	!inputInfo.pointer->coreGrab.grab) /* VCP shouldn't have deviceGrab */
+	!inputInfo.pointer->deviceGrab.grab) /* VCP shouldn't have deviceGrab */
 	inputInfo.pointer->valuator->motionHintWindow = NullWindow;
     RecalculateDeliverableEvents(pWin);
     return Success;
@@ -3848,7 +3847,7 @@ EnterLeaveEvent(
     xEvent              event;
     WindowPtr		focus;
     DeviceIntPtr        keybd;
-    GrabPtr	        grab = mouse->coreGrab.grab;
+    GrabPtr	        grab = mouse->deviceGrab.grab;
     GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
     int*                inWindow; /* no of sprites inside pWin */
@@ -4401,7 +4400,7 @@ SetInputFocus(
     if ((CompareTimeStamps(time, currentTime) == LATER) ||
 	(CompareTimeStamps(time, focus->time) == EARLIER))
 	return Success;
-    mode = (dev->coreGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
+    mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
     if (focus->win == FollowKeyboardWin)
 	DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
     else
@@ -4556,7 +4555,7 @@ ProcGrabPointer(ClientPtr client)
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
     rep.length = 0;
-    grab = device->coreGrab.grab;
+    grab = device->deviceGrab.grab;
     if ((grab) && !SameClient(grab, client))
 	rep.status = AlreadyGrabbed;
     else if ((!pWin->realized) ||
@@ -4564,12 +4563,12 @@ ProcGrabPointer(ClientPtr client)
                 !(confineTo->realized 
                     && BorderSizeNotEmpty(device, confineTo))))
 	rep.status = GrabNotViewable;
-    else if (device->coreGrab.sync.frozen &&
-	     device->coreGrab.sync.other && 
-             !SameClient(device->coreGrab.sync.other, client))
+    else if (device->deviceGrab.sync.frozen &&
+	     device->deviceGrab.sync.other && 
+             !SameClient(device->deviceGrab.sync.other, client))
 	rep.status = GrabFrozen;
     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
-	     (CompareTimeStamps(time, device->coreGrab.grabTime) == EARLIER))
+	     (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
 	rep.status = GrabInvalidTime;
     else
     {
@@ -4592,7 +4591,8 @@ ProcGrabPointer(ClientPtr client)
 	tempGrab.pointerMode = stuff->pointerMode;
 	tempGrab.device = device;
         tempGrab.coreGrab = True;
-	(*device->coreGrab.ActivateGrab)(device, &tempGrab, time, FALSE);
+        tempGrab.genericMasks = NULL;
+	(*device->deviceGrab.ActivateGrab)(device, &tempGrab, time, FALSE);
 	if (oldCursor)
 	    FreeCursor (oldCursor, (Cursor)0);
 	rep.status = GrabSuccess;
@@ -4613,7 +4613,7 @@ int
 ProcChangeActivePointerGrab(ClientPtr client)
 {
     DeviceIntPtr device = PickPointer(client);
-    GrabPtr      grab = device->coreGrab.grab;
+    GrabPtr      grab = device->deviceGrab.grab;
     CursorPtr newCursor, oldCursor;
     REQUEST(xChangeActivePointerGrabReq);
     TimeStamp time;
@@ -4642,7 +4642,7 @@ ProcChangeActivePointerGrab(ClientPtr cl
 	return Success;
     time = ClientTimeToServerTime(stuff->time);
     if ((CompareTimeStamps(time, currentTime) == LATER) ||
-	     (CompareTimeStamps(time, device->coreGrab.grabTime) == EARLIER))
+	     (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
 	return Success;
     oldCursor = grab->cursor;
     grab->cursor = newCursor;
@@ -4670,12 +4670,12 @@ ProcUngrabPointer(ClientPtr client)
 
     REQUEST_SIZE_MATCH(xResourceReq);
     UpdateCurrentTime();
-    grab = device->coreGrab.grab;
+    grab = device->deviceGrab.grab;
     time = ClientTimeToServerTime(stuff->id);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
-	    (CompareTimeStamps(time, device->coreGrab.grabTime) != EARLIER) &&
+	    (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
 	    (grab) && SameClient(grab, client))
-	(*device->coreGrab.DeactivateGrab)(device);
+	(*device->deviceGrab.DeactivateGrab)(device);
     return Success;
 }
 
@@ -4701,13 +4701,13 @@ int
 GrabDevice(ClientPtr client, DeviceIntPtr dev, 
            unsigned this_mode, unsigned other_mode, Window grabWindow, 
            unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status,
-           Bool coreGrab)
+           Bool deviceGrab)
 {
     WindowPtr pWin;
     GrabPtr grab;
     TimeStamp time;
     int rc;
-    GrabInfoPtr grabInfo = (coreGrab) ? &dev->coreGrab : &dev->deviceGrab;
+    GrabInfoPtr grabInfo = (deviceGrab) ? &dev->deviceGrab : &dev->deviceGrab;
 
     UpdateCurrentTime();
     if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
@@ -4755,7 +4755,8 @@ GrabDevice(ClientPtr client, DeviceIntPt
 	tempGrab.eventMask = mask;
 	tempGrab.device = dev;
         tempGrab.cursor = NULL;
-        tempGrab.coreGrab = coreGrab;
+        tempGrab.coreGrab = deviceGrab;
+        tempGrab.genericMasks = NULL;
 
 	(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
 	*status = GrabSuccess;
@@ -4812,12 +4813,12 @@ ProcUngrabKeyboard(ClientPtr client)
 
     REQUEST_SIZE_MATCH(xResourceReq);
     UpdateCurrentTime();
-    grab = device->coreGrab.grab;
+    grab = device->deviceGrab.grab;
     time = ClientTimeToServerTime(stuff->id);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
-	(CompareTimeStamps(time, device->coreGrab.grabTime) != EARLIER) &&
-	(grab) && SameClient(grab, client))
-	(*device->coreGrab.DeactivateGrab)(device);
+	(CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
+	(grab) && SameClient(grab, client) && grab->coreGrab)
+	(*device->deviceGrab.DeactivateGrab)(device);
     return Success;
 }
 
@@ -5282,23 +5283,23 @@ DeleteWindowFromAnyEvents(WindowPtr pWin
 
     /* Deactivate any grabs performed on this window, before making any
 	input focus changes. */
-    grab = mouse->coreGrab.grab;
+    grab = mouse->deviceGrab.grab;
     if (grab &&
 	((grab->window == pWin) || (grab->confineTo == pWin)))
-	(*mouse->coreGrab.DeactivateGrab)(mouse);
+	(*mouse->deviceGrab.DeactivateGrab)(mouse);
 
 
     /* Deactivating a keyboard grab should cause focus events. */
-    grab = keybd->coreGrab.grab;
+    grab = keybd->deviceGrab.grab;
     if (grab && (grab->window == pWin))
-	(*keybd->coreGrab.DeactivateGrab)(keybd);
+	(*keybd->deviceGrab.DeactivateGrab)(keybd);
 
     /* And now the real devices */
     for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
     {
-        grab = mouse->coreGrab.grab;
+        grab = mouse->deviceGrab.grab;
         if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
-            (*mouse->coreGrab.DeactivateGrab)(mouse);
+            (*mouse->deviceGrab.DeactivateGrab)(mouse);
     }
 
 
@@ -5317,7 +5318,7 @@ DeleteWindowFromAnyEvents(WindowPtr pWin
 
                 /* If a grab is in progress, then alter the mode of focus events. */
 
-                if (keybd->coreGrab.grab)
+                if (keybd->deviceGrab.grab)
                     focusEventMode = NotifyWhileGrabbed;
 
                 switch (focus->revert)
@@ -5398,11 +5399,11 @@ CheckCursorConfinement(WindowPtr pWin)
     {
         if (DevHasCursor(pDev))
         {
-            grab = pDev->coreGrab.grab;
+            grab = pDev->deviceGrab.grab;
             if (grab && (confineTo = grab->confineTo))
             {
                 if (!BorderSizeNotEmpty(pDev, confineTo))
-                    (*inputInfo.pointer->coreGrab.DeactivateGrab)(pDev);
+                    (*inputInfo.pointer->deviceGrab.DeactivateGrab)(pDev);
                 else if ((pWin == confineTo) || IsParent(pWin, confineTo))
                     ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
             }
@@ -5683,7 +5684,7 @@ IsInterferingGrab(ClientPtr client, Wind
     DeviceIntPtr it;
     Bool mayInterfere = FALSE;
 
-    if (dev->coreGrab.grab && SameClient(dev->coreGrab.grab, client))
+    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
         return FALSE;
 
     switch(event->u.u.type)
@@ -5705,7 +5706,7 @@ IsInterferingGrab(ClientPtr client, Wind
     {
         if (it != dev)
         {
-            if (it->coreGrab.grab && SameClient(it->coreGrab.grab, client))
+            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client))
             {
                 /* there's a client with a grab on some device. 
                  * if we're delivering to the very same window that is
@@ -5713,7 +5714,7 @@ IsInterferingGrab(ClientPtr client, Wind
                 WindowPtr parent = win;
                 while(parent)
                 {
-                    if (it->coreGrab.grab->window == parent)
+                    if (it->deviceGrab.grab->window == parent)
                         return FALSE;
                     parent = parent->parent;
                 }
@@ -5742,11 +5743,10 @@ SetGenericFilter(int extension, Mask* fi
 
 
 /**
- * Grab a device properly. 
+ * Grab a device for core events, XI events or XGE events.
  * 
- * grabmode decides if the grab should be for core events and/or XI device
- * events. The latter also applies to generic events.
- * grabmode is also used to ungrab a device.
+ * The latter also applies to generic events.
+ * grabmode is used to ungrab a device.
  * 
  *
  */
@@ -5768,59 +5768,6 @@ ExtGrabDevice(ClientPtr client, 
     GrabRec     newGrab;
 
     UpdateCurrentTime();
-    if (grabmode & CoreOnlyGrab)
-    {
-        CursorPtr oldCursor   = NullCursor;
-
-        grabinfo = &dev->coreGrab;
-
-        if (grabinfo->grab && !SameClient(grabinfo->grab, client))
-            return AlreadyGrabbed;
-
-        if ((!grabWindow->realized) ||
-                (confineTo && !(confineTo->realized &&
-                                BorderSizeNotEmpty(dev, confineTo))))
-            return GrabNotViewable;
-        
-        if (grabinfo->sync.frozen && grabinfo->sync.other &&
-                !SameClient(grabinfo->sync.other, client))
-            return GrabFrozen;
-
-        if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
-            (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER))
-            return GrabInvalidTime;
-
-        if (grabinfo->grab)
-        {
-            if (grabinfo->grab->confineTo)
-                ConfineCursorToWindow(dev, RootWindow(dev), FALSE, FALSE);
-            oldCursor = dev->coreGrab.grab->cursor;
-        }
-
-        memset(&newGrab, 0, sizeof(GrabRec));
-        newGrab.cursor        = cursor;
-        newGrab.resource      = client->clientAsMask;
-        newGrab.ownerEvents   = ownerEvents;
-        newGrab.confineTo     = confineTo;
-        newGrab.window        = grabWindow;
-        newGrab.coreGrab      = True;
-        newGrab.device        = dev;
-        newGrab.eventMask     = core_mask;
-        if (IsPointerDevice(dev))
-        {
-            newGrab.keyboardMode = GrabModeAsync;
-            newGrab.pointerMode  = device_mode;
-        } else
-        {
-            newGrab.keyboardMode = device_mode;
-            newGrab.pointerMode  = GrabModeAsync;
-        }
-
-        (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
-
-        if (oldCursor)
-            FreeCursor(oldCursor, 0);
-    }
 
     if (grabmode & DeviceOnlyGrab)
     {
@@ -5883,10 +5830,7 @@ ExtGrabDevice(ClientPtr client, 
 
     if (grabmode & UngrabAll)
     {
-        if (grabmode & UngrabCoreOnly)
-            grabinfo = &dev->coreGrab;
-        else 
-            grabinfo = &dev->deviceGrab;
+        grabinfo = &dev->deviceGrab;
         if (grabinfo->grab && SameClient(grabinfo->grab, client))
             (*grabinfo->DeactivateGrab)(dev);
     }
diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
index 83dffa1..074c1c7 100644
--- a/hw/xfree86/common/xf86DGA.c
+++ b/hw/xfree86/common/xf86DGA.c
@@ -1114,7 +1114,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScre
     else
     {
 	/* If the keyboard is actively grabbed, deliver a grabbed core event */
-	if (keybd->coreGrab.grab && !keybd->coreGrab.fromPassiveGrab)
+	if (keybd->deviceGrab.grab && !keybd->deviceGrab.fromPassiveGrab)
 	{
             /* I've got no clue if that is correct but only working on core
              * grabs seems the right thing here. (whot) */
@@ -1195,7 +1195,7 @@ DGAProcessPointerEvent (ScreenPtr pScree
     else
     {
 	/* If the pointer is actively grabbed, deliver a grabbed core event */
-	if (mouse->coreGrab.grab && !mouse->coreGrab.fromPassiveGrab)
+	if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab)
 	{
             /* I've got no clue if that is correct but only working on core
              * grabs seems the right thing here. (whot) */
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 8458899..a2f7a2c 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -290,13 +290,13 @@ xf86ProcessActionEvent(ActionEvent actio
 	break;
     case ACTION_DISABLEGRAB:
 	if (!xf86Info.grabInfo.disabled && xf86Info.grabInfo.allowDeactivate) {
-	  if (inputInfo.pointer && inputInfo.pointer->coreGrab.grab != NULL &&
-	      inputInfo.pointer->coreGrab.DeactivateGrab)
-	    inputInfo.pointer->coreGrab.DeactivateGrab(inputInfo.pointer);
+	  if (inputInfo.pointer && inputInfo.pointer->deviceGrab.grab != NULL &&
+	      inputInfo.pointer->deviceGrab.DeactivateGrab)
+	    inputInfo.pointer->deviceGrab.DeactivateGrab(inputInfo.pointer);
 	  if (inputInfo.keyboard && 
-                  inputInfo.keyboard->coreGrab.grab != NULL &&
-	      inputInfo.keyboard->coreGrab.DeactivateGrab)
-	    inputInfo.keyboard->coreGrab.DeactivateGrab(inputInfo.keyboard);
+                  inputInfo.keyboard->deviceGrab.grab != NULL &&
+	      inputInfo.keyboard->deviceGrab.DeactivateGrab)
+	    inputInfo.keyboard->deviceGrab.DeactivateGrab(inputInfo.keyboard);
 	}
 	break;
     case ACTION_CLOSECLIENT:
@@ -304,11 +304,11 @@ xf86ProcessActionEvent(ActionEvent actio
 	  ClientPtr pointer, keyboard, server;
 
 	  pointer = keyboard = server = NULL;
-	  if (inputInfo.pointer && inputInfo.pointer->coreGrab.grab != NULL)
-	    pointer = clients[CLIENT_ID(inputInfo.pointer->coreGrab.grab->resource)];
-	  if (inputInfo.keyboard && inputInfo.keyboard->coreGrab.grab != NULL)
+	  if (inputInfo.pointer && inputInfo.pointer->deviceGrab.grab != NULL)
+	    pointer = clients[CLIENT_ID(inputInfo.pointer->deviceGrab.grab->resource)];
+	  if (inputInfo.keyboard && inputInfo.keyboard->deviceGrab.grab != NULL)
           {
-	    keyboard = clients[CLIENT_ID(inputInfo.keyboard->coreGrab.grab->resource)];
+	    keyboard = clients[CLIENT_ID(inputInfo.keyboard->deviceGrab.grab->resource)];
 	    if (keyboard == pointer)
 	      keyboard = NULL;
 	  }
diff --git a/include/inputstr.h b/include/inputstr.h
index 837afaa..a535884 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -371,8 +371,7 @@ typedef struct _DeviceIntRec {
     Bool	inited;			/* TRUE if INIT returns Success */
     Bool        enabled;                /* TRUE if ON returns Success */
     Bool        coreEvents;             /* TRUE if device also sends core */
-    GrabInfoRec coreGrab;               /* grab on core events */
-    GrabInfoRec deviceGrab;             /* grab on device events */
+    GrabInfoRec deviceGrab;             /* grab on the device */
     Atom		type;
     char		*name;
     CARD8		id;
diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c
index 1e5a43b..973e1ad 100644
--- a/xkb/xkbEvents.c
+++ b/xkb/xkbEvents.c
@@ -832,9 +832,8 @@ GrabInfoPtr grabinfo;
 	     	(_XkbIsReleaseEvent(xE[0].u.u.type)) ) {
 	    return False;
 	}
-        /* just coreGrab is fine, pXDev is inputInfo.keyboard (see above) */
-	if ((pXDev->coreGrab.grab != NullGrab) 
-                && pXDev->coreGrab.fromPassiveGrab &&
+	if ((pXDev->deviceGrab.grab != NullGrab) 
+                && pXDev->deviceGrab.fromPassiveGrab &&
 	    ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) {
 	    register unsigned state,flags;
 
diff-tree 4dc973f08c54294e06bc831bd2839fd3aa24ecfb (from cb22bdbe678a9948eda75d464d6701a729664ef0)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 14 10:42:03 2007 +0930

    Add ExtendedGrabDevice handling.
    Add XGE handling in DeliverGrabbedEvent.
    
    We can now grab something selecting XGE events, but the current code is a
    bit messy and doesn't work too well yet.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index d020210..2cf11a0 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -29,6 +29,8 @@ libXi_la_SOURCES =	\
 	devbell.h \
 	exevents.c \
 	exglobals.h \
+        extgrbdev.c \
+        extgrbdev.h \
 	extinit.c \
 	fakedevdata.c \
 	fakedevdata.h \
diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
new file mode 100644
index 0000000..0f0fd30
--- /dev/null
+++ b/Xi/extgrbdev.c
@@ -0,0 +1,238 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+/***********************************************************************
+ *
+ * Request to fake data for a given device.
+ *
+ */
+
+#define	 NEED_EVENTS
+#define	 NEED_REPLIES
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>	/* for inputstr.h    */
+#include <X11/Xproto.h>	/* Request macro     */
+#include "inputstr.h"	/* DeviceIntPtr      */
+#include "windowstr.h"	/* window structure  */
+#include "scrnintstr.h"	/* screen structure  */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "gestr.h"
+#include "extnsionst.h"
+#include "extinit.h"	/* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+
+#include "extgrbdev.h"
+
+int 
+SProcXExtendedGrabDevice(ClientPtr client)
+{
+    char        n;
+    int         i;
+    long*       p;
+
+    REQUEST(xExtendedGrabDeviceReq);
+    swaps(&stuff->length, n);
+    REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq);
+
+    swapl(&stuff->grab_window, n);
+    swapl(&stuff->time, n);
+    swapl(&stuff->confine_to, n);
+    swapl(&stuff->cursor, n);
+    swaps(&stuff->event_mask, n);
+    swaps(&stuff->event_count, n);
+    swaps(&stuff->ge_event_count, n);
+
+    p = (long *)&stuff[1];
+    for (i = 0; i < stuff->event_count; i++) {
+	swapl(p, n);
+	p++;
+    }
+
+    for (i = 0; i < stuff->ge_event_count; i++) {
+        p++; /* first 4 bytes are extension type and padding */
+        swapl(p, n);
+        p++;
+    }
+
+    return ProcXExtendedGrabDevice(client);
+}
+
+
+int 
+ProcXExtendedGrabDevice(ClientPtr client)
+{
+    xExtendedGrabDeviceReply rep;
+    DeviceIntPtr             dev;
+    int                      err, 
+                             errval = 0,
+                             i;
+    WindowPtr                grab_window, 
+                             confineTo = 0;
+    CursorPtr                cursor = NULL;
+    struct tmask             tmp[EMASKSIZE];
+    TimeStamp                time;
+    XgeEventMask*            xgeMask;
+    GenericMaskPtr           gemasks = NULL;
+
+    REQUEST(xExtendedGrabDeviceReq);
+    REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq);
+
+    if (stuff->length != (sizeof(xExtendedGrabDeviceReq) >> 2) + 
+            stuff->event_count + 2 * stuff->ge_event_count)
+    {
+        errval = 0;
+        err = BadLength;
+        goto cleanup;
+    }
+
+    dev = LookupDeviceIntRec(stuff->deviceid);
+    if (dev == NULL) {
+        errval = stuff->deviceid;
+        err = BadDevice;
+	goto cleanup;
+    }
+
+    err = dixLookupWindow(&grab_window, 
+                          stuff->grab_window, 
+                          client, 
+                          DixReadAccess);
+    if (err != Success)
+    {
+        errval = stuff->grab_window;
+        goto cleanup;
+    }
+    
+    if (stuff->confine_to)
+    {
+        err = dixLookupWindow(&confineTo, 
+                              stuff->confine_to, 
+                              client, 
+                              DixReadAccess);
+        if (err != Success)
+        {
+            errval = stuff->confine_to;
+            goto cleanup;
+        }
+    }
+
+    if (stuff->cursor)
+    {
+        cursor = (CursorPtr)SecurityLookupIDByType(client, 
+                                                    stuff->cursor,
+                                                    RT_CURSOR, 
+                                                    DixReadAccess); 
+        if (!cursor)
+        {
+            errval = stuff->cursor;
+            err = BadCursor;
+            goto cleanup;
+        }
+    }
+
+    rep.repType         = X_Reply;
+    rep.RepType         = X_ExtendedGrabDevice;
+    rep.sequenceNumber  = client->sequence;
+    rep.length          = 0;
+
+    if (CreateMaskFromList(client, 
+                           (XEventClass*)&stuff[1],
+                           stuff->event_count, 
+                           tmp, 
+                           dev, 
+                           X_GrabDevice) != Success)
+        return Success;
+
+    time = ClientTimeToServerTime(stuff->time);
+
+    if (stuff->ge_event_count)
+    {
+        xgeMask = 
+            (XgeEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
+
+        gemasks = xcalloc(1, sizeof(GenericMaskRec));
+        gemasks->extension = xgeMask->extension;
+        gemasks->mask = xgeMask->evmask;
+        gemasks->next = NULL;
+        xgeMask++;
+
+        for (i = 1; i < stuff->ge_event_count; i++, xgeMask++)
+        {
+            gemasks->next = xcalloc(1, sizeof(GenericMaskRec));
+            gemasks = gemasks->next;
+            gemasks->extension = xgeMask->extension;
+            gemasks->mask = xgeMask->evmask;
+            gemasks->next = NULL;
+        }
+    }
+
+    ExtGrabDevice(client, dev, stuff->grabmode, stuff->device_mode, 
+                  grab_window, confineTo, time, stuff->owner_events, 
+                  cursor, stuff->event_mask, tmp[stuff->deviceid].mask, 
+                  gemasks);
+
+    if (err != Success) {
+        errval = 0;
+        goto cleanup;
+    }
+    
+cleanup:
+
+    while(gemasks)
+    {
+        GenericMaskPtr prev = gemasks;
+        gemasks = gemasks->next;
+        xfree(prev);
+    }
+
+    if (err == Success)
+    {
+        WriteReplyToClient(client, sizeof(xGrabDeviceReply), &rep);
+    } 
+    else 
+    {
+        SendErrorToClient(client, IReqCode, 
+                          X_ExtendedGrabDevice, 
+                          errval, err);
+    }
+    return Success;
+}
+
+void
+SRepXExtendedGrabDevice(ClientPtr client, int size, 
+                        xExtendedGrabDeviceReply* rep)
+{
+    char n;
+    swaps(&rep->sequenceNumber, n);
+    swaps(&rep->length, n);
+    WriteToClient(client, size, (char*)rep);
+}
diff --git a/Xi/extgrbdev.h b/Xi/extgrbdev.h
new file mode 100644
index 0000000..93075b1
--- /dev/null
+++ b/Xi/extgrbdev.h
@@ -0,0 +1,46 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef EXTGRBDEV_H
+#define EXTGRBDEV_H 1
+
+int SProcXExtendedGrabDevice(ClientPtr	/* client */
+    );
+
+int ProcXExtendedGrabDevice(ClientPtr	/* client */
+    );
+
+void SRepXExtendedGrabDevice(ClientPtr   client, 
+                            int         size, 
+                            xExtendedGrabDeviceReply* rep);
+
+#endif /* EXTGRBDEV_H */
diff --git a/Xi/extinit.c b/Xi/extinit.c
index bfb2bc7..0888730 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -85,6 +85,7 @@ SOFTWARE.
 #include "chgptr.h"
 #include "chpkpair.h"
 #include "closedev.h"
+#include "extgrbdev.h"
 #include "devbell.h"
 #include "fakedevdata.h"
 #include "getbmap.h"
@@ -346,6 +347,8 @@ ProcIDispatch(ClientPtr client)
         return ProcXGetPairedPointer(client);
     else if (stuff->data == X_FakeDeviceData)
         return ProcXFakeDeviceData(client);
+    else if (stuff->data == X_ExtendedGrabDevice)
+        return ProcXExtendedGrabDevice(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -461,6 +464,8 @@ SProcIDispatch(ClientPtr client)
         return SProcXGetPairedPointer(client);
     else if (stuff->data == X_FakeDeviceData)
         return SProcXFakeDeviceData(client);
+    else if (stuff->data == X_ExtendedGrabDevice)
+        return SProcXExtendedGrabDevice(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -549,6 +554,8 @@ SReplyIDispatch(ClientPtr client, int le
         SRepXGetClientPointer(client, len, (xGetClientPointerReply*) rep);
     else if (rep->RepType == X_GetPairedPointer)
         SRepXGetPairedPointer(client, len, (xGetPairedPointerReply*) rep);
+    else if (rep->RepType == X_ExtendedGrabDevice)
+        SRepXExtendedGrabDevice(client, len, (xExtendedGrabDeviceReply*) rep);
     else {
 	FatalError("XINPUT confused sending swapped reply");
     }
diff --git a/Xi/grabdev.c b/Xi/grabdev.c
index 143b98c..f3349ba 100644
--- a/Xi/grabdev.c
+++ b/Xi/grabdev.c
@@ -155,6 +155,13 @@ ProcXGrabDevice(ClientPtr client)
  *
  * This procedure creates an event mask from a list of XEventClasses.
  *
+ * Procedure is as follows: 
+ * An XEventClass is (deviceid << 8 | eventtype). For each entry in the list,
+ * get the device. Then run through all available event indices (those are
+ * set when XI starts up) and binary OR's the device's mask to whatever the
+ * event mask for the given event type was. 
+ *
+ * mask has to be size EMASKSIZE and pre-allocated.
  */
 
 int
diff --git a/dix/devices.c b/dix/devices.c
index bd145a0..d663649 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -653,7 +653,7 @@ CloseDevice(DeviceIntPtr dev)
     /* a client may have the device set as client pointer */
     for (j = 0; j < currentMaxClients; j++)
     {
-        if (clients[j]->clientPtr == dev)
+        if (clients[j] && clients[j]->clientPtr == dev)
         {
             clients[j]->clientPtr = NULL;
             clients[j]->clientPtr = PickPointer(clients[j]);
diff --git a/dix/events.c b/dix/events.c
index c8b0eb2..415db6e 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -170,6 +170,7 @@ static xEvent *xeviexE;
 #endif
 
 #include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI.h>
 #include "exglobals.h"
 #include "exevents.h"
 #include "exglobals.h"
@@ -1401,8 +1402,10 @@ void
 ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 
                     TimeStamp time, Bool autoGrab)
 {
-    WindowPtr oldWin = (mouse->coreGrab.grab) ? 
-                        mouse->coreGrab.grab->window
+    GrabInfoPtr grabinfo = 
+        (grab->coreGrab) ? &mouse->coreGrab : &mouse->deviceGrab;
+    WindowPtr oldWin = (grabinfo->grab) ? 
+                        grabinfo->grab->window
                         : mouse->spriteInfo->sprite->win;
 
     if (grab->confineTo)
@@ -1416,14 +1419,14 @@ ActivatePointerGrab(DeviceIntPtr mouse, 
     DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
     mouse->valuator->motionHintWindow = NullWindow;
     if (syncEvents.playingEvents)
-        mouse->coreGrab.grabTime = syncEvents.time;
+        grabinfo->grabTime = syncEvents.time;
     else
-	mouse->coreGrab.grabTime = time;
+	grabinfo->grabTime = time;
     if (grab->cursor)
 	grab->cursor->refcnt++;
-    mouse->coreGrab.activeGrab = *grab;
-    mouse->coreGrab.grab = &mouse->coreGrab.activeGrab;
-    mouse->coreGrab.fromPassiveGrab = autoGrab;
+    grabinfo->activeGrab = *grab;
+    grabinfo->grab = &grabinfo->activeGrab;
+    grabinfo->fromPassiveGrab = autoGrab;
     PostNewCursor(mouse);
     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
 }
@@ -1467,10 +1470,12 @@ DeactivatePointerGrab(DeviceIntPtr mouse
 void
 ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
 {
+    GrabInfoPtr grabinfo = 
+        (grab->coreGrab) ? &keybd->coreGrab : &keybd->deviceGrab;
     WindowPtr oldWin;
 
-    if (keybd->coreGrab.grab)
-	oldWin = keybd->coreGrab.grab->window;
+    if (grabinfo->grab)
+	oldWin = grabinfo->grab->window;
     else if (keybd->focus)
 	oldWin = keybd->focus->win;
     else
@@ -1481,12 +1486,12 @@ ActivateKeyboardGrab(DeviceIntPtr keybd,
 	keybd->valuator->motionHintWindow = NullWindow;
     DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
     if (syncEvents.playingEvents)
-	keybd->coreGrab.grabTime = syncEvents.time;
+	grabinfo->grabTime = syncEvents.time;
     else
-	keybd->coreGrab.grabTime = time;
-    keybd->coreGrab.activeGrab = *grab;
-    keybd->coreGrab.grab = &keybd->coreGrab.activeGrab;
-    keybd->coreGrab.fromPassiveGrab = passive;
+	grabinfo->grabTime = time;
+    grabinfo->activeGrab = *grab;
+    grabinfo->grab = &grabinfo->activeGrab;
+    grabinfo->fromPassiveGrab = passive;
     CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
 }
 
@@ -1501,6 +1506,9 @@ DeactivateKeyboardGrab(DeviceIntPtr keyb
     WindowPtr focusWin = keybd->focus ? keybd->focus->win
                                            : keybd->spriteInfo->sprite->win;
 
+    if (!grab)
+        grab = keybd->deviceGrab.grab;
+
     if (focusWin == FollowKeyboardWin)
 	focusWin = inputInfo.keyboard->focus->win;
     if (keybd->valuator)
@@ -3154,7 +3162,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIn
     xEvent *dxE;
     SpritePtr pSprite = thisDev->spriteInfo->sprite;
 
-    if (xE->u.u.type & EXTENSION_EVENT_BASE)
+    if (xE->u.u.type & EXTENSION_EVENT_BASE || xE->u.u.type == GenericEvent)
         grabinfo = &thisDev->deviceGrab;
     else
         grabinfo = &thisDev->coreGrab;
@@ -3188,11 +3196,32 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIn
     {
         if (ACDeviceAllowed(grab->window, thisDev))
         {
+            if (xE->u.u.type == GenericEvent)
+            {
+                /* find evmask for event's extension */
+                xGenericEvent* ge = ((xGenericEvent*)xE);
+                GenericMaskPtr gemask = grab->genericMasks;
+                while(gemask)
+                {
+                    if (gemask->extension == ge->extension)
+                        break;
+                    gemask = gemask->next;
+                }
+
+                if (!gemask)
+                    return;
 
-            FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
-            deliveries = TryClientEvents(rClient(grab), xE, count,
-                    (Mask)grab->eventMask,
-                    filters[xE->u.u.type], grab);
+                deliveries = TryClientEvents(rClient(grab), xE, count, 
+                        gemask->mask,
+                        generic_filters[GEEXTIDX(ge)][ge->evtype],
+                        grab);
+            } else 
+            {
+                FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
+                deliveries = TryClientEvents(rClient(grab), xE, count,
+                        (Mask)grab->eventMask,
+                        filters[xE->u.u.type], grab);
+            }
             if (deliveries && (xE->u.u.type == MotionNotify
 #ifdef XINPUT
                         || xE->u.u.type == DeviceMotionNotify
@@ -4726,6 +4755,7 @@ GrabDevice(ClientPtr client, DeviceIntPt
 	tempGrab.eventMask = mask;
 	tempGrab.device = dev;
         tempGrab.cursor = NULL;
+        tempGrab.coreGrab = coreGrab;
 
 	(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
 	*status = GrabSuccess;
@@ -5709,3 +5739,158 @@ SetGenericFilter(int extension, Mask* fi
 {
     generic_filters[extension & 0x7f] = filters;
 }
+
+
+/**
+ * Grab a device properly. 
+ * 
+ * grabmode decides if the grab should be for core events and/or XI device
+ * events. The latter also applies to generic events.
+ * grabmode is also used to ungrab a device.
+ * 
+ *
+ */
+_X_EXPORT int
+ExtGrabDevice(ClientPtr client, 
+              DeviceIntPtr dev, 
+              int grabmode, 
+              int device_mode,
+              WindowPtr grabWindow, 
+              WindowPtr confineTo, 
+              TimeStamp ctime, 
+              Bool ownerEvents, 
+              CursorPtr cursor, 
+              Mask core_mask, 
+              Mask xi_mask, 
+              GenericMaskPtr ge_masks)
+{
+    GrabInfoPtr grabinfo;
+    GrabRec     newGrab;
+
+    UpdateCurrentTime();
+    if (grabmode & CoreOnlyGrab)
+    {
+        CursorPtr oldCursor   = NullCursor;
+
+        grabinfo = &dev->coreGrab;
+
+        if (grabinfo->grab && !SameClient(grabinfo->grab, client))
+            return AlreadyGrabbed;
+
+        if ((!grabWindow->realized) ||
+                (confineTo && !(confineTo->realized &&
+                                BorderSizeNotEmpty(dev, confineTo))))
+            return GrabNotViewable;
+        
+        if (grabinfo->sync.frozen && grabinfo->sync.other &&
+                !SameClient(grabinfo->sync.other, client))
+            return GrabFrozen;
+
+        if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
+            (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER))
+            return GrabInvalidTime;
+
+        if (grabinfo->grab)
+        {
+            if (grabinfo->grab->confineTo)
+                ConfineCursorToWindow(dev, RootWindow(dev), FALSE, FALSE);
+            oldCursor = dev->coreGrab.grab->cursor;
+        }
+
+        memset(&newGrab, 0, sizeof(GrabRec));
+        newGrab.cursor        = cursor;
+        newGrab.resource      = client->clientAsMask;
+        newGrab.ownerEvents   = ownerEvents;
+        newGrab.confineTo     = confineTo;
+        newGrab.window        = grabWindow;
+        newGrab.coreGrab      = True;
+        newGrab.device        = dev;
+        newGrab.eventMask     = core_mask;
+        if (IsPointerDevice(dev))
+        {
+            newGrab.keyboardMode = GrabModeAsync;
+            newGrab.pointerMode  = device_mode;
+        } else
+        {
+            newGrab.keyboardMode = device_mode;
+            newGrab.pointerMode  = GrabModeAsync;
+        }
+
+        (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
+
+        if (oldCursor)
+            FreeCursor(oldCursor, 0);
+    }
+
+    if (grabmode & DeviceOnlyGrab)
+    {
+        grabinfo = &dev->deviceGrab;
+
+        if (grabinfo->grab && !SameClient(grabinfo->grab, client))
+            return AlreadyGrabbed;
+
+        if (!grabWindow->realized)
+            return GrabNotViewable;
+
+        if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
+            (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER))
+            return GrabInvalidTime;
+
+        if (grabinfo->sync.frozen && grabinfo->sync.other &&
+                !SameClient(grabinfo->sync.other, client))
+            return GrabFrozen;
+
+        memset(&newGrab, 0, sizeof(GrabRec));
+        newGrab.window         = grabWindow;
+        newGrab.resource       = client->clientAsMask;
+        newGrab.ownerEvents    = ownerEvents;
+        newGrab.device         = dev;
+        newGrab.cursor         = cursor;
+        newGrab.confineTo      = confineTo;
+        newGrab.eventMask      = xi_mask;
+        newGrab.genericMasks   = NULL;
+
+        if (ge_masks)
+        {
+            GenericMaskPtr last;
+            newGrab.genericMasks  = xcalloc(1, sizeof(GenericMaskRec));
+            *newGrab.genericMasks = *ge_masks;
+            newGrab.genericMasks->next = NULL;
+            ge_masks = ge_masks->next;
+            last     = newGrab.genericMasks;
+
+            while(ge_masks)
+            {
+                last->next = xcalloc(1, sizeof(GenericMaskRec));
+                last = last->next;
+                *last = *ge_masks;
+                ge_masks = ge_masks->next;
+            }
+        }
+
+        if (IsPointerDevice(dev))
+        {
+            newGrab.keyboardMode = GrabModeAsync;
+            newGrab.pointerMode  = device_mode;
+        } else
+        {
+            newGrab.keyboardMode = device_mode;
+            newGrab.pointerMode  = GrabModeAsync;
+        }
+
+        (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
+    }
+
+    if (grabmode & UngrabAll)
+    {
+        if (grabmode & UngrabCoreOnly)
+            grabinfo = &dev->coreGrab;
+        else 
+            grabinfo = &dev->deviceGrab;
+        if (grabinfo->grab && SameClient(grabinfo->grab, client))
+            (*grabinfo->DeactivateGrab)(dev);
+    }
+
+    return GrabSuccess;
+}
+
diff --git a/include/dix.h b/include/dix.h
index 1828f43..60a68ee 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -51,6 +51,8 @@ SOFTWARE.
 #include "gc.h"
 #include "window.h"
 #include "input.h"
+#include "cursor.h"
+#include <X11/extensions/XI.h>
 
 #define EARLIER -1
 #define SAMETIME 0
@@ -693,6 +695,19 @@ extern Bool IsKeyboardDevice(DeviceIntPt
 
 
 /* GE stuff */
-void SetGenericFilter(int extension, Mask* filters);
+extern void SetGenericFilter(int extension, Mask* filters);
+
+extern int ExtGrabDevice(ClientPtr client,
+                         DeviceIntPtr dev,
+                         int grabmode,
+                         int device_mode,
+                         WindowPtr grabWindow,
+                         WindowPtr confineTo,
+                         TimeStamp ctime,
+                         Bool ownerEvents,
+                         CursorPtr cursor, 
+                         Mask core_mask, 
+                         Mask xi_mask,
+                         GenericMaskPtr ge_masks);
 
 #endif /* DIX_H */
diff --git a/include/inputstr.h b/include/inputstr.h
index 4924cb1..837afaa 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -102,6 +102,22 @@ typedef struct _DetailRec {		/* Grab det
     Mask                *pMask;
 } DetailRec;
 
+typedef struct _GenericMaskRec {
+    int                 extension;
+    Mask                mask;
+    struct _GenericMaskRec* next;
+} GenericMaskRec;
+
+/**
+ * Central struct for device grabs. 
+ * The same struct is used for both core grabs and device grabs, with
+ * different fields being set. 
+ * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask
+ * is a combination of standard event masks (i.e. PointerMotionMask |
+ * ButtonPressMask).
+ * If the grab is a device grab (GrabDevice), then the eventMask is a
+ * combination of event masks for a given XI event type (see SetEventInfo).
+ */
 typedef struct _GrabRec {
     GrabPtr		next;		/* for chain of passive grabs */
     XID			resource;
@@ -119,6 +135,7 @@ typedef struct _GrabRec {
     WindowPtr		confineTo;	/* always NULL for keyboards */
     CursorPtr		cursor;		/* always NULL for keyboards */
     Mask		eventMask;
+    GenericMaskPtr      genericMasks;   /* null terminated list */
 } GrabRec;
 
 typedef struct _KeyClassRec {
diff --git a/include/misc.h b/include/misc.h
index 2be1d66..05c3dff 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -243,6 +243,7 @@ typedef struct _Box *BoxPtr;
 typedef struct _xEvent *xEventPtr;
 typedef struct _xRectangle *xRectanglePtr;
 typedef struct _GrabRec *GrabPtr;
+typedef struct _GenericMaskRec *GenericMaskPtr;
 
 /*  typedefs from other places - duplicated here to minimize the amount
  *  of unnecessary junk that one would normally have to include to get
diff-tree cb22bdbe678a9948eda75d464d6701a729664ef0 (from c03d9a7217f9895feed8cfed3ede4752faf6187c)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 3 10:05:58 2007 +0930

    Add selected RamDac functions to xfree86LookupTab.
    
    Adding those makes drivers for s3 and tga work again.

diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c
index 5175f01..ca32d6e 100644
--- a/hw/xfree86/loader/xf86sym.c
+++ b/hw/xfree86/loader/xf86sym.c
@@ -97,6 +97,9 @@
 #include "xf86DDC.h"
 #include "edid.h"
 
+#include "xf86RamDac.h"
+#include "BT.h"
+
 #ifndef HAS_GLIBC_SIGSETJMP
 #if defined(setjmp) && defined(__GNU_LIBRARY__) && \
     (!defined(__GLIBC__) || (__GLIBC__ < 2) || \
@@ -1255,4 +1258,14 @@ _X_HIDDEN void *xfree86LookupTab[] = {
     SYMFUNC(xf86I2CWriteRead)
     SYMFUNC(xf86I2CWriteVec)
     SYMFUNC(xf86I2CWriteWord)
+
+    /* ramdac */
+    SYMFUNC(RamDacInit)
+    SYMFUNC(RamDacCreateInfoRec)
+    SYMFUNC(RamDacDestroyInfoRec)
+    SYMFUNC(RamDacHelperCreateInfoRec)
+    SYMFUNC(RamDacFreeRec)
+    SYMFUNC(RamDacHandleColormaps)
+    SYMFUNC(RamDacGetHWIndex)
+    SYMFUNC(BTramdacProbe)
 };
diff-tree c03d9a7217f9895feed8cfed3ede4752faf6187c (from e6fd4a24ebd205013b41e44aacbbfb847709d2fd)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 2 18:16:40 2007 +0930

    Cleaning up a bit.
    
    Register correct event in EventSwapVector.
    Fix up event swap for GE events, register XI's swap function at GE.

diff --git a/Xext/geext.c b/Xext/geext.c
index 7c4573e..fed74dc 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -235,8 +235,7 @@ GEExtensionInit(void)
 
         memset(GEExtensions, 0, sizeof(GEExtensions));
 
-        EventSwapVector[GEEventBase + X_GenericEvent] = 
-            (EventSwapPtr) SGEGenericEvent;
+        EventSwapVector[X_GenericEvent] = (EventSwapPtr) SGEGenericEvent;
     } else {
         FatalError("GEInit: AddExtensions failed.\n");
     }
diff --git a/Xi/chpkpair.c b/Xi/chpkpair.c
index 555c8e1..db8e7f6 100644
--- a/Xi/chpkpair.c
+++ b/Xi/chpkpair.c
@@ -131,5 +131,7 @@ SPointerKeyboardPairingChangedNotifyEven
 
     *to = *from;
     swaps(&to->sequenceNumber, n);
+    swapl(&to->length, n);
+    swapl(&to->evtype, n);
     swapl(&to->time, n);
 }
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 6d8c961..bfb2bc7 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -238,25 +238,6 @@ static XExtensionVersion thisversion = {
     XI_Add_DevicePresenceNotify_Minor
 };
 
-/****************************************************************
- *
- * EventSwap for generic events coming from the GE extension.
- */
-
-static void 
-XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
-{
-    int n;
-
-    swaps(&from->sequenceNumber, n);
-    switch(from->evtype)
-    {
-        case XI_PointerKeyboardPairingChangedNotify:
-            SPointerKeyboardPairingChangedNotifyEvent
-                ((pairingChangedNotify*)from, (pairingChangedNotify*)to);
-            break;
-    }
-}
 
 /*************************************************************************
  *
@@ -700,6 +681,22 @@ SDeviceLeaveNotifyEvent (deviceLeaveNoti
     swaps(&to->eventY, n);
 }
 
+static void
+SRawDeviceEvent(rawDeviceEvent* from, rawDeviceEvent *to)
+{
+    char n;
+    int i;
+    CARD32* valptr;
+    
+
+    *to = *from;
+    swaps(&to->sequenceNumber, n);
+    swapl(&to->length, n);
+    swapl(&to->evtype, n);
+    valptr = &to->valuator0;
+    for (i = 0; i < from->num_valuators; i++, valptr++)
+        swapl(valptr, n);
+}
 
 /**************************************************************************
  *
@@ -994,7 +991,6 @@ IResetProc(ExtensionEntry * unused)
     EventSwapVector[DevicePresenceNotify] = NotImplemented;
     EventSwapVector[DeviceEnterNotify] = NotImplemented;
     EventSwapVector[DeviceLeaveNotify] = NotImplemented;
-    EventSwapVector[PointerKeyboardPairingChangedNotify] = NotImplemented;
     RestoreExtensionEvents();
 }
 
@@ -1128,6 +1124,29 @@ SEventIDispatch(xEvent * from, xEvent * 
     }
 }
 
+/****************************************************************
+ *
+ * EventSwap for generic events coming from the GE extension.
+ */
+
+static void 
+XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
+{
+    int n;
+
+    swaps(&from->sequenceNumber, n);
+    switch(from->evtype)
+    {
+        case XI_PointerKeyboardPairingChangedNotify:
+            SPointerKeyboardPairingChangedNotifyEvent
+                ((pairingChangedNotify*)from, (pairingChangedNotify*)to);
+            break;
+        case XI_RawDeviceEvent:
+            SRawDeviceEvent((rawDeviceEvent*)from, (rawDeviceEvent*)to);
+            break;
+    }
+}
+
 /**********************************************************************
  *
  * IExtensionInit - initialize the input extension.
@@ -1172,6 +1191,7 @@ XInputExtensionInit(void)
 	EventSwapVector[DeviceLeaveNotify] = SEventIDispatch;
 
         /* init GE events */
+        GERegisterExtension(IReqCode, XIGEEventSwap);
         SetGenericFilter(IReqCode, xi_filters);
     } else {
 	FatalError("IExtensionInit: AddExtensions failed\n");
diff-tree e6fd4a24ebd205013b41e44aacbbfb847709d2fd (from af25720598bb35d9d953ac8d9a07528289ebfb4a)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 2 17:49:20 2007 +0930

    Add handling for FakeDeviceEvent request.
    Fix a stupid bug from last commit, mask names were wrong.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 346453c..d020210 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -30,6 +30,8 @@ libXi_la_SOURCES =	\
 	exevents.c \
 	exglobals.h \
 	extinit.c \
+	fakedevdata.c \
+	fakedevdata.h \
 	getbmap.c \
 	getbmap.h \
 	getcptr.c \
diff --git a/Xi/extinit.c b/Xi/extinit.c
index beac426..6d8c961 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -86,6 +86,7 @@ SOFTWARE.
 #include "chpkpair.h"
 #include "closedev.h"
 #include "devbell.h"
+#include "fakedevdata.h"
 #include "getbmap.h"
 #include "getbmap.h"
 #include "getcptr.h"
@@ -133,8 +134,8 @@ Mask ExtExclusiveMasks[EMASKSIZE];
 
 
 static Mask xi_filters[3] = {
-    XI_PointerKeyboardPairingChangedNotifyMask,
-    XI_RandomStringEventMask,
+    XI_PointerKeyboardPairingChangedMask,
+    XI_RandomStringMask,
     XI_RawDeviceEventMask,  
 };
 
@@ -362,6 +363,8 @@ ProcIDispatch(ClientPtr client)
         return ProcXGetClientPointer(client);
     else if (stuff->data == X_GetPairedPointer)
         return ProcXGetPairedPointer(client);
+    else if (stuff->data == X_FakeDeviceData)
+        return ProcXFakeDeviceData(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -475,6 +478,8 @@ SProcIDispatch(ClientPtr client)
         return SProcXGetClientPointer(client);
     else if (stuff->data == X_GetPairedPointer)
         return SProcXGetPairedPointer(client);
+    else if (stuff->data == X_FakeDeviceData)
+        return SProcXFakeDeviceData(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
diff --git a/Xi/fakedevdata.c b/Xi/fakedevdata.c
new file mode 100644
index 0000000..64f2ea6
--- /dev/null
+++ b/Xi/fakedevdata.c
@@ -0,0 +1,128 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+/***********************************************************************
+ *
+ * Request to fake data for a given device.
+ *
+ */
+
+#define	 NEED_EVENTS
+#define	 NEED_REPLIES
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>	/* for inputstr.h    */
+#include <X11/Xproto.h>	/* Request macro     */
+#include "inputstr.h"	/* DeviceIntPtr      */
+#include "windowstr.h"	/* window structure  */
+#include "scrnintstr.h"	/* screen structure  */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "extinit.h"	/* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+#include "mi.h"
+
+#include "fakedevdata.h"
+
+static EventListPtr fake_events = NULL;
+
+int
+SProcXFakeDeviceData(ClientPtr client)
+{
+    char n;
+    int i;
+    ValuatorData* p;
+
+    REQUEST(xFakeDeviceDataReq);
+
+    swaps(&stuff->length, n);
+    REQUEST_AT_LEAST_SIZE(xFakeDeviceDataReq);
+
+    p = (ValuatorData*)&stuff[1];
+    for (i = 0; i <  stuff->num_valuators; i++, p++)
+        swapl(p, n);
+
+    return ProcXFakeDeviceData(client);;
+}
+
+int 
+ProcXFakeDeviceData(ClientPtr client)
+{
+    DeviceIntPtr dev;
+    int nevents, i;
+    int* valuators = NULL;
+
+    REQUEST(xFakeDeviceDataReq);
+    REQUEST_AT_LEAST_SIZE(xFakeDeviceDataReq);
+
+    if (stuff->length != (sizeof(xFakeDeviceDataReq) >> 2) + stuff->num_valuators)
+    {
+        SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadLength);
+        return Success;
+    }
+
+    dev = LookupDeviceIntRec(stuff->deviceid);
+    if (dev == NULL) {
+        SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadDevice); 
+        return Success;
+    }
+
+    if (!fake_events && !(fake_events = InitEventList(GetMaximumEventsNum())))
+    {
+        SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadAlloc);
+        return Success;
+    }
+    if (stuff->num_valuators)
+    {
+        CARD32* valptr = (CARD32*)&stuff[1];
+
+        valuators = xcalloc(stuff->num_valuators, sizeof(int));
+        if (!valuators)
+        {
+            SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadAlloc);
+            return Success;
+        }
+        for (i = 0; i < stuff->num_valuators; i++, valptr++)
+            valuators[i] = (int)(*valptr);
+    }
+
+    nevents = GetPointerEvents(fake_events, dev, stuff->type, stuff->buttons,
+            POINTER_RELATIVE, stuff->first_valuator, stuff->num_valuators,
+            valuators);
+
+    OsBlockSignals();
+    for (i = 0; i < nevents; i++)
+        mieqEnqueue(dev, (fake_events+ i)->event);
+    OsReleaseSignals();
+    xfree(valuators);
+    return Success;
+}
diff --git a/Xi/fakedevdata.h b/Xi/fakedevdata.h
new file mode 100644
index 0000000..28dd729
--- /dev/null
+++ b/Xi/fakedevdata.h
@@ -0,0 +1,42 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef FAKEDEVDATA_H
+#define FAKEDEVDATA_H 1
+
+int SProcXFakeDeviceData(ClientPtr	/* client */
+    );
+
+int ProcXFakeDeviceData(ClientPtr	/* client */
+    );
+
+#endif /* FAKEDEVDATA_H */
diff-tree af25720598bb35d9d953ac8d9a07528289ebfb4a (from 58c0fd29272fb6c2f193cff82fb0b0573c607eec)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 2 13:51:16 2007 +0930

    Add missing files for ProcXiSelectEvent.
    
    Should have been a part of 5e439109292e54b5c4d1a7bc7b6ac0e42ee285f7. Oh well.

diff --git a/Xi/xiselev.c b/Xi/xiselev.c
new file mode 100644
index 0000000..8740487
--- /dev/null
+++ b/Xi/xiselev.c
@@ -0,0 +1,78 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#define	 NEED_EVENTS
+#define	 NEED_REPLIES
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/extensions/XIproto.h>
+
+#include "dixstruct.h"
+#include "windowstr.h"
+
+#include "exglobals.h"
+#include "xiselev.h"
+#include "geext.h"
+
+int
+SProcXiSelectEvent(ClientPtr client)
+{
+    char n;
+
+    REQUEST(xXiSelectEventReq);
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(xXiSelectEventReq);
+    swapl(&stuff->window, n);
+    swapl(&stuff->mask, n);
+    return (ProcXiSelectEvent(client));
+}
+
+
+int
+ProcXiSelectEvent(ClientPtr client)
+{
+    int ret;
+    WindowPtr pWin;
+    REQUEST(xXiSelectEventReq);
+    REQUEST_SIZE_MATCH(xXiSelectEventReq);
+
+    ret = dixLookupWindow(&pWin, stuff->window, client, DixReadWriteAccess);
+    if (ret != Success)
+    {
+        SendErrorToClient(client, IReqCode, X_XiSelectEvent, 0, ret);
+        return Success;
+    }
+
+    GEWindowSetMask(client, pWin, IReqCode, stuff->mask);
+
+    return Success;
+}
+
diff --git a/Xi/xiselev.h b/Xi/xiselev.h
new file mode 100644
index 0000000..9102815
--- /dev/null
+++ b/Xi/xiselev.h
@@ -0,0 +1,44 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef XISELEV_H
+#define XISELEV_H 1
+
+int SProcXiSelectEvent(ClientPtr /* client */
+    );
+
+int ProcXiSelectEvent(ClientPtr	/* client */
+    );
+
+#endif /* XISELEV_H */
+
diff-tree 58c0fd29272fb6c2f193cff82fb0b0573c607eec (from 0214d0b96a9b900a8cf5c7f2183add3a411441f3)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 2 13:50:09 2007 +0930

    Adjust EQ to support long events.
    Add RawDeviceEvent (pointers only for now).
    
    This commit changes the event queue to use EventLists instead of xEvent
    arrays. Only EQ is affected, event delivery still uses xEvent* (look for
    comment in mieqProcessInputEvent).
    
    RawDeviceEvents deliver driver information to the client, without clipping or
    acceleration.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index d00dc29..2ecec96 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -61,6 +61,7 @@ SOFTWARE.
 #include <X11/Xproto.h>
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
+#include <X11/extensions/geproto.h>
 #include "inputstr.h"
 #include "windowstr.h"
 #include "miscstruct.h"
@@ -127,7 +128,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIn
     ValuatorClassPtr v = device->valuator;
     deviceValuator *xV = (deviceValuator *) xE;
 
-    if (xE->u.u.type != DeviceValuator) {
+    if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
         DeviceIntPtr mouse = NULL, kbd = NULL;
 	GetSpritePosition(device, &rootX, &rootY);
 	xE->u.keyButtonPointer.rootX = rootX;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index c58a10f..beac426 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -131,6 +131,13 @@ int ExtEventIndex;
 Mask ExtValidMasks[EMASKSIZE];
 Mask ExtExclusiveMasks[EMASKSIZE];
 
+
+static Mask xi_filters[3] = {
+    XI_PointerKeyboardPairingChangedNotifyMask,
+    XI_RandomStringEventMask,
+    XI_RawDeviceEventMask,  
+};
+
 static struct dev_type
 {
     Atom type;
@@ -1158,6 +1165,9 @@ XInputExtensionInit(void)
 	EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
 	EventSwapVector[DeviceEnterNotify] = SEventIDispatch;
 	EventSwapVector[DeviceLeaveNotify] = SEventIDispatch;
+
+        /* init GE events */
+        SetGenericFilter(IReqCode, xi_filters);
     } else {
 	FatalError("IExtensionInit: AddExtensions failed\n");
     }
diff --git a/dix/events.c b/dix/events.c
index dc7bbfb..c8b0eb2 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -367,6 +367,14 @@ static Mask filters[128] =
 	CantBeFiltered		       /* MappingNotify */
 };
 
+
+/** 
+ * same principle as filters, but one set of filters for each extension.
+ * The extension is responsible for setting the filters by calling 
+ * SetGenericFilter().
+ */
+static Mask* generic_filters[MAXEXTENSIONS];
+
 static CARD8 criticalEvents[32] =
 {
     0x7c				/* key and button events */
@@ -2176,24 +2184,53 @@ DeliverDeviceEvents(WindowPtr pWin, xEve
     }
     else
     {
-	if (!(filter & pWin->deliverableEvents))
-	    return 0;
-	while (pWin)
-	{
-	    if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
-	    {
-		FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
-		deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter,
-						   grab, 0);
-		if (deliveries > 0)
-		    return deliveries;
-	    }
-	    if ((deliveries < 0) ||
-		(pWin == stopAt) ||
-		(filter & wDontPropagateMask(pWin)))
-		return 0;
-	    child = pWin->drawable.id;
-	    pWin = pWin->parent;
+        /* handle generic events */
+        if (type == GenericEvent)
+        {
+            xGenericEvent* ge = (xGenericEvent*)xE;
+
+            if (count > 1)
+            {
+                ErrorF("Do not send more than one GenericEvent at a time!\n");
+                return 0;
+            }
+            filter = generic_filters[GEEXTIDX(xE)][ge->evtype];
+
+            while(pWin)
+            {
+                if (GEMaskIsSet(pWin, GEEXT(xE), filter))
+                {
+                    deliveries = DeliverEventsToWindow(dev, pWin, xE, count, 
+                                                        filter, grab, 0);
+                    if (deliveries > 0)
+                        return deliveries;
+                }
+
+                pWin = pWin->parent;
+            }
+        } 
+        else
+        {
+            /* core protocol events */
+            if (!(filter & pWin->deliverableEvents))
+                return 0;
+            while (pWin)
+            {
+                if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
+                {
+                    FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
+                    deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter,
+                            grab, 0);
+                    if (deliveries > 0)
+                        return deliveries;
+                }
+                if ((deliveries < 0) ||
+                        (pWin == stopAt) ||
+                        (filter & wDontPropagateMask(pWin)))
+                    return 0;
+                child = pWin->drawable.id;
+                pWin = pWin->parent;
+            }
 	}
     }
     return 0;
@@ -5660,3 +5697,15 @@ IsInterferingGrab(ClientPtr client, Wind
     return mayInterfere;
 }
 
+/**
+ * Set the filters for a extension. 
+ * The filters array needs to contain the Masks that are applicable for each
+ * event type for the given extension.
+ * e.g. if generic event type 2 should be let through for windows with
+ * MyExampleMask set, make sure that filters[2] == MyExampleMask.
+ */
+_X_EXPORT void 
+SetGenericFilter(int extension, Mask* filters)
+{
+    generic_filters[extension & 0x7f] = filters;
+}
diff --git a/dix/getevents.c b/dix/getevents.c
index 116bab9..4f7993f 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -314,13 +314,14 @@ clipValuators(DeviceIntPtr pDev, int fir
  *        last posted, not just x and y; otherwise relative non-x/y
  *        valuators, though a very narrow use case, will be broken.
  */
-static xEvent *
-getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator,
+static EventList *
+getValuatorEvents(EventList *events, DeviceIntPtr pDev, int first_valuator,
                   int num_valuators, int *valuators) {
-    deviceValuator *xv = (deviceValuator *) events;
+    deviceValuator *xv;
     int i = 0, final_valuator = first_valuator + num_valuators;
 
-    for (i = first_valuator; i < final_valuator; i += 6, xv++, events++) {
+    for (i = first_valuator; i < final_valuator; i += 6, events++) {
+        xv = (deviceValuator*)events->event;
         xv->type = DeviceValuator;
         xv->first_valuator = i;
         xv->num_valuators = num_valuators;
@@ -353,7 +354,7 @@ getValuatorEvents(xEvent *events, Device
  * valuators.
  */
 _X_EXPORT int
-GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) {
+GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
     return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
 }
 
@@ -376,7 +377,7 @@ GetKeyboardEvents(xEvent *events, Device
  * KeyPresses.
  */
 _X_EXPORT int
-GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
+GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
                           int key_code, int first_valuator,
                           int num_valuators, int *valuators) {
     int numEvents = 0;
@@ -448,7 +449,7 @@ GetKeyboardValuatorEvents(xEvent *events
 
     ms = GetTimeInMillis();
 
-    kbp = (deviceKeyButtonPointer *) events;
+    kbp = (deviceKeyButtonPointer *) events->event;
     kbp->time = ms;
     kbp->deviceid = pDev->id;
     if (type == KeyPress)
@@ -465,31 +466,85 @@ GetKeyboardValuatorEvents(xEvent *events
     }
 
     if (pDev->coreEvents) {
-        events->u.keyButtonPointer.time = ms;
-        events->u.u.type = type;
-        events->u.u.detail = key_code;
+        xEvent* evt = events->event;
+        evt->u.keyButtonPointer.time = ms;
+        evt->u.u.type = type;
+        evt->u.u.detail = key_code;
     }
 
     return numEvents;
 }
 
+/**
+ * Initialize an event list and fill with 32 byte sized events. 
+ * This event list is to be passed into GetPointerEvents() and
+ * GetKeyboardEvents().
+ *
+ * @param num_events Number of elements in list.
+ */
+_X_EXPORT EventListPtr
+InitEventList(int num_events)
+{
+    EventListPtr events;
+    int i;
+
+    events = (EventListPtr)xcalloc(num_events, sizeof(EventList));
+    if (!events)
+        return NULL;
+
+    for (i = 0; i < num_events; i++)
+    {
+        events[i].evlen = sizeof(xEvent);
+        events[i].event = xcalloc(1, sizeof(xEvent));
+        if (!events[i].event)
+        {
+            /* rollback */
+            while(i--)
+                xfree(events[i].event);
+            xfree(events);
+            events = NULL;
+            break;
+        }
+    }
+
+    return events;
+}
 
 /**
- * Generate a series of xEvents (returned in xE) representing pointer
- * motion, or button presses.  Xi and XKB-aware.
+ * Free an event list.
+ *
+ * @param list The list to be freed.
+ * @param num_events Number of elements in list.
+ */
+_X_EXPORT void
+FreeEventList(EventListPtr list, int num_events)
+{
+    if (!list)
+        return;
+    while(num_events--)
+        xfree(list[num_events].event);
+    xfree(list);
+}
+
+/**
+ * Generate a series of xEvents (filled into the EventList) representing
+ * pointer motion, or button presses.  Xi and XKB-aware.
  *
  * events is not NULL-terminated; the return value is the number of events.
  * The DDX is responsible for allocating the event structure in the first
- * place via GetMaximumEventsNum(), and for freeing it.
+ * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
  *
  */
 _X_EXPORT int
-GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
+GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
                  int flags, int first_valuator, int num_valuators,
                  int *valuators) {
-    int num_events = 0, final_valuator = 0;
+    int num_events = 0, final_valuator = 0, i;
     CARD32 ms = 0;
+    CARD32* valptr;
     deviceKeyButtonPointer *kbp = NULL;
+    rawDeviceEvent* ev;
+
     /* Thanks to a broken lib, we _always_ have to chase DeviceMotionNotifies
      * with DeviceValuators. */
     Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
@@ -506,9 +561,9 @@ GetPointerEvents(xEvent *events, DeviceI
         return 0;
 
     if (!coreOnly && (pDev->coreEvents))
-        num_events = 2;
+        num_events = 3;
     else
-        num_events = 1;
+        num_events = 2;
 
     if (type == MotionNotify && num_valuators <= 0) {
         return 0;
@@ -529,6 +584,34 @@ GetPointerEvents(xEvent *events, DeviceI
 
     ms = GetTimeInMillis();
 
+
+    /* fill up the raw event, after checking that it is large enough to
+     * accommodate all valuators. 
+     */
+    if (events->evlen < 
+            (sizeof(xEvent) + ((num_valuators - 4) * sizeof(CARD32))))
+    {
+        events->evlen = sizeof(xEvent) + 
+            ((num_valuators - 4) * sizeof(CARD32));
+        events->event = realloc(events->event, events->evlen);
+        if (!events->event)
+            FatalError("Could not allocate event storage.\n");
+    }
+
+    ev = (rawDeviceEvent*)events->event;
+    ev->type = GenericEvent;
+    ev->evtype = XI_RawDeviceEvent;
+    ev->extension = IReqCode;
+    ev->length = (num_valuators > 4) ? (num_valuators - 4) : 0;
+    ev->buttons = buttons;
+    ev->num_valuators = num_valuators;
+    ev->first_valuator = first_valuator;
+    ev->deviceid = pDev->id;
+    valptr = &(ev->valuator0);
+    for (i = 0; i < num_valuators; i++, valptr++)
+        *valptr = valuators[i];
+
+    events++;
     pointer = pDev;
 
     /* Set x and y based on whether this is absolute or relative, and
@@ -588,7 +671,7 @@ GetPointerEvents(xEvent *events, DeviceI
     /* create Xi event */
     if (!coreOnly)
     {
-        kbp = (deviceKeyButtonPointer *) events;
+        kbp = (deviceKeyButtonPointer *) events->event;
         kbp->time = ms;
         kbp->deviceid = pDev->id;
 
@@ -616,19 +699,20 @@ GetPointerEvents(xEvent *events, DeviceI
     }
 
     if (coreOnly || pDev->coreEvents) {
-        events->u.u.type = type;
-        events->u.keyButtonPointer.time = ms;
-        events->u.keyButtonPointer.rootX = x;
-        events->u.keyButtonPointer.rootY = y;
+        xEvent* evt = events->event;
+        evt->u.u.type = type;
+        evt->u.keyButtonPointer.time = ms;
+        evt->u.keyButtonPointer.rootX = x;
+        evt->u.keyButtonPointer.rootY = y;
 
         if (type == ButtonPress || type == ButtonRelease) {
             /* We hijack SetPointerMapping to work on all core-sending
              * devices, so we use the device-specific map here instead of
              * the core one. */
-            events->u.u.detail = pDev->button->map[buttons];
+            evt->u.u.detail = pDev->button->map[buttons];
         }
         else {
-            events->u.u.detail = 0;
+            evt->u.u.detail = 0;
         }
     }
 
@@ -644,11 +728,11 @@ GetPointerEvents(xEvent *events, DeviceI
  * place via GetMaximumEventsNum(), and for freeing it.
  */
 _X_EXPORT int
-GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type,
+GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
                    int first_valuator, int num_valuators, int *valuators)
 {
     int num_events = 0;
-    deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events;
+    deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events->event;
 
     /* Sanity checks. */
     if (type != ProximityIn && type != ProximityOut)
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 59ce8da..0a2f28e 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -38,6 +38,7 @@
 
 #include "xf86Privstr.h"
 #include "propertyst.h"
+#include "input.h"
 
 /*
  * Parameters set ONLY from the command line options
@@ -202,7 +203,7 @@ void xf86UnlockServer(void);
 void xf86InitXkb(void);
 
 /* xf86Xinput.c */
-extern xEvent *xf86Events;
+extern EventList *xf86Events;
 
 #endif /* _NO_XF86_PROTOTYPES */
 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 6bf18f1..1cce136 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -103,7 +103,7 @@
 #include "dgaproc.h"
 #endif
 
-xEvent *xf86Events = NULL;
+EventListPtr xf86Events = NULL;
 
 static Bool
 xf86SendDragEvents(DeviceIntPtr	device)
@@ -544,7 +544,7 @@ xf86PostMotionEvent(DeviceIntPtr	device,
 #endif
 
     if (!xf86Events)
-        xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        xf86Events = InitEventList(GetMaximumEventsNum());
     if (!xf86Events)
         FatalError("Couldn't allocate event store\n");
 
@@ -553,11 +553,11 @@ xf86PostMotionEvent(DeviceIntPtr	device,
                                valuators);
 
     for (i = 0; i < nevents; i++) {
-        xE = xf86Events + i;
+        xE = (xf86Events + i)->event;
         /* Don't post core motion events for devices not registered to send
          * drag events. */
         if (xE->u.u.type != MotionNotify || drag) {
-            mieqEnqueue(device, xf86Events + i);
+            mieqEnqueue(device, (xf86Events + i)->event);
         }
     }
 
@@ -583,7 +583,7 @@ xf86PostProximityEvent(DeviceIntPtr	devi
     va_end(var);
 
     if (!xf86Events)
-        xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        xf86Events = InitEventList(GetMaximumEventsNum());
     if (!xf86Events)
         FatalError("Couldn't allocate event store\n");
 
@@ -591,7 +591,7 @@ xf86PostProximityEvent(DeviceIntPtr	devi
                                  is_in ? ProximityIn : ProximityOut, 
                                  first_valuator, num_valuators, valuators);
     for (i = 0; i < nevents; i++)
-        mieqEnqueue(device, xf86Events + i);
+        mieqEnqueue(device, (xf86Events + i)->event);
 
     xfree(valuators);
 }
@@ -625,7 +625,7 @@ xf86PostButtonEvent(DeviceIntPtr	device,
     va_end(var);
 
     if (!xf86Events)
-        xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        xf86Events = InitEventList(GetMaximumEventsNum());
     if (!xf86Events)
         FatalError("Couldn't allocate event store\n");
 
@@ -635,7 +635,7 @@ xf86PostButtonEvent(DeviceIntPtr	device,
                                first_valuator, num_valuators, valuators);
 
     for (i = 0; i < nevents; i++)
-        mieqEnqueue(device, xf86Events + i);
+        mieqEnqueue(device, (xf86Events + i)->event);
 
     xfree(valuators);
 }
@@ -658,7 +658,7 @@ xf86PostKeyEvent(DeviceIntPtr	device,
            "broken.\n");
 
     if (!xf86Events)
-        xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        xf86Events = InitEventList(GetMaximumEventsNum());
     if (!xf86Events)
         FatalError("Couldn't allocate event store\n");
 
@@ -682,7 +682,7 @@ xf86PostKeyEvent(DeviceIntPtr	device,
     }
 
     for (i = 0; i < nevents; i++)
-        mieqEnqueue(device, xf86Events + i);
+        mieqEnqueue(device, (xf86Events + i)->event);
 }
 
 _X_EXPORT void
@@ -702,7 +702,7 @@ xf86PostKeyboardEvent(DeviceIntPtr      
 #endif
 
     if (!xf86Events)
-        xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        xf86Events = InitEventList(GetMaximumEventsNum());
     if (!xf86Events)
         FatalError("Couldn't allocate event store\n");
 
@@ -710,7 +710,7 @@ xf86PostKeyboardEvent(DeviceIntPtr      
                                 is_down ? KeyPress : KeyRelease, key_code);
 
     for (i = 0; i < nevents; i++)
-        mieqEnqueue(device, xf86Events + i);
+        mieqEnqueue(device, (xf86Events + i)->event);
 }
 
 _X_EXPORT LocalDevicePtr
diff --git a/include/dix.h b/include/dix.h
index 93472e8..1828f43 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -691,4 +691,8 @@ extern Bool DevHasCursor(DeviceIntPtr pD
 extern Bool IsPointerDevice( DeviceIntPtr dev);
 extern Bool IsKeyboardDevice(DeviceIntPtr dev);
 
+
+/* GE stuff */
+void SetGenericFilter(int extension, Mask* filters);
+
 #endif /* DIX_H */
diff --git a/include/input.h b/include/input.h
index 401fcec..6443a58 100644
--- a/include/input.h
+++ b/include/input.h
@@ -85,6 +85,15 @@ typedef struct _OtherClients *OtherClien
 typedef struct _InputClients *InputClientsPtr;
 typedef struct _DeviceIntRec *DeviceIntPtr;
 
+typedef struct _EventList {
+    xEvent* event;
+    int evlen; /* length of allocated memory for event in bytes.  This is not
+                  the actual length of the event. The event's actual length is
+                  32 for standard events or 32 +
+                  ((xGenericEvent*)event)->length * 4 for GenericEvents */
+} EventList, *EventListPtr;
+
+
 typedef int (*DeviceProc)(
     DeviceIntPtr /*device*/,
     int /*what*/);
@@ -390,8 +399,11 @@ extern void InitInput(
 
 extern int GetMaximumEventsNum(void);
 
+extern EventListPtr InitEventList(int num_events);
+extern void FreeEventList(EventListPtr list, int num_events);
+
 extern int GetPointerEvents(
-    xEvent *events,
+    EventListPtr events,
     DeviceIntPtr pDev,
     int type,
     int buttons,
@@ -401,13 +413,13 @@ extern int GetPointerEvents(
     int *valuators);
 
 extern int GetKeyboardEvents(
-    xEvent *events,
+    EventListPtr events,
     DeviceIntPtr pDev,
     int type,
     int key_code);
 
 extern int GetKeyboardValuatorEvents(
-    xEvent *events,
+    EventListPtr events,
     DeviceIntPtr pDev,
     int type,
     int key_code,
@@ -416,7 +428,7 @@ extern int GetKeyboardValuatorEvents(
     int *valuators);
 
 extern int GetProximityEvents(
-    xEvent *events,
+    EventListPtr events,
     DeviceIntPtr pDev,
     int type,
     int first_valuator,
diff --git a/mi/mieq.c b/mi/mieq.c
index 2eeb21e..06fdffc 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -56,6 +56,7 @@ in this Software without prior written a
 # include   "scrnintstr.h"
 # include   <X11/extensions/XI.h>
 # include   <X11/extensions/XIproto.h>
+# include   <X11/extensions/geproto.h>
 # include   "extinit.h"
 # include   "exglobals.h"
 
@@ -71,7 +72,7 @@ in this Software without prior written a
 #define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
 
 typedef struct _Event {
-    xEvent          event[7];
+    EventListPtr    events;
     int             nevents;
     ScreenPtr	    pScreen;
     DeviceIntPtr    pDev; /* device this event _originated_ from */
@@ -97,6 +98,13 @@ mieqInit(void)
     miEventQueue.lastMotion = FALSE;
     for (i = 0; i < 128; i++)
         miEventQueue.handlers[i] = NULL;
+    for (i = 0; i < QUEUE_SIZE; i++)
+    {
+        EventListPtr evlist = InitEventList(7); /* 1 + MAX_VALUATOR_EVENTS */
+        if (!evlist)
+            FatalError("Could not allocate event queue.\n");
+        miEventQueue.events[i].events = evlist;
+    }
     SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
     return TRUE;
 }
@@ -112,23 +120,26 @@ void
 mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 {
     HWEventQueueType       oldtail = miEventQueue.tail, newtail;
+    EventListPtr           evt;
     int                    isMotion = 0;
-    deviceValuator         *v = (deviceValuator *) e;
-    EventPtr               laste = &miEventQueue.events[oldtail - 1];
-    deviceKeyButtonPointer *lastkbp = (deviceKeyButtonPointer *)
-                                      &laste->event[0];
+    int evlen;
 
     /* avoid merging events from different devices */
     if (e->u.u.type == MotionNotify)
         isMotion = pDev->id;
-    else if (e->u.u.type == MotionNotify)
-        isMotion = inputInfo.pointer->id;
     else if (e->u.u.type == DeviceMotionNotify)
         isMotion = pDev->id | (1 << 8); /* flag to indicate DeviceMotion */
 
     /* We silently steal valuator events: just tack them on to the last
      * motion event they need to be attached to.  Sigh. */
     if (e->u.u.type == DeviceValuator) {
+        deviceValuator         *v = (deviceValuator *) e;
+        EventPtr               laste;
+        deviceKeyButtonPointer *lastkbp;
+
+        laste = &miEventQueue.events[(oldtail ? oldtail : QUEUE_SIZE)- 1];
+        lastkbp = (deviceKeyButtonPointer *) laste->events->event;
+
         if (laste->nevents > 6) {
             ErrorF("mieqEnqueue: more than six valuator events; dropping.\n");
             return;
@@ -142,7 +153,8 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e
             ErrorF("mieqEnequeue: out-of-order valuator event; dropping.\n");
             return;
         }
-        memcpy(&(laste->event[laste->nevents++]), e, sizeof(xEvent));
+
+        memcpy((laste->events[laste->nevents++].event), e, sizeof(xEvent));
         return;
     }
 
@@ -166,18 +178,27 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e
 	miEventQueue.tail = newtail;
     }
 
-    memcpy(&(miEventQueue.events[oldtail].event[0]), e, sizeof(xEvent));
+    evlen = sizeof(xEvent);
+    if (e->u.u.type == GenericEvent)
+        evlen += ((xGenericEvent*)e)->length * 4;
+
+    evt = miEventQueue.events[oldtail].events;
+    if (evt->evlen < evlen)
+    {
+        evt->evlen = evlen;
+        evt->event = xrealloc(evt->event, evt->evlen);
+    }
+
+    memcpy(evt->event, e, evlen);
     miEventQueue.events[oldtail].nevents = 1;
 
     /* Make sure that event times don't go backwards - this
      * is "unnecessary", but very useful. */
     if (e->u.keyButtonPointer.time < miEventQueue.lastEventTime &&
 	miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
-	miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time =
-	    miEventQueue.lastEventTime;
+        evt->event->u.keyButtonPointer.time = miEventQueue.lastEventTime;
 
-    miEventQueue.lastEventTime =
-	miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time;
+    miEventQueue.lastEventTime = evt->event->u.keyButtonPointer.time;
     miEventQueue.events[oldtail].pScreen = EnqueueScreen(pDev);
     miEventQueue.events[oldtail].pDev = pDev;
 
@@ -209,6 +230,7 @@ mieqProcessInputEvents(void)
     EventRec *e = NULL;
     int x = 0, y = 0;
     DeviceIntPtr dev = NULL;
+    xEvent* event;
 
     while (miEventQueue.head != miEventQueue.tail) {
         if (screenIsSaved == SCREEN_SAVER_ON)
@@ -225,8 +247,8 @@ mieqProcessInputEvents(void)
         /* Assumption - screen switching can only occur on motion events. */
         if (e->pScreen != DequeueScreen(e->pDev)) {
             DequeueScreen(e->pDev) = e->pScreen;
-            x = e->event[0].u.keyButtonPointer.rootX;
-            y = e->event[0].u.keyButtonPointer.rootY;
+            x = e->events[0].event->u.keyButtonPointer.rootX;
+            y = e->events[0].event->u.keyButtonPointer.rootY;
             if (miEventQueue.head == QUEUE_SIZE - 1)
                 miEventQueue.head = 0;
             else
@@ -241,39 +263,60 @@ mieqProcessInputEvents(void)
 
             /* If someone's registered a custom event handler, let them
              * steal it. */
-            if (miEventQueue.handlers[e->event->u.u.type]) {
-                miEventQueue.handlers[e->event->u.u.type](
-						  DequeueScreen(e->pDev)->myNum,
-                                                          e->event, dev,
-                                                          e->nevents);
+            if (miEventQueue.handlers[e->events->event->u.u.type]) {
+                miEventQueue.handlers[e->events->event->u.u.type](
+                                              DequeueScreen(e->pDev)->myNum,
+                                                      e->events->event, dev,
+                                                      e->nevents);
                 return;
             }
 
             /* If this is a core event, make sure our keymap, et al, is
              * changed to suit. */
-            if (e->event[0].u.u.type == KeyPress ||
-                e->event[0].u.u.type == KeyRelease) {
+            if (e->events->event[0].u.u.type == KeyPress ||
+                e->events->event[0].u.u.type == KeyRelease) {
                 SwitchCoreKeyboard(e->pDev);
                 dev = inputInfo.keyboard;
             }
-            else if (e->event[0].u.u.type == MotionNotify ||
-                     e->event[0].u.u.type == ButtonPress ||
-                     e->event[0].u.u.type == ButtonRelease) {
+            else if (e->events->event[0].u.u.type == MotionNotify ||
+                     e->events->event[0].u.u.type == ButtonPress ||
+                     e->events->event[0].u.u.type == ButtonRelease) {
                 dev = inputInfo.pointer;
             }
             else {
                 dev = e->pDev;
             }
 
+
+            /* FIXME: Bad hack. The only event where we actually get multiple
+             * events at once is a DeviceMotionNotify followed by
+             * DeviceValuators. For now it's save enough to just take the
+             * event directly or copy the bunch of events and pass in the
+             * copy. Eventually the interface for the processInputProc needs
+             * to be changed. (whot)
+             */ 
+            if (e->nevents > 1)
+            {
+                int i;
+                event = xcalloc(e->nevents, sizeof(xEvent));
+                for (i = 0; i < e->nevents; i++)
+                    memcpy(&event[i], e->events[i].event, sizeof(xEvent));
+            }
+            else 
+                event = e->events->event;
+
             /* MPX devices send both core and Xi events. 
              * Use dev to get the correct processing function but supply
              *  e->pDev to pass the correct device 
              */
-            dev->public.processInputProc(e->event, e->pDev, e->nevents);
+            dev->public.processInputProc(event, e->pDev, e->nevents);
+
+            if (e->nevents > 1)
+                xfree(event);
         }
 
         /* Update the sprite now. Next event may be from different device. */
-        if (e->event[0].u.u.type == MotionNotify && e->pDev->coreEvents)
+        if (e->events->event[0].u.u.type == MotionNotify && e->pDev->coreEvents)
         {
             miPointerUpdateSprite(e->pDev);
         }
diff --git a/mi/mipointer.c b/mi/mipointer.c
index b14c2c7..8dc7c7f 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -86,7 +86,7 @@ static Bool miPointerDeviceInitialize(De
 static void miPointerDeviceCleanup(DeviceIntPtr pDev,
                                    ScreenPtr pScreen);
 
-static xEvent* events; /* for WarpPointer MotionNotifies */
+static EventList* events; /* for WarpPointer MotionNotifies */
 
 _X_EXPORT Bool
 miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
@@ -175,7 +175,7 @@ miPointerCloseScreen (index, pScreen)
 
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
     xfree ((pointer) pScreenPriv);
-    xfree ((pointer) events);
+    FreeEventList(events, GetMaximumEventsNum());
     events = NULL;
     return (*pScreen->CloseScreen) (index, pScreen);
 }
@@ -624,7 +624,7 @@ miPointerMove (DeviceIntPtr pDev, Screen
 
     if (!events)
     {
-        events = (xEvent*)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        events = InitEventList(GetMaximumEventsNum());
 
         if (!events)
         {
@@ -635,6 +635,8 @@ miPointerMove (DeviceIntPtr pDev, Screen
 
     nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_ABSOLUTE, 0, 2, valuators);
 
+    OsBlockSignals();
     for (i = 0; i < nevents; i++)
-        mieqEnqueue(pDev, &events[i]);
+        mieqEnqueue(pDev, events[i].event);
+    OsReleaseSignals();
 }
diff-tree 0214d0b96a9b900a8cf5c7f2183add3a411441f3 (from 11d0e2109b699714055e263e8963f2c39eded28b)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 1 15:49:41 2007 +0930

    Start devices after windows are initialized.
    
    This fixes the hotplug segfault introduced with the multihead changes and
    cleans up the code a bit as well.

diff --git a/dix/devices.c b/dix/devices.c
index a415a8e..bd145a0 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -202,10 +202,11 @@ EnableDevice(DeviceIntPtr dev)
 	 prev = &(*prev)->next)
 	;
 
-    /* Sprites will be initialized with their 'windows' just when inside the
-     * DefineInitialRootWindow function! */
+    /* Sprites pop up on the first root window, so we can supply it directly
+     * here. 
+     */
     if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
-        InitializeSprite(dev, NullWindow);
+        InitializeSprite(dev, WindowTable[0]);
     else
         PairDevices(NULL, inputInfo.pointer, dev);
 
@@ -301,11 +302,6 @@ ActivateDevice(DeviceIntPtr dev)
     return ret;
 }
 
-int
-DeactivateDevice(DeviceIntPtr dev)
-{
-}
-
 static void
 CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
 {
@@ -451,14 +447,7 @@ InitCoreDevices(void)
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
         (void)ActivateDevice(dev);
 
-        /* Enable device, and then remove it from the device list. Virtual
-         * devices are kept separate, not in the standard device list. 
-         */
-        if (dev->inited && dev->startup)
-            EnableDevice(dev);
-        inputInfo.off_devices = inputInfo.devices = NULL;
         inputInfo.keyboard = dev;
-        inputInfo.keyboard->next = NULL;
     }
 
     if (!inputInfo.pointer) {
@@ -478,35 +467,25 @@ InitCoreDevices(void)
         dev->coreGrab.ActivateGrab = ActivatePointerGrab;
         dev->coreGrab.DeactivateGrab = DeactivatePointerGrab;
         dev->coreEvents = FALSE;
+        dev->spriteInfo->spriteOwner = TRUE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate pointer devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
         (void)ActivateDevice(dev);
 
-        /* Enable device, and then remove it from the device list. Virtual
-         * devices are kept separate, not in the standard device list. 
-         */
-        if (dev->inited && dev->startup)
-            EnableDevice(dev);
-        inputInfo.off_devices = inputInfo.devices = NULL;
         inputInfo.pointer = dev;
-        inputInfo.pointer->next = NULL;
-
-        /* the core keyboard is initialised by now. set the keyboard's sprite
-         * to the core pointer's sprite. */
-        PairDevices(pairingClient, inputInfo.pointer, inputInfo.keyboard);
     }
 }
 
 /**
  * Activate and enable all devices. 
  *
- * After InitAndStartDevices() all devices are finished with their setup
- * routines and start emitting events.
- * Each physical keyboard is paired with the first available unpaired pointer.
+ * InitAndStartDevices needs to be called AFTER the windows are initialized.
+ * Devices will start sending events after InitAndStartDevices() has
+ * completed.
  */
 int
-InitAndStartDevices(void)
+InitAndStartDevices(WindowPtr root)
 {
     DeviceIntPtr dev, next;
 
@@ -514,13 +493,6 @@ InitAndStartDevices(void)
         DebugF("(dix) initialising device %d\n", dev->id);
 	ActivateDevice(dev);
     }
-    for (dev = inputInfo.off_devices; dev; dev = next)
-    {
-        DebugF("(dix) enabling device %d\n", dev->id);
-	next = dev->next;
-	if (dev->inited && dev->startup)
-	    (void)EnableDevice(dev);
-    }
 
     if (!inputInfo.keyboard) {
 	ErrorF("No core keyboard\n");
@@ -531,12 +503,37 @@ InitAndStartDevices(void)
 	return BadImplementation;
     }
 
-    /* All of the devices are started up now. Try to pair each keyboard with a
-     * real pointer, if possible. */
+    /* Now enable all devices */
+    if (inputInfo.keyboard->inited && inputInfo.keyboard->startup)
+        EnableDevice(inputInfo.keyboard);
+    if (inputInfo.pointer->inited && inputInfo.pointer->startup)
+        EnableDevice(inputInfo.pointer);
+
+    /* Remove VCP and VCK from device list */
+    inputInfo.devices = NULL;
+    inputInfo.keyboard->next = inputInfo.pointer->next = NULL;
+
+    /* enable real devices */
+    for (dev = inputInfo.off_devices; dev; dev = next)
+    {
+        DebugF("(dix) enabling device %d\n", dev->id);
+	next = dev->next;
+	if (dev->inited && dev->startup)
+	    (void)EnableDevice(dev);
+    }
+
+    /* All of the devices are started up now. Pair VCK with VCP, then
+     * pair each real keyboard with a real pointer. 
+     */ 
+    PairDevices(NULL, inputInfo.pointer, inputInfo.keyboard);
+
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
         if (!DevHasCursor(dev))
             PairDevices(NULL, GuessFreePointerDevice(), dev);
+        else
+            /* enter/leave counter on root window */
+            ((FocusSemaphoresPtr)root->devPrivates[FocusPrivatesIndex].ptr)->enterleave++;
     }
 
     return Success;
diff --git a/dix/events.c b/dix/events.c
index 7d11d14..dc7bbfb 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2501,23 +2501,10 @@ void ReinitializeRootWindow(WindowPtr wi
 void
 DefineInitialRootWindow(WindowPtr win)
 {
-    DeviceIntPtr pDev = inputInfo.devices;
-
 #ifdef XEVIE
     xeviewin = win;
 #endif
 
-    InitializeSprite(inputInfo.pointer, win);
-
-    while (pDev)
-    {
-        if (DevHasCursor(pDev))
-        {
-            InitializeSprite(pDev, win);
-            ((FocusSemaphoresPtr)win->devPrivates[FocusPrivatesIndex].ptr)->enterleave++;
-        }
-        pDev = pDev->next;
-    }
 }
 
 void 
diff --git a/dix/main.c b/dix/main.c
index 2f064a9..e7c7000 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -396,10 +396,6 @@ main(int argc, char *argv[], char *envp[
 	    if (!CreateRootWindow(pScreen))
 		FatalError("failed to create root window");
 	}
-        InitCoreDevices();
-	InitInput(argc, argv);
-	if (InitAndStartDevices() != Success)
-	    FatalError("failed to initialize core devices");
 
 	InitFonts();
 #ifdef BUILTIN_FONTS
@@ -451,6 +447,12 @@ main(int argc, char *argv[], char *envp[
 	for (i = 0; i < screenInfo.numScreens; i++)
 	    InitRootWindow(WindowTable[i]);
 	DefineInitialRootWindow(WindowTable[0]);
+
+        InitCoreDevices();
+	InitInput(argc, argv);
+	if (InitAndStartDevices(WindowTable[0]) != Success)
+	    FatalError("failed to initialize core devices");
+
 	SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
 
 #ifdef PANORAMIX
diff --git a/include/input.h b/include/input.h
index 4ba0cad..401fcec 100644
--- a/include/input.h
+++ b/include/input.h
@@ -186,7 +186,9 @@ extern Bool ActivateDevice(
 extern Bool DisableDevice(
     DeviceIntPtr /*device*/);
 
-extern int InitAndStartDevices(void);
+extern int InitAndStartDevices(
+    WindowPtr /*root*/);
+
 
 extern void CloseDownDevices(void);
 
diff-tree 11d0e2109b699714055e263e8963f2c39eded28b (from 8b42ba64e169a35df2a90528dcb0cd06be0f67a1)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 1 14:16:36 2007 +0930

    Correct enterleave semaphore value for root window.

diff --git a/dix/events.c b/dix/events.c
index f767f70..7d11d14 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2514,7 +2514,7 @@ DefineInitialRootWindow(WindowPtr win)
         if (DevHasCursor(pDev))
         {
             InitializeSprite(pDev, win);
-            win->devPrivates[FocusPrivatesIndex].val++;
+            ((FocusSemaphoresPtr)win->devPrivates[FocusPrivatesIndex].ptr)->enterleave++;
         }
         pDev = pDev->next;
     }
diff-tree 8b42ba64e169a35df2a90528dcb0cd06be0f67a1 (from 325380adb20ec2b82e176d75599fd4bc97a3b918)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 1 12:12:58 2007 +0930

    Send PointerKeyboardPairingChangedNotifyEvent using XGE.
    
    Needs updated inputproto and libXi.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 9b1253e..346453c 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -97,6 +97,8 @@ libXi_la_SOURCES =	\
 	ungrdevk.c \
 	ungrdevk.h \
 	warpdevp.c \
-	warpdevp.h 
+	warpdevp.h \
+        xiselev.c \
+        xiselev.h 
 
 EXTRA_DIST = stubs.c
diff --git a/Xi/chpkpair.c b/Xi/chpkpair.c
index fcbdcdf..555c8e1 100644
--- a/Xi/chpkpair.c
+++ b/Xi/chpkpair.c
@@ -44,11 +44,14 @@ from the author.
 #include "windowstr.h"	/* window structure  */
 #include "scrnintstr.h"	/* screen structure  */
 #include <X11/extensions/XI.h>
+#include <X11/extensions/XInput.h>
 #include <X11/extensions/XIproto.h>
+#include <X11/extensions/geproto.h>
 #include "extnsionst.h"
 #include "extinit.h"	/* LookupDeviceIntRec */
 #include "exevents.h"
 #include "exglobals.h"
+#include "geext.h"
 
 
 #include "chpkpair.h"
@@ -74,6 +77,7 @@ ProcXChangePointerKeyboardPairing(Client
 {
     DeviceIntPtr pPointer, pKeyboard;
     int ret;
+    pairingChangedNotify ev; 
 
     REQUEST(xChangePointerKeyboardPairingReq);
     REQUEST_SIZE_MATCH(xChangePointerKeyboardPairingReq);
@@ -105,6 +109,27 @@ ProcXChangePointerKeyboardPairing(Client
     }
 
 
-    /* TODO: generate event here... */
+    memset(&ev, 0, sizeof(pairingChangedNotify));
+    GEInitEvent(GEV(&ev), IReqCode);
+    ev.evtype = XI_PointerKeyboardPairingChangedNotify;
+    ev.pointer = pPointer->id;
+    ev.keyboard = pKeyboard->id;
+    ev.length = 0;
+    ev.time = currentTime.milliseconds;
+    SendEventToAllWindows(inputInfo.pointer, 
+            XI_PointerKeyboardPairingChangedMask,
+            (xEvent*)&ev, 1);
     return Success;
 }
+
+/* Event swap proc */
+void 
+SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify *from, 
+                                                pairingChangedNotify *to)
+{
+    char n;
+
+    *to = *from;
+    swaps(&to->sequenceNumber, n);
+    swapl(&to->time, n);
+}
diff --git a/Xi/chpkpair.h b/Xi/chpkpair.h
index 1acf549..b0d410d 100644
--- a/Xi/chpkpair.h
+++ b/Xi/chpkpair.h
@@ -36,5 +36,10 @@ int SProcXChangePointerKeyboardPairing(C
 int ProcXChangePointerKeyboardPairing(ClientPtr	/* client */
     );
 
+void 
+SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify* /* from */, 
+                                           pairingChangedNotify* /* to */
+   );
+
 #endif /* WARPDEVP_H */
 
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 9d921fa..c58a10f 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -65,6 +65,8 @@ SOFTWARE.
 #include "extnsionst.h"	/* extension entry   */
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
+#include <X11/extensions/geproto.h>
+#include "geext.h" /* extension interfaces for ge */
 
 #include "dixevents.h"
 #include "exevents.h"
@@ -121,6 +123,8 @@ SOFTWARE.
 #include "ungrdevb.h"
 #include "ungrdevk.h"
 #include "warpdevp.h"
+#include "xiselev.h"
+
 
 static Mask lastExtEventMask = 1;
 int ExtEventIndex;
@@ -180,7 +184,6 @@ Mask DeviceButtonMotionMask;
 Mask DevicePresenceNotifyMask;
 Mask DeviceEnterWindowMask;
 Mask DeviceLeaveWindowMask;
-Mask PointerKeyboardPairingChangedMask;
 
 int DeviceValuator;
 int DeviceKeyPress;
@@ -200,6 +203,8 @@ int ChangeDeviceNotify;
 int DevicePresenceNotify;
 int DeviceEnterNotify;
 int DeviceLeaveNotify;
+
+/* GE events */
 int PointerKeyboardPairingChangedNotify;
 
 int RT_INPUTCLIENT;
@@ -225,6 +230,26 @@ static XExtensionVersion thisversion = {
     XI_Add_DevicePresenceNotify_Minor
 };
 
+/****************************************************************
+ *
+ * EventSwap for generic events coming from the GE extension.
+ */
+
+static void 
+XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
+{
+    int n;
+
+    swaps(&from->sequenceNumber, n);
+    switch(from->evtype)
+    {
+        case XI_PointerKeyboardPairingChangedNotify:
+            SPointerKeyboardPairingChangedNotifyEvent
+                ((pairingChangedNotify*)from, (pairingChangedNotify*)to);
+            break;
+    }
+}
+
 /*************************************************************************
  *
  * ProcIDispatch - main dispatch routine for requests to this extension.
@@ -314,6 +339,8 @@ ProcIDispatch(ClientPtr client)
         return (ProcXChangeDeviceCursor(client));
     else if (stuff->data == X_ChangePointerKeyboardPairing)
         return (ProcXChangePointerKeyboardPairing(client));
+    else if (stuff->data == X_XiSelectEvent)
+        return (ProcXiSelectEvent(client));
     else if (stuff->data == X_RegisterPairingClient)
         return (ProcXRegisterPairingClient(client));
     else if (stuff->data == X_GrabAccessControl)
@@ -425,6 +452,8 @@ SProcIDispatch(ClientPtr client)
         return (SProcXChangeDeviceCursor(client));
     else if (stuff->data == X_ChangePointerKeyboardPairing)
         return (SProcXChangePointerKeyboardPairing(client));
+    else if (stuff->data == X_XiSelectEvent)
+        return (SProcXiSelectEvent(client));
     else if (stuff->data == X_RegisterPairingClient)
         return (SProcXRegisterPairingClient(client));
     else if (stuff->data == X_GrabAccessControl)
@@ -659,16 +688,6 @@ SDeviceLeaveNotifyEvent (deviceLeaveNoti
     swaps(&to->eventY, n);
 }
 
-static void 
-SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify *from, 
-                                                pairingChangedNotify *to)
-{
-    char n;
-
-    *to = *from;
-    swaps(&to->sequenceNumber, n);
-    swapl(&to->time, n);
-}
 
 /**************************************************************************
  *
@@ -792,7 +811,10 @@ FixExtensionEvents(ExtensionEntry * extE
     DevicePresenceNotify = DeviceButtonStateNotify + 1;
     DeviceEnterNotify = DevicePresenceNotify + 1;
     DeviceLeaveNotify = DeviceEnterNotify + 1;
-    PointerKeyboardPairingChangedNotify = DeviceLeaveNotify + 1;
+
+    /* GE Events */
+    PointerKeyboardPairingChangedNotify =
+        XI_PointerKeyboardPairingChangedNotify;
 
     event_base[KeyClass] = DeviceKeyPress;
     event_base[ButtonClass] = DeviceButtonPress;
@@ -877,11 +899,6 @@ FixExtensionEvents(ExtensionEntry * extE
     SetMaskForExtEvent(DeviceLeaveWindowMask, DeviceLeaveNotify);
     AllowPropagateSuppress(DeviceLeaveWindowMask);
 
-    PointerKeyboardPairingChangedMask = GetNextExtEventMask();
-    SetMaskForExtEvent(PointerKeyboardPairingChangedMask, 
-            PointerKeyboardPairingChangedNotify);
-    AllowPropagateSuppress(PointerKeyboardPairingChangedMask);
-
     SetEventInfo(0, _noExtensionEvent);
 }
 
@@ -925,7 +942,6 @@ RestoreExtensionEvents(void)
     DevicePresenceNotify = 14;
     DeviceEnterNotify = 15;
     DeviceLeaveNotify = 16;
-    PointerKeyboardPairingChangedNotify = 17;
 
     BadDevice = 0;
     BadEvent = 1;
@@ -1095,8 +1111,6 @@ SEventIDispatch(xEvent * from, xEvent * 
         DO_SWAP(SDeviceEnterNotifyEvent, deviceEnterNotify);
     else if (type == DeviceLeaveNotify)
         DO_SWAP(SDeviceLeaveNotifyEvent, deviceLeaveNotify);
-    else if (type == PointerKeyboardPairingChangedNotify)
-        DO_SWAP(SPointerKeyboardPairingChangedNotifyEvent, pairingChangedNotify);
     else {
 	FatalError("XInputExtension: Impossible event!\n");
     }
@@ -1144,7 +1158,6 @@ XInputExtensionInit(void)
 	EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
 	EventSwapVector[DeviceEnterNotify] = SEventIDispatch;
 	EventSwapVector[DeviceLeaveNotify] = SEventIDispatch;
-	EventSwapVector[PointerKeyboardPairingChangedNotify] = SEventIDispatch;
     } else {
 	FatalError("IExtensionInit: AddExtensions failed\n");
     }
diff-tree 325380adb20ec2b82e176d75599fd4bc97a3b918 (from b043a184509cfe5c4c4691ecde1a4a065e53d575)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 1 11:02:05 2007 +0930

    Check and re-set paired devices when initializing sprites.
    
    If we don't do this, a device that is paired before a sprite has been
    initialized for the paired device will not actually get the right sprite and
    segfault the server on focus events. Happens for the VCK.

diff --git a/dix/devices.c b/dix/devices.c
index 27271f3..a415a8e 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2158,6 +2158,7 @@ PairDevices(ClientPtr client, DeviceIntP
     }
 
     kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
+    kbd->spriteInfo->paired = ptr;
     return Success;
 }
 
diff --git a/dix/events.c b/dix/events.c
index 836d755..f767f70 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2528,9 +2528,25 @@ InitializeSprite(DeviceIntPtr pDev, Wind
 
     if (!pDev->spriteInfo->sprite)
     {
+        DeviceIntPtr it;
+
         pDev->spriteInfo->sprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec));
         if (!pDev->spriteInfo->sprite)
             FatalError("InitializeSprite: failed to allocate sprite struct");
+
+        /* We may have paired another device with this device before our
+         * device had a actual sprite. We need to check for this and reset the
+         * sprite field for all paired devices.
+         *
+         * The VCK is always paired with the VCP before the VCP has a sprite.
+         */
+        for (it = inputInfo.devices; it; it = it->next)
+        {
+            if (it->spriteInfo->paired == pDev)
+                it->spriteInfo->sprite = pDev->spriteInfo->sprite;
+        }
+        if (inputInfo.keyboard->spriteInfo->paired == pDev)
+            inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
     }
 
     pSprite = pDev->spriteInfo->sprite;
diff-tree b043a184509cfe5c4c4691ecde1a4a065e53d575 (from 5e439109292e54b5c4d1a7bc7b6ac0e42ee285f7)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 1 09:54:33 2007 +0930

    Check VCP's and VCK's ids when searching for a new device id.
    
    Both VCP and VCK are not in the inputInfo.devices list anymore, so we need to
    check them separately. If we don't do this, we end up re-using ids 0 and 1,
    causing all sorts of grief for clients.

diff --git a/dix/devices.c b/dix/devices.c
index a6e1415..27271f3 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -99,6 +99,10 @@ AddInputDevice(DeviceProc deviceProc, Bo
 
     /* Find next available id */
     memset(devind, 0, sizeof(char)*MAX_DEVICES);
+    if (inputInfo.keyboard)
+        devind[inputInfo.keyboard->id]++;
+    if (inputInfo.pointer)
+        devind[inputInfo.pointer->id]++;
     for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next)
 	devind[devtmp->id]++;
     for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next)
diff-tree 5e439109292e54b5c4d1a7bc7b6ac0e42ee285f7 (from f28eea0647f007c2e2415ecc6fceef46201faad4)
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 30 12:57:42 2007 +0930

    Add GenericEvent extension to Xext.
    
    This adds (unconditional) support for the GE extension. Anything from now on
    that sends events in MPX will have to use the GE extension. No GE, no MPX
    events. GE is not actually used yet from anywhere with this commit.
    
    You will need to update x11proto, xextproto, libX11, libXext and xcb to the
    matching xge branches. Things will _NOT_ work without the updated protocol
    headers and libraries.

diff --git a/Xext/Makefile.am b/Xext/Makefile.am
index 6ea3d74..29a01ee 100644
--- a/Xext/Makefile.am
+++ b/Xext/Makefile.am
@@ -23,7 +23,8 @@ BUILTIN_SRCS =			\
 	shape.c			\
 	sleepuntil.c		\
 	sleepuntil.h		\
-	xtest.c
+	xtest.c                 \
+        geext.c
 
 # Sources always included in libXextmodule.la & libXext.la
 MODULE_SRCS =			\
@@ -178,5 +179,6 @@ EXTRA_DIST = \
 	$(EXTRA_MULTIBUFFER_SRCS) \
 	$(FONTCACHE_SRCS) \
 	$(BIGFONT_SRCS) \
-	$(DPMS_SRCS)
+	$(DPMS_SRCS) \
+        $(GE_SRCS)
 
diff --git a/Xext/geext.c b/Xext/geext.c
new file mode 100644
index 0000000..7c4573e
--- /dev/null
+++ b/Xext/geext.c
@@ -0,0 +1,384 @@
+/* 
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include "windowstr.h"
+#include <X11/extensions/ge.h>
+
+#include "geint.h"
+#include "geext.h"
+
+int GEEventBase;
+int GEErrorBase;
+int GEClientPrivateIndex;
+int GEEventType; /* The opcode for all GenericEvents will have. */
+
+/* Struct to keep information about registered extensions
+ */
+typedef struct _GEExtension {
+    /* event swap function */
+    void (*evswap)(xGenericEvent* from, xGenericEvent* to);
+} GEExtension, *GEExtensionPtr;
+
+/* All registered extensions */
+static GEExtension GEExtensions[MAXEXTENSIONS];
+
+/* Major available requests */
+static const int version_requests[] = {
+    X_GEQueryVersion,	/* before client sends QueryVersion */
+    X_GEQueryVersion,	/* must be set to last request in version 1 */
+};
+
+/* Forward declarations */
+static void SGEGenericEvent(xEvent* from, xEvent* to);
+
+#define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0]))
+
+/************************************************************/
+/*                request handlers                          */
+/************************************************************/
+
+static int ProcGEQueryVersion(ClientPtr client)
+{
+    int n;
+    GEClientInfoPtr pGEClient = GEGetClient(client);
+    xGEQueryVersionReply rep;
+    REQUEST(xGEQueryVersionReq);
+
+    REQUEST_SIZE_MATCH(xGEQueryVersionReq);
+
+    rep.repType = X_Reply;
+    rep.RepType = X_GEQueryVersion;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+
+    if (stuff->majorVersion < GE_MAJOR) {
+        rep.majorVersion = stuff->majorVersion;
+        rep.minorVersion = stuff->minorVersion;
+    } else {
+        rep.majorVersion = GE_MAJOR;
+        if (stuff->majorVersion == GE_MAJOR && 
+                stuff->minorVersion < GE_MINOR)
+            rep.minorVersion = stuff->minorVersion;
+        else
+            rep.minorVersion = GE_MINOR;
+    }
+
+    pGEClient->major_version = rep.majorVersion;
+    pGEClient->minor_version = rep.minorVersion;
+
+    if (client->swapped)
+    {
+    	swaps(&rep.sequenceNumber, n);
+    	swapl(&rep.length, n);
+        swaps(&rep.majorVersion, n);
+        swaps(&rep.minorVersion, n);
+    }
+
+
+    WriteToClient(client, sizeof(xGEQueryVersionReply), (char*)&rep);
+    return(client->noClientException);
+}
+
+int (*ProcGEVector[GENumberRequests])(ClientPtr) = {
+    /* Version 1.0 */
+    ProcGEQueryVersion
+};
+
+/************************************************************/
+/*                swapped request handlers                  */
+/************************************************************/
+static int
+SProcGEQueryVersion(ClientPtr client)
+{
+    int n;
+    REQUEST(xGEQueryVersionReq);
+
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(xGEQueryVersionReq);
+    swaps(&stuff->majorVersion, n);
+    swaps(&stuff->minorVersion, n);
+    return(*ProcGEVector[stuff->ReqType])(client);
+}
+
+int (*SProcGEVector[GENumberRequests])(ClientPtr) = {
+    /* Version 1.0 */
+    SProcGEQueryVersion
+};
+
+
+/************************************************************/
+/*                callbacks                                 */
+/************************************************************/
+
+/* dispatch requests */
+static int 
+ProcGEDispatch(ClientPtr client)
+{
+    GEClientInfoPtr pGEClient = GEGetClient(client);
+    REQUEST(xGEReq);
+
+    if (pGEClient->major_version >= NUM_VERSION_REQUESTS)
+        return BadRequest;
+    if (stuff->ReqType > version_requests[pGEClient->major_version])
+        return BadRequest;
+
+    return (ProcGEVector[stuff->ReqType])(client);
+}
+
+/* dispatch swapped requests */
+static int
+SProcGEDispatch(ClientPtr client)
+{
+    REQUEST(xGEReq);
+    if (stuff->ReqType >= GENumberRequests)
+        return BadRequest;
+    return (*SProcGEVector[stuff->ReqType])(client);
+}
+
+/* new client callback */
+static void GEClientCallback(CallbackListPtr *list,
+        pointer closure,
+        pointer data)
+{
+    NewClientInfoRec	*clientinfo = (NewClientInfoRec *) data;
+    ClientPtr		pClient = clientinfo->client;
+    GEClientInfoPtr     pGEClient = GEGetClient(pClient);
+
+    pGEClient->major_version = 0;
+    pGEClient->minor_version = 0;
+}
+
+/* reset extension */
+static void
+GEResetProc(ExtensionEntry *extEntry)
+{
+    DeleteCallback(&ClientStateCallback, GEClientCallback, 0);
+    EventSwapVector[GenericEvent] = NotImplemented;
+
+    GEEventBase = 0;
+    GEErrorBase = 0;
+    GEEventType = 0;
+}
+
+/*  Calls the registered event swap function for the extension. */
+static void 
+SGEGenericEvent(xEvent* from, xEvent* to)
+{
+    xGenericEvent* gefrom = (xGenericEvent*)from;
+    xGenericEvent* geto = (xGenericEvent*)to;
+
+    if (gefrom->extension > MAXEXTENSIONS)
+    {
+        ErrorF("GE: Invalid extension offset for event.\n");
+        return;
+    }
+
+    if (GEExtensions[gefrom->extension & 0x7F].evswap)
+        GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto);
+}
+
+/* init extension, register at server */
+void 
+GEExtensionInit(void)
+{
+    ExtensionEntry *extEntry;
+
+    GEClientPrivateIndex = AllocateClientPrivateIndex(); 
+    if (!AllocateClientPrivate(GEClientPrivateIndex, 
+                               sizeof(GEClientRec)))
+    {
+        FatalError("GEExtensionInit: Alloc client private failed.\n");
+    }
+
+    if(!AddCallback(&ClientStateCallback, GEClientCallback, 0))
+    {
+        FatalError("GEExtensionInit: register client callback failed.\n");
+    }
+
+    if((extEntry = AddExtension(GE_NAME, 
+                        GENumberEvents, GENumberErrors, 
+                        ProcGEDispatch, SProcGEDispatch, 
+                        GEResetProc, StandardMinorOpcode)) != 0)
+    {
+        GEEventBase = extEntry->eventBase;
+        GEErrorBase = extEntry->errorBase;
+        GEEventType = GEEventBase;
+
+        memset(GEExtensions, 0, sizeof(GEExtensions));
+
+        EventSwapVector[GEEventBase + X_GenericEvent] = 
+            (EventSwapPtr) SGEGenericEvent;
+    } else {
+        FatalError("GEInit: AddExtensions failed.\n");
+    }
+
+}
+
+/************************************************************/
+/*                interface for extensions                  */
+/************************************************************/
+
+/* Register extension with GE. 
+ * Requires the event swap function as parameter. The function will be called
+ * each time an event is sent to a client with different byte order.
+ * Returns extension offset. This offset is to be used in all generic events
+ * sent to the client.
+ */
+void GERegisterExtension(
+        int extension, 
+        void (*ev_swap)(xGenericEvent* from, xGenericEvent* to)
+        )
+{
+    if ((extension & 0x7F) >=  MAXEXTENSIONS)
+        FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n");
+
+    /* extension opcodes are > 128, might as well save some space here */
+    GEExtensions[extension & 0x7f].evswap = ev_swap;
+}
+
+
+/* Sets type and extension field for a generic event. This is just an
+ * auxiliary function, extensions could do it manually too. */
+void GEInitEvent(xGenericEvent* ev, int extension)
+{
+    ev->type = GenericEvent;
+    ev->extension = extension;
+    ev->length = 0;
+}
+
+/* Recalculates the summary mask for the window. */
+static void 
+GERecalculateWinMask(WindowPtr pWin)
+{
+    int i;
+    GEClientPtr it;
+    GEEventMasksPtr evmasks;
+
+    if (!pWin->optional)
+        return;
+
+    evmasks = pWin->optional->geMasks;
+
+    for (i = 0; i < MAXEXTENSIONS; i++)
+    {
+        evmasks->eventMasks[i] = 0;
+    }
+
+    it = pWin->optional->geMasks->geClients;
+    while(it)
+    {
+        for (i = 0; i < MAXEXTENSIONS; i++)
+        {
+            evmasks->eventMasks[i] |= it->eventMask[i];
+        }
+        it = it->next;
+    }
+}
+
+/* Set generic event mask for given window. */
+void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask)
+{
+    GEClientPtr cli;
+
+    extension = (extension & 0x7F);
+
+    if (extension > MAXEXTENSIONS)
+    {
+        ErrorF("Invalid extension number.\n");
+        return;
+    }
+
+    if (!pWin->optional && !MakeWindowOptional(pWin))
+    {
+        ErrorF("GE: Could not make window optional.\n");
+        return;
+    }
+
+    if (mask)
+    {
+        GEEventMasksPtr evmasks = pWin->optional->geMasks;
+
+        /* check for existing client */
+        cli = evmasks->geClients;
+        while(cli)
+        {
+            if (cli->client == pClient)
+                break;
+            cli = cli->next;
+        }
+        if (!cli)
+        {
+            /* new client */
+            cli  = (GEClientPtr)xcalloc(1, sizeof(GEClientRec));
+            if (!cli)
+            {
+                ErrorF("GE: Insufficient memory to alloc client.\n");
+                return;
+            }
+            cli->next = evmasks->geClients;
+            cli->client = pClient;
+            evmasks->geClients = cli;
+        }
+        cli->eventMask[extension] = mask;
+    } else
+    {
+        /* remove client. */
+        cli = pWin->optional->geMasks->geClients;
+        if (cli->client == pClient)
+        {
+            pWin->optional->geMasks->geClients = cli->next;
+            xfree(cli);
+        } else 
+        { 
+            GEClientPtr prev = cli;
+            cli = cli->next;
+
+            while(cli)
+            {
+                if (cli->client == pClient)
+                {
+                    prev->next = cli->next;
+                    xfree(cli);
+                    break;
+                }
+                prev = cli;
+                cli = cli->next;
+            }
+        }
+        if (!cli)
+            return;
+    }
+
+    GERecalculateWinMask(pWin);
+}
+
+
diff --git a/Xext/geext.h b/Xext/geext.h
new file mode 100644
index 0000000..53aa21c
--- /dev/null
+++ b/Xext/geext.h
@@ -0,0 +1,64 @@
+/* 
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _GEEXT_H_
+#define _GEEXT_H_
+#include <X11/extensions/geproto.h>
+
+/* Returns the extension offset from the event */
+#define GEEXT(ev) (((xGenericEvent*)(ev))->extension)
+
+#define GEEXTIDX(ev) (GEEXT(ev) & 0x7F)
+/* Typecast to generic event */
+#define GEV(ev) ((xGenericEvent*)(ev))
+/* True if mask is set for extension on window */
+#define GEMaskIsSet(pWin, extension, mask) \
+    ((pWin)->optional && \
+     (pWin)->optional->geMasks && \
+     ((pWin)->optional->geMasks->eventMasks[(extension) & 0x7F] & (mask)))
+
+/* Returns first client */
+#define GECLIENT(pWin) \
+    (((pWin)->optional) ? (pWin)->optional->geMasks->geClients : NULL)
+
+/* Interface for other extensions */
+Mask GENextMask(int extension);
+void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask);
+void GERegisterExtension(
+        int extension,
+        void (*ev_dispatch)(xGenericEvent* from, xGenericEvent* to));
+void GEInitEvent(xGenericEvent* ev, int extension);
+
+
+void GEExtensionInit(void);
+
+#endif /* _GEEXT_H_ */
diff --git a/Xext/geint.h b/Xext/geint.h
new file mode 100644
index 0000000..9e131d3
--- /dev/null
+++ b/Xext/geint.h
@@ -0,0 +1,60 @@
+/* 
+
+Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
+
+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.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _GEINT_H_
+#define _GEINT_H_
+
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include <X11/extensions/geproto.h>
+
+extern int GEEventType;
+extern int GEEventBase;
+extern int GEErrorBase;
+extern int GEClientPrivateIndex;
+
+typedef struct _GEClientInfo {
+    CARD32  major_version;
+    CARD32  minor_version;
+} GEClientInfoRec, *GEClientInfoPtr;
+
+#define GEGetClient(pClient)    ((GEClientInfoPtr) (pClient)->devPrivates[GEClientPrivateIndex].ptr)
+
+extern int (*ProcGEVector[/*GENumRequests*/])(ClientPtr);
+extern int (*SProcGEVector[/*GENumRequests*/])(ClientPtr);
+
+#endif /* _GEINT_H_ */
diff --git a/dix/events.c b/dix/events.c
index deb2da1..836d755 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -178,6 +178,11 @@ static xEvent *xeviexE;
 #include "dixevents.h"
 #include "dixgrabs.h"
 #include "dispatch.h"
+
+#include <X11/extensions/ge.h>
+#include "geext.h"
+#include "geint.h"
+
 /**
  * Extension events type numbering starts at EXTENSION_EVENT_BASE.
  */
@@ -260,6 +265,9 @@ static struct {
 
 #define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
 
+static xEvent* swapEvent = NULL;
+static int swapEventLen = 0;
+
 /** 
  * True if device owns a cursor, false if device shares a cursor sprite with
  * another device.
@@ -1850,7 +1858,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev,
         return 0;
 
     /* CantBeFiltered means only window owner gets the event */
-    if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
+    if ((filter == CantBeFiltered) || 
+            (!(type & EXTENSION_EVENT_BASE) && type != GenericEvent))
     {
 	/* if nobody ever wants to see this event, skip some work */
 	if (filter != CantBeFiltered &&
@@ -1875,37 +1884,70 @@ DeliverEventsToWindow(DeviceIntPtr pDev,
     }
     if (filter != CantBeFiltered)
     {
-	if (type & EXTENSION_EVENT_BASE)
-	{
-	    OtherInputMasks *inputMasks;
+        /* Handle generic events */
+        if (type == GenericEvent)
+        {
+            GEClientPtr pClient;
+            /* FIXME: We don't do more than one GenericEvent at a time yet. */
+            if (count > 1)
+            {
+                ErrorF("Do not send more than one GenericEvent at a time!\n");
+                return 0;
+            }
 
-	    inputMasks = wOtherInputMasks(pWin);
-	    if (!inputMasks ||
-		!(inputMasks->inputEvents[mskidx] & filter))
-		return 0;
-	    other = inputMasks->inputClients;
-	}
-	else
-	    other = (InputClients *)wOtherClients(pWin);
-	for (; other; other = other->next)
-	{
-            /* core event? check for grab interference */
-            if (!(type & EXTENSION_EVENT_BASE) &&
-                    IsInterferingGrab(rClient(other), pWin, pDev, pEvents))
-                continue;
+            /* if we get here, filter should be set to the GE specific mask.
+               check if any client wants it */
+            if (!GEMaskIsSet(pWin, GEEXT(pEvents), filter))
+                return 0;
 
-	    if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
-					  other->mask[mskidx], filter, grab)) )
-	    {
-		if (attempt > 0)
-		{
-		    deliveries++;
-		    client = rClient(other);
-		    deliveryMask = other->mask[mskidx];
-		} else
-		    nondeliveries--;
-	    }
-	}
+            /* run through all clients, deliver event */
+            for (pClient = GECLIENT(pWin); pClient; pClient = pClient->next)
+            {
+                if (pClient->eventMask[GEEXTIDX(pEvents)] & filter)
+                {
+                    if (TryClientEvents(pClient->client, pEvents, count, 
+                            pClient->eventMask[GEEXTIDX(pEvents)], filter, grab) > 0)
+                    {
+                        deliveries++;
+                    } else 
+                        nondeliveries--;
+                }
+            }
+        }
+        else {
+            /* Traditional event */
+            if (type & EXTENSION_EVENT_BASE)
+            {
+                OtherInputMasks *inputMasks;
+
+                inputMasks = wOtherInputMasks(pWin);
+                if (!inputMasks ||
+                        !(inputMasks->inputEvents[mskidx] & filter))
+                    return 0;
+                other = inputMasks->inputClients;
+            }
+            else
+                other = (InputClients *)wOtherClients(pWin);
+            for (; other; other = other->next)
+            {
+                /* core event? check for grab interference */
+                if (!(type & EXTENSION_EVENT_BASE) &&
+                        IsInterferingGrab(rClient(other), pWin, pDev, pEvents))
+                    continue;
+
+                if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
+                                other->mask[mskidx], filter, grab)) )
+                {
+                    if (attempt > 0)
+                    {
+                        deliveries++;
+                        client = rClient(other);
+                        deliveryMask = other->mask[mskidx];
+                    } else
+                        nondeliveries--;
+                }
+            }
+        }
     }
     if ((type == ButtonPress) && deliveries && (!grab))
     {
@@ -5378,8 +5420,9 @@ WriteEventsToClient(ClientPtr pClient, i
 #ifdef PANORAMIX
     xEvent    eventCopy;
 #endif
-    xEvent    eventTo, *eventFrom;
-    int       i;
+    xEvent    *eventTo, *eventFrom;
+    int       i,
+              eventlength = sizeof(xEvent);
 
 #ifdef XKB
     if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
@@ -5436,21 +5479,53 @@ WriteEventsToClient(ClientPtr pClient, i
 	}
     }
 #endif	
+    /* Just a safety check to make sure we only have one GenericEvent, it just
+     * makes things easier for me right now. (whot) */
+    for (i = 1; i < count; i++)
+    {
+        if (events[i].u.u.type == GenericEvent)
+        {
+            ErrorF("TryClientEvents: Only one GenericEvent at a time.");
+            return; 
+        }
+    }
+
+    if (events->u.u.type == GenericEvent)
+    {
+        eventlength += ((xGenericEvent*)events)->length * 4;
+        if (eventlength > swapEventLen)
+        {
+            swapEventLen = eventlength;
+            swapEvent = Xrealloc(swapEvent, swapEventLen);
+            if (!swapEvent)
+            {
+                FatalError("WriteEventsToClient: Out of memory.\n");
+                return;
+            }
+        }
+    }
+
     if(pClient->swapped)
     {
 	for(i = 0; i < count; i++)
 	{
 	    eventFrom = &events[i];
+            eventTo = swapEvent;
+
 	    /* Remember to strip off the leading bit of type in case
 	       this event was sent with "SendEvent." */
 	    (*EventSwapVector[eventFrom->u.u.type & 0177])
-		(eventFrom, &eventTo);
-	    (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo);
+		(eventFrom, eventTo);
+
+	    (void)WriteToClient(pClient, eventlength, (char *)&eventTo);
 	}
     }
     else
     {
-	(void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
+        /* only one GenericEvent, remember? that means either count is 1 and
+         * eventlength is arbitrary or eventlength is 32 and count doesn't
+         * matter. And we're all set. Woohoo. */
+	(void)WriteToClient(pClient, count * eventlength, (char *) events);
     }
 }
 
diff --git a/dix/window.c b/dix/window.c
index 4846939..b49abdf 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -455,6 +455,7 @@ CreateRootWindow(ScreenPtr pScreen)
 #ifdef XINPUT
     pWin->optional->inputMasks = NULL;
     pWin->optional->deviceCursors = NULL;
+    pWin->optional->geMasks = NULL;
 #endif
 
     pWin->optional->access.perm = NULL;
@@ -3700,6 +3701,9 @@ CheckWindowOptionalNeed (WindowPtr w)
             optional->access.ndeny != 0)
         return;
 
+    if (optional->geMasks != NULL)
+        return;
+
     parentOptional = FindWindowWithOptional(w)->optional;
     if (optional->visual != parentOptional->visual)
 	return;
@@ -3746,6 +3750,19 @@ MakeWindowOptional (WindowPtr pWin)
     optional->inputMasks = NULL;
 #endif
     optional->deviceCursors = NULL;
+
+    optional->geMasks = (GEEventMasksPtr)xalloc(sizeof(GEEventMasksRec));
+    if (!optional->geMasks)
+    {
+        xfree(optional);
+        return FALSE;
+    } else {
+        int i;
+        optional->geMasks->geClients = 0;
+        for (i = 0; i < MAXEXTENSIONS; i++)
+            optional->geMasks->eventMasks[i] = 0;
+    }
+
     optional->access.nperm = 0;
     optional->access.ndeny = 0;
     optional->access.perm = NULL;
diff --git a/include/windowstr.h b/include/windowstr.h
index 87158b2..a1d501d 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -77,6 +77,18 @@ typedef struct _DevCursorNode {
     struct _DevCursorNode*      next;
 } DevCursNodeRec, *DevCursNodePtr, *DevCursorList;
 
+typedef struct _GEClientRec {
+    Mask        eventMask[MAXEXTENSIONS];
+    ClientPtr   client;
+    struct _GEClientRec* next;
+} GEClientRec, *GEClientPtr;
+
+/* Mask structure for GE extension. Allows one mask per extension. */
+typedef struct _GEEventMasks {
+    Mask        eventMasks[MAXEXTENSIONS];
+    struct _GEClientRec*  geClients;
+} GEEventMasksRec, *GEEventMasksPtr;
+
 typedef struct _WindowAccessRec {
     int                  defaultRule;      /* WindowAccessDenyAll */
     DeviceIntPtr*        perm;
@@ -105,6 +117,7 @@ typedef struct _WindowOpt {
     struct _OtherInputMasks *inputMasks;   /* default: NULL */
 #endif
     DevCursorList       deviceCursors;     /* default: NULL */
+    struct _GEEventMasks* geMasks;         /* default: NULL */
     WindowAccessRec     access;
 } WindowOptRec, *WindowOptPtr;
 
diff --git a/mi/miinitext.c b/mi/miinitext.c
index 0fc6d15..cad978d 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -215,6 +215,7 @@ extern Bool noXIdleExtension;
 #ifdef XV
 extern Bool noXvExtension;
 #endif
+extern Bool noGEExtension;
 
 #ifndef XFree86LOADER
 #define INITARGS void
@@ -386,6 +387,7 @@ extern void DamageExtensionInit(INITARGS
 #ifdef COMPOSITE
 extern void CompositeExtensionInit(INITARGS);
 #endif
+extern void GEExtensionInit(INITARGS);
 
 /* The following is only a small first step towards run-time
  * configurable extensions.
@@ -398,6 +400,7 @@ typedef struct {
 static ExtensionToggle ExtensionToggleList[] =
 {
     /* sort order is extension name string as shown in xdpyinfo */
+    { "Generic Events", &noGEExtension },
 #ifdef BIGREQS
     { "BIG-REQUESTS", &noBigReqExtension },
 #endif
@@ -531,6 +534,8 @@ InitExtensions(argc, argv)
     int		argc;
     char	*argv[];
 {
+    if (!noGEExtension) GEExtensionInit();
+
 #ifdef XCSECURITY
     SecurityExtensionSetup();
 #endif
@@ -684,6 +689,7 @@ InitVisualWrap()
 #else /* XFree86LOADER */
 /* List of built-in (statically linked) extensions */
 static ExtensionModule staticExtensions[] = {
+    { GEExtensionInit, "Generic Event Extension", &noGEExtension, NULL, NULL},
 #ifdef MITSHM
     { ShmExtensionInit, SHMNAME, &noMITShmExtension, NULL, NULL },
 #endif
diff --git a/os/utils.c b/os/utils.c
index 5058285..e45edd1 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -236,6 +236,8 @@ _X_EXPORT Bool noXIdleExtension = FALSE;
 _X_EXPORT Bool noXvExtension = FALSE;
 #endif
 
+_X_EXPORT Bool noGEExtension = FALSE;
+
 #define X_INCLUDE_NETDB_H
 #include <X11/Xos_r.h>
 


More information about the xorg-commit mailing list