xserver: Branch 'master' - 542 commits

Peter Hutterer whot at kemper.freedesktop.org
Mon May 26 21:39:10 PDT 2008


 COPYING                             |    1 
 XTrap/xtrapddmi.c                   |    9 
 XTrap/xtrapdi.c                     |    9 
 Xext/Makefile.am                    |    8 
 Xext/bigreq.c                       |    4 
 Xext/dpms.c                         |   60 
 Xext/fontcache.c                    |   28 
 Xext/geext.c                        |  427 +++
 Xext/geext.h                        |  114 +
 Xext/geint.h                        |   56 
 Xext/mbuf.c                         |   76 
 Xext/mbufbf.c                       |    8 
 Xext/panoramiX.c                    |   12 
 Xext/panoramiXSwap.c                |   12 
 Xext/saver.c                        |   10 
 Xext/security.c                     |   12 
 Xext/shape.c                        |   74 
 Xext/shm.c                          |   42 
 Xext/sync.c                         |   38 
 Xext/xcmisc.c                       |   28 
 Xext/xevie.c                        |   28 
 Xext/xres.c                         |    4 
 Xext/xtest.c                        |  741 +++---
 Xext/xvmain.c                       |    8 
 Xext/xvmc.c                         |    4 
 Xi/Makefile.am                      |   22 
 Xi/allowev.c                        |   12 
 Xi/chaccess.c                       |  158 +
 Xi/chaccess.h                       |   36 
 Xi/chdevcur.c                       |  111 +
 Xi/chdevcur.h                       |   39 
 Xi/chdevhier.c                      |  306 ++
 Xi/chdevhier.h                      |   42 
 Xi/chgdctl.c                        |    2 
 Xi/closedev.c                       |    6 
 Xi/exevents.c                       | 1100 ++++++++--
 Xi/exglobals.h                      |    7 
 Xi/extgrbdev.c                      |  221 ++
 Xi/extgrbdev.h                      |   43 
 Xi/extinit.c                        |  513 +++-
 Xi/getcptr.c                        |  108 
 Xi/getcptr.h                        |   43 
 Xi/getvers.c                        |   29 
 Xi/grabdev.c                        |   22 
 Xi/grabdevb.c                       |    2 
 Xi/grabdevk.c                       |    2 
 Xi/gtmotion.c                       |   14 
 Xi/listdev.c                        |  114 -
 Xi/listdev.h                        |   13 
 Xi/opendev.c                        |   16 
 Xi/qryacces.c                       |  121 +
 Xi/qryacces.h                       |   38 
 Xi/querydp.c                        |  166 +
 Xi/querydp.h                        |   44 
 Xi/sendexev.c                       |    2 
 Xi/setcptr.c                        |  103 
 Xi/setcptr.h                        |   36 
 Xi/setdval.c                        |    2 
 Xi/setmode.c                        |    2 
 Xi/stubs.c                          |   10 
 Xi/ungrdev.c                        |    8 
 Xi/ungrdevb.c                       |    2 
 Xi/ungrdevk.c                       |    2 
 Xi/warpdevp.c                       |  177 +
 Xi/warpdevp.h                       |   39 
 Xi/xiselev.c                        |   81 
 Xi/xiselev.h                        |   40 
 autogen.sh                          |    2 
 configure.ac                        |    2 
 dix/Makefile.am                     |    1 
 dix/access.c                        |  315 ++
 dix/cursor.c                        |  136 -
 dix/devices.c                       | 1057 +++++++--
 dix/dispatch.c                      |    3 
 dix/dixfonts.c                      |    6 
 dix/events.c                        | 3938 ++++++++++++++++++++++++------------
 dix/getevents.c                     |  881 +++++---
 dix/grabs.c                         |   34 
 dix/main.c                          |   17 
 dix/property.c                      |    8 
 dix/resource.c                      |    2 
 dix/selection.c                     |    6 
 dix/window.c                        |  322 ++
 fb/fbarc.c                          |    2 
 fb/fbpict.c                         |    2 
 hw/dmx/dmxclient.h                  |    2 
 hw/dmx/dmxcursor.c                  |   18 
 hw/dmx/dmxcursor.h                  |    2 
 hw/dmx/dmxinput.h                   |    4 
 hw/dmx/dmxlog.c                     |    4 
 hw/dmx/dmxlog.h                     |    2 
 hw/dmx/input/dmxcommon.h            |    4 
 hw/dmx/input/dmxeq.c                |   31 
 hw/dmx/input/dmxevents.c            |   41 
 hw/dmx/input/dmxinputinit.c         |   21 
 hw/dmx/input/dmxxinput.c            |    5 
 hw/kdrive/ephyr/ephyr.c             |    2 
 hw/kdrive/ephyr/ephyrinit.c         |    8 
 hw/kdrive/src/kinput.c              |   27 
 hw/vfb/InitInput.c                  |    7 
 hw/xfree86/common/xf86Config.c      |    4 
 hw/xfree86/common/xf86Cursor.c      |   63 
 hw/xfree86/common/xf86DGA.c         |  180 -
 hw/xfree86/common/xf86Events.c      |   26 
 hw/xfree86/common/xf86Globals.c     |    2 
 hw/xfree86/common/xf86Helper.c      |    4 
 hw/xfree86/common/xf86Init.c        |    4 
 hw/xfree86/common/xf86MiscExt.c     |    4 
 hw/xfree86/common/xf86Module.h      |    2 
 hw/xfree86/common/xf86Priv.h        |    3 
 hw/xfree86/common/xf86Privstr.h     |    2 
 hw/xfree86/common/xf86RandR.c       |    3 
 hw/xfree86/common/xf86Xinput.c      |  133 -
 hw/xfree86/common/xf86Xinput.h      |    6 
 hw/xfree86/dixmods/extmod/dgaproc.h |    7 
 hw/xfree86/dri/dri.c                |    3 
 hw/xfree86/loader/dixsym.c          |    6 
 hw/xfree86/loader/loadmod.c         |    2 
 hw/xfree86/loader/xf86sym.c         |    9 
 hw/xfree86/modes/xf86Cursors.c      |    9 
 hw/xfree86/modes/xf86RandR12.c      |    7 
 hw/xfree86/rac/xf86RAC.c            |   74 
 hw/xfree86/ramdac/xf86Cursor.c      |  219 +-
 hw/xgl/egl/kinput.c                 |    2 
 hw/xnest/Events.c                   |    4 
 hw/xnest/Init.c                     |    4 
 hw/xnest/Pointer.c                  |    1 
 hw/xquartz/darwin.c                 |    2 
 hw/xwin/winmouse.c                  |    8 
 hw/xwin/winwin32rootlesswndproc.c   |    8 
 include/cursor.h                    |   10 
 include/dix-config.h.in             |    3 
 include/dix.h                       |   80 
 include/dixevents.h                 |    8 
 include/dixgrabs.h                  |    3 
 include/dixstruct.h                 |    2 
 include/exevents.h                  |   15 
 include/extinit.h                   |    5 
 include/globals.h                   |    2 
 include/input.h                     |  151 +
 include/inputstr.h                  |  154 +
 include/misc.h                      |    1 
 include/scrnintstr.h                |   19 
 include/window.h                    |   13 
 include/windowstr.h                 |   47 
 include/xkbsrv.h                    |   16 
 mi/mi.h                             |    6 
 mi/micursor.c                       |   16 
 mi/midispcur.c                      |  322 ++
 mi/mieq.c                           |  243 +-
 mi/miexpose.c                       |    4 
 mi/miinitext.c                      |   20 
 mi/mipointer.c                      |  431 ++-
 mi/mipointer.h                      |   20 
 mi/miregion.c                       |    8 
 mi/misprite.c                       |  728 ++++--
 mi/misprite.h                       |   13 
 mi/mispritest.h                     |   54 
 os/utils.c                          |    4 
 randr/rrpointer.c                   |   32 
 record/record.c                     |    3 
 render/animcur.c                    |  140 -
 xfixes/cursor.c                     |   15 
 xkb/ddxBeep.c                       |    2 
 xkb/ddxDevBtn.c                     |    2 
 xkb/ddxFakeBtn.c                    |    2 
 xkb/ddxFakeMtn.c                    |    8 
 xkb/ddxList.c                       |    6 
 xkb/ddxLoad.c                       |   10 
 xkb/xkb.c                           |   36 
 xkb/xkbAccessX.c                    |   11 
 xkb/xkbActions.c                    |   21 
 xkb/xkbEvents.c                     |   31 
 xkb/xkbInit.c                       |   15 
 xkb/xkbLEDs.c                       |   43 
 xkb/xkbPrKeyEv.c                    |   10 
 xkb/xkbSwap.c                       |    2 
 xkb/xkbUtils.c                      |   13 
 178 files changed, 11951 insertions(+), 4229 deletions(-)

New commits:
commit 3a1278907ea8059546c7b9ab0c02714832c693e3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 26 18:01:07 2008 +0930

    xfree86: Bump XINPUT ABI to 3.0.

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index 240155c..78a22ec 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -84,7 +84,7 @@ typedef enum {
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 3)
 #define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(4, 0)
-#define ABI_XINPUT_VERSION	SET_ABI_VERSION(2, 0)
+#define ABI_XINPUT_VERSION	SET_ABI_VERSION(3, 0)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(1, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 5)
 
commit 0050165a67bb462e0bf644a11644ad9d587c62bb
Author: Simon Thum <simon.thum at gmx.de>
Date:   Mon May 26 17:56:08 2008 +0930

    input: change dxremaind, dyremaind to floats for better acceleration #9156
    
    X.Org Bug 9156 <http://bugs.freedesktop.org/show_bug.cgi?id=9156>
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/include/inputstr.h b/include/inputstr.h
index 5e745b3..7209b2c 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -174,7 +174,7 @@ typedef struct _ValuatorClassRec {
     AxisInfoPtr 	  axes;
     unsigned short	  numAxes;
     int			  *axisVal; /* always absolute, but device-coord system */
-    int                   dxremaind, dyremaind; /* for acceleration */
+    float                 dxremaind, dyremaind; /* for acceleration */
     CARD8	 	  mode;
 } ValuatorClassRec, *ValuatorClassPtr;
 
commit 26c1958c322be3ac4dfec9ba2c41c5202bd03709
Merge: 5fe5778... 2958610...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 26 17:37:31 2008 +0930

    Merge branch 'master' into mpx

commit 5fe57787faa2ea4f2f57b25455d200bf924206d6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 26 17:23:34 2008 +0930

    dix: store the absolute values in the motion history.
    
    The core protocol requires absolute values and it's a bit hard to get them if
    we only have relative ones in the history. Switch the motion history to
    absolute, and if we really need the relative values, we can probably generated
    them from the abs. ones in the future.

diff --git a/Xi/gtmotion.c b/Xi/gtmotion.c
index 7cc5c26..ce1312e 100644
--- a/Xi/gtmotion.c
+++ b/Xi/gtmotion.c
@@ -119,7 +119,7 @@ ProcXGetDeviceMotionEvents(ClientPtr client)
     rep.sequenceNumber = client->sequence;
     rep.nEvents = 0;
     rep.axes = axes;
-    rep.mode = v->mode & DeviceMode;
+    rep.mode = Absolute; /* XXX we don't do relative at the moment */
     rep.length = 0;
     start = ClientTimeToServerTime(stuff->start);
     stop = ClientTimeToServerTime(stuff->stop);
diff --git a/dix/getevents.c b/dix/getevents.c
index 643e977..b5657a8 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1003,10 +1003,11 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     y = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
                         pDev->valuator->axes + 1, scr->height);
 
-    updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
+    updateMotionHistory(pDev, ms, first_valuator, num_valuators,
+            &pDev->last.valuators[first_valuator]);
     if (master)
         updateMotionHistory(master, ms, first_valuator, num_valuators,
-                valuators);
+                &pDev->last.valuators[first_valuator]);
 
     /* Update the valuators with the true value sent to the client*/
     if(v0) *v0 = x;
commit 1883485edd7eb90c0b76bca41c71e26ae2c0b91a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 26 16:35:23 2008 +0930

    If core motion history is required, scale back to screen coords and INT16.

diff --git a/Xi/gtmotion.c b/Xi/gtmotion.c
index 8b59d67..7cc5c26 100644
--- a/Xi/gtmotion.c
+++ b/Xi/gtmotion.c
@@ -135,7 +135,7 @@ ProcXGetDeviceMotionEvents(ClientPtr client)
         size = sizeof(Time) + (axes * sizeof(INT32));
 	rep.nEvents = GetMotionHistory(dev, (xTimecoord **) &coords,/* XXX */
 					start.milliseconds, stop.milliseconds,
-					(ScreenPtr) NULL);
+					(ScreenPtr) NULL, FALSE);
     }
     if (rep.nEvents > 0) {
 	length = (rep.nEvents * size + 3) >> 2;
diff --git a/dix/devices.c b/dix/devices.c
index 9db276b..60d48b2 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2308,12 +2308,9 @@ ProcGetMotionEvents(ClientPtr client)
     {
 	if (CompareTimeStamps(stop, currentTime) == LATER)
 	    stop = currentTime;
-	coords = (xTimecoord *)xalloc(mouse->valuator->numMotionEvents
-					      * sizeof(xTimecoord));
-	if (!coords)
-	    return BadAlloc;
-	count = GetMotionHistory(mouse, coords, start.milliseconds,
-				 stop.milliseconds, pWin->drawable.pScreen);
+	count = GetMotionHistory(mouse, &coords, start.milliseconds,
+				 stop.milliseconds, pWin->drawable.pScreen,
+                                 TRUE);
 	xmin = pWin->drawable.x - wBorderWidth (pWin);
 	xmax = pWin->drawable.x + (int)pWin->drawable.width +
 		wBorderWidth (pWin);
diff --git a/dix/getevents.c b/dix/getevents.c
index 349823d..643e977 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -258,15 +258,16 @@ AllocateMotionHistory(DeviceIntPtr pDev)
                 pDev->name, size * pDev->valuator->numMotionEvents);
 }
 
-
 /**
  * Dump the motion history between start and stop into the supplied buffer.
  * Only records the event for a given screen in theory, but in practice, we
  * sort of ignore this.
+ *
+ * If core is set, we only generate x/y, in INT16, scaled to screen coords.
  */
 _X_EXPORT int
 GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
-                 unsigned long stop, ScreenPtr pScreen)
+                 unsigned long stop, ScreenPtr pScreen, BOOL core)
 {
     char *ibuff = NULL, *obuff;
     int i = 0, ret = 0;
@@ -277,10 +278,15 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
     int dflt;
     AxisInfo from, *to; /* for scaling */
     CARD32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
+    INT16 *corebuf;
+    AxisInfo core_axis = {0};
 
     if (!pDev->valuator || !pDev->valuator->numMotionEvents)
         return 0;
 
+    if (core && !pScreen)
+        return 0;
+
     if (pDev->isMaster)
         size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
     else
@@ -304,7 +310,36 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
             return ret;
         }
         else if (current >= start) {
-            if (pDev->isMaster)
+            if (core)
+            {
+                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
+
+                icbuf = (INT32*)(ibuff + sizeof(Time));
+                corebuf = (INT16*)(obuff + sizeof(Time));
+
+                /* fetch x coordinate + range */
+                memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                memcpy(&coord, icbuf++, sizeof(INT32));
+
+                /* scale to screen coords */
+                to = &core_axis;
+                to->max_value = pScreen->width;
+                coord = rescaleValuatorAxis(coord, &from, to, pScreen->width);
+
+                memcpy(corebuf, &coord, sizeof(INT16));
+                corebuf++;
+
+                /* fetch y coordinate + range */
+                memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                memcpy(&coord, icbuf++, sizeof(INT32));
+
+                to->max_value = pScreen->height;
+                coord = rescaleValuatorAxis(coord, &from, to, pScreen->height);
+                memcpy(corebuf, &coord, sizeof(INT16));
+
+            } else if (pDev->isMaster)
             {
                 memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
 
@@ -345,7 +380,10 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
 
             /* don't advance by size here. size may be different to the
              * actually written size if the MD has less valuators than MAX */
-            obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+            if (core)
+                obuff += sizeof(INT32) + sizeof(Time);
+            else
+                obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
             ret++;
         }
     }
diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index 1dd0bbc..eaa6c76 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -2933,9 +2933,9 @@ xf86MotionHistoryAllocate(LocalDevicePtr local)
 
 _X_EXPORT int
 xf86GetMotionEvents(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
-                    unsigned long stop, ScreenPtr pScreen)
+                    unsigned long stop, ScreenPtr pScreen, BOOL core)
 {
-    return GetMotionHistory(pDev, buff, start, stop, pScreen);
+    return GetMotionHistory(pDev, buff, start, stop, pScreen, core);
 }
 
 _X_EXPORT void
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index dd72ec7..02f657d 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -197,7 +197,7 @@ void xf86DeleteInput(InputInfoPtr pInp, int flags);
 void xf86MotionHistoryAllocate(LocalDevicePtr local);
 int xf86GetMotionEvents(DeviceIntPtr dev, xTimecoord *buff,
                         unsigned long start, unsigned long stop,
-                        ScreenPtr pScreen);
+                        ScreenPtr pScreen, BOOL core);
 
 /* xf86Option.c */
 void xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts,
diff --git a/include/input.h b/include/input.h
index 3071d75..a816385 100644
--- a/include/input.h
+++ b/include/input.h
@@ -486,7 +486,8 @@ extern int GetMotionHistory(
     xTimecoord **buff,
     unsigned long start,
     unsigned long stop,
-    ScreenPtr pScreen);
+    ScreenPtr pScreen,
+    BOOL core);
 
 extern void SwitchCorePointer(DeviceIntPtr pDev);
 
commit 0b88510069bdf6d020d73b424f62c2923c0db4a4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 26 13:53:45 2008 +0930

    Ensure the motion history is merged for master devices.
    
    Add each event to the master's MH as well as to the SDs. In the MD, store
    min/max and the actual value. When retrieving the MH, rescale all coordinates
    to the current coordinate range and only post those valuators that are
    currently active on the device.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f13959f..725c578 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -571,12 +571,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         v = to->valuator;
         if (!v)
             FatalError("[Xi] no memory for class shift.\n");
-        memcpy(v, from->valuator, sizeof(ValuatorClassRec));
-        v->motion = NULL;
-        AllocateMotionHistory(to); /*XXX should be copied somehow */
-        v->first_motion = 0;
-        v->last_motion = 0;
 
+        v->numAxes = from->valuator->numAxes;
         v->axes = (AxisInfoPtr)&v[1];
         memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
 
diff --git a/Xi/gtmotion.c b/Xi/gtmotion.c
index 7994890..8b59d67 100644
--- a/Xi/gtmotion.c
+++ b/Xi/gtmotion.c
@@ -132,12 +132,8 @@ ProcXGetDeviceMotionEvents(ClientPtr client)
 	stop = currentTime;
     num_events = v->numMotionEvents;
     if (num_events) {
-	size = sizeof(Time) + (axes * sizeof(INT32));
-	tsize = num_events * size;
-	coords = (INT32 *) xalloc(tsize);
-	if (!coords)
-	    return BadAlloc;
-	rep.nEvents = GetMotionHistory(dev, (xTimecoord *) coords,/* XXX */
+        size = sizeof(Time) + (axes * sizeof(INT32));
+	rep.nEvents = GetMotionHistory(dev, (xTimecoord **) &coords,/* XXX */
 					start.milliseconds, stop.milliseconds,
 					(ScreenPtr) NULL);
     }
diff --git a/dix/getevents.c b/dix/getevents.c
index 6e723f8..349823d 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -253,6 +253,9 @@ AllocateMotionHistory(DeviceIntPtr pDev)
     pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size);
     pDev->valuator->first_motion = 0;
     pDev->valuator->last_motion = 0;
+    if (!pDev->valuator->motion)
+        ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
+                pDev->name, size * pDev->valuator->numMotionEvents);
 }
 
 
@@ -262,18 +265,32 @@ AllocateMotionHistory(DeviceIntPtr pDev)
  * sort of ignore this.
  */
 _X_EXPORT int
-GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
+GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
                  unsigned long stop, ScreenPtr pScreen)
 {
-    char *ibuff = NULL, *obuff = (char *) buff;
+    char *ibuff = NULL, *obuff;
     int i = 0, ret = 0;
+    int j, coord;
     Time current;
     /* The size of a single motion event. */
-    int size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+    int size;
+    int dflt;
+    AxisInfo from, *to; /* for scaling */
+    CARD32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
 
     if (!pDev->valuator || !pDev->valuator->numMotionEvents)
         return 0;
 
+    if (pDev->isMaster)
+        size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
+    else
+        size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+
+    *buff = xalloc(size * pDev->valuator->numMotionEvents);
+    if (!(*buff))
+        return 0;
+    obuff = *buff;
+
     for (i = pDev->valuator->first_motion;
          i != pDev->valuator->last_motion;
          i = (i + 1) % pDev->valuator->numMotionEvents) {
@@ -287,8 +304,48 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
             return ret;
         }
         else if (current >= start) {
-            memcpy(obuff, ibuff, size);
-            obuff += size;
+            if (pDev->isMaster)
+            {
+                memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
+
+                ocbuf = (INT32*)(obuff + sizeof(Time));
+                icbuf = (INT32*)(ibuff + sizeof(Time));
+                for (j = 0; j < MAX_VALUATORS; j++)
+                {
+                    if (j >= pDev->valuator->numAxes)
+                        break;
+
+                    /* fetch min/max/coordinate */
+                    memcpy(&from.min_value, icbuf++, sizeof(INT32));
+                    memcpy(&from.max_value, icbuf++, sizeof(INT32));
+                    memcpy(&coord, icbuf++, sizeof(INT32));
+
+                    to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
+
+                    /* x/y scaled to screen if no range is present */
+                    if (j == 0 && (from.max_value < from.min_value))
+                        from.max_value = pScreen->width;
+                    else if (j == 1 && (from.max_value < from.min_value))
+                        from.max_value = pScreen->height;
+
+                    if (j == 0 && (to->max_value < to->min_value))
+                        dflt = pScreen->width;
+                    else if (j == 1 && (to->max_value < to->min_value))
+                        dflt = pScreen->height;
+                    else
+                        dflt = 0;
+
+                    /* scale from stored range into current range */
+                    coord = rescaleValuatorAxis(coord, &from, to, 0);
+                    memcpy(ocbuf, &coord, sizeof(INT32));
+                    ocbuf++;
+                }
+            } else
+                memcpy(obuff, ibuff, size);
+
+            /* don't advance by size here. size may be different to the
+             * actually written size if the MD has less valuators than MAX */
+            obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
             ret++;
         }
     }
@@ -300,29 +357,63 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord *buff, unsigned long start,
 /**
  * Update the motion history for a specific device, with the list of
  * valuators.
+ *
+ * Layout of the history buffer:
+ *   for SDs: [time] [val0] [val1] ... [valn]
+ *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
+ *
+ * For events that have some valuators unset (first_valuator > 0):
+ *      min_val == max_val == val == 0.
  */
 static void
 updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
                     int num_valuators, int *valuators)
 {
     char *buff = (char *) pDev->valuator->motion;
+    ValuatorClassPtr v;
+    int i;
 
     if (!pDev->valuator->numMotionEvents)
         return;
 
-    buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
+    v = pDev->valuator;
+    if (pDev->isMaster)
+    {
+        buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
+                v->last_motion;
+
+        memcpy(buff, &ms, sizeof(Time));
+        buff += sizeof(Time);
+
+        memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
+        buff += 3 * sizeof(INT32) * first_valuator;
+
+        for (i = first_valuator; i < first_valuator + num_valuators; i++)
+        {
+            memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
+            buff += sizeof(INT32);
+            memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
+            buff += sizeof(INT32);
+            memcpy(buff, &valuators[i - first_valuator], sizeof(INT32));
+            buff += sizeof(INT32);
+        }
+    } else
+    {
+
+        buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
             pDev->valuator->last_motion;
-    memcpy(buff, &ms, sizeof(Time));
 
-    buff += sizeof(Time);
-    bzero(buff, sizeof(INT32) * pDev->valuator->numAxes);
+        memcpy(buff, &ms, sizeof(Time));
+        buff += sizeof(Time);
 
-    buff += sizeof(INT32) * first_valuator;
-    memcpy(buff, valuators, sizeof(INT32) * num_valuators);
+        memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
+        buff += sizeof(INT32) * first_valuator;
 
-    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
-                                  pDev->valuator->numMotionEvents;
+        memcpy(buff, valuators, sizeof(INT32) * num_valuators);
+    }
 
+    pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
+        pDev->valuator->numMotionEvents;
     /* If we're wrapping around, just keep the circular buffer going. */
     if (pDev->valuator->first_motion == pDev->valuator->last_motion)
         pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
@@ -875,6 +966,9 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
                         pDev->valuator->axes + 1, scr->height);
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
+    if (master)
+        updateMotionHistory(master, ms, first_valuator, num_valuators,
+                valuators);
 
     /* Update the valuators with the true value sent to the client*/
     if(v0) *v0 = x;
diff --git a/include/input.h b/include/input.h
index 70f3de6..3071d75 100644
--- a/include/input.h
+++ b/include/input.h
@@ -483,7 +483,7 @@ extern void AllocateMotionHistory(
 
 extern int GetMotionHistory(
     DeviceIntPtr pDev,
-    xTimecoord *buff,
+    xTimecoord **buff,
     unsigned long start,
     unsigned long stop,
     ScreenPtr pScreen);
commit d22c25bda450f6f1dfa634f0f72b32c4bec429cd
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 26 09:26:18 2008 +0930

    dix: Allocate MD's motion history to be large enough for potential valuators
    
    Since we can't predict how many valuators may be in a future SD attached to an
    MD, we need to preallocate a history buffer that is large enough to keep
    MAX_VALUATORS coordinates per event.
    
    In addition, the history buffer needs to memorize the coordinate ranges at the
    time, thus requiring MDs to store (min_val, max_val, current_val, time)
    instead of (current_val, time) for each motion history entry.
    
    This commit only fixes the allocation.

diff --git a/dix/getevents.c b/dix/getevents.c
index dda681d..6e723f8 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -232,15 +232,25 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
 _X_EXPORT void
 AllocateMotionHistory(DeviceIntPtr pDev)
 {
+    int size;
     if (pDev->valuator->motion)
         xfree(pDev->valuator->motion);
 
     if (pDev->valuator->numMotionEvents < 1)
         return;
 
-    pDev->valuator->motion = xalloc(((sizeof(INT32) * pDev->valuator->numAxes)
-                                    + sizeof(Time)) *
-                                    pDev->valuator->numMotionEvents);
+    /* An MD must have a motion history size large enough to keep all
+     * potential valuators, plus the respective range of the valuators.
+     * 3 * INT32 for (min_val, max_val, curr_val))
+     */
+    if (pDev->isMaster)
+        size = sizeof(INT32) * 3 * MAX_VALUATORS;
+    else
+        size = sizeof(INT32) * pDev->valuator->numAxes;
+
+    size += sizeof(Time);
+
+    pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size);
     pDev->valuator->first_motion = 0;
     pDev->valuator->last_motion = 0;
 }
diff --git a/include/inputstr.h b/include/inputstr.h
index 86b1667..5e745b3 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -167,9 +167,9 @@ typedef struct _ValuatorClassRec {
     int		 	  numMotionEvents;
     int                   first_motion;
     int                   last_motion;
-    void                  *motion; /* motion history buffer */
-
-    WindowPtr    	  motionHintWindow;
+    void                  *motion; /* motion history buffer. Different layout
+                                      for MDs and SDs!*/
+    WindowPtr             motionHintWindow;
 
     AxisInfoPtr 	  axes;
     unsigned short	  numAxes;
commit 0877de13ac6ddfb55108aa3456d47f970c6c442c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun May 25 22:49:54 2008 +0930

    Remove GetMotionProc from ValuatorClassRec.
    
    With the MD/SD device hierarchy we need control over the generation of the
    motion history as well as the conversion later before posting it to the
    client. So let's not let the drivers change it.
    
    No x.org driver currently uses it anyway, linuxwacom doesn't either so dumping
    it seems safe enough.

diff --git a/Xi/gtmotion.c b/Xi/gtmotion.c
index 4f4d7cb..7994890 100644
--- a/Xi/gtmotion.c
+++ b/Xi/gtmotion.c
@@ -137,9 +137,9 @@ ProcXGetDeviceMotionEvents(ClientPtr client)
 	coords = (INT32 *) xalloc(tsize);
 	if (!coords)
 	    return BadAlloc;
-	rep.nEvents = (v->GetMotionProc) (dev, (xTimecoord *) coords,	/* XXX */
-					  start.milliseconds, stop.milliseconds,
-					  (ScreenPtr) NULL);
+	rep.nEvents = GetMotionHistory(dev, (xTimecoord *) coords,/* XXX */
+					start.milliseconds, stop.milliseconds,
+					(ScreenPtr) NULL);
     }
     if (rep.nEvents > 0) {
 	length = (rep.nEvents * size + 3) >> 2;
diff --git a/dix/devices.c b/dix/devices.c
index 2521186..9db276b 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -492,7 +492,7 @@ CorePointerProc(DeviceIntPtr pDev, int what)
         for (i = 1; i <= 32; i++)
             map[i] = i;
         InitPointerDeviceStruct((DevicePtr)pDev, map, 32,
-                                GetMotionHistory, (PtrCtrlProcPtr)NoopDDA,
+                                (PtrCtrlProcPtr)NoopDDA,
                                 GetMotionHistorySize(), 2);
         pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
         pDev->last.valuators[0] = pDev->valuator->axisVal[0];
@@ -643,7 +643,7 @@ FreeDeviceClass(int type, pointer *class)
                 ValuatorClassPtr *v = (ValuatorClassPtr*)class;
 
                 /* Counterpart to 'biggest hack ever' in init. */
-                if ((*v)->motion && (*v)->GetMotionProc == GetMotionHistory)
+                if ((*v)->motion)
                     xfree((*v)->motion);
                 xfree((*v));
                 break;
@@ -1157,7 +1157,6 @@ InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons,
 
 _X_EXPORT Bool
 InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
-                              ValuatorMotionProcPtr motionProc,
                               int numMotionEvents, int mode)
 {
     int i;
@@ -1175,7 +1174,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
     valc->motion = NULL;
     valc->first_motion = 0;
     valc->last_motion = 0;
-    valc->GetMotionProc = motionProc;
 
     valc->numMotionEvents = numMotionEvents;
     valc->motionHintWindow = NullWindow;
@@ -1187,9 +1185,7 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
     valc->dyremaind = 0;
     dev->valuator = valc;
 
-    /* biggest hack ever. */
-    if (motionProc == GetMotionHistory)
-        AllocateMotionHistory(dev);
+    AllocateMotionHistory(dev);
 
     for (i=0; i<numAxes; i++) {
         InitValuatorAxisStruct(dev, i, NO_AXIS_LIMITS, NO_AXIS_LIMITS,
@@ -1414,14 +1410,13 @@ InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr contr
 
 _X_EXPORT Bool
 InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons,
-                        ValuatorMotionProcPtr motionProc,
                         PtrCtrlProcPtr controlProc, int numMotionEvents,
                         int numAxes)
 {
     DeviceIntPtr dev = (DeviceIntPtr)device;
 
     return(InitButtonClassDeviceStruct(dev, numButtons, map) &&
-	   InitValuatorClassDeviceStruct(dev, numAxes, motionProc,
+	   InitValuatorClassDeviceStruct(dev, numAxes,
 					 numMotionEvents, 0) &&
 	   InitPtrFeedbackClassDeviceStruct(dev, controlProc));
 }
@@ -2317,10 +2312,8 @@ ProcGetMotionEvents(ClientPtr client)
 					      * sizeof(xTimecoord));
 	if (!coords)
 	    return BadAlloc;
-	count = (*mouse->valuator->GetMotionProc) (mouse, coords,
-						   start.milliseconds,
-						   stop.milliseconds,
-						   pWin->drawable.pScreen);
+	count = GetMotionHistory(mouse, coords, start.milliseconds,
+				 stop.milliseconds, pWin->drawable.pScreen);
 	xmin = pWin->drawable.x - wBorderWidth (pWin);
 	xmax = pWin->drawable.x + (int)pWin->drawable.width +
 		wBorderWidth (pWin);
diff --git a/dix/getevents.c b/dix/getevents.c
index 7c7c63f..dda681d 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -238,8 +238,8 @@ AllocateMotionHistory(DeviceIntPtr pDev)
     if (pDev->valuator->numMotionEvents < 1)
         return;
 
-    pDev->valuator->motion = xalloc(((sizeof(INT32) * pDev->valuator->numAxes) +
-                                     sizeof(Time)) *
+    pDev->valuator->motion = xalloc(((sizeof(INT32) * pDev->valuator->numAxes)
+                                    + sizeof(Time)) *
                                     pDev->valuator->numMotionEvents);
     pDev->valuator->first_motion = 0;
     pDev->valuator->last_motion = 0;
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index c6724e4..005465f 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -438,7 +438,6 @@ KdPointerProc(DeviceIntPtr pDevice, int onoff)
         }
 
 	InitPointerDeviceStruct(pDev, pi->map, pi->nButtons,
-	    GetMotionHistory,
 	    (PtrCtrlProcPtr)NoopDDA,
 	    GetMotionHistorySize(), pi->nAxes);
 
diff --git a/hw/vfb/InitInput.c b/hw/vfb/InitInput.c
index 3b001ee..2af3c64 100644
--- a/hw/vfb/InitInput.c
+++ b/hw/vfb/InitInput.c
@@ -295,7 +295,7 @@ vfbMouseProc(DeviceIntPtr pDevice, int onoff)
 	    map[1] = 1;
 	    map[2] = 2;
 	    map[3] = 3;
-	    InitPointerDeviceStruct(pDev, map, 3, GetMotionHistory,
+	    InitPointerDeviceStruct(pDev, map, 3,
 		(PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2);
 	    break;
 
diff --git a/hw/xnest/Pointer.c b/hw/xnest/Pointer.c
index b0de13b..8f764a6 100644
--- a/hw/xnest/Pointer.c
+++ b/hw/xnest/Pointer.c
@@ -56,7 +56,6 @@ xnestPointerProc(DeviceIntPtr pDev, int onoff)
       for (i = 0; i <= nmap; i++)
 	map[i] = i; /* buttons are already mapped */
       InitPointerDeviceStruct(&pDev->public, map, nmap,
-			      GetMotionHistory,
 			      xnestChangePointerControl,
 			      GetMotionHistorySize(), 2);
       break;
diff --git a/include/input.h b/include/input.h
index 9b92ea3..70f3de6 100644
--- a/include/input.h
+++ b/include/input.h
@@ -274,17 +274,9 @@ extern Bool InitButtonClassDeviceStruct(
     int /*numButtons*/,
     CARD8* /*map*/);
 
-typedef int (*ValuatorMotionProcPtr)(
-		DeviceIntPtr /*pdevice*/,
-		xTimecoord * /*coords*/,
-		unsigned long /*start*/,
-		unsigned long /*stop*/,
-		ScreenPtr /*pScreen*/);
-
 extern Bool InitValuatorClassDeviceStruct(
     DeviceIntPtr /*device*/,
     int /*numAxes*/,
-    ValuatorMotionProcPtr /* motionProc */,
     int /*numMotionEvents*/,
     int /*mode*/);
 
@@ -358,7 +350,6 @@ extern Bool InitPointerDeviceStruct(
     DevicePtr /*device*/,
     CARD8* /*map*/,
     int /*numButtons*/,
-    ValuatorMotionProcPtr /*motionProc*/,
     PtrCtrlProcPtr /*controlProc*/,
     int /*numMotionEvents*/,
     int /*numAxes*/);
diff --git a/include/inputstr.h b/include/inputstr.h
index d26eb13..86b1667 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -164,11 +164,10 @@ typedef struct _AxisInfo {
 } AxisInfo, *AxisInfoPtr;
 
 typedef struct _ValuatorClassRec {
-    ValuatorMotionProcPtr GetMotionProc;
     int		 	  numMotionEvents;
     int                   first_motion;
     int                   last_motion;
-    void                  *motion;
+    void                  *motion; /* motion history buffer */
 
     WindowPtr    	  motionHintWindow;
 
commit 00b4339168c10dd4ce026deb8e04bfb63dfd11dc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun May 25 22:34:11 2008 +0930

    dmx: remove some #if 0'd code.

diff --git a/hw/dmx/input/dmxxinput.c b/hw/dmx/input/dmxxinput.c
index 97bea75..692e647 100644
--- a/hw/dmx/input/dmxxinput.c
+++ b/hw/dmx/input/dmxxinput.c
@@ -98,13 +98,8 @@ int ChangePointerDevice(DeviceIntPtr old_dev,
     }
     dmxLocalNew->savedMotionProc       = new_dev->valuator->GetMotionProc;
     dmxLocalNew->savedMotionEvents     = new_dev->valuator->numMotionEvents;
-#if 00 /*BP*/
-    new_dev->valuator->GetMotionProc   = miPointerGetMotionEvents;
-    new_dev->valuator->numMotionEvents = miPointerGetMotionBufferSize();
-#else
     new_dev->valuator->GetMotionProc   = GetMotionHistory;
     new_dev->valuator->numMotionEvents = GetMaximumEventsNum();
-#endif
                                 /* Switch our notion of core pointer */
     dmxLocalOld->isCore         = 0;
     dmxLocalOld->sendsCore      = dmxLocalOld->savedSendsCore;
commit 096117cf023dc92dcadc91677931fc6ad1feb4a0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun May 25 10:38:33 2008 +0930

    Xi: reset motion history when swapping device classes.
    
    This isn't really the correct solution, but it'll have to do until I figured
    out how to transfer the history over correctly.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index a48ba11..f13959f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -574,6 +574,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         memcpy(v, from->valuator, sizeof(ValuatorClassRec));
         v->motion = NULL;
         AllocateMotionHistory(to); /*XXX should be copied somehow */
+        v->first_motion = 0;
+        v->last_motion = 0;
 
         v->axes = (AxisInfoPtr)&v[1];
         memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
commit ba557e0263eee0b75847c596f31c71492611b22c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat May 24 17:23:10 2008 +0930

    Xi: remove deprecated comment.
    
    Axis clipping wouldn't be necessary here, it's already performed in GPE.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f477a73..a48ba11 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -839,8 +839,6 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
                  *      swap = (event - device)
                  *      dev = event
                  *      event = delta
-                 *
-                 * XXX: axis clipping for relative events?
                  */
 		axisvals = v->axisVal;
                 int delta;
commit 3ae0f4fc832462444d03024c5fbb867f19d5e960
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 23 15:02:43 2008 +0930

    dix: update valuators > 2 as well.
    
    master->last.valuator[x] for x > 2 is undefined. For all other devices, it's
    the respective device's last valuators.
    
    If the lastSlave did not have a valuator that is to be updated now, it is
    reset to 0.

diff --git a/dix/getevents.c b/dix/getevents.c
index 23ec6c4..7c7c63f 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -191,18 +191,39 @@ static void
 updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
 {
     ScreenPtr scr = miPointerGetScreen(pDev);
+    int i;
+    DeviceIntPtr lastSlave;
 
     /* master->last.valuators[0]/[1] is in screen coords and the actual
      * position of the pointer */
     pDev->last.valuators[0] = master->last.valuators[0];
     pDev->last.valuators[1] = master->last.valuators[1];
 
+    if (!pDev->valuator)
+        return;
+
     /* scale back to device coordinates */
     if(pDev->valuator->numAxes > 0)
         pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL, pDev->valuator->axes + 0, scr->width);
     if(pDev->valuator->numAxes > 1)
         pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL, pDev->valuator->axes + 1, scr->height);
-    /*TODO calculate the other axis as well based on info from the old slave-device */
+
+    /* calculate the other axis as well based on info from the old
+     * slave-device. If the old slave had less axes than this one,
+     * last.valuators is reset to 0.
+     */
+    if ((lastSlave = master->u.lastSlave) && lastSlave->valuator) {
+        for (i = 2; i < pDev->valuator->numAxes; i++) {
+            if (i >= lastSlave->valuator->numAxes)
+                pDev->last.valuators[i] = 0;
+            else
+                pDev->last.valuators[i] =
+                    rescaleValuatorAxis(pDev->last.valuators[i],
+                            lastSlave->valuator->axes + i,
+                            pDev->valuator->axes + i, 0);
+        }
+    }
+
 }
 
 /**
@@ -540,13 +561,9 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
     if (master && master->u.lastSlave != pDev)
     {
         CreateClassesChangedEvent(events, master, pDev);
-
-        if (master->valuator && pDev->valuator)
-        {
-            pDev->last.valuators[0] = master->last.valuators[0];
-            pDev->last.valuators[1] = master->last.valuators[1];
-        }
+        updateSlaveDeviceCoords(master, pDev);
         master->u.lastSlave = pDev;
+        master->last.numValuators = pDev->last.numValuators;
         numEvents++;
         events++;
     }
@@ -713,6 +730,8 @@ FreeEventList(EventListPtr list, int num_events)
  *
  * last.valuators[x] of the device is always in absolute device coords.
  * last.valuators[x] of the master device is in absolute screen coords.
+ *
+ * master->last.valuators[x] for x > 2 is undefined.
  */
 _X_EXPORT int
 GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
@@ -726,6 +745,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         cx, cy; /* only screen coordinates */
     ScreenPtr scr = miPointerGetScreen(pDev);
     int *v0 = NULL, *v1 = NULL;
+    int i;
 
     /* Sanity checks. */
     if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
@@ -760,6 +780,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         CreateClassesChangedEvent(events, master, pDev);
         updateSlaveDeviceCoords(master, pDev);
         master->u.lastSlave = pDev;
+        master->last.numValuators = pDev->last.numValuators;
         num_events++;
         events++;
     }
@@ -777,12 +798,17 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     if (flags & POINTER_ABSOLUTE) {
         if(v0) x = *v0;
         if(v1) y = *v1;
-        /*TODO: Update the rest of the valuators */
 
         /* Clip both x and y to the defined limits (usually co-ord space limit). */
         clipAxis(pDev, 0, &x);
         clipAxis(pDev, 1, &y);
-        /*TODO: Clip the rest of the valuators */
+
+        i = (first_valuator > 2) ? 0 : 2;
+        for (; i < num_valuators; i++)
+        {
+            pDev->last.valuators[i + first_valuator] = valuators[i];
+            clipAxis(pDev, i, &pDev->last.valuators[i + first_valuator]);
+        }
     }
     else {
         if (flags & POINTER_ACCELERATE)
@@ -791,7 +817,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
         if(v0) x += *v0;
         if(v1) y += *v1;
-        /*TODO: Update the rest of the valuators */
 
         /* if attached, clip both x and y to the defined limits (usually
          * co-ord space limit). If it is attached, we need x/y to go over the
@@ -800,7 +825,15 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
             clipAxis(pDev, 0, &x);
             clipAxis(pDev, 1, &y);
         }
-        /*TODO: Clip the rest of the valuators (Yes, here. Only x&y get special treatment) */
+
+        /* calc other axes, clip, drop back into valuators */
+        i = (first_valuator > 2) ? 0 : 2;
+        for (; i < num_valuators; i++)
+        {
+            pDev->last.valuators[i + first_valuator] += valuators[i];
+            clipAxis(pDev, i, &pDev->last.valuators[i + first_valuator]);
+            valuators[i] = pDev->last.valuators[i + first_valuator];
+        }
     }
 
     /* scale x&y to screen */
@@ -836,7 +869,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     /* Update the valuators with the true value sent to the client*/
     if(v0) *v0 = x;
     if(v1) *v1 = y;
-    /* TODO: other axes */
 
     /* dropy x/y (device coordinates) back into valuators for next event */
     pDev->last.valuators[0] = x;
@@ -914,6 +946,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
         CreateClassesChangedEvent(events, master, pDev);
         updateSlaveDeviceCoords(master, pDev);
         master->u.lastSlave = pDev;
+        master->last.numValuators = pDev->last.numValuators;
         num_events++;
         events++;
     }
commit 0d1b41ace38bc918e2cc2a0a6ad107c76346fd00
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 23 13:32:33 2008 +0930

    Xi: update device valuators based on the event.
    
    Event is always absolute, update the device's valuators (always absolute too),
    and then change the deviceValuator event to reflect the device's reporting
    mode.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 42b77c1..f477a73 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -831,90 +831,50 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 		FatalError("Bad valuators reported for device %s\n",
 			   device->name);
 	    if (v && v->axisVal) {
-                /* The device always stores values in absolute. Only the
+                /* v->axisVal is always in absolute coordinates. Only the
                  * delivery mode changes.
-                 * If device is mode Absolute, and event is Relative
-                 *     dev += event
-                 *     event = dev
-                 * If device is mode Absolute, and event is Absolute
+                 * If device is mode Absolute
                  *     dev = event
-                 * If device is mode Relative, and event is Absolute
+                 * If device is mode Relative
                  *      swap = (event - device)
                  *      dev = event
                  *      event = delta
-                 * If device is mode Relative, and event is Relative
-                 *      dev += event
                  *
                  * XXX: axis clipping for relative events?
                  */
 		axisvals = v->axisVal;
-                if (xV->sequenceNumber & Absolute) {
-                    int delta;
-                    if (v->mode == Relative) /* device reports relative */
-                    {
-                        change = TRUE;
-                        xV->sequenceNumber &= ~Absolute;
-                    }
-
-                    switch (xV->num_valuators) {
-                        case 6:
-                            if (change) delta = xV->valuator5 - *(axisvals + first + 5);
-                            *(axisvals + first + 5) = xV->valuator5;
-                            if (change) xV->valuator5 = delta;
-                        case 5:
-                            if (change) delta = xV->valuator4 - *(axisvals + first + 4);
-                            *(axisvals + first + 4) = xV->valuator4;
-                            if (change) xV->valuator4 = delta;
-                        case 4:
-                            if (change) delta = xV->valuator3 - *(axisvals + first + 3);
-                            *(axisvals + first + 3) = xV->valuator3;
-                            if (change) xV->valuator3 = delta;
-                        case 3:
-                            if (change) delta = xV->valuator2 - *(axisvals + first + 2);
-                            *(axisvals + first + 2) = xV->valuator2;
-                            if (change) xV->valuator2 = delta;
-                        case 2:
-                            if (change) delta = xV->valuator1 - *(axisvals + first + 1);
-                            *(axisvals + first + 1) = xV->valuator1;
-                            if (change) xV->valuator1 = delta;
-                        case 1:
-                            if (change) delta = xV->valuator0 - *(axisvals + first);
-                            *(axisvals + first) = xV->valuator0;
-                            if (change) xV->valuator0 = delta;
-                        case 0:
-                        default:
-                            break;
-                    }
-		} else { /* event is relative */
-                    if (v->mode == Absolute) /* device reports absolute */
-                    {
-                        change = TRUE;
-                        xV->sequenceNumber |= Absolute;
-                    }
-
-                    switch (xV->num_valuators) {
-                        case 6:
-                            *(axisvals + first + 5) += xV->valuator5;
-                            if (change) xV->valuator5 = *(axisvals + first + 5);
-                        case 5:
-                            *(axisvals + first + 4) += xV->valuator4;
-                            if (change) xV->valuator4 = *(axisvals + first + 4);
-                        case 4:
-                            *(axisvals + first + 3) += xV->valuator3;
-                            if (change) xV->valuator3 = *(axisvals + first + 3);
-                        case 3:
-                            *(axisvals + first + 2) += xV->valuator2;
-                            if (change) xV->valuator2 = *(axisvals + first + 2);
-                        case 2:
-                            *(axisvals + first + 1) += xV->valuator1;
-                            if (change) xV->valuator1 = *(axisvals + first + 1);
-                        case 1:
-                            *(axisvals + first) += xV->valuator0;
-                            if (change) xV->valuator0 = *(axisvals + first);
-                        case 0:
-                        default:
-                            break;
-                    }
+                int delta;
+                if (v->mode == Relative) /* device reports relative */
+                    change = TRUE;
+
+                switch (xV->num_valuators) {
+                    case 6:
+                        if (change) delta = xV->valuator5 - *(axisvals + first + 5);
+                        *(axisvals + first + 5) = xV->valuator5;
+                        if (change) xV->valuator5 = delta;
+                    case 5:
+                        if (change) delta = xV->valuator4 - *(axisvals + first + 4);
+                        *(axisvals + first + 4) = xV->valuator4;
+                        if (change) xV->valuator4 = delta;
+                    case 4:
+                        if (change) delta = xV->valuator3 - *(axisvals + first + 3);
+                        *(axisvals + first + 3) = xV->valuator3;
+                        if (change) xV->valuator3 = delta;
+                    case 3:
+                        if (change) delta = xV->valuator2 - *(axisvals + first + 2);
+                        *(axisvals + first + 2) = xV->valuator2;
+                        if (change) xV->valuator2 = delta;
+                    case 2:
+                        if (change) delta = xV->valuator1 - *(axisvals + first + 1);
+                        *(axisvals + first + 1) = xV->valuator1;
+                        if (change) xV->valuator1 = delta;
+                    case 1:
+                        if (change) delta = xV->valuator0 - *(axisvals + first);
+                        *(axisvals + first) = xV->valuator0;
+                        if (change) xV->valuator0 = delta;
+                    case 0:
+                    default:
+                        break;
                 }
 	    }
 	}
commit 7eec1c23a34591064ea64499acb24f22ada08dfa
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 23 13:23:02 2008 +0930

    dix: don't allow relative data in deviceValuators.
    
    In GPE, we don't care about the device mode. Let's put the absolute values
    into the deviceValuator event and worry about relative valuators on the other
    side of the EQ.

diff --git a/dix/getevents.c b/dix/getevents.c
index 48aa0e8..23ec6c4 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -833,23 +833,10 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
-
-    /* update the valuators based on the mode of the InputDevice */
-    if(pDev->valuator->mode == Absolute) {
-        /* Update the valuators with the true value sent to the client*/
-        if(v0) *v0 = x;
-        if(v1) *v1 = y;
-        /*TODO Ensure that valuator 2 and onward also are absolute */
-    } else {/* Relative mode */
-        /* If driver reported in absolute, calculate the relative valuator
-         * values as a delta from the old absolute values of the valuator
-         * values. If relative report, keep it as-is.*/
-        if (flags & POINTER_ABSOLUTE) {
-            int i;
-            for (i = 0; i < num_valuators && i < pDev->last.numValuators; i++)
-                valuators[i] = valuators[i] - pDev->last.valuators[i + first_valuator];
-        }
-    }
+    /* Update the valuators with the true value sent to the client*/
+    if(v0) *v0 = x;
+    if(v1) *v1 = y;
+    /* TODO: other axes */
 
     /* dropy x/y (device coordinates) back into valuators for next event */
     pDev->last.valuators[0] = x;
commit 75551a2ef949c2cfb53fdc4b97f3964a5e2f45f5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 23 12:55:50 2008 +0930

    Revert "dix: Correct values in the device axisVal are calculated in GPE"
    
    We can't rely on GPE to update device->valuators->axisVal. If a SIGIO occurs
    during event processing this may have incoherent results.
    
    This reverts commit f6645ddbf754c80e9a8b1672519534a887622270.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index da6cf8d..42b77c1 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -818,8 +818,107 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
         bit = 1 << (key & 7);
     }
 
-    /* Device axis are calculated in GetPointerEvents and need
-     * no more processing */
+    /* Update device axis */
+    for (i = 1; i < count; i++) {
+	if ((++xV)->type == DeviceValuator) {
+	    int *axisvals;
+            int first = xV->first_valuator;
+            BOOL change = FALSE;
+
+	    if (xV->num_valuators &&
+                (!v || (xV->num_valuators &&
+                      (first + xV->num_valuators > v->numAxes))))
+		FatalError("Bad valuators reported for device %s\n",
+			   device->name);
+	    if (v && v->axisVal) {
+                /* The device always stores values in absolute. Only the
+                 * delivery mode changes.
+                 * If device is mode Absolute, and event is Relative
+                 *     dev += event
+                 *     event = dev
+                 * If device is mode Absolute, and event is Absolute
+                 *     dev = event
+                 * If device is mode Relative, and event is Absolute
+                 *      swap = (event - device)
+                 *      dev = event
+                 *      event = delta
+                 * If device is mode Relative, and event is Relative
+                 *      dev += event
+                 *
+                 * XXX: axis clipping for relative events?
+                 */
+		axisvals = v->axisVal;
+                if (xV->sequenceNumber & Absolute) {
+                    int delta;
+                    if (v->mode == Relative) /* device reports relative */
+                    {
+                        change = TRUE;
+                        xV->sequenceNumber &= ~Absolute;
+                    }
+
+                    switch (xV->num_valuators) {
+                        case 6:
+                            if (change) delta = xV->valuator5 - *(axisvals + first + 5);
+                            *(axisvals + first + 5) = xV->valuator5;
+                            if (change) xV->valuator5 = delta;
+                        case 5:
+                            if (change) delta = xV->valuator4 - *(axisvals + first + 4);
+                            *(axisvals + first + 4) = xV->valuator4;
+                            if (change) xV->valuator4 = delta;
+                        case 4:
+                            if (change) delta = xV->valuator3 - *(axisvals + first + 3);
+                            *(axisvals + first + 3) = xV->valuator3;
+                            if (change) xV->valuator3 = delta;
+                        case 3:
+                            if (change) delta = xV->valuator2 - *(axisvals + first + 2);
+                            *(axisvals + first + 2) = xV->valuator2;
+                            if (change) xV->valuator2 = delta;
+                        case 2:
+                            if (change) delta = xV->valuator1 - *(axisvals + first + 1);
+                            *(axisvals + first + 1) = xV->valuator1;
+                            if (change) xV->valuator1 = delta;
+                        case 1:
+                            if (change) delta = xV->valuator0 - *(axisvals + first);
+                            *(axisvals + first) = xV->valuator0;
+                            if (change) xV->valuator0 = delta;
+                        case 0:
+                        default:
+                            break;
+                    }
+		} else { /* event is relative */
+                    if (v->mode == Absolute) /* device reports absolute */
+                    {
+                        change = TRUE;
+                        xV->sequenceNumber |= Absolute;
+                    }
+
+                    switch (xV->num_valuators) {
+                        case 6:
+                            *(axisvals + first + 5) += xV->valuator5;
+                            if (change) xV->valuator5 = *(axisvals + first + 5);
+                        case 5:
+                            *(axisvals + first + 4) += xV->valuator4;
+                            if (change) xV->valuator4 = *(axisvals + first + 4);
+                        case 4:
+                            *(axisvals + first + 3) += xV->valuator3;
+                            if (change) xV->valuator3 = *(axisvals + first + 3);
+                        case 3:
+                            *(axisvals + first + 2) += xV->valuator2;
+                            if (change) xV->valuator2 = *(axisvals + first + 2);
+                        case 2:
+                            *(axisvals + first + 1) += xV->valuator1;
+                            if (change) xV->valuator1 = *(axisvals + first + 1);
+                        case 1:
+                            *(axisvals + first) += xV->valuator0;
+                            if (change) xV->valuator0 = *(axisvals + first);
+                        case 0:
+                        default:
+                            break;
+                    }
+                }
+	    }
+	}
+    }
 
     if (xE->u.u.type == DeviceKeyPress) {
         if (!k)
commit fe59b1a62b2c7f467d20132db4913317bbf308eb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 23 12:51:52 2008 +0930

    dix: more device scaling insanity.
    
    Assuming master->last.valuators is in screen coords, SD's are always in device
    coordinates.
    
    1. If an event comes in, scale masters->last to the device, drop into device's
    last->valuators.
    2. Apply motion from the actual event
    3. Scale back to screen coords, check if we may need to cross screens
    4. Drop screen coords into master->last
    5. Rescale to device coords, drop into deviceValuator event and SD->last
    6. Drop screen coords into ev->root_x/y
    
    Whoopee...

diff --git a/dix/getevents.c b/dix/getevents.c
index 300dae5..48aa0e8 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -183,24 +183,25 @@ rescaleValuatorAxis(int coord, AxisInfoPtr from, AxisInfoPtr to,
  * Update all coordinates when changing to a different SD
  * to ensure that relative reporting will work as expected
  * without loss of precision.
+ *
+ * pDev->last.valuators will be in absolute device coordinates after this
+ * function.
  */
 static void
 updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
 {
     ScreenPtr scr = miPointerGetScreen(pDev);
 
-    /* last.valuators[0]/[1] is in screen coords and the actual position
-     * of the pointer */
+    /* master->last.valuators[0]/[1] is in screen coords and the actual
+     * position of the pointer */
     pDev->last.valuators[0] = master->last.valuators[0];
     pDev->last.valuators[1] = master->last.valuators[1];
-    /* the valuator axis is in device coords and holds the
-     * position of the pointer, but in device coords. */
+
+    /* scale back to device coordinates */
     if(pDev->valuator->numAxes > 0)
-        pDev->valuator->axisVal[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL,
-                                            pDev->valuator->axes + 0, scr->width);
+        pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL, pDev->valuator->axes + 0, scr->width);
     if(pDev->valuator->numAxes > 1)
-        pDev->valuator->axisVal[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
-                                            pDev->valuator->axes + 1, scr->height);
+        pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL, pDev->valuator->axes + 1, scr->height);
     /*TODO calculate the other axis as well based on info from the old slave-device */
 }
 
@@ -709,8 +710,9 @@ FreeEventList(EventListPtr list, int num_events)
  *
  * In the generated events rootX/Y will be in absolute screen coords and
  * the valuator information in the absolute or relative device coords.
- * last.valuators[0]/[1] of the device is always in absolute screen coords
- * while the device valuator struct contain the absolute device coords.
+ *
+ * last.valuators[x] of the device is always in absolute device coords.
+ * last.valuators[x] of the master device is in absolute screen coords.
  */
 _X_EXPORT int
 GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
@@ -720,7 +722,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     CARD32 ms;
     deviceKeyButtonPointer *kbp = NULL;
     DeviceIntPtr master;
-    int x, y, cx, cy;
+    int x, y, /* switches between device and screen coords */
+        cx, cy; /* only screen coordinates */
     ScreenPtr scr = miPointerGetScreen(pDev);
     int *v0 = NULL, *v1 = NULL;
 
@@ -769,8 +772,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     /* Set x and y based on whether this is absolute or relative, and
      * accelerate if we need to. */
-    x = pDev->valuator->axisVal[0];
-    y = pDev->valuator->axisVal[1];
+    x = pDev->last.valuators[0];
+    y = pDev->last.valuators[1];
     if (flags & POINTER_ABSOLUTE) {
         if(v0) x = *v0;
         if(v1) y = *v1;
@@ -811,20 +814,25 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
      * so we don't set this for both the device and core.*/
     miPointerSetPosition(pDev, &pDev->last.valuators[0], &pDev->last.valuators[1], ms);
 
-    scr = miPointerGetScreen(pDev);
+    if (master) {
+        master->last.valuators[0] = pDev->last.valuators[0];
+        master->last.valuators[1] = pDev->last.valuators[1];
+    }
+
     if(cx != pDev->last.valuators[0])
-        x = rescaleValuatorAxis(pDev->last.valuators[0], NULL,
-                                pDev->valuator->axes + 0, scr->width);
+        cx = pDev->last.valuators[0];
     if(cy != pDev->last.valuators[1])
-        y = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
-                                pDev->valuator->axes + 1, scr->height);
+        cy = pDev->last.valuators[1];
+
+    /* scale x/y back to device coordinates */
+    scr = miPointerGetScreen(pDev);
+    x = rescaleValuatorAxis(pDev->last.valuators[0], NULL,
+                        pDev->valuator->axes + 0, scr->width);
+    y = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
+                        pDev->valuator->axes + 1, scr->height);
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
-    if (master) {
-        master->last.valuators[0] = pDev->last.valuators[0];
-        master->last.valuators[1] = pDev->last.valuators[1];
-    }
 
     /* update the valuators based on the mode of the InputDevice */
     if(pDev->valuator->mode == Absolute) {
@@ -838,14 +846,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
          * values. If relative report, keep it as-is.*/
         if (flags & POINTER_ABSOLUTE) {
             int i;
-            for (i = 0; i < num_valuators; i++)
-                valuators[i] = valuators[i] - pDev->valuator->axisVal[i + first_valuator];
+            for (i = 0; i < num_valuators && i < pDev->last.numValuators; i++)
+                valuators[i] = valuators[i] - pDev->last.valuators[i + first_valuator];
         }
     }
-    /* Save the last calculated device axis value in the device
-     * valuator for next event */
-    pDev->valuator->axisVal[0] = x;
-    pDev->valuator->axisVal[1] = y;
+
+    /* dropy x/y (device coordinates) back into valuators for next event */
+    pDev->last.valuators[0] = x;
+    pDev->last.valuators[1] = y;
 
     kbp = (deviceKeyButtonPointer *) events->event;
     kbp->time = ms;
@@ -862,8 +870,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         kbp->detail = pDev->button->map[buttons];
     }
 
-    kbp->root_x = pDev->last.valuators[0];
-    kbp->root_y = pDev->last.valuators[1];
+    kbp->root_x = cx; /* root_x/y always in screen coords */
+    kbp->root_y = cy;
 
     events++;
     if (num_valuators) {
diff --git a/include/inputstr.h b/include/inputstr.h
index d1cc448..d26eb13 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -422,6 +422,8 @@ typedef struct _DeviceIntRec {
     } u;
 
     /* last valuator values recorded, not posted to client;
+     * for slave devices, valuators is in device coordinates
+     * for master devices, valuators is in screen coordinates
      * see dix/getevents.c */
     struct {
         int             valuators[MAX_VALUATORS];
commit 6c9e9f8a40e20fb1761440acd2755f5fd31f4d44
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 23 11:51:53 2008 +0930

    input: instead of lastx/y, use a last.valuators[] array on the device.
    
    During GetPointerEvents (and others), we need to access the last coordinates
    posted for this device from the driver (not as posted to the client!). Lastx/y
    is ok if we only have two axes, but with more complex devices we also need to
    transition between all other axes.
    
    ABI break, recompile your input drivers.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index a42faa7..58e20ef 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -470,16 +470,16 @@ ProcXTestFakeInput(client)
                      ev->u.keyButtonPointer.rootX,
                      ev->u.keyButtonPointer.rootY, FALSE);
             }
-            dev->lastx = ev->u.keyButtonPointer.rootX;
-            dev->lasty = ev->u.keyButtonPointer.rootY;
+            dev->last.valuators[0] = ev->u.keyButtonPointer.rootX;
+            dev->last.valuators[1] = ev->u.keyButtonPointer.rootY;
             break;
         case ButtonPress:
         case ButtonRelease:
             if (!extension)
                 dev = PickPointer(client);
 
-            ev->u.keyButtonPointer.rootX = dev->lastx;
-            ev->u.keyButtonPointer.rootY = dev->lasty;
+            ev->u.keyButtonPointer.rootX = dev->last.valuators[0];
+            ev->u.keyButtonPointer.rootY = dev->last.valuators[1];
             if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
             {
                 client->errorValue = ev->u.u.detail;
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index 3720441..502cab4 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -166,8 +166,8 @@ ProcXWarpDevicePointer(ClientPtr client)
     }
 
     /* if we don't update the device, we get a jump next time it moves */
-    pDev->lastx = x;
-    pDev->lasty = x;
+    pDev->last.valuators[0] = x;
+    pDev->last.valuators[1] = x;
     miPointerUpdateSprite(pDev);
 
     /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
diff --git a/dix/devices.c b/dix/devices.c
index 1b71a42..2521186 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -168,6 +168,10 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
     dev->spriteInfo->sprite = NULL;
     dev->spriteInfo->spriteOwner = FALSE;
 
+    /* last valuators */
+    memset(dev->last.valuators, 0, sizeof(dev->last.valuators));
+    dev->last.numValuators = 0;
+
     /*  security creation/labeling check
      */
     if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) {
@@ -491,9 +495,9 @@ CorePointerProc(DeviceIntPtr pDev, int what)
                                 GetMotionHistory, (PtrCtrlProcPtr)NoopDDA,
                                 GetMotionHistorySize(), 2);
         pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
-        pDev->lastx = pDev->valuator->axisVal[0];
+        pDev->last.valuators[0] = pDev->valuator->axisVal[0];
         pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
-        pDev->lasty = pDev->valuator->axisVal[1];
+        pDev->last.valuators[1] = pDev->valuator->axisVal[1];
         break;
 
     case DEVICE_CLOSE:
@@ -1192,6 +1196,8 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
                                0, 0, 0);
 	valc->axisVal[i]=0;
     }
+
+    dev->last.numValuators = numAxes;
     return TRUE;
 }
 
diff --git a/dix/getevents.c b/dix/getevents.c
index fea5285..300dae5 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -189,17 +189,17 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
 {
     ScreenPtr scr = miPointerGetScreen(pDev);
 
-    /* lastx/y is in screen coords and the actual position
+    /* last.valuators[0]/[1] is in screen coords and the actual position
      * of the pointer */
-    pDev->lastx = master->lastx;
-    pDev->lasty = master->lasty;
+    pDev->last.valuators[0] = master->last.valuators[0];
+    pDev->last.valuators[1] = master->last.valuators[1];
     /* the valuator axis is in device coords and holds the
      * position of the pointer, but in device coords. */
     if(pDev->valuator->numAxes > 0)
-        pDev->valuator->axisVal[0] = rescaleValuatorAxis(pDev->lastx, NULL,
+        pDev->valuator->axisVal[0] = rescaleValuatorAxis(pDev->last.valuators[0], NULL,
                                             pDev->valuator->axes + 0, scr->width);
     if(pDev->valuator->numAxes > 1)
-        pDev->valuator->axisVal[1] = rescaleValuatorAxis(pDev->lasty, NULL,
+        pDev->valuator->axisVal[1] = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
                                             pDev->valuator->axes + 1, scr->height);
     /*TODO calculate the other axis as well based on info from the old slave-device */
 }
@@ -542,8 +542,8 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
 
         if (master->valuator && pDev->valuator)
         {
-            pDev->lastx = master->lastx;
-            pDev->lasty = master->lasty;
+            pDev->last.valuators[0] = master->last.valuators[0];
+            pDev->last.valuators[1] = master->last.valuators[1];
         }
         master->u.lastSlave = pDev;
         numEvents++;
@@ -709,8 +709,8 @@ FreeEventList(EventListPtr list, int num_events)
  *
  * In the generated events rootX/Y will be in absolute screen coords and
  * the valuator information in the absolute or relative device coords.
- * lastx/y of the device is always in absolute screen coords while the
- * device valuator struct contain the absolute device coords.
+ * last.valuators[0]/[1] of the device is always in absolute screen coords
+ * while the device valuator struct contain the absolute device coords.
  */
 _X_EXPORT int
 GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
@@ -801,29 +801,29 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     }
 
     /* scale x&y to screen */
-    pDev->lastx = cx = rescaleValuatorAxis(x, pDev->valuator->axes + 0,
+    pDev->last.valuators[0] = cx = rescaleValuatorAxis(x, pDev->valuator->axes + 0,
                                            NULL, scr->width);
-    pDev->lasty = cy = rescaleValuatorAxis(y, pDev->valuator->axes + 1,
+    pDev->last.valuators[1] = cy = rescaleValuatorAxis(y, pDev->valuator->axes + 1,
                                            NULL, scr->height);
 
     /* This takes care of crossing screens for us, as well as clipping
      * to the current screen.  Right now, we only have one history buffer,
      * so we don't set this for both the device and core.*/
-    miPointerSetPosition(pDev, &pDev->lastx, &pDev->lasty, ms);
+    miPointerSetPosition(pDev, &pDev->last.valuators[0], &pDev->last.valuators[1], ms);
 
     scr = miPointerGetScreen(pDev);
-    if(cx != pDev->lastx)
-        x = rescaleValuatorAxis(pDev->lastx, NULL,
+    if(cx != pDev->last.valuators[0])
+        x = rescaleValuatorAxis(pDev->last.valuators[0], NULL,
                                 pDev->valuator->axes + 0, scr->width);
-    if(cy != pDev->lasty)
-        y = rescaleValuatorAxis(pDev->lasty, NULL,
+    if(cy != pDev->last.valuators[1])
+        y = rescaleValuatorAxis(pDev->last.valuators[1], NULL,
                                 pDev->valuator->axes + 1, scr->height);
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
     if (master) {
-        master->lastx = pDev->lastx;
-        master->lasty = pDev->lasty;
+        master->last.valuators[0] = pDev->last.valuators[0];
+        master->last.valuators[1] = pDev->last.valuators[1];
     }
 
     /* update the valuators based on the mode of the InputDevice */
@@ -862,13 +862,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         kbp->detail = pDev->button->map[buttons];
     }
 
-    kbp->root_x = pDev->lastx;
-    kbp->root_y = pDev->lasty;
+    kbp->root_x = pDev->last.valuators[0];
+    kbp->root_y = pDev->last.valuators[1];
 
     events++;
     if (num_valuators) {
         kbp->deviceid |= MORE_EVENTS;
-        clipValuators(pDev, first_valuator, num_valuators, valuators);
+        if (flags & POINTER_ABSOLUTE)
+            clipValuators(pDev, first_valuator, num_valuators, valuators);
         events = getValuatorEvents(events, pDev, first_valuator,
                                    num_valuators, valuators);
     }
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 9961624..2ae4630 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -505,8 +505,6 @@ DeleteInputDeviceRequest(DeviceIntPtr pDev)
  * convenient functions to post events
  */
 
-#define MAX_VALUATORS 36 /* XXX from comment in dix/getevents.c */
-
 _X_EXPORT void
 xf86PostMotionEvent(DeviceIntPtr	device,
                     int			is_absolute,
@@ -566,14 +564,14 @@ xf86PostMotionEventP(DeviceIntPtr	device,
             {
                 dx = valuators[0];
                 if (is_absolute)
-                    dx -= device->lastx;
+                    dx -= device->last.valuators[0];
             }
 
             if (first_valuator == 1 || num_valuators >= 2)
             {
                 dy = valuators[1 - first_valuator];
                 if (is_absolute)
-                    dy -= device->lasty;
+                    dy -= device->last.valuators[1];
             }
 
             if (DGAStealMotionEvent(device, index, dx, dy))
@@ -833,11 +831,11 @@ xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum)
 {
     if (axnum == 0) {
 	dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
-        dev->lastx = dev->valuator->axisVal[0];
+        dev->last.valuators[0] = dev->valuator->axisVal[0];
     }
     else if (axnum == 1) {
 	dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
-        dev->lasty = dev->valuator->axisVal[1];
+        dev->last.valuators[1] = dev->valuator->axisVal[1];
     }
 }
 
diff --git a/include/input.h b/include/input.h
index 13902d7..9b92ea3 100644
--- a/include/input.h
+++ b/include/input.h
@@ -63,6 +63,8 @@ SOFTWARE.
 #define POINTER_ABSOLUTE (1 << 2)
 #define POINTER_ACCELERATE (1 << 3)
 
+#define MAX_VALUATORS 36 /* XXX from comment in dix/getevents.c */
+
 #define NO_AXIS_LIMITS -1
 
 #define MAP_LENGTH	256
diff --git a/include/inputstr.h b/include/inputstr.h
index d117e55..d1cc448 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -420,8 +420,13 @@ typedef struct _DeviceIntRec {
     DeviceIntPtr        master;       /* master device */
     DeviceIntPtr        lastSlave;    /* last slave device used */
     } u;
-    int                 lastx, lasty; /* last event recorded, not posted to
-                                       * client; see dix/devices.c */
+
+    /* last valuator values recorded, not posted to client;
+     * see dix/getevents.c */
+    struct {
+        int             valuators[MAX_VALUATORS];
+        int             numValuators;
+    } last;
 } DeviceIntRec;
 
 typedef struct {
commit fb146cbb0f28e4e480e5d16d61476ac46b5d00ce
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 23 12:00:13 2008 +0930

    dix: coreEvents doesn't have meaning here, use master instead.
    
    We mustn't clip x/y if we are attached, otherwise we can't change screens.

diff --git a/dix/getevents.c b/dix/getevents.c
index 0caa764..fea5285 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -790,9 +790,10 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         if(v1) y += *v1;
         /*TODO: Update the rest of the valuators */
 
-        /* if not core -> clip both x and y to the defined limits (usually
-         * co-ord space limit). */
-        if(!pDev->coreEvents) {
+        /* if attached, clip both x and y to the defined limits (usually
+         * co-ord space limit). If it is attached, we need x/y to go over the
+         * limits to be able to change screens. */
+        if(master) {
             clipAxis(pDev, 0, &x);
             clipAxis(pDev, 1, &y);
         }
commit fc1cc0adcb91fdfa4c547bf379a85f9558c959ff
Author: Magnus Vigerlöf <Magnus.Vigerlof at ipbo.se>
Date:   Fri May 23 00:33:18 2008 +0200

    dix: Cleanup of GetPointerEvents
    
    Changed all the checks for x&y valuator so the more complex
    calculation is only made once.
    Added TODOs for valuator/axis 2 and above for future correct
    handling of relative reporting of these.
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/dix/getevents.c b/dix/getevents.c
index 26add12..0caa764 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -159,20 +159,22 @@ CreateClassesChangedEvent(EventList* event,
  * Rescale the coord between the two axis ranges.
  */
 static int
-rescaleValuatorAxis(int coord, int fmin, int fmax,
-                    int tmin, int tmax, int smax)
+rescaleValuatorAxis(int coord, AxisInfoPtr from, AxisInfoPtr to,
+                    int defmax)
 {
-    if(fmin >= fmax) {
-        fmin = 0;
-        fmax = smax;
+    int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax;
+
+    if(from && from->min_value < from->max_value) {
+        fmin = from->min_value;
+        fmax = from->max_value;
     }
-    if(tmin >= tmax) {
-        tmin = 0;
-        tmax = smax;
+    if(to && to->min_value < to->max_value) {
+        tmin = to->min_value;
+        tmax = to->max_value;
     }
+
     if(fmin == tmin && fmax == tmax)
         return coord;
-
     return (int)(((float)(coord - fmin)) * (tmax - tmin + 1) /
                  (fmax - fmin + 1)) + tmin;
 }
@@ -194,13 +196,11 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
     /* the valuator axis is in device coords and holds the
      * position of the pointer, but in device coords. */
     if(pDev->valuator->numAxes > 0)
-        pDev->valuator->axisVal[0] = rescaleValuatorAxis(pDev->lastx, 0, scr->width,
-                                            pDev->valuator->axes[0].min_value,
-                                            pDev->valuator->axes[0].max_value, scr->width);
+        pDev->valuator->axisVal[0] = rescaleValuatorAxis(pDev->lastx, NULL,
+                                            pDev->valuator->axes + 0, scr->width);
     if(pDev->valuator->numAxes > 1)
-        pDev->valuator->axisVal[1] = rescaleValuatorAxis(pDev->lasty, 0, scr->height,
-                                            pDev->valuator->axes[1].min_value,
-                                            pDev->valuator->axes[1].max_value, scr->height);
+        pDev->valuator->axisVal[1] = rescaleValuatorAxis(pDev->lasty, NULL,
+                                            pDev->valuator->axes + 1, scr->height);
     /*TODO calculate the other axis as well based on info from the old slave-device */
 }
 
@@ -707,17 +707,22 @@ FreeEventList(EventListPtr list, int num_events)
  * The DDX is responsible for allocating the event structure in the first
  * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
  *
+ * In the generated events rootX/Y will be in absolute screen coords and
+ * the valuator information in the absolute or relative device coords.
+ * lastx/y of the device is always in absolute screen coords while the
+ * device valuator struct contain the absolute device coords.
  */
 _X_EXPORT int
 GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
                  int flags, int first_valuator, int num_valuators,
                  int *valuators) {
     int num_events = 1;
-    CARD32 ms = 0;
+    CARD32 ms;
     deviceKeyButtonPointer *kbp = NULL;
     DeviceIntPtr master;
     int x, y, cx, cy;
     ScreenPtr scr = miPointerGetScreen(pDev);
+    int *v0 = NULL, *v1 = NULL;
 
     /* Sanity checks. */
     if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
@@ -756,29 +761,34 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         events++;
     }
 
+    /* Fetch pointers into the valuator array for more easy to read code */
+    if (num_valuators >= 1 && first_valuator == 0)
+        v0 = valuators + 0;
+    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
+        v1 = valuators + 1 - first_valuator;
+
     /* Set x and y based on whether this is absolute or relative, and
      * accelerate if we need to. */
     x = pDev->valuator->axisVal[0];
     y = pDev->valuator->axisVal[1];
     if (flags & POINTER_ABSOLUTE) {
-        if (num_valuators >= 1 && first_valuator == 0)
-            x = valuators[0];
-        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-            y = valuators[1 - first_valuator];
+        if(v0) x = *v0;
+        if(v1) y = *v1;
+        /*TODO: Update the rest of the valuators */
 
         /* Clip both x and y to the defined limits (usually co-ord space limit). */
         clipAxis(pDev, 0, &x);
         clipAxis(pDev, 1, &y);
+        /*TODO: Clip the rest of the valuators */
     }
     else {
         if (flags & POINTER_ACCELERATE)
             acceleratePointer(pDev, first_valuator, num_valuators,
                               valuators);
 
-        if (first_valuator == 0 && num_valuators >= 1)
-            x += valuators[0];
-        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-            y += valuators[1 - first_valuator];
+        if(v0) x += *v0;
+        if(v1) y += *v1;
+        /*TODO: Update the rest of the valuators */
 
         /* if not core -> clip both x and y to the defined limits (usually
          * co-ord space limit). */
@@ -786,15 +796,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
             clipAxis(pDev, 0, &x);
             clipAxis(pDev, 1, &y);
         }
+        /*TODO: Clip the rest of the valuators (Yes, here. Only x&y get special treatment) */
     }
 
     /* scale x&y to screen */
-    pDev->lastx = cx = rescaleValuatorAxis(x, pDev->valuator->axes[0].min_value,
-                                           pDev->valuator->axes[0].max_value,
-                                           0, scr->width, scr->width);
-    pDev->lasty = cy = rescaleValuatorAxis(y, pDev->valuator->axes[1].min_value,
-                                           pDev->valuator->axes[1].max_value,
-                                           0, scr->height, scr->height);
+    pDev->lastx = cx = rescaleValuatorAxis(x, pDev->valuator->axes + 0,
+                                           NULL, scr->width);
+    pDev->lasty = cy = rescaleValuatorAxis(y, pDev->valuator->axes + 1,
+                                           NULL, scr->height);
 
     /* This takes care of crossing screens for us, as well as clipping
      * to the current screen.  Right now, we only have one history buffer,
@@ -803,15 +812,11 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     scr = miPointerGetScreen(pDev);
     if(cx != pDev->lastx)
-        x = rescaleValuatorAxis(pDev->lastx, 0, scr->width,
-                                pDev->valuator->axes[0].min_value,
-                                pDev->valuator->axes[0].max_value,
-                                scr->width);
+        x = rescaleValuatorAxis(pDev->lastx, NULL,
+                                pDev->valuator->axes + 0, scr->width);
     if(cy != pDev->lasty)
-        y = rescaleValuatorAxis(pDev->lasty, 0, scr->height,
-                                pDev->valuator->axes[1].min_value,
-                                pDev->valuator->axes[1].max_value,
-                                scr->height);
+        y = rescaleValuatorAxis(pDev->lasty, NULL,
+                                pDev->valuator->axes + 1, scr->height);
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
@@ -823,19 +828,17 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     /* update the valuators based on the mode of the InputDevice */
     if(pDev->valuator->mode == Absolute) {
         /* Update the valuators with the true value sent to the client*/
-        if (first_valuator == 0 && num_valuators >= 1)
-            valuators[0] = x;
-        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-            valuators[1] = y;
+        if(v0) *v0 = x;
+        if(v1) *v1 = y;
+        /*TODO Ensure that valuator 2 and onward also are absolute */
     } else {/* Relative mode */
         /* If driver reported in absolute, calculate the relative valuator
          * values as a delta from the old absolute values of the valuator
          * values. If relative report, keep it as-is.*/
         if (flags & POINTER_ABSOLUTE) {
             int i;
-            for (i = first_valuator; i < num_valuators; i++)
-                valuators[i] = valuators[i] - pDev->valuator->axisVal[i];
-
+            for (i = 0; i < num_valuators; i++)
+                valuators[i] = valuators[i] - pDev->valuator->axisVal[i + first_valuator];
         }
     }
     /* Save the last calculated device axis value in the device
commit a0241d5380bb5d8b10865f8ea81a9a011de4aaf1
Author: Magnus Vigerlöf <Magnus.Vigerlof at ipbo.se>
Date:   Fri May 23 00:36:11 2008 +0200

    dix: Correct clipAxis so it can handle devices with value ranges properly
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/dix/getevents.c b/dix/getevents.c
index fafb632..26add12 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -406,22 +406,15 @@ static void
 clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
 {
     AxisInfoPtr axis = pDev->valuator->axes + axisNum;
-
     /* InitValuatoraAxisStruct ensures that (min < max). */
 
-
-    /* FIXME: drivers need to be updated, evdev e.g. inits axes as min = 0 and
-     * max = -1. Leave this extra check until the drivers have been updated.
-     */
-    if (axis->max_value < axis->min_value)
+    /* If a value range is defined, clip. If not, do nothing */
+    if (axis->max_value <= axis->min_value)
         return;
 
-    if (axis->min_value != NO_AXIS_LIMITS &&
-            *val < axis->min_value)
+    if (*val < axis->min_value)
         *val = axis->min_value;
-
-    if (axis->max_value != NO_AXIS_LIMITS &&
-            *val > axis->max_value)
+    if (*val > axis->max_value)
         *val = axis->max_value;
 }
 
commit f6645ddbf754c80e9a8b1672519534a887622270
Author: Magnus Vigerlöf <Magnus.Vigerlof at ipbo.se>
Date:   Thu May 22 23:33:45 2008 +0200

    dix: Correct values in the device axisVal are calculated in GPE
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 42b77c1..da6cf8d 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -818,107 +818,8 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
         bit = 1 << (key & 7);
     }
 
-    /* Update device axis */
-    for (i = 1; i < count; i++) {
-	if ((++xV)->type == DeviceValuator) {
-	    int *axisvals;
-            int first = xV->first_valuator;
-            BOOL change = FALSE;
-
-	    if (xV->num_valuators &&
-                (!v || (xV->num_valuators &&
-                      (first + xV->num_valuators > v->numAxes))))
-		FatalError("Bad valuators reported for device %s\n",
-			   device->name);
-	    if (v && v->axisVal) {
-                /* The device always stores values in absolute. Only the
-                 * delivery mode changes.
-                 * If device is mode Absolute, and event is Relative
-                 *     dev += event
-                 *     event = dev
-                 * If device is mode Absolute, and event is Absolute
-                 *     dev = event
-                 * If device is mode Relative, and event is Absolute
-                 *      swap = (event - device)
-                 *      dev = event
-                 *      event = delta
-                 * If device is mode Relative, and event is Relative
-                 *      dev += event
-                 *
-                 * XXX: axis clipping for relative events?
-                 */
-		axisvals = v->axisVal;
-                if (xV->sequenceNumber & Absolute) {
-                    int delta;
-                    if (v->mode == Relative) /* device reports relative */
-                    {
-                        change = TRUE;
-                        xV->sequenceNumber &= ~Absolute;
-                    }
-
-                    switch (xV->num_valuators) {
-                        case 6:
-                            if (change) delta = xV->valuator5 - *(axisvals + first + 5);
-                            *(axisvals + first + 5) = xV->valuator5;
-                            if (change) xV->valuator5 = delta;
-                        case 5:
-                            if (change) delta = xV->valuator4 - *(axisvals + first + 4);
-                            *(axisvals + first + 4) = xV->valuator4;
-                            if (change) xV->valuator4 = delta;
-                        case 4:
-                            if (change) delta = xV->valuator3 - *(axisvals + first + 3);
-                            *(axisvals + first + 3) = xV->valuator3;
-                            if (change) xV->valuator3 = delta;
-                        case 3:
-                            if (change) delta = xV->valuator2 - *(axisvals + first + 2);
-                            *(axisvals + first + 2) = xV->valuator2;
-                            if (change) xV->valuator2 = delta;
-                        case 2:
-                            if (change) delta = xV->valuator1 - *(axisvals + first + 1);
-                            *(axisvals + first + 1) = xV->valuator1;
-                            if (change) xV->valuator1 = delta;
-                        case 1:
-                            if (change) delta = xV->valuator0 - *(axisvals + first);
-                            *(axisvals + first) = xV->valuator0;
-                            if (change) xV->valuator0 = delta;
-                        case 0:
-                        default:
-                            break;
-                    }
-		} else { /* event is relative */
-                    if (v->mode == Absolute) /* device reports absolute */
-                    {
-                        change = TRUE;
-                        xV->sequenceNumber |= Absolute;
-                    }
-
-                    switch (xV->num_valuators) {
-                        case 6:
-                            *(axisvals + first + 5) += xV->valuator5;
-                            if (change) xV->valuator5 = *(axisvals + first + 5);
-                        case 5:
-                            *(axisvals + first + 4) += xV->valuator4;
-                            if (change) xV->valuator4 = *(axisvals + first + 4);
-                        case 4:
-                            *(axisvals + first + 3) += xV->valuator3;
-                            if (change) xV->valuator3 = *(axisvals + first + 3);
-                        case 3:
-                            *(axisvals + first + 2) += xV->valuator2;
-                            if (change) xV->valuator2 = *(axisvals + first + 2);
-                        case 2:
-                            *(axisvals + first + 1) += xV->valuator1;
-                            if (change) xV->valuator1 = *(axisvals + first + 1);
-                        case 1:
-                            *(axisvals + first) += xV->valuator0;
-                            if (change) xV->valuator0 = *(axisvals + first);
-                        case 0:
-                        default:
-                            break;
-                    }
-                }
-	    }
-	}
-    }
+    /* Device axis are calculated in GetPointerEvents and need
+     * no more processing */
 
     if (xE->u.u.type == DeviceKeyPress) {
         if (!k)
commit 7f85acdf70c67c567de688439e25081be5a7d5df
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 22 23:27:15 2008 +0930

    dix: fill valuators with the correct values depending on the device mode (GPE)
    
    valuators[] is passed from the DDX. Depending on the device mode, update it
    with either absolute values or relative values. The deviceValuator event sent
    to the client will then contain the respective values.

diff --git a/dix/getevents.c b/dix/getevents.c
index 15e7f3b..fafb632 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -827,19 +827,23 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         master->lasty = pDev->lasty;
     }
 
-    /* update the contents of the valuators based on the mode of the InputDevice */
-    if(1) { /*TODO Absolute mode */
-        /* Update the valuators with the true value sent to the client
-         * (only absolute mode on the InputDevice) */
+    /* update the valuators based on the mode of the InputDevice */
+    if(pDev->valuator->mode == Absolute) {
+        /* Update the valuators with the true value sent to the client*/
         if (first_valuator == 0 && num_valuators >= 1)
-            pDev->valuator->axisVal[0] = x;
+            valuators[0] = x;
         if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-            pDev->valuator->axisVal[1] = y;
+            valuators[1] = y;
     } else {/* Relative mode */
         /* If driver reported in absolute, calculate the relative valuator
          * values as a delta from the old absolute values of the valuator
          * values. If relative report, keep it as-is.*/
-        /*TODO*/
+        if (flags & POINTER_ABSOLUTE) {
+            int i;
+            for (i = first_valuator; i < num_valuators; i++)
+                valuators[i] = valuators[i] - pDev->valuator->axisVal[i];
+
+        }
     }
     /* Save the last calculated device axis value in the device
      * valuator for next event */
commit 1a3f351c50cba66f71a73239318174b09fd9b63b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 22 23:25:20 2008 +0930

    dix: when floating a device, create a new cursor sprite.
    
    This is essentially necessary to allow calls to miPointerGetSprite etc. to
    work for floating slave devices.

diff --git a/dix/devices.c b/dix/devices.c
index 5606543..1b71a42 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2415,6 +2415,7 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
 int
 AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 {
+    ScreenPtr screen;
     DeviceIntPtr oldmaster;
     if (!dev || dev->isMaster)
         return BadDevice;
@@ -2428,7 +2429,11 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 
     /* free the existing sprite. */
     if (!dev->u.master && dev->spriteInfo->paired == dev)
+    {
+        screen = miPointerGetScreen(dev);
+        screen->DeviceCursorCleanup(dev, screen);
         xfree(dev->spriteInfo->sprite);
+    }
 
     oldmaster = dev->u.master;
     dev->u.master = master;
@@ -2442,10 +2447,14 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
     if (!master)
     {
         WindowPtr currentRoot = dev->spriteInfo->sprite->spriteTrace[0];
+        /* we need to init a fake sprite */
+        screen = currentRoot->drawable.pScreen;
+        screen->DeviceCursorInitialize(dev, screen);
         dev->spriteInfo->sprite = NULL;
         InitializeSprite(dev, currentRoot);
         dev->spriteInfo->spriteOwner = FALSE;
         dev->spriteInfo->paired = dev;
+
     } else
     {
         dev->spriteInfo->sprite = master->spriteInfo->sprite;
commit e0fbe404a436aef24624a3a15e8405a9ca38aadb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 22 23:24:29 2008 +0930

    mi: handle sprite even for floating slave devices.
    
    We still don't render it, but we accept all the other calls to update it's
    internal state.

diff --git a/mi/mipointer.c b/mi/mipointer.c
index e49b3df..28f3b4e 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -50,7 +50,7 @@ _X_EXPORT DevPrivateKey miPointerScreenKey = &miPointerScreenKey;
 static DevPrivateKey miPointerPrivKey = &miPointerPrivKey;
 
 #define MIPOINTER(dev) \
-    ((DevHasCursor((dev))) ? \
+    ((DevHasCursor((dev)) || (!dev->isMaster && !dev->u.master)) ? \
         (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
         (miPointerPtr)dixLookupPrivate(&(dev)->u.master->devPrivates, miPointerPrivKey))
 
@@ -193,9 +193,6 @@ miPointerDisplayCursor (pDev, pScreen, pCursor)
 {
     miPointerPtr pPointer;
     
-    if (!pDev->isMaster && !pDev->u.master)
-        return FALSE;
-
     /* return for keyboards */
     if ((pDev->isMaster && !DevHasCursor(pDev)) ||
         (!pDev->isMaster && pDev->u.master && !DevHasCursor(pDev->u.master)))
@@ -217,9 +214,6 @@ miPointerConstrainCursor (pDev, pScreen, pBox)
 {
     miPointerPtr pPointer;
 
-    if (!pDev->isMaster && !pDev->u.master)
-        return;
-    
     pPointer = MIPOINTER(pDev);
 
     pPointer->limits = *pBox;
@@ -313,13 +307,13 @@ miPointerDeviceCleanup(pDev, pScreen)
     DeviceIntPtr pDev;
     ScreenPtr pScreen;
 {
-    if (DevHasCursor(pDev))
-    {
-        SetupScreen(pScreen);
-        (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
-        xfree(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
-        dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
-    }
+    if (!pDev->isMaster && pDev->u.master)
+        return;
+
+    SetupScreen(pScreen);
+    (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
+    xfree(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
+    dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
 }
 
 
@@ -334,8 +328,6 @@ miPointerWarpCursor (pDev, pScreen, x, y)
     miPointerPtr pPointer;
     BOOL changedScreen = FALSE;
 
-    if (!pDev->isMaster && !pDev->u.master)
-        return;
     pPointer = MIPOINTER(pDev);
     SetupScreen (pScreen);
 
@@ -388,7 +380,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     int			x, y, devx, devy;
     miPointerPtr        pPointer;
 
-    if (!pDev || !pDev->coreEvents || (!pDev->isMaster && !pDev->u.master))
+    if (!pDev || !pDev->coreEvents)
         return;
 
     pPointer = MIPOINTER(pDev);
@@ -477,10 +469,7 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
 {
 	miPointerScreenPtr pScreenPriv;
 	ScreenPtr pScreen;
-        miPointerPtr pPointer; 
-        
-        if (!pDev->isMaster && !pDev->u.master)
-            return;
+        miPointerPtr pPointer;
 
         pPointer = MIPOINTER(pDev);
 
@@ -502,10 +491,8 @@ miPointerCurrentScreen ()
 _X_EXPORT ScreenPtr
 miPointerGetScreen(DeviceIntPtr pDev)
 {
-    if (!pDev || (!pDev->isMaster && !pDev->u.master))
-        return NULL;
-
-    return MIPOINTER(pDev)->pScreen;
+    miPointerPtr pPointer = MIPOINTER(pDev);
+    return (pPointer) ? pPointer->pScreen : NULL;
 }
 
 /* Move the pointer to x, y on the current screen, update the sprite, and
@@ -525,9 +512,6 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
     miPointerPtr pPointer;
     SetupScreen(pScreen);
 
-    if (!pDev->isMaster && !pDev->u.master) 
-        return;
-
     pPointer = MIPOINTER(pDev);
 
     /* Hack: We mustn't call into ->MoveCursor for anything but the
@@ -556,9 +540,6 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     ScreenPtr		newScreen;
 
     miPointerPtr        pPointer; 
-    
-    if (!pDev->isMaster && !pDev->u.master)
-        return;
 
     pPointer = MIPOINTER(pDev);
     pScreen = pPointer->pScreen;
@@ -613,12 +594,6 @@ miPointerPosition (int *x, int *y)
 _X_EXPORT void
 miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
 {
-    if (!pDev->isMaster && !pDev->u.master)
-    {
-        ErrorF("[mi] miPointerGetPosition called for floating device.\n");
-        return;
-    }
-
     *x = MIPOINTER(pDev)->x;
     *y = MIPOINTER(pDev)->y;
 }
commit 0f15875a271889ae3cc4997ad15f787ea28b3a08
Author: Magnus Vigerlöf <Magnus.Vigerlof at ipbo.se>
Date:   Sat May 17 19:24:00 2008 +0200

    Make all conversion handling in GPE.
    
    This isn't quite finished yet, but at least it gives us the ability to use a
    tablet as a normal mouse - with all the scaling in place.
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/dix/getevents.c b/dix/getevents.c
index 0879434..15e7f3b 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -156,6 +156,55 @@ CreateClassesChangedEvent(EventList* event,
 }
 
 /**
+ * Rescale the coord between the two axis ranges.
+ */
+static int
+rescaleValuatorAxis(int coord, int fmin, int fmax,
+                    int tmin, int tmax, int smax)
+{
+    if(fmin >= fmax) {
+        fmin = 0;
+        fmax = smax;
+    }
+    if(tmin >= tmax) {
+        tmin = 0;
+        tmax = smax;
+    }
+    if(fmin == tmin && fmax == tmax)
+        return coord;
+
+    return (int)(((float)(coord - fmin)) * (tmax - tmin + 1) /
+                 (fmax - fmin + 1)) + tmin;
+}
+
+/**
+ * Update all coordinates when changing to a different SD
+ * to ensure that relative reporting will work as expected
+ * without loss of precision.
+ */
+static void
+updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
+{
+    ScreenPtr scr = miPointerGetScreen(pDev);
+
+    /* lastx/y is in screen coords and the actual position
+     * of the pointer */
+    pDev->lastx = master->lastx;
+    pDev->lasty = master->lasty;
+    /* the valuator axis is in device coords and holds the
+     * position of the pointer, but in device coords. */
+    if(pDev->valuator->numAxes > 0)
+        pDev->valuator->axisVal[0] = rescaleValuatorAxis(pDev->lastx, 0, scr->width,
+                                            pDev->valuator->axes[0].min_value,
+                                            pDev->valuator->axes[0].max_value, scr->width);
+    if(pDev->valuator->numAxes > 1)
+        pDev->valuator->axisVal[1] = rescaleValuatorAxis(pDev->lasty, 0, scr->height,
+                                            pDev->valuator->axes[1].min_value,
+                                            pDev->valuator->axes[1].max_value, scr->height);
+    /*TODO calculate the other axis as well based on info from the old slave-device */
+}
+
+/**
  * Allocate the motion history buffer.
  */
 _X_EXPORT void
@@ -395,25 +444,23 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
  * Fills events with valuator events for pDev, as given by the other
  * parameters.
  *
- * Note that we mis-use the sequence number to store the absolute bit.
- *
  * FIXME: Need to fix ValuatorClassRec to store all the valuators as
  *        last posted, not just x and y; otherwise relative non-x/y
  *        valuators, though a very narrow use case, will be broken.
  */
 static EventList *
-getValuatorEvents(EventList *events, DeviceIntPtr pDev, int absolute,
+getValuatorEvents(EventList *events, DeviceIntPtr pDev,
         int first_valuator, int num_valuators, int *valuators) {
     deviceValuator *xv;
-    int i = 0, final_valuator = first_valuator + num_valuators;
+    int i;
 
-    for (i = first_valuator; i < final_valuator; i += 6, events++) {
+    for (i = 0; i < num_valuators; i += 6, events++) {
         xv = (deviceValuator*)events->event;
         xv->type = DeviceValuator;
-        xv->first_valuator = i;
-        xv->num_valuators = ((final_valuator - i) > 6) ? 6 : (final_valuator - i);
+        xv->first_valuator = first_valuator + i;
+        xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i);
         xv->deviceid = pDev->id;
-        switch (final_valuator - i) {
+        switch (num_valuators - i) {
         case 6:
             xv->valuator5 = valuators[i + 5];
         case 5:
@@ -425,13 +472,11 @@ getValuatorEvents(EventList *events, DeviceIntPtr pDev, int absolute,
         case 2:
             xv->valuator1 = valuators[i + 1];
         case 1:
-            xv->valuator0 = valuators[i];
+            xv->valuator0 = valuators[i + 0];
         }
 
-        if (i + 6 < final_valuator)
+        if (i + 6 < num_valuators)
             xv->deviceid |= MORE_EVENTS;
-
-        xv->sequenceNumber = (absolute) ? Absolute : Relative;
     }
 
     return events;
@@ -576,8 +621,8 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
     if (num_valuators) {
         kbp->deviceid |= MORE_EVENTS;
         clipValuators(pDev, first_valuator, num_valuators, valuators);
-        events = getValuatorEvents(events, pDev, FALSE /* relative */,
-                                   first_valuator, num_valuators, valuators);
+        events = getValuatorEvents(events, pDev, first_valuator,
+                                   num_valuators, valuators);
     }
 
     return numEvents;
@@ -674,44 +719,28 @@ _X_EXPORT int
 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 = 1;
     CARD32 ms = 0;
     deviceKeyButtonPointer *kbp = NULL;
     DeviceIntPtr master;
-    int x = 0, y = 0;
+    int x, y, cx, cy;
+    ScreenPtr scr = miPointerGetScreen(pDev);
 
     /* Sanity checks. */
     if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
         return 0;
-
-    if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
+    if (type != MotionNotify && !pDev->button)
         return 0;
-
     /* FIXME: I guess it should, in theory, be possible to post button events
      *        from devices without valuators. */
-    if (!pDev->valuator)
+    /* This method require at least valuator 0&1 defined on the InputDevice */
+    if (!pDev->valuator || pDev->valuator->numAxes < 2)
         return 0;
-
     if (type == MotionNotify && num_valuators <= 0)
         return 0;
 
     ms = GetTimeInMillis();
 
-    num_events = 1;
-
-    master = pDev->u.master;
-    if (master && master->u.lastSlave != pDev)
-    {
-        CreateClassesChangedEvent(events, master, pDev);
-
-        pDev->lastx = master->lastx;
-        pDev->lasty = master->lasty;
-        master->u.lastSlave = pDev;
-
-        num_events++;
-        events++;
-    }
-
     /* Do we need to send a DeviceValuator event? */
     if (num_valuators) {
         if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
@@ -719,28 +748,34 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         num_events += ((num_valuators - 1) / 6) + 1;
     }
 
-    final_valuator = num_valuators + first_valuator;
-
     /* You fail. */
-    if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes)
+    if (first_valuator < 0 ||
+        (num_valuators + first_valuator) > pDev->valuator->numAxes)
         return 0;
 
+    master = pDev->u.master;
+    if (master && master->u.lastSlave != pDev)
+    {
+        CreateClassesChangedEvent(events, master, pDev);
+        updateSlaveDeviceCoords(master, pDev);
+        master->u.lastSlave = pDev;
+        num_events++;
+        events++;
+    }
+
     /* Set x and y based on whether this is absolute or relative, and
      * accelerate if we need to. */
+    x = pDev->valuator->axisVal[0];
+    y = pDev->valuator->axisVal[1];
     if (flags & POINTER_ABSOLUTE) {
-        if (num_valuators >= 1 && first_valuator == 0) {
+        if (num_valuators >= 1 && first_valuator == 0)
             x = valuators[0];
-        }
-        else {
-            x = pDev->lastx;
-        }
-
-        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
+        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
             y = valuators[1 - first_valuator];
-        }
-        else {
-            y = pDev->lasty;
-        }
+
+        /* Clip both x and y to the defined limits (usually co-ord space limit). */
+        clipAxis(pDev, 0, &x);
+        clipAxis(pDev, 1, &y);
     }
     else {
         if (flags & POINTER_ACCELERATE)
@@ -748,34 +783,69 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
                               valuators);
 
         if (first_valuator == 0 && num_valuators >= 1)
-            x = pDev->lastx + valuators[0];
-        else
-            x = pDev->lastx;
-
+            x += valuators[0];
         if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-            y = pDev->lasty + valuators[1 - first_valuator];
-        else
-            y = pDev->lasty;
+            y += valuators[1 - first_valuator];
+
+        /* if not core -> clip both x and y to the defined limits (usually
+         * co-ord space limit). */
+        if(!pDev->coreEvents) {
+            clipAxis(pDev, 0, &x);
+            clipAxis(pDev, 1, &y);
+        }
     }
 
-    /* Clip both x and y to the defined limits (usually co-ord space limit). */
-    clipAxis(pDev, 0, &x);
-    clipAxis(pDev, 1, &y);
+    /* scale x&y to screen */
+    pDev->lastx = cx = rescaleValuatorAxis(x, pDev->valuator->axes[0].min_value,
+                                           pDev->valuator->axes[0].max_value,
+                                           0, scr->width, scr->width);
+    pDev->lasty = cy = rescaleValuatorAxis(y, pDev->valuator->axes[1].min_value,
+                                           pDev->valuator->axes[1].max_value,
+                                           0, scr->height, scr->height);
 
     /* This takes care of crossing screens for us, as well as clipping
      * to the current screen.  Right now, we only have one history buffer,
      * so we don't set this for both the device and core.*/
-    miPointerSetPosition(pDev, &x, &y, ms);
+    miPointerSetPosition(pDev, &pDev->lastx, &pDev->lasty, ms);
+
+    scr = miPointerGetScreen(pDev);
+    if(cx != pDev->lastx)
+        x = rescaleValuatorAxis(pDev->lastx, 0, scr->width,
+                                pDev->valuator->axes[0].min_value,
+                                pDev->valuator->axes[0].max_value,
+                                scr->width);
+    if(cy != pDev->lasty)
+        y = rescaleValuatorAxis(pDev->lasty, 0, scr->height,
+                                pDev->valuator->axes[1].min_value,
+                                pDev->valuator->axes[1].max_value,
+                                scr->height);
+
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
-    pDev->lastx = x;
-    pDev->lasty = y;
-    if (master)
-    {
-        master->lastx = x;
-        master->lasty = y;
+    if (master) {
+        master->lastx = pDev->lastx;
+        master->lasty = pDev->lasty;
     }
 
+    /* update the contents of the valuators based on the mode of the InputDevice */
+    if(1) { /*TODO Absolute mode */
+        /* Update the valuators with the true value sent to the client
+         * (only absolute mode on the InputDevice) */
+        if (first_valuator == 0 && num_valuators >= 1)
+            pDev->valuator->axisVal[0] = x;
+        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
+            pDev->valuator->axisVal[1] = y;
+    } else {/* Relative mode */
+        /* If driver reported in absolute, calculate the relative valuator
+         * values as a delta from the old absolute values of the valuator
+         * values. If relative report, keep it as-is.*/
+        /*TODO*/
+    }
+    /* Save the last calculated device axis value in the device
+     * valuator for next event */
+    pDev->valuator->axisVal[0] = x;
+    pDev->valuator->axisVal[1] = y;
+
     kbp = (deviceKeyButtonPointer *) events->event;
     kbp->time = ms;
     kbp->deviceid = pDev->id;
@@ -791,15 +861,15 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         kbp->detail = pDev->button->map[buttons];
     }
 
-    kbp->root_x = x;
-    kbp->root_y = y;
+    kbp->root_x = pDev->lastx;
+    kbp->root_y = pDev->lasty;
 
     events++;
     if (num_valuators) {
         kbp->deviceid |= MORE_EVENTS;
         clipValuators(pDev, first_valuator, num_valuators, valuators);
-        events = getValuatorEvents(events, pDev, (flags & POINTER_ABSOLUTE),
-                first_valuator, num_valuators, valuators);
+        events = getValuatorEvents(events, pDev, first_valuator,
+                                   num_valuators, valuators);
     }
 
     return num_events;
@@ -824,10 +894,8 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
     /* Sanity checks. */
     if (type != ProximityIn && type != ProximityOut)
         return 0;
-
     if (!pDev->valuator)
         return 0;
-
     /* Do we need to send a DeviceValuator event? */
     if ((pDev->valuator->mode & 1) == Relative)
         num_valuators = 0;
@@ -847,11 +915,8 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
     if (master && master->u.lastSlave != pDev)
     {
         CreateClassesChangedEvent(events, master, pDev);
-
-        pDev->lastx = master->lastx;
-        pDev->lasty = master->lasty;
+        updateSlaveDeviceCoords(master, pDev);
         master->u.lastSlave = pDev;
-
         num_events++;
         events++;
     }
@@ -866,8 +931,8 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
         kbp->deviceid |= MORE_EVENTS;
         events++;
         clipValuators(pDev, first_valuator, num_valuators, valuators);
-        events = getValuatorEvents(events, pDev, False /* relative */,
-                                   first_valuator, num_valuators, valuators);
+        events = getValuatorEvents(events, pDev, first_valuator,
+                                   num_valuators, valuators);
     }
 
     return num_events;
commit 74372fd0049676787904f1f9f80f836b97f5f60e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 22 18:02:10 2008 +0930

    xfree86: suspend signals while removing a device.
    
    Getting a keyboard event while halfway through freeing memory can be
    unpleasant.

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index e53756f..9961624 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -475,6 +475,7 @@ DeleteInputDeviceRequest(DeviceIntPtr pDev)
         drv = pInfo->drv;
         idev = pInfo->conf_idev;
     }
+    OsBlockSignals();
     RemoveDevice(pDev);
 
     if (pDev->isMaster)
@@ -484,6 +485,7 @@ DeleteInputDeviceRequest(DeviceIntPtr pDev)
         drv->UnInit(drv, pInfo, 0);
     else
         xf86DeleteInput(pInfo, 0);
+    OsReleaseSignals();
 
     /* devices added through HAL aren't in the config layout */
     it = xf86ConfigLayout.inputs;
commit 30e9a33f7d1972dcf1c29c7455b2cea4e5857913
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 22 16:00:21 2008 +0930

    xkb: fix crash caused by uninitialised variable.

diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c
index 2b8efce..edc389f 100644
--- a/xkb/xkbLEDs.c
+++ b/xkb/xkbLEDs.c
@@ -629,7 +629,7 @@ XkbCopySrvLedInfo(	DeviceIntPtr		from,
 			KbdFeedbackPtr		kf,
 			LedFeedbackPtr		lf)
 {
-    XkbSrvLedInfoPtr sli_new;
+    XkbSrvLedInfoPtr sli_new = NULL;
 
     if (!src)
 	goto finish;
commit 5c5a1eaf68eb11053fd5b99d24eb8024b6d5b218
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 21 21:51:27 2008 +0930

    Replace UniSA with full Uni name in Author affiliation.
    
    Big boss says UniSA isn't unique enough. Who am I to argue?

diff --git a/Xext/geext.c b/Xext/geext.c
index afede22..e49e71f 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xext/geint.h b/Xext/geint.h
index 2e0eb09..60cba7d 100644
--- a/Xext/geint.h
+++ b/Xext/geint.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/chaccess.c b/Xi/chaccess.c
index 3ef29fc..a6798b7 100644
--- a/Xi/chaccess.c
+++ b/Xi/chaccess.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #define	 NEED_EVENTS
diff --git a/Xi/chaccess.h b/Xi/chaccess.h
index 090258c..baea69c 100644
--- a/Xi/chaccess.h
+++ b/Xi/chaccess.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xi/chdevcur.c b/Xi/chdevcur.c
index 867bf97..121f792 100644
--- a/Xi/chdevcur.c
+++ b/Xi/chdevcur.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 /***********************************************************************
diff --git a/Xi/chdevcur.h b/Xi/chdevcur.h
index af86279..e6df9eb 100644
--- a/Xi/chdevcur.h
+++ b/Xi/chdevcur.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
index 1d57843..99957fe 100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 /***********************************************************************
diff --git a/Xi/chdevhier.h b/Xi/chdevhier.h
index 85c1a39..07afd53 100644
--- a/Xi/chdevhier.h
+++ b/Xi/chdevhier.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 /***********************************************************************
diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
index c92c31d..1a2584f 100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 /***********************************************************************
diff --git a/Xi/extgrbdev.h b/Xi/extgrbdev.h
index 7e2b0ea..6e3e371 100644
--- a/Xi/extgrbdev.h
+++ b/Xi/extgrbdev.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xi/getcptr.c b/Xi/getcptr.c
index c85fced..ae45b13 100644
--- a/Xi/getcptr.c
+++ b/Xi/getcptr.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #define	 NEED_EVENTS
diff --git a/Xi/getcptr.h b/Xi/getcptr.h
index cf8cd2e..2745833 100644
--- a/Xi/getcptr.h
+++ b/Xi/getcptr.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xi/qryacces.c b/Xi/qryacces.c
index b3cc27a..99221ea 100644
--- a/Xi/qryacces.c
+++ b/Xi/qryacces.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #define	 NEED_EVENTS
diff --git a/Xi/qryacces.h b/Xi/qryacces.h
index 085d93a..238cdba 100644
--- a/Xi/qryacces.h
+++ b/Xi/qryacces.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xi/querydp.c b/Xi/querydp.c
index bd0a1c5..d63bed1 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 /***********************************************************************
diff --git a/Xi/querydp.h b/Xi/querydp.h
index e8c5165..5370ed4 100644
--- a/Xi/querydp.h
+++ b/Xi/querydp.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xi/setcptr.c b/Xi/setcptr.c
index f73a44c..81ce66b 100644
--- a/Xi/setcptr.c
+++ b/Xi/setcptr.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 /***********************************************************************
diff --git a/Xi/setcptr.h b/Xi/setcptr.h
index 114623c..df38add 100644
--- a/Xi/setcptr.h
+++ b/Xi/setcptr.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index 5ea6132..3720441 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 /***********************************************************************
diff --git a/Xi/warpdevp.h b/Xi/warpdevp.h
index 7034e16..00a4dff 100644
--- a/Xi/warpdevp.h
+++ b/Xi/warpdevp.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/Xi/xiselev.c b/Xi/xiselev.c
index fc0a0f0..0f84334 100644
--- a/Xi/xiselev.c
+++ b/Xi/xiselev.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #define	 NEED_EVENTS
diff --git a/Xi/xiselev.h b/Xi/xiselev.h
index e846407..b751c5d 100644
--- a/Xi/xiselev.h
+++ b/Xi/xiselev.h
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 #ifdef HAVE_DIX_CONFIG_H
diff --git a/dix/access.c b/dix/access.c
index e29ab86..f71b3cc 100644
--- a/dix/access.c
+++ b/dix/access.c
@@ -20,7 +20,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  *
- * Author: Peter Hutterer, UniSA, NICTA
+ * Author: Peter Hutterer, University of South Australia, NICTA
  */
 
 /* This file controls the access control lists for each window. 
commit 7509fb498c02fe1cebe4139612b8871ec877c130
Merge: 2ae3bed... dfb7de6...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 21 16:25:35 2008 +0930

    Merge branch 'hwcursor' into mpx

commit 2ae3bed33731d800bb28a968e3a1c8066d179740
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 21 15:51:35 2008 +0930

    mi: shut up compiler warning (return w/o a value)

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 484947d..0d5c984 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -199,7 +199,7 @@ miPointerDisplayCursor (pDev, pScreen, pCursor)
     /* return for keyboards */
     if ((pDev->isMaster && !DevHasCursor(pDev)) ||
         (!pDev->isMaster && pDev->u.master && !DevHasCursor(pDev->u.master)))
-            return;
+            return FALSE;
 
     pPointer = MIPOINTER(pDev);
 
commit 4056595fc77c20052e226b402e38a2a914dca123
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 20 18:57:31 2008 +0930

    xkb: remove superfluous checks in if statement.

diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index 19a171a..0727ad8 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -2052,7 +2052,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
              * just MapNotify.  we also need to send NKN if the geometry
              * changed (obviously ...). */
             if ((src->min_key_code != dst->min_key_code ||
-                 src->max_key_code != dst->max_key_code) && sendNotifies) {
+                 src->max_key_code != dst->max_key_code)) {
                 nkn.oldMinKeyCode = dst->min_key_code;
                 nkn.oldMaxKeyCode = dst->max_key_code;
                 nkn.deviceID = nkn.oldDeviceID = pDev->id;
@@ -2062,8 +2062,8 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
                 nkn.requestMinor = X_kbSetMap; /* XXX bare-faced lie */
                 nkn.changed = XkbAllNewKeyboardEventsMask;
                 XkbSendNewKeyboardNotify(pDev, &nkn);
-            }
-            else if (sendNotifies) {
+            } else
+            {
                 mn.deviceID = pDev->id;
                 mn.minKeyCode = src->min_key_code;
                 mn.maxKeyCode = src->max_key_code;
commit 7a550cefd9417c22a4397ea4d103ddc347ab1a0f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 20 11:07:39 2008 +0930

    dix: shut up two compiler warnings.

diff --git a/dix/devices.c b/dix/devices.c
index 4dd1dc5..5606543 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -71,6 +71,7 @@ SOFTWARE.
 #endif
 #include "privates.h"
 #include "xace.h"
+#include "mi.h"
 
 #include "dispatch.h"
 #include "swaprep.h"
diff --git a/dix/main.c b/dix/main.c
index 11ea29b..328c0b4 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -240,7 +240,7 @@ int dix_main(int argc, char *argv[], char *envp[])
 int main(int argc, char *argv[], char *envp[])
 #endif
 {
-    int		i, j, k, error;
+    int		i, j, k;
     char	*xauthfile;
     HWEventQueueType	alwaysCheckForInput[2];
 
commit f9edecd1b53a2e234def9cbd954a47c4bda2bebc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 20 11:07:17 2008 +0930

    mi: sync declaration and definition of mieqResizeEvents.

diff --git a/mi/mi.h b/mi/mi.h
index 0af1a1b..2fdaf20 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -153,7 +153,7 @@ extern Bool mieqInit(
     void
 );
 
-extern void mieqResize(
+extern void mieqResizeEvents(
     int /* min_size */
 );
 
diff --git a/mi/mieq.c b/mi/mieq.c
index 3ab8936..830bab8 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -103,7 +103,7 @@ mieqInit(void)
 }
 
 /* Ensure all events in the EQ are at least size bytes. */
-Bool
+void
 mieqResizeEvents(int min_size)
 {
     int i;
commit e73a03d589b47ac9131f3932da7f78d2fef7bfb5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 20 10:54:32 2008 +0930

    fb: shut up two compiler warnings.

diff --git a/fb/fbarc.c b/fb/fbarc.c
index f89b81c..3a8a2c5 100644
--- a/fb/fbarc.c
+++ b/fb/fbarc.c
@@ -77,6 +77,8 @@ fbPolyArc (DrawablePtr	pDrawable,
 	    fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
 #ifdef FB_ACCESS_WRAPPER
 	    wrapped = 1;
+#else
+	    wrapped = 0;
 #endif
 	    while (narcs--)
 	    {
diff --git a/fb/fbpict.c b/fb/fbpict.c
index 85b5171..1355e90 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -292,7 +292,7 @@ create_bits_picture (PicturePtr pict,
     
     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
 
-    bits = (CARD8*)bits + yoff * stride * sizeof(FbBits) + xoff * (bpp / 8);
+    bits = (FbBits*)((CARD8*)bits + yoff * stride * sizeof(FbBits) + xoff * (bpp / 8));
 
     image = pixman_image_create_bits (
 	pict->format,
commit 99d28c3ef37aeffe7d8ec41e45a650ba248c6958
Merge: fc7e256... 0178b6a...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 20 10:20:14 2008 +0930

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	Xext/xprint.c (removed in master)
    	config/hal.c
    	dix/main.c
    	hw/kdrive/ati/ati_cursor.c (removed in master)
    	hw/kdrive/i810/i810_cursor.c (removed in master)
    	hw/xprint/ddxInit.c (removed in master)
    	xkb/ddxLoad.c

diff --cc dix/main.c
index 42d3309,2e12b70..11ea29b
--- a/dix/main.c
+++ b/dix/main.c
@@@ -372,15 -358,14 +358,10 @@@ int main(int argc, char *argv[], char *
  	    if (!CreateRootWindow(pScreen))
  		FatalError("failed to create root window");
  	}
 -        InitCoreDevices();
 -	InitInput(argc, argv);
 -	if (InitAndStartDevices() != Success)
 -	    FatalError("failed to initialize core devices");
  
  	InitFonts();
- 	if (loadableFonts)
- 	    SetFontPath(serverClient, 0, (unsigned char *)defaultFontPath,
- 			&error);
-         else {
- 	    if (SetDefaultFontPath(defaultFontPath) != Success)
- 		ErrorF("[dix] failed to set default font path '%s'",
- 			defaultFontPath);
+ 	if (SetDefaultFontPath(defaultFontPath) != Success) {
 -	    ErrorF("failed to set default font path '%s'", defaultFontPath);
++	    ErrorF("[dix] failed to set default font path '%s'", defaultFontPath);
  	}
  	if (!SetDefaultFont(defaultTextFont)) {
  	    FatalError("could not open default font '%s'", defaultTextFont);
diff --cc mi/miinitext.c
index 00f0d27,9a87360..a4374d5
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@@ -491,10 -460,8 +457,10 @@@ InitExtensions(argc, argv
      int		argc;
      char	*argv[];
  {
 +    if (!noGEExtension) GEExtensionInit();
 +
  #ifdef PANORAMIX
- # if !defined(PRINT_ONLY_SERVER) && !defined(NO_PANORAMIX)
+ # if !defined(NO_PANORAMIX)
    if (!noPanoramiXExtension) PanoramiXExtensionInit();
  # endif
  #endif
commit fc7e2566cc076c0d979f74871bc436df43401058
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 16 16:59:34 2008 +0930

    Xext: fix typo in condition.
    
    Fall-out from dc3aba8a559d4304844ee1cc306c577a63b82762.
    We must free the event if it is NOT an extension event.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 791f6a2..a42faa7 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -500,7 +500,7 @@ ProcXTestFakeInput(client)
         xfree(master_event);
     } else
         (*dev->public.processInputProc)(ev, dev, nev);
-    if (extension)
+    if (!extension)
         xfree(ev);
     return client->noClientException;
 }
commit 6fb76acc4524d6af4bfb6bc6d862c1ee2bbb8baa
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 16 19:22:32 2008 +0930

    mi: remove miPointerUpdate() -> replaced by miPointerUpdateSprite().
    
    In the xnest and vfb DDX we don't need the call anyway, it's performed by
    mieqProcessInputEvent.

diff --git a/hw/vfb/InitInput.c b/hw/vfb/InitInput.c
index 393698f..3b001ee 100644
--- a/hw/vfb/InitInput.c
+++ b/hw/vfb/InitInput.c
@@ -52,7 +52,6 @@ void
 ProcessInputEvents()
 {
     mieqProcessInputEvents();
-    miPointerUpdate();
 }
 
 void DDXRingBell(int volume, int pitch, int duration)
diff --git a/hw/xnest/Events.c b/hw/xnest/Events.c
index 02ff27b..f7a551c 100644
--- a/hw/xnest/Events.c
+++ b/hw/xnest/Events.c
@@ -49,7 +49,6 @@ void
 ProcessInputEvents()
 {
   mieqProcessInputEvents();
-  miPointerUpdate();
 }
 
 int
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 2c226dc..484947d 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -374,18 +374,12 @@ miPointerWarpCursor (pDev, pScreen, x, y)
  */
 
 /*
- * miPointerUpdate
+ * miPointerUpdateSprite
  *
  * Syncronize the sprite with the cursor - called from ProcessInputEvents
  */
 
 void
-miPointerUpdate ()
-{
-    miPointerUpdateSprite(inputInfo.pointer);
-}
-
-void
 miPointerUpdateSprite (DeviceIntPtr pDev)
 {
     ScreenPtr		pScreen;
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 5cbf527..fccbfa0 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -122,11 +122,6 @@ extern int miPointerGetMotionEvents(
     ScreenPtr /*pScreen*/
 );
 
-/* Deprecated in favour of miPointerUpdateSprite. */
-extern void miPointerUpdate(
-    void
-) _X_DEPRECATED;
-
 /* Deprecated in favour of miSetPointerPosition. */
 extern void miPointerDeltaCursor(
     int /*dx*/,
commit dfb7de6571345061d1cd88ab915064fc376529fd
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 16 20:56:04 2008 +0930

    mi: don't call from miPointerMoved into the spriteFuncs for anything but VCP.
    
    Calling ->MoveCursor for anything but the HW-rendered VCP causes the
    SW-rendered cursor routines to be started, including mallocs, etc. Since
    miPointerMoved is called during SIGIO, this is a bad idea.

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 484947d..6f39bcb 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -530,7 +530,11 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
 
     pPointer = MIPOINTER(pDev);
 
-    if (pDev && pDev->coreEvents 
+    /* Hack: We mustn't call into ->MoveCursor for anything but the
+     * VCP, as this may cause a non-HW rendered cursor to be rendered during
+     * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
+     */
+    if ((pDev == inputInfo.pointer || (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
         && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
     {
 	pPointer->devx = x;
commit f611719edce2ae51dca8e53947a3938b53c20b00
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 16 19:49:29 2008 +0930

    xfree86: always render first cursor in HW, all others in SW.

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 50f8fb7..7695962 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -20,8 +20,6 @@ extern InputInfo inputInfo;
 
 DevPrivateKey xf86CursorScreenKey = &xf86CursorScreenKey;
 
-#define XF86_FORCE_SW_CURSOR (1 << 7)
-
 /* sprite functions */
 
 static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
@@ -304,14 +302,14 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
 
 
     if (pCurs == NullCursor) {	/* means we're supposed to remove the cursor */
-        if (ScreenPriv->SWCursor)
+        if (ScreenPriv->SWCursor || pDev != inputInfo.pointer)
             (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor,
                                                   x, y);
         else if (ScreenPriv->isUp) {
             xf86SetCursor(pScreen, NullCursor, x, y);
             ScreenPriv->isUp = FALSE;
-	    }
-	    return;
+        }
+        return;
     }
 
     /* only update for VCP, otherwise we get cursor jumps when removing a
@@ -324,13 +322,10 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
 	ScreenPriv->CursorToRestore = NULL;
 	ScreenPriv->HotX = pCurs->bits->xhot;
 	ScreenPriv->HotY = pCurs->bits->yhot;
-    }
 
-    if (!infoPtr->pScrn->vtSema)
-	 ScreenPriv->SavedCursor = pCurs;
+        if (!infoPtr->pScrn->vtSema)
+            ScreenPriv->SavedCursor = pCurs;
 
-    if (!(ScreenPriv->SWCursor & XF86_FORCE_SW_CURSOR))
-    {
 	if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || ((
 #ifdef ARGB_CURSOR
 			    pCurs->bits->argb && infoPtr->UseHWCursorARGB &&
@@ -352,22 +347,22 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
 	    return;
 	}
 
-    }
+        PointPriv->waitForUpdate = TRUE;
 
-    PointPriv->waitForUpdate = TRUE;
+        if (ScreenPriv->isUp) {
+            /* Remove the HW cursor, or make it transparent */
+            if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) {
+                xf86SetTransparentCursor(pScreen);
+            } else {
+                xf86SetCursor(pScreen, NullCursor, x, y);
+                ScreenPriv->isUp = FALSE;
+            }
+        }
 
-    if (ScreenPriv->isUp) {
-	/* Remove the HW cursor, or make it transparent */
-	if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) {
-	    xf86SetTransparentCursor(pScreen);
-	} else {
-	    xf86SetCursor(pScreen, NullCursor, x, y);
-	    ScreenPriv->isUp = FALSE;
-	}
-    }
+        if (!ScreenPriv->SWCursor)
+            ScreenPriv->SWCursor = TRUE;
 
-    if (!ScreenPriv->SWCursor)
-        ScreenPriv->SWCursor = TRUE;
+    }
 
     if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent)
 	pCurs = NullCursor;
@@ -384,18 +379,19 @@ xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
     /* only update coordinate state for first sprite, otherwise we get jumps
        when removing a sprite. The second sprite is never HW rendered anyway */
     if (pDev == inputInfo.pointer ||
-            (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
+            !pDev->isMaster && pDev->u.master == inputInfo.pointer)
     {
 	ScreenPriv->x = x;
 	ScreenPriv->y = y;
-    }
 
-    if (ScreenPriv->CursorToRestore)
-	xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x, y);
-    else if (ScreenPriv->SWCursor)
-	(*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y);
-    else if (ScreenPriv->isUp)
-	xf86MoveCursor(pScreen, x, y);
+        if (ScreenPriv->CursorToRestore)
+            xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x, y);
+        else if (ScreenPriv->SWCursor)
+            (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y);
+        else if (ScreenPriv->isUp)
+            xf86MoveCursor(pScreen, x, y);
+    } else
+        (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y);
 }
 
 void
@@ -455,13 +451,6 @@ xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
     /* Init SW cursor */
     ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen);
 
-    if (pDev != inputInfo.pointer)
-    {
-	    ScreenPriv->spriteFuncs->SetCursor(inputInfo.pointer, pScreen,
-		    ScreenPriv->CurrentCursor, ScreenPriv->x, ScreenPriv->y);
-        ScreenPriv->SWCursor = TRUE | XF86_FORCE_SW_CURSOR;
-    }
-
     return ret;
 }
 
@@ -475,21 +464,7 @@ xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
             &pScreen->devPrivates, xf86CursorScreenKey);
 
-    for (it = inputInfo.devices; it; it = it->next)
-    {
-        if (it->isMaster && it != inputInfo.pointer && it !=
-                inputInfo.keyboard)
-            break;
-    }
-
-    if (!it) /* no other sprites except VCP. restore HW rendering */
-    {
-	ScreenPriv->SWCursor = TRUE;
-	xf86CursorSetCursor(inputInfo.pointer, pScreen,
-		ScreenPriv->CurrentCursor, ScreenPriv->x, ScreenPriv->y);
-    }
-
-    /* Clean up SW cursor */
+   /* Clean up SW cursor */
     (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
 }
 
commit 48ba58feacedf9781db81c82adbb37197d9a5cd1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 16 19:22:32 2008 +0930

    mi: remove miPointerUpdate() -> replaced by miPointerUpdateSprite().
    
    In the xnest and vfb DDX we don't need the call anyway, it's performed by
    mieqProcessInputEvent.

diff --git a/hw/vfb/InitInput.c b/hw/vfb/InitInput.c
index 393698f..3b001ee 100644
--- a/hw/vfb/InitInput.c
+++ b/hw/vfb/InitInput.c
@@ -52,7 +52,6 @@ void
 ProcessInputEvents()
 {
     mieqProcessInputEvents();
-    miPointerUpdate();
 }
 
 void DDXRingBell(int volume, int pitch, int duration)
diff --git a/hw/xnest/Events.c b/hw/xnest/Events.c
index 02ff27b..f7a551c 100644
--- a/hw/xnest/Events.c
+++ b/hw/xnest/Events.c
@@ -49,7 +49,6 @@ void
 ProcessInputEvents()
 {
   mieqProcessInputEvents();
-  miPointerUpdate();
 }
 
 int
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 2c226dc..484947d 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -374,18 +374,12 @@ miPointerWarpCursor (pDev, pScreen, x, y)
  */
 
 /*
- * miPointerUpdate
+ * miPointerUpdateSprite
  *
  * Syncronize the sprite with the cursor - called from ProcessInputEvents
  */
 
 void
-miPointerUpdate ()
-{
-    miPointerUpdateSprite(inputInfo.pointer);
-}
-
-void
 miPointerUpdateSprite (DeviceIntPtr pDev)
 {
     ScreenPtr		pScreen;
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 5cbf527..fccbfa0 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -122,11 +122,6 @@ extern int miPointerGetMotionEvents(
     ScreenPtr /*pScreen*/
 );
 
-/* Deprecated in favour of miPointerUpdateSprite. */
-extern void miPointerUpdate(
-    void
-) _X_DEPRECATED;
-
 /* Deprecated in favour of miSetPointerPosition. */
 extern void miPointerDeltaCursor(
     int /*dx*/,
commit 622d7c1d899a6146773a2ebd1d632a805f24025e
Author: Tiago Vignatti <vignatti at c3sl.ufpr.br>
Date:   Wed May 14 14:49:09 2008 -0300

    Restructure and organize the code.
    
    It was removed and simplified some conditionals. We don't need test for
    pDev->isMaster inside xf86CursorSetCursor() because only MD enters there.
    
    In the last chunk, ScreenPriv fields were being assigned without need, so
    that code was wrapped inside the conditional to avoid it.
    
    I also tried to make the identation more sane in some parts that I touched.
    
    Signed-off-by: Tiago Vignatti <vignatti at c3sl.ufpr.br>
    
    Minor modification, part of the original patch led to cursors not being
    updated properly when controlled through XTest.
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 2d69074..50f8fb7 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -299,43 +299,36 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
 	&pScreen->devPrivates, xf86CursorScreenKey);
     xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
-    miPointerScreenPtr PointPriv;
+    miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate(
+    &pScreen->devPrivates, miPointerScreenKey);
+
+
+    if (pCurs == NullCursor) {	/* means we're supposed to remove the cursor */
+        if (ScreenPriv->SWCursor)
+            (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor,
+                                                  x, y);
+        else if (ScreenPriv->isUp) {
+            xf86SetCursor(pScreen, NullCursor, x, y);
+            ScreenPriv->isUp = FALSE;
+	    }
+	    return;
+    }
 
     /* only update for VCP, otherwise we get cursor jumps when removing a
        sprite. The second cursor is never HW rendered anyway. */
-    if (pDev == inputInfo.pointer ||
-	    (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
+    if (pDev == inputInfo.pointer)
     {
 	ScreenPriv->CurrentCursor = pCurs;
 	ScreenPriv->x = x;
 	ScreenPriv->y = y;
 	ScreenPriv->CursorToRestore = NULL;
+	ScreenPriv->HotX = pCurs->bits->xhot;
+	ScreenPriv->HotY = pCurs->bits->yhot;
     }
 
     if (!infoPtr->pScrn->vtSema)
 	 ScreenPriv->SavedCursor = pCurs;
 
-    if (pCurs == NullCursor) {	/* means we're supposed to remove the cursor */
-	if (ScreenPriv->SWCursor)
-            (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor,
-                                                  x, y); 
-        else if
-                (ScreenPriv->isUp) {
-	    xf86SetCursor(pScreen, NullCursor, x, y);
-	    ScreenPriv->isUp = FALSE;
-	}
-	return;
-    }
-
-    if (pDev == inputInfo.pointer ||
-	    (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
-    {
-	ScreenPriv->HotX = pCurs->bits->xhot;
-	ScreenPriv->HotY = pCurs->bits->yhot;
-    }
-
-    PointPriv = (miPointerScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
-						     miPointerScreenKey);
     if (!(ScreenPriv->SWCursor & XF86_FORCE_SW_CURSOR))
     {
 	if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || ((
@@ -346,18 +339,18 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
 #endif
 			    (pCurs->bits->height <= infoPtr->MaxHeight) &&
 			    (pCurs->bits->width <= infoPtr->MaxWidth) &&
-			    (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs))))))
+                            (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs))))))
 	{
 
-	if (ScreenPriv->SWCursor)	/* remove the SW cursor */
-	  (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y);
+	    if (ScreenPriv->SWCursor)	/* remove the SW cursor */
+		(*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y);
 
-	xf86SetCursor(pScreen, pCurs, x, y);
-	ScreenPriv->SWCursor = FALSE;
-	ScreenPriv->isUp = TRUE;
-	PointPriv->waitForUpdate = !infoPtr->pScrn->silkenMouse;
-	return;
-  }
+	    xf86SetCursor(pScreen, pCurs, x, y);
+	    ScreenPriv->SWCursor = FALSE;
+	    ScreenPriv->isUp = TRUE;
+	    PointPriv->waitForUpdate = !infoPtr->pScrn->silkenMouse;
+	    return;
+	}
 
     }
 
commit 5af90025fee6a92e7d94642978feed21f902d0cb
Author: Tiago Vignatti <vignatti at c3sl.ufpr.br>
Date:   Wed May 14 02:45:49 2008 -0300

    Remove redundancy.
    
    The only function that cat set SWCursor before xf86DeviceCursorInitialize()
    is xf86InitCursor() when VCP and is created.
    
    Signed-off-by: Tiago Vignatti <vignatti at c3sl.ufpr.br>
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 4d64f62..2d69074 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -464,11 +464,8 @@ xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
 
     if (pDev != inputInfo.pointer)
     {
-	if (!ScreenPriv->SWCursor)
-	{
 	    ScreenPriv->spriteFuncs->SetCursor(inputInfo.pointer, pScreen,
 		    ScreenPriv->CurrentCursor, ScreenPriv->x, ScreenPriv->y);
-	}
         ScreenPriv->SWCursor = TRUE | XF86_FORCE_SW_CURSOR;
     }
 
commit 9fc94edfe3df4c4a84ad70714c0a4ef8bbf57fc9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 16 16:59:34 2008 +0930

    Xext: fix typo in condition.
    
    Fall-out from dc3aba8a559d4304844ee1cc306c577a63b82762.
    We must free the event if it is NOT an extension event.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 791f6a2..a42faa7 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -500,7 +500,7 @@ ProcXTestFakeInput(client)
         xfree(master_event);
     } else
         (*dev->public.processInputProc)(ev, dev, nev);
-    if (extension)
+    if (!extension)
         xfree(ev);
     return client->noClientException;
 }
commit 5127942f80983b2e053dddd5c5747d0c3d2f9d6d
Author: Brian Rogers <brian_rogers at comcast.net>
Date:   Fri May 16 10:08:04 2008 +0930

    DGA: pass nevents to UpdateDeviceState. #15936
    
    Missing parameter caused event processing to go nuts when checking valuators.
    
    X.Org Bug 15936 <http://bugs.freedesktop.org/show_bug.cgi?id=15936>
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
index 9c79505..a7e24a6 100644
--- a/hw/xfree86/common/xf86DGA.c
+++ b/hw/xfree86/common/xf86DGA.c
@@ -1043,7 +1043,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
     de->u.event.state = keyc->state | pointer->button->state;
 
     de->u.u.type = (IEventBase - 1) + coreEquiv; /* change to XI event */
-    UpdateDeviceState(keybd, de);
+    UpdateDeviceState(keybd, de, 1);
     de->u.u.type = *XDGAEventBase + coreEquiv; /* change back */
 
     /*
@@ -1090,7 +1090,7 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
     de->u.event.state = butc->state | GetPairedDevice(mouse)->key->state;
 
     de->u.u.type = (IEventBase - 1) + coreEquiv; /* change to XI event */
-    UpdateDeviceState(mouse, de);
+    UpdateDeviceState(mouse, de, 1);
     de->u.u.type = *XDGAEventBase + coreEquiv; /* change back */
 
     /*
commit 28378d26b4bae377ef1212f6a51cda9b5529f1b5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 15 11:09:15 2008 +0930

    Xi: assemble button/modifier state before updating the device. #15934
    
    The state field of the event must specify the state of the devices before the
    event occured. With the code as it was, the state would also include the
    event (e.g. state from a button press event would show the button as pressed)
    Gathering the state before updating the device should fix this.
    
    X.Org Bug 15934 <http://bugs.freedesktop.org/show_bug.cgi?id=15934>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index b284547..42b77c1 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1021,6 +1021,26 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     ValuatorClassPtr v;
     deviceValuator *xV  = (deviceValuator *) xE;
     int ret = 0;
+    int state;
+    DeviceIntPtr mouse = NULL, kbd = NULL;
+
+    if (IsPointerDevice(device))
+    {
+        kbd = GetPairedDevice(device);
+        mouse = device;
+        if (!kbd->key) /* can happen with floating SDs */
+            kbd = NULL;
+    } else
+    {
+        mouse = GetPairedDevice(device);
+        kbd = device;
+        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
+            mouse = NULL;
+    }
+
+    /* State needs to be assembled BEFORE the device is updated. */
+    state = (kbd) ? kbd->key->state : 0;
+    state |= (mouse) ? (mouse->button->state) : 0;
 
     ret = UpdateDeviceState(device, xE, count);
     if (ret == DONT_PROCESS)
@@ -1034,33 +1054,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
         CheckMotion(xE, device);
 
     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;
 	xE->u.keyButtonPointer.rootY = rootY;
 	NoticeEventTime(xE);
 
-        /* If 'device' is a pointer device, we need to get the paired keyboard
-         * for the state. If there is none, the kbd bits of state are 0.
-         * If 'device' is a keyboard device, get the paired pointer and use the
-         * pointer's state for the button bits.
-         */
-        if (IsPointerDevice(device))
-        {
-            kbd = GetPairedDevice(device);
-            mouse = device;
-            if (!kbd->key) /* can happen with floating SDs */
-                kbd = NULL;
-        }
-        else
-        {
-            mouse = GetPairedDevice(device);
-            kbd = device;
-            if (!mouse->valuator || !mouse->button) /* may be float. SDs */
-                mouse = NULL;
-        }
-        xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0;
-        xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0;
+        xE->u.keyButtonPointer.state = state;
 
         key = xE->u.u.detail;
     }
commit 937e5aae33d3b5112b5d10d605e25f57b48caa3f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 14 22:30:15 2008 +0930

    dix: don't undisplay cursor if we don't own a sprite.
    
    Sometimes we didn't have a cursor when coming back from suspend. Reason was
    that the suspend caused the server to lose the device that was attached to the
    VCP, and a RemoveDevice() would then set the cursor to NULL.
    Solution: only set the cursor to NULL if we actually own the sprite.

diff --git a/dix/devices.c b/dix/devices.c
index 05a6b51..4dd1dc5 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -885,7 +885,8 @@ RemoveDevice(DeviceIntPtr dev)
         return BadImplementation;
 
     initialized = dev->inited;
-    screen->DisplayCursor(dev, screen, NullCursor);
+    if (DevHasCursor(dev))
+        screen->DisplayCursor(dev, screen, NullCursor);
 
     deviceid = dev->id;
     DisableDevice(dev);
commit 68b4f250eef441a3d75e3b9b2665a51d3a1538d6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 14 16:18:48 2008 +0930

    dmx: fix build.
    
    Just because it builds, doesn't mean it works.

diff --git a/hw/dmx/dmxcursor.c b/hw/dmx/dmxcursor.c
index 8a80116..3dcbc33 100644
--- a/hw/dmx/dmxcursor.c
+++ b/hw/dmx/dmxcursor.c
@@ -178,14 +178,14 @@ static void dmxCrossScreen(ScreenPtr pScreen, Bool entering)
 {
 }
 
-static void dmxWarpCursor(ScreenPtr pScreen, int x, int y)
+static void dmxWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     DMXDBG3("dmxWarpCursor(%d,%d,%d)\n", pScreen->myNum, x, y);
 #if 11 /*BP*/
     /* This call is depracated.  Replace with???? */
-    miPointerWarpCursor(pScreen, x, y);
+    miPointerWarpCursor(pDev, pScreen, x, y);
 #else
-    pScreen->SetCursorPosition(pScreen, x, y, FALSE);
+    pScreen->SetCursorPosition(pDev, pScreen, x, y, FALSE);
 #endif
 }
 
@@ -753,7 +753,7 @@ static void _dmxSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
     if (dmxScreen->beDisplay) dmxSync(dmxScreen, TRUE);
 }
 
-static Bool dmxRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+static Bool dmxRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
     DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
     DMXScreenInfo *pt;
@@ -771,7 +771,7 @@ static Bool dmxRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
     return TRUE;
 }
 
-static Bool dmxUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+static Bool dmxUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
     DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
     DMXScreenInfo *pt;
@@ -794,14 +794,14 @@ static CursorPtr dmxFindCursor(DMXScreenInfo *start)
     DMXScreenInfo *pt;
 
     if (!start || !start->over)
-        return GetSpriteCursor();
+        return GetSpriteCursor(inputInfo.pointer);
     for (pt = start->over; /* condition at end of loop */; pt = pt->over) {
         if (pt->cursor)
             return pt->cursor;
         if (pt == start)
             break;
     }
-    return GetSpriteCursor();
+    return GetSpriteCursor(inputInfo.pointer);
 }
 
 /** Move the cursor to coordinates (\a x, \a y)on \a pScreen.  This
@@ -813,7 +813,7 @@ static CursorPtr dmxFindCursor(DMXScreenInfo *start)
  * back-end screens and see if they contain the global coord.  If so, call
  * _dmxMoveCursor() (XWarpPointer) to position the pointer on that screen.
  */
-void dmxMoveCursor(ScreenPtr pScreen, int x, int y)
+void dmxMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
     DMXScreenInfo *pt;
@@ -860,7 +860,7 @@ void dmxMoveCursor(ScreenPtr pScreen, int x, int y)
     }
 }
 
-static void dmxSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+static void dmxSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
 {
     DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
     DMXScreenInfo *pt;
diff --git a/hw/dmx/dmxcursor.h b/hw/dmx/dmxcursor.h
index d909bd0..da8ea5e 100644
--- a/hw/dmx/dmxcursor.h
+++ b/hw/dmx/dmxcursor.h
@@ -55,7 +55,7 @@ extern void dmxReInitOrigins(void);
 extern void dmxInitOrigins(void);
 extern void dmxInitOverlap(void);
 extern void dmxCursorNoMulti(void);
-extern void dmxMoveCursor(ScreenPtr pScreen, int x, int y);
+extern void dmxMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
 extern void dmxCheckCursor(void);
 extern int  dmxOnScreen(int x, int y, DMXScreenInfo *dmxScreen);
 extern void dmxHideCursor(DMXScreenInfo *dmxScreen);
diff --git a/hw/dmx/dmxinput.h b/hw/dmx/dmxinput.h
index 8a3ccdc..7af7b18 100644
--- a/hw/dmx/dmxinput.h
+++ b/hw/dmx/dmxinput.h
@@ -141,8 +141,8 @@ extern void dmxUpdateWindowInfo(DMXUpdateType type, WindowPtr pWindow);
 
 /* These functions are defined in input/dmxeq.c */
 extern Bool dmxeqInitialized(void);
-extern void dmxeqEnqueue(xEvent *e);
-extern void dmxeqSwitchScreen(ScreenPtr pScreen, Bool fromDIX);
+extern void dmxeqEnqueue(DeviceIntPtr pDev, xEvent *e);
+extern void dmxeqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX);
 
 /* This type is used in input/dmxevents.c.  Also, these functions are
  * defined in input/dmxevents.c */
diff --git a/hw/dmx/input/dmxeq.c b/hw/dmx/input/dmxeq.c
index afa2b2c..86ba960 100644
--- a/hw/dmx/input/dmxeq.c
+++ b/hw/dmx/input/dmxeq.c
@@ -99,6 +99,7 @@ typedef struct _Event {
     xEvent	   event;    /**< Event. */
     ScreenPtr	   pScreen;  /**< Screen on which event occurred. */
     deviceValuator valuator; /**< XInput device valuator information. */
+    DeviceIntPtr   pDev;
 } EventRec, *EventPtr;
 
 /** Event queue. */
@@ -154,7 +155,7 @@ Bool dmxeqInit(DevicePtr pKbd, DevicePtr pPtr)
  * called from regular code.
  */
 
-void dmxeqEnqueue(xEvent *e)
+void dmxeqEnqueue(DeviceIntPtr pDev, xEvent *e)
 {
     HWEventQueueType oldtail, newtail;
     Bool             isMotion;
@@ -179,6 +180,7 @@ void dmxeqEnqueue(xEvent *e)
 
                                 /* Store the event in the queue */
     dmxEventQueue.events[oldtail].event   = *e;
+    dmxEventQueue.events[oldtail].pDev    = pDev;
                             /* If this is an XInput event, store the
                              * valuator event, too */
     deviceKeyButtonPointer *ev = (deviceKeyButtonPointer *)e;
@@ -197,7 +199,7 @@ void dmxeqEnqueue(xEvent *e)
 
 /** Make \a pScreen the new screen for enqueueing events.  If \a fromDIX
  * is TRUE, also make \a pScreen the new screen for dequeuing events. */
-void dmxeqSwitchScreen(ScreenPtr pScreen, Bool fromDIX)
+void dmxeqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
 {
     dmxEventQueue.pEnqueueScreen = pScreen;
     if (fromDIX) dmxEventQueue.pDequeueScreen = pScreen;
@@ -258,7 +260,7 @@ void dmxeqProcessInputEvents(void)
 	    y = e->event.u.keyButtonPointer.rootY;
 	    if (dmxEventQueue.head == QUEUE_SIZE - 1) dmxEventQueue.head = 0;
 	    else                                      ++dmxEventQueue.head;
-	    NewCurrentScreen(dmxEventQueue.pDequeueScreen, x, y);
+	    NewCurrentScreen(e->pDev, dmxEventQueue.pDequeueScreen, x, y);
 	} else {
 	    xe[0] = e->event;
 	    if (dmxEventQueue.head == QUEUE_SIZE - 1) dmxEventQueue.head = 0;
diff --git a/hw/dmx/input/dmxevents.c b/hw/dmx/input/dmxevents.c
index 2e24ff4..1d0e872 100644
--- a/hw/dmx/input/dmxevents.c
+++ b/hw/dmx/input/dmxevents.c
@@ -201,7 +201,7 @@ static void dmxEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, xEvent *e,
 
     if (block)
         dmxSigioBlock();
-    dmxeqEnqueue(xE);
+    dmxeqEnqueue(pDevice, xE);
     if (block)
         dmxSigioUnblock();
 }
@@ -227,14 +227,16 @@ static void enqueueMotion(DevicePtr pDev, int x, int y)
     GETDMXLOCALFROMPDEV;
     DeviceIntPtr p = dmxLocal->pDevice;
     int i, nevents, valuators[3];
-    xEvent *events = Xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+    EventListPtr events;
     int detail = 0;  /* XXX should this be mask of pressed buttons? */
     valuators[0] = x;
     valuators[1] = y;
+
+    GetEventList(&events);
     nevents = GetPointerEvents(events, p, MotionNotify, detail,
                                POINTER_ABSOLUTE, 0, 2, valuators);
     for (i = 0; i < nevents; i++)
-       mieqEnqueue(p, events + i);
+       mieqEnqueue(p, (events + i)->event);
     xfree(events);
     return;
 }
@@ -419,7 +421,7 @@ static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
     if (block)
         dmxSigioBlock();
     dmxPointerPutMotionEvent(pDevice, firstAxis, axesCount, v, xev->time);
-    dmxeqEnqueue(xE);
+    dmxeqEnqueue(pDevice, xE);
     if (block)
         dmxSigioUnblock();
 }
@@ -434,6 +436,7 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
     int                    event   = -1;
     XDeviceKeyEvent        *ke     = (XDeviceKeyEvent *)e;
     XDeviceMotionEvent     *me     = (XDeviceMotionEvent *)e;
+    DeviceIntPtr           pDevice = dmxLocal->pDevice;
 
     if (!e)
         return -1;          /* No extended event passed, cannot handle */
@@ -499,7 +502,7 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
 
         if (block)
             dmxSigioBlock();
-        dmxeqEnqueue(xE);
+        dmxeqEnqueue(pDevice, xE);
         if (block)
             dmxSigioUnblock();
         break;
@@ -674,7 +677,7 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
     xEvent xE;
     DeviceIntPtr p = dmxLocal->pDevice;
     int i, nevents, valuators[3];
-    xEvent *events;
+    EventListPtr events;
 
     DMXDBG2("dmxEnqueue: Enqueuing type=%d detail=0x%0x\n", type, detail);
 
@@ -688,25 +691,24 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
         if (dmxLocal->sendsCore && dmxLocal != dmxLocalCoreKeyboard)
             xE.u.u.detail = dmxFixup(pDev, detail, keySym);
 
-        events = Xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        GetEventList(&events);
         /*ErrorF("KEY %d  sym %d\n", detail, (int) keySym);*/
         nevents = GetKeyboardEvents(events, p, type, detail);
         for (i = 0; i < nevents; i++)
-            mieqEnqueue(p, events + i);
-        xfree(events);
+            mieqEnqueue(p, (events + i)->event);
         return;
 
     case ButtonPress:
     case ButtonRelease:
         detail = dmxGetButtonMapping(dmxLocal, detail);
-        events = Xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        GetEventList(&events);
         nevents = GetPointerEvents(events, p, type, detail,
                                    POINTER_ABSOLUTE,
                                    0,   /* first_valuator = 0 */
                                    0,   /* num_valuators = 0 */
                                    valuators);
         for (i = 0; i < nevents; i++)
-            mieqEnqueue(p, events + i);
+            mieqEnqueue(p, (events + i)->event);
         xfree(events);
         return;
 
@@ -718,8 +720,7 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
         nevents = GetPointerEvents(events, p, type, detail, 
                                    POINTER_ABSOLUTE, 0, 3, valuators);
         for (i = 0; i < nevents; i++)
-            mieqEnqueue(p, events + i);
-        xfree(events);
+            mieqEnqueue(p, (events + i)->event);
         return;
 
     case EnterNotify:
diff --git a/hw/dmx/input/dmxinputinit.c b/hw/dmx/input/dmxinputinit.c
index 7b5cc73..277e164 100644
--- a/hw/dmx/input/dmxinputinit.c
+++ b/hw/dmx/input/dmxinputinit.c
@@ -755,7 +755,7 @@ static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal)
     if (!name || !registerProcPtr)
         dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name);
 
-    pDevice                       = AddInputDevice(dmxDeviceOnOff, TRUE);
+    pDevice                       = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE);
     if (!pDevice) {
         dmxLog(dmxError, "Too many devices -- cannot add device %s\n",
                dmxLocal->name);
commit 00db0f35acc00cb771ab1c23f35b0db1c25d81bb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 14 15:29:28 2008 +0930

    dix: InitAndStartDevices doesn't need a window parameter.
    
    Leftover from the old pointer-keyboard pairing code, obsolete and gone now.

diff --git a/dix/devices.c b/dix/devices.c
index 644ee29..05a6b51 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -539,7 +539,7 @@ InitCoreDevices(void)
  * @return Success or error code on failure.
  */
 int
-InitAndStartDevices(WindowPtr root)
+InitAndStartDevices()
 {
     DeviceIntPtr dev, next;
 
diff --git a/dix/main.c b/dix/main.c
index 5dce3df..42d3309 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -412,7 +412,7 @@ int main(int argc, char *argv[], char *envp[])
 
         InitCoreDevices();
 	InitInput(argc, argv);
-	if (InitAndStartDevices(WindowTable[0]) != Success)
+	if (InitAndStartDevices() != Success)
 	    FatalError("failed to initialize core devices");
 
 	dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
diff --git a/include/input.h b/include/input.h
index ec6ac90..13902d7 100644
--- a/include/input.h
+++ b/include/input.h
@@ -231,9 +231,7 @@ extern Bool ActivateDevice(
 extern Bool DisableDevice(
     DeviceIntPtr /*device*/);
 
-extern int InitAndStartDevices(
-    WindowPtr /*root*/);
-
+extern int InitAndStartDevices(void);
 
 extern void CloseDownDevices(void);
 
commit da728f2127aaa5c1ed5d22bb9f3d0c8ff19e4933
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 14 15:17:05 2008 +0930

    dix: don't use serverClient in AddInputDevice, use the one supplied instead.
    
    We pass in the client that wants to create the device anyway, lets use the
    parameter instead of hardcoding the serverClient.
    
    Wow. I hope this is merge detritus, otherwise it'd be a sign that I didn't
    have enough coffee that day.

diff --git a/dix/devices.c b/dix/devices.c
index 82eece7..644ee29 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -169,7 +169,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
 
     /*  security creation/labeling check
      */
-    if (XaceHook(XACE_DEVICE_ACCESS, serverClient, dev, DixCreateAccess)) {
+    if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) {
 	xfree(dev);
 	return NULL;
     }
commit a6659291c798f417a76d9aa7944694ff27c01fa7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 14 09:42:50 2008 +0930

    mi: protect against NULL-pointer dereference.
    
    Required by the recent patch to use a NullCursor instead of UndisplayCursor().

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 8243947..2c226dc 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -357,7 +357,7 @@ miPointerWarpCursor (pDev, pScreen, x, y)
     	{
 	    pPointer->devx = x;
 	    pPointer->devy = y;
-	    if(!pPointer->pCursor->bits->emptyMask)
+	    if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
 		(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     	}
 	pPointer->x = x;
@@ -541,7 +541,7 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
     {
 	pPointer->devx = x;
 	pPointer->devy = y;
-	if(!pPointer->pCursor->bits->emptyMask)
+	if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
 	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     }
 
commit dc3aba8a559d4304844ee1cc306c577a63b82762
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 13 14:37:26 2008 +0930

    Xext: emulate XI events from core events when faking input.
    
    We need XI events for event processing, so lets get rid of the pure core
    events ASAP.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index e96375d..791f6a2 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -52,6 +52,7 @@
 #include "modinit.h"
 
 extern int DeviceValuator;
+extern int DeviceMotionNotify;
 
 #ifdef PANORAMIX
 #include "panoramiX.h"
@@ -235,6 +236,26 @@ ProcXTestFakeInput(client)
                 client->errorValue = ev->u.u.type;
                 return BadValue;
         }
+
+        ev->u.u.type += (DeviceValuator - 1);
+        if (ev->u.u.type == DeviceMotionNotify)
+        {
+            /* fake up valuator */
+            xEvent *ne = xalloc(2 * sizeof(xEvent));
+            if (ne) {
+                memcpy(ne, ev, sizeof(xEvent));
+                memcpy(&ne[1], ev, sizeof(xEvent));
+                ev = ne;
+
+                dv = (deviceValuator*)(ne + 1);
+                dv->type = DeviceValuator;
+                dv->first_valuator = 0;
+                dv->num_valuators = 2;
+                dv->valuator0 = ev->u.keyButtonPointer.rootX;
+                dv->valuator1 = ev->u.keyButtonPointer.rootY;
+                nev = 2;
+            }
+        }
     }
 
     /* If the event has a time set, wait for it to pass */
@@ -338,6 +359,7 @@ ProcXTestFakeInput(client)
                         values += 6;
                     }
                 }
+
                 /* For XI events, the actual event is mostly unset. Since we
                  * want to update the sprite nontheless, we need to fake up
                  * sane values for the event. */
@@ -468,6 +490,7 @@ ProcXTestFakeInput(client)
     if (screenIsSaved == SCREEN_SAVER_ON)
         dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
     ev->u.keyButtonPointer.time = currentTime.milliseconds;
+
     if (!dev->isMaster && dev->u.master)
     {   /* duplicate and route through master */
         xEvent *master_event = NULL;
@@ -477,6 +500,8 @@ ProcXTestFakeInput(client)
         xfree(master_event);
     } else
         (*dev->public.processInputProc)(ev, dev, nev);
+    if (extension)
+        xfree(ev);
     return client->noClientException;
 }
 
commit 8b3802d32041547fd6ed5393a56281c5c83d260e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 13 13:47:52 2008 +0930

    Xext: core button events have rootX/Y unset too.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index e11f358..e96375d 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -455,12 +455,9 @@ ProcXTestFakeInput(client)
         case ButtonRelease:
             if (!extension)
                 dev = PickPointer(client);
-            else
-            {
-                /* For XI events, the rootX/Y is unset. */
-                ev->u.keyButtonPointer.rootX = dev->lastx;
-                ev->u.keyButtonPointer.rootY = dev->lasty;
-            }
+
+            ev->u.keyButtonPointer.rootX = dev->lastx;
+            ev->u.keyButtonPointer.rootY = dev->lasty;
             if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
             {
                 client->errorValue = ev->u.u.detail;
commit 8234af6c6a3ade13f7720743bde79957c7df3f6c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 13 11:17:39 2008 +0930

    xfree86: remove Ubuntu-ism.
    
    Additional #include was required due to broken libc headers or something like
    that. Remove it, there's more to the world than ubuntu alone.

diff --git a/hw/xfree86/os-support/linux/lnx_agp.c b/hw/xfree86/os-support/linux/lnx_agp.c
index 300b08d..ded9e0f 100644
--- a/hw/xfree86/os-support/linux/lnx_agp.c
+++ b/hw/xfree86/os-support/linux/lnx_agp.c
@@ -10,7 +10,6 @@
 
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
-#include <linux/types.h>
 #endif
 
 #include <X11/X.h>
commit 59b8d29b3a91c65787dfadb5610342a62e85c48c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 12 21:22:54 2008 +0930

    Xi: Fix up ProcIVector, got out of sync with the protocol.
    
    When the opcode squash happened in the protocol, the processing vector got out
    of sync for a few requests. As a result, client and server would interpret
    requests differently, leading to a couple of BadLength problems.

diff --git a/Xi/extinit.c b/Xi/extinit.c
index 1d68d1e..613472a 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -212,11 +212,11 @@ static int (*ProcIVector[])(ClientPtr) = {
         ProcXWarpDevicePointer,                 /* 37 */
         ProcXChangeDeviceCursor,                /* 38 */
         ProcXChangeDeviceHierarchy,             /* 39 */
-        ProcXiSelectEvent,                      /* 40 */
-        ProcXChangeWindowAccess,                /* 41 */
-        ProcXQueryWindowAccess,                 /* 42 */
-        ProcXSetClientPointer,                  /* 43 */
-        ProcXGetClientPointer,                  /* 44 */
+        ProcXChangeWindowAccess,                /* 40 */
+        ProcXQueryWindowAccess,                 /* 41 */
+        ProcXSetClientPointer,                  /* 42 */
+        ProcXGetClientPointer,                  /* 43 */
+        ProcXiSelectEvent,                      /* 44 */
         ProcXExtendedGrabDevice                 /* 45 */
 };
 
@@ -262,11 +262,11 @@ static int (*SProcIVector[])(ClientPtr) = {
         SProcXWarpDevicePointer,                 /* 37 */
         SProcXChangeDeviceCursor,                /* 38 */
         SProcXChangeDeviceHierarchy,             /* 39 */
-        SProcXiSelectEvent,                      /* 40 */
-        SProcXChangeWindowAccess,                /* 41 */
-        SProcXQueryWindowAccess,                 /* 42 */
-        SProcXSetClientPointer,                  /* 43 */
-        SProcXGetClientPointer,                  /* 44 */
+        SProcXChangeWindowAccess,                /* 40 */
+        SProcXQueryWindowAccess,                 /* 41 */
+        SProcXSetClientPointer,                  /* 42 */
+        SProcXGetClientPointer,                  /* 43 */
+        SProcXiSelectEvent,                      /* 44 */
         SProcXExtendedGrabDevice                 /* 45 */
 };
 
commit 1fc1a2897e9185838c29d9ffff07c39d2fdf174f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 12 20:14:05 2008 +0930

    Remove UndisplayCursor API.
    
    We can achieve the same thing by simply displaying a NullCursor, there's no
    need for a separate API.

diff --git a/dix/devices.c b/dix/devices.c
index 802bf79..82eece7 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -854,9 +854,7 @@ UndisplayDevices()
     ScreenPtr screen = screenInfo.screens[0];
 
     for (dev = inputInfo.devices; dev; dev = dev->next)
-    {
-        screen->UndisplayCursor(dev, screen);
-    }
+        screen->DisplayCursor(dev, screen, NullCursor);
 }
 
 /**
@@ -887,7 +885,7 @@ RemoveDevice(DeviceIntPtr dev)
         return BadImplementation;
 
     initialized = dev->inited;
-    screen->UndisplayCursor(dev, screen);
+    screen->DisplayCursor(dev, screen, NullCursor);
 
     deviceid = dev->id;
     DisableDevice(dev);
diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 010575b..4d64f62 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -38,8 +38,7 @@ static miPointerSpriteFuncRec xf86CursorSpriteFuncs = {
    xf86CursorSetCursor,
    xf86CursorMoveCursor,
    xf86DeviceCursorInitialize,
-   xf86DeviceCursorCleanup,
-   xf86DeviceCursorUndisplay
+   xf86DeviceCursorCleanup
 };
 
 /* Screen functions */
@@ -504,16 +503,3 @@ xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
     (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
 }
 
-/**
- * Called on server shutdown to remove all cursors from the screen before
- * bringing the server down.
- */
-static void
-xf86DeviceCursorUndisplay(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
-    xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
-            &pScreen->devPrivates, xf86CursorScreenKey);
-
-    /* Undisplay SW cursor */
-    (*ScreenPriv->spriteFuncs->UndisplayCursor)(pDev, pScreen);
-}
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 8a1de4a..6cf9333 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -440,10 +440,6 @@ typedef    void (* MarkUnrealizedWindowProcPtr)(
 	WindowPtr /*pWin*/,
 	Bool /*fromConfigure*/);
 
-typedef    void (* UndisplayCursorProcPtr)(
-        DeviceIntPtr /* pDev */,
-        ScreenPtr    /* pScreen */);
-
 typedef    Bool (* DeviceCursorInitializeProcPtr)(
         DeviceIntPtr /* pDev */,
         ScreenPtr    /* pScreen */);
@@ -601,7 +597,6 @@ typedef struct _Screen {
     MarkUnrealizedWindowProcPtr	MarkUnrealizedWindow;
 
     /* Device cursor procedures */
-    UndisplayCursorProcPtr        UndisplayCursor;
     DeviceCursorInitializeProcPtr DeviceCursorInitialize;
     DeviceCursorCleanupProcPtr    DeviceCursorCleanup;
 } ScreenRec;
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 572af1b..8243947 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -60,7 +60,6 @@ static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
                                      CursorPtr pCursor);
 static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                    CursorPtr pCursor);
-static void miPointerUndisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
 static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
                                      BoxPtr pBox); 
 static void miPointerPointerNonInterestBox(DeviceIntPtr pDev, 
@@ -113,8 +112,6 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     pScreen->ConstrainCursor = miPointerConstrainCursor;
     pScreen->CursorLimits = miPointerCursorLimits;
     pScreen->DisplayCursor = miPointerDisplayCursor;
-    pScreen->UndisplayCursor = miPointerUndisplayCursor;
-    pScreen->UndisplayCursor = miPointerUndisplayCursor;
     pScreen->RealizeCursor = miPointerRealizeCursor;
     pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
     pScreen->SetCursorPosition = miPointerSetCursorPosition;
@@ -213,16 +210,6 @@ miPointerDisplayCursor (pDev, pScreen, pCursor)
 }
 
 static void
-miPointerUndisplayCursor(pDev, pScreen)
-    DeviceIntPtr pDev;
-    ScreenPtr 	 pScreen;
-{
-    SetupScreen(pScreen);
-    if (pDev->isMaster && pDev->spriteInfo->spriteOwner)
-        (*pScreenPriv->spriteFuncs->UndisplayCursor)(pDev, pScreen);
-}
-
-static void
 miPointerConstrainCursor (pDev, pScreen, pBox)
     DeviceIntPtr pDev;
     ScreenPtr	pScreen;
diff --git a/mi/mipointer.h b/mi/mipointer.h
index ed518d1..5cbf527 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -62,10 +62,6 @@ typedef struct _miPointerSpriteFuncRec {
                     DeviceIntPtr /* pDev */,
                     ScreenPtr /* pScr */
                     );
-    void        (*UndisplayCursor)(
-                    DeviceIntPtr /* pDev */,
-                    ScreenPtr /* pScr */
-                    );
 } miPointerSpriteFuncRec, *miPointerSpriteFuncPtr;
 
 typedef struct _miPointerScreenFuncRec {
diff --git a/mi/misprite.c b/mi/misprite.c
index 9e4b685..1218023 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -125,7 +125,6 @@ static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
                               CursorPtr pCursor, int x, int y);
 static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                int x, int y);
-static void miSpriteUndisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
 
 _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
     miSpriteRealizeCursor,
@@ -134,7 +133,6 @@ _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
     miSpriteMoveCursor,
     miSpriteDeviceCursorInitialize,
     miSpriteDeviceCursorCleanup,
-    miSpriteUndisplayCursor
 };
 
 /*
@@ -911,23 +909,6 @@ miSpriteDeviceCursorCleanup(pDev, pScreen)
     }
 }
 
-static void
-miSpriteUndisplayCursor(pDev, pScreen)
-    DeviceIntPtr pDev;
-    ScreenPtr    pScreen;
-{
-    miCursorInfoPtr pCursorInfo;
-
-    if (!pDev->isMaster && !pDev->u.master)
-    {
-        ErrorF("[mi] miSpriteUndisplayCursor called for floating device.\n");
-        return;
-    }
-    pCursorInfo = MISPRITE(pDev);
-    if (pCursorInfo && pCursorInfo->isUp)
-        miSpriteRemoveCursor(pDev, pScreen);
-}
-
 /*
  * undraw/draw cursor
  */
commit 913989d643595030e67e7c0a758a16ae0da62ed9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 12 20:05:43 2008 +0930

    mi: don't try to display a cursor for devices w/o cursors.

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 8f8086c..572af1b 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -199,6 +199,11 @@ miPointerDisplayCursor (pDev, pScreen, pCursor)
     if (!pDev->isMaster && !pDev->u.master)
         return FALSE;
 
+    /* return for keyboards */
+    if ((pDev->isMaster && !DevHasCursor(pDev)) ||
+        (!pDev->isMaster && pDev->u.master && !DevHasCursor(pDev->u.master)))
+            return;
+
     pPointer = MIPOINTER(pDev);
 
     pPointer->pCursor = pCursor;
@@ -449,7 +454,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     else if (pPointer->pCursor != pPointer->pSpriteCursor)
     {
 	pCursor = pPointer->pCursor;
-	if (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)
+	if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
 	    pCursor = NullCursor;
 	(*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
 
@@ -461,7 +466,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     {
 	pPointer->devx = x;
 	pPointer->devy = y;
-	if(!pPointer->pCursor->bits->emptyMask)
+	if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
 	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     }
 }
commit 248a1df63430717550adb0e79068d8f9fcfacb0b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon May 12 20:05:21 2008 +0930

    render: don't dereference cursor if cursor is NULL.

diff --git a/render/animcur.c b/render/animcur.c
index a87718d..362607f 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -93,7 +93,7 @@ static CursorBits   animCursorBits = {
 static int AnimCurGeneration;
 static DevPrivateKey AnimCurScreenPrivateKey = &AnimCurScreenPrivateKey;
 
-#define IsAnimCur(c)	    ((c)->bits == &animCursorBits)
+#define IsAnimCur(c)	    ((c) && ((c)->bits == &animCursorBits))
 #define GetAnimCur(c)	    ((AnimCurPtr) ((c) + 1))
 #define GetAnimCurScreen(s) ((AnimCurScreenPtr)dixLookupPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey))
 #define GetAnimCurScreenIfSet(s) GetAnimCurScreen(s)
commit fc35d1e3be201e3821413bb2eeb8d43e1e56ba17
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 8 16:58:31 2008 +0930

    config: override xkb_{r,m,l,v} with Xkb{r,m,l,v} if the latter is set.
    
    The HAL spec says that input.xkb.{rmlv}* can be sent, but if the user
    specifies a X-specific {rmlv}, then this is overridden through the use of
    input.x11_options.Xkb{RMLV}.
    However, the way how the server parses options--by ignoring capitalisation,
    underscores and spaces--the HAL and the x11_options would override each other.
    
    So we simply filter the options, letting Xkb{RMLV} override xkb_{rmlv} and
    only actually add them to the device after parsing _all_ options.
    
    * rmlv ... rules, model, layout, variant
    
    See Bug 13037 <http://bugs.freedesktop.org/show_bug.cgi?id=13037>

diff --git a/config/hal.c b/config/hal.c
index 7794d8e..67ffa03 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -48,6 +48,15 @@ struct config_hal_info {
     LibHalContext *hal_ctx;
 };
 
+/* Used for special handling of xkb options. */
+struct xkb_options {
+    char* layout;
+    char* model;
+    char* rules;
+    char* variant;
+};
+
+
 static void
 remove_device(DeviceIntPtr dev)
 {
@@ -164,10 +173,11 @@ device_added(LibHalContext *hal_ctx, const char *udi)
     InputOption *options = NULL, *tmpo = NULL;
     DeviceIntPtr dev;
     DBusError error;
+    struct xkb_options xkb_opts = {0};
 
     LibHalPropertySet *set = NULL;
 	LibHalPropertySetIterator set_iter;
-    char *psi_key = NULL, *tmp_val, *tmp_key;
+    char *psi_key = NULL, *tmp_val;
 
 
     dbus_error_init(&error);
@@ -241,27 +251,71 @@ device_added(LibHalContext *hal_ctx, const char *udi)
                 tmp_val = get_prop_string(hal_ctx, udi, psi_key);
 
                 if (tmp_val){
-                    add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val);
-                    xfree(tmp_val);
+                    char* tmp;
+
+                    /* xkb needs special handling. HAL specs include
+                     * input.xkb.xyz options, but the x11-input.fdi specifies
+                     * input.x11_options.Xkbxyz options. By default, we use
+                     * the former, unless the specific X11 ones are specified.
+                     * Since we can't predict the order in which the keys
+                     * arrive, we need to store them.
+                     */
+                    if ((tmp = strcasestr(psi_key, "xkb")))
+                    {
+                        if (!strcasecmp(&tmp[3], "layout"))
+                        {
+                            if (xkb_opts.layout)
+                                xfree(xkb_opts.layout);
+                            xkb_opts.layout = strdup(tmp_val);
+                        } else if (!strcasecmp(&tmp[3], "model"))
+                        {
+                            if (xkb_opts.model)
+                                xfree(xkb_opts.model);
+                            xkb_opts.model = strdup(tmp_val);
+                        } else if (!strcasecmp(&tmp[3], "rules"))
+                        {
+                            if (xkb_opts.rules)
+                                xfree(xkb_opts.rules);
+                            xkb_opts.rules = strdup(tmp_val);
+                        } else if (!strcasecmp(&tmp[3], "variant"))
+                        {
+                            if (xkb_opts.variant)
+                                xfree(xkb_opts.variant);
+                            xkb_opts.variant = strdup(tmp_val);
+                        }
+                    } else
+                    {
+                        /* all others */
+                        add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val);
+                        xfree(tmp_val);
+                    }
                 }
-
-            /* evdev's XKB options... we should probably depreciate this usage */
             } else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){
 
                 /* only support strings for all values */
                 tmp_val = get_prop_string(hal_ctx, udi, psi_key);
 
                 if (tmp_val){
-                    /* add "xkb_" + NULL */
-		    tmp_key = xalloc(strlen(psi_key) - ( sizeof(LIBHAL_XKB_PROP_KEY) - 1) + 5);
-
-                    if (!tmp_key){
-                        LogMessage(X_ERROR, "config/hal: couldn't allocate memory for option %s\n", psi_key);
-                    } else {
-                        sprintf(tmp_key, "xkb_%s", psi_key + sizeof(LIBHAL_XKB_PROP_KEY)-1);
-                        add_option(&options, tmp_key, tmp_val);
-
-                        xfree(tmp_key);
+                    char* tmp;
+
+                    tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1];
+
+                    if (!strcasecmp(tmp, "layout"))
+                    {
+                        if (!xkb_opts.layout)
+                            xkb_opts.layout = strdup(tmp_val);
+                    } else if (!strcasecmp(tmp, "rules"))
+                    {
+                        if (!xkb_opts.rules)
+                            xkb_opts.rules = strdup(tmp_val);
+                    } else if (!strcasecmp(tmp, "variant"))
+                    {
+                        if (!xkb_opts.variant)
+                            xkb_opts.variant = strdup(tmp_val);
+                    } else if (!strcasecmp(tmp, "model"))
+                    {
+                        if (!xkb_opts.model)
+                            xkb_opts.model = strdup(tmp_val);
                     }
                     xfree(tmp_val);
                 }
@@ -272,6 +326,17 @@ device_added(LibHalContext *hal_ctx, const char *udi)
         libhal_psi_next(&set_iter);
     }
 
+
+    /* Now add xkb options */
+    if (xkb_opts.layout)
+        add_option(&options, "xkb_layout", xkb_opts.layout);
+    if (xkb_opts.rules)
+        add_option(&options, "xkb_rules", xkb_opts.rules);
+    if (xkb_opts.variant)
+        add_option(&options, "xkb_variant", xkb_opts.variant);
+    if (xkb_opts.model)
+        add_option(&options, "xkb_model", xkb_opts.model);
+
     /* this isn't an error, but how else do you output something that the user can see? */
     LogMessage(X_INFO, "config/hal: Adding input device %s\n", name);
     if (NewInputDeviceRequest(options, &dev) != Success) {
@@ -304,6 +369,15 @@ unwind:
         xfree(tmpo);
     }
 
+    if (xkb_opts.layout)
+        xfree(xkb_opts.layout);
+    if (xkb_opts.rules)
+        xfree(xkb_opts.rules);
+    if (xkb_opts.model)
+        xfree(xkb_opts.model);
+    if (xkb_opts.variant)
+        xfree(xkb_opts.variant);
+
     dbus_error_free(&error);
 
     return;
commit 1f54c05cf8a6b82e5fc6362f7f8e8fdc2444b9e8
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 8 14:05:56 2008 +0930

    config: remove trailing whitespaces.
    
    It makes my vim look ugly. Put "let c_space_errors=1" into your .vimrc.

diff --git a/config/hal.c b/config/hal.c
index f150646..7794d8e 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -119,7 +119,7 @@ get_prop_string(LibHalContext *hal_ctx, const char *udi, const char *name)
     return ret;
 }
 
-/* this function is no longer used... keep it here in case its needed in 
+/* this function is no longer used... keep it here in case its needed in
  * the future. */
 #if 0
 static char *
@@ -155,7 +155,7 @@ get_prop_string_array(LibHalContext *hal_ctx, const char *udi, const char *prop)
 
     return ret;
 }
-#endif 
+#endif
 
 static void
 device_added(LibHalContext *hal_ctx, const char *udi)
@@ -164,12 +164,12 @@ device_added(LibHalContext *hal_ctx, const char *udi)
     InputOption *options = NULL, *tmpo = NULL;
     DeviceIntPtr dev;
     DBusError error;
-	
+
     LibHalPropertySet *set = NULL;
 	LibHalPropertySetIterator set_iter;
     char *psi_key = NULL, *tmp_val, *tmp_key;
-    
-    
+
+
     dbus_error_init(&error);
 
     driver = get_prop_string(hal_ctx, udi, "input.x11_driver");
@@ -178,13 +178,13 @@ device_added(LibHalContext *hal_ctx, const char *udi)
         LogMessageVerb(X_INFO,7,"config/hal: no driver specified for device %s\n", udi);
         goto unwind;
     }
-    
+
     path = get_prop_string(hal_ctx, udi, "input.device");
     if (!path) {
         LogMessage(X_WARNING,"config/hal: no driver or path specified for %s\n", udi);
         goto unwind;
     }
-    
+
     name = get_prop_string(hal_ctx, udi, "info.product");
     if (!name)
         name = xstrdup("(unnamed)");
@@ -194,7 +194,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
         LogMessage(X_ERROR, "config/hal: couldn't allocate space for input options!\n");
         goto unwind;
     }
-    
+
     options->key = xstrdup("_source");
     options->value = xstrdup("server/hal");
     if (!options->key || !options->value) {
@@ -202,14 +202,14 @@ device_added(LibHalContext *hal_ctx, const char *udi)
         goto unwind;
     }
 
-    /* most drivers use device.. not path. evdev uses both however, but the 
+    /* most drivers use device.. not path. evdev uses both however, but the
      * path version isn't documented apparently. support both for now. */
     add_option(&options, "path", path);
     add_option(&options, "device", path);
-    
+
     add_option(&options, "driver", driver);
     add_option(&options, "name", name);
-    
+
     config_info = xalloc(strlen(udi) + 5); /* "hal:" and NULL */
     if (!config_info) {
         LogMessage(X_ERROR, "config/hal: couldn't allocate name\n");
@@ -220,58 +220,58 @@ device_added(LibHalContext *hal_ctx, const char *udi)
     /* ok, grab options from hal.. iterate through all properties
     * and lets see if any of them are options that we can add */
     set = libhal_device_get_all_properties(hal_ctx, udi, &error);
-    
+
     if (!set) {
         LogMessage(X_ERROR, "config/hal: couldn't get property list for %s: %s (%s)\n",
                udi, error.name, error.message);
         goto unwind;
     }
-	
+
     libhal_psi_init(&set_iter,set);
     while (libhal_psi_has_more(&set_iter)) {
         /* we are looking for supported keys.. extract and add to options */
-        psi_key = libhal_psi_get_key(&set_iter);    
-        
+        psi_key = libhal_psi_get_key(&set_iter);
+
         if (psi_key){
 
             /* normal options first (input.x11_options.<propname>) */
             if (!strncasecmp(psi_key, LIBHAL_PROP_KEY, sizeof(LIBHAL_PROP_KEY)-1)){
-                
+
                 /* only support strings for all values */
                 tmp_val = get_prop_string(hal_ctx, udi, psi_key);
-                
+
                 if (tmp_val){
                     add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val);
                     xfree(tmp_val);
                 }
-            
+
             /* evdev's XKB options... we should probably depreciate this usage */
             } else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){
-                
+
                 /* only support strings for all values */
                 tmp_val = get_prop_string(hal_ctx, udi, psi_key);
-                
+
                 if (tmp_val){
                     /* add "xkb_" + NULL */
 		    tmp_key = xalloc(strlen(psi_key) - ( sizeof(LIBHAL_XKB_PROP_KEY) - 1) + 5);
-                    
+
                     if (!tmp_key){
                         LogMessage(X_ERROR, "config/hal: couldn't allocate memory for option %s\n", psi_key);
                     } else {
                         sprintf(tmp_key, "xkb_%s", psi_key + sizeof(LIBHAL_XKB_PROP_KEY)-1);
                         add_option(&options, tmp_key, tmp_val);
-                        
+
                         xfree(tmp_key);
                     }
                     xfree(tmp_val);
-                }   
+                }
             }
         }
-        
+
         /* psi_key doesn't need to be freed */
         libhal_psi_next(&set_iter);
     }
-	
+
     /* this isn't an error, but how else do you output something that the user can see? */
     LogMessage(X_INFO, "config/hal: Adding input device %s\n", name);
     if (NewInputDeviceRequest(options, &dev) != Success) {
@@ -413,7 +413,7 @@ config_hal_init(void)
 
     /* verbose message */
     LogMessageVerb(X_INFO,7,"config/hal: initialized");
-    
+
     return 1;
 }
 
commit 1a314a1ef06222977e7ccb94331ce31c17534b2a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 8 13:16:48 2008 +0930

    Revert "config: deprecate (and ignore) the use of input.xkb.whatever options."
    
    daniels:
    "Hrm, I'd prefer to have input.xkb.{m,l,v,o} be the primary keys, and
    have input.x11_options be a backup for that, rather than the former
    being deprecated, for the reasons I listed earlier ..."
    
    see http://bugs.freedesktop.org/show_bug.cgi?id=13037#c51
    
    This reverts commit 26188875de1ccc84ac60bfb251e3ec43de2b9e22.

diff --git a/config/hal.c b/config/hal.c
index 05a02cc..f150646 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -167,7 +167,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
 	
     LibHalPropertySet *set = NULL;
 	LibHalPropertySetIterator set_iter;
-    char *psi_key = NULL, *tmp_val;
+    char *psi_key = NULL, *tmp_val, *tmp_key;
     
     
     dbus_error_init(&error);
@@ -244,10 +244,27 @@ device_added(LibHalContext *hal_ctx, const char *udi)
                     add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val);
                     xfree(tmp_val);
                 }
-            }           /* don't accept input.xkb.whatever options anymore */
-            else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){
-                LogMessage(X_ERROR, "config/hal: Option '%s' is "
-                        "deprecated (ignoring).\n", psi_key);
+            
+            /* evdev's XKB options... we should probably depreciate this usage */
+            } else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){
+                
+                /* only support strings for all values */
+                tmp_val = get_prop_string(hal_ctx, udi, psi_key);
+                
+                if (tmp_val){
+                    /* add "xkb_" + NULL */
+		    tmp_key = xalloc(strlen(psi_key) - ( sizeof(LIBHAL_XKB_PROP_KEY) - 1) + 5);
+                    
+                    if (!tmp_key){
+                        LogMessage(X_ERROR, "config/hal: couldn't allocate memory for option %s\n", psi_key);
+                    } else {
+                        sprintf(tmp_key, "xkb_%s", psi_key + sizeof(LIBHAL_XKB_PROP_KEY)-1);
+                        add_option(&options, tmp_key, tmp_val);
+                        
+                        xfree(tmp_key);
+                    }
+                    xfree(tmp_val);
+                }   
             }
         }
         
diff --git a/config/x11-input.fdi b/config/x11-input.fdi
index 85d7a1f..f2e2d50 100644
--- a/config/x11-input.fdi
+++ b/config/x11-input.fdi
@@ -26,21 +26,19 @@
 	    Do not specify "input.x11_options.Device" since "input.device"
 	    will be used automatically.
 
-
-        XKB configuration:
-	     "input.x11_options.XkbRules"
-	     "input.x11_options.XkbModel"
-	     "input.x11_options.XkbLayout"
-	     "input.x11_options.XkbVariant"
-	     "input.x11_options.XkbOptions"
-
-        Legacy Keys (deprecated and ignored by the server):
+        Legacy Keys
 	     "input.xkb.rules"
              "input.xkb.model"
              "input.xkb.layout"
              "input.xkb.variant"
              "input.xkb.options"
              
+            These keys are deprecated. Use these instead:
+	     "input.x11_options.XkbRules"
+	     "input.x11_options.XkbModel"
+	     "input.x11_options.XkbLayout"
+	     "input.x11_options.XkbVariant"
+	     "input.x11_options.XkbOptions"
 
 	    See the evdev documentation for more information. 
     
commit 26188875de1ccc84ac60bfb251e3ec43de2b9e22
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 7 13:13:57 2008 +0930

    config: deprecate (and ignore) the use of input.xkb.whatever options.
    
    These options are still sent by some HAL implementations (e.g. HAL on FC8),
    and may overwrite the options set in the x11-input.fdi file.
    For a more detailed description of why see Bug #13037, comment 42.
    
    X.Org Bug 13037 <http://bugs.freedesktop.org/show_bug.cgi?id=13037#c42>

diff --git a/config/hal.c b/config/hal.c
index f150646..05a02cc 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -167,7 +167,7 @@ device_added(LibHalContext *hal_ctx, const char *udi)
 	
     LibHalPropertySet *set = NULL;
 	LibHalPropertySetIterator set_iter;
-    char *psi_key = NULL, *tmp_val, *tmp_key;
+    char *psi_key = NULL, *tmp_val;
     
     
     dbus_error_init(&error);
@@ -244,27 +244,10 @@ device_added(LibHalContext *hal_ctx, const char *udi)
                     add_option(&options, psi_key + sizeof(LIBHAL_PROP_KEY)-1, tmp_val);
                     xfree(tmp_val);
                 }
-            
-            /* evdev's XKB options... we should probably depreciate this usage */
-            } else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){
-                
-                /* only support strings for all values */
-                tmp_val = get_prop_string(hal_ctx, udi, psi_key);
-                
-                if (tmp_val){
-                    /* add "xkb_" + NULL */
-		    tmp_key = xalloc(strlen(psi_key) - ( sizeof(LIBHAL_XKB_PROP_KEY) - 1) + 5);
-                    
-                    if (!tmp_key){
-                        LogMessage(X_ERROR, "config/hal: couldn't allocate memory for option %s\n", psi_key);
-                    } else {
-                        sprintf(tmp_key, "xkb_%s", psi_key + sizeof(LIBHAL_XKB_PROP_KEY)-1);
-                        add_option(&options, tmp_key, tmp_val);
-                        
-                        xfree(tmp_key);
-                    }
-                    xfree(tmp_val);
-                }   
+            }           /* don't accept input.xkb.whatever options anymore */
+            else if (!strncasecmp(psi_key, LIBHAL_XKB_PROP_KEY, sizeof(LIBHAL_XKB_PROP_KEY)-1)){
+                LogMessage(X_ERROR, "config/hal: Option '%s' is "
+                        "deprecated (ignoring).\n", psi_key);
             }
         }
         
diff --git a/config/x11-input.fdi b/config/x11-input.fdi
index f2e2d50..85d7a1f 100644
--- a/config/x11-input.fdi
+++ b/config/x11-input.fdi
@@ -26,19 +26,21 @@
 	    Do not specify "input.x11_options.Device" since "input.device"
 	    will be used automatically.
 
-        Legacy Keys
+
+        XKB configuration:
+	     "input.x11_options.XkbRules"
+	     "input.x11_options.XkbModel"
+	     "input.x11_options.XkbLayout"
+	     "input.x11_options.XkbVariant"
+	     "input.x11_options.XkbOptions"
+
+        Legacy Keys (deprecated and ignored by the server):
 	     "input.xkb.rules"
              "input.xkb.model"
              "input.xkb.layout"
              "input.xkb.variant"
              "input.xkb.options"
              
-            These keys are deprecated. Use these instead:
-	     "input.x11_options.XkbRules"
-	     "input.x11_options.XkbModel"
-	     "input.x11_options.XkbLayout"
-	     "input.x11_options.XkbVariant"
-	     "input.x11_options.XkbOptions"
 
 	    See the evdev documentation for more information. 
     
commit 9e0d73fd8a43647b648ec5b2f0bcaae30c03259c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 6 17:52:15 2008 +0930

    xfree86: call SetCursor for the VCP when switching between SW/HW rendering.
    
    We need a manual call to SetCursor when we switch from SW to HW rendering and
    the other way round. This way we display the new cursor after removing the old
    one.
    In addition, we only update the internal state for the VCP's sprite. This way,
    when we switch back to HW rendering the state is up-to-date and wasn't
    overwritten with the other sprite's state.
    
    The second part is a hack. It would be better to keep a state for each sprite,
    but then again we don't have hardware that can render multiple cursors so we
    might as well do with the hack.

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 4ecb03e..010575b 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -302,10 +302,16 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
     xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
     miPointerScreenPtr PointPriv;
 
-    ScreenPriv->CurrentCursor = pCurs;
-    ScreenPriv->x = x;
-    ScreenPriv->y = y;
-    ScreenPriv->CursorToRestore = NULL;
+    /* only update for VCP, otherwise we get cursor jumps when removing a
+       sprite. The second cursor is never HW rendered anyway. */
+    if (pDev == inputInfo.pointer ||
+	    (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
+    {
+	ScreenPriv->CurrentCursor = pCurs;
+	ScreenPriv->x = x;
+	ScreenPriv->y = y;
+	ScreenPriv->CursorToRestore = NULL;
+    }
 
     if (!infoPtr->pScrn->vtSema)
 	 ScreenPriv->SavedCursor = pCurs;
@@ -322,8 +328,12 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
 	return;
     }
 
-    ScreenPriv->HotX = pCurs->bits->xhot;
-    ScreenPriv->HotY = pCurs->bits->yhot;
+    if (pDev == inputInfo.pointer ||
+	    (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
+    {
+	ScreenPriv->HotX = pCurs->bits->xhot;
+	ScreenPriv->HotY = pCurs->bits->yhot;
+    }
 
     PointPriv = (miPointerScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
 						     miPointerScreenKey);
@@ -379,12 +389,17 @@ xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
 	&pScreen->devPrivates, xf86CursorScreenKey);
 
-    ScreenPriv->x = x;
-    ScreenPriv->y = y;
+    /* only update coordinate state for first sprite, otherwise we get jumps
+       when removing a sprite. The second sprite is never HW rendered anyway */
+    if (pDev == inputInfo.pointer ||
+            (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
+    {
+	ScreenPriv->x = x;
+	ScreenPriv->y = y;
+    }
 
     if (ScreenPriv->CursorToRestore)
-	xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore,
-			    ScreenPriv->x, ScreenPriv->y);
+	xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x, y);
     else if (ScreenPriv->SWCursor)
 	(*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y);
     else if (ScreenPriv->isUp)
@@ -441,14 +456,24 @@ xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr)
 static Bool
 xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
 {
+    int ret;
     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
             &pScreen->devPrivates, xf86CursorScreenKey);
 
+    /* Init SW cursor */
+    ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen);
+
     if (pDev != inputInfo.pointer)
+    {
+	if (!ScreenPriv->SWCursor)
+	{
+	    ScreenPriv->spriteFuncs->SetCursor(inputInfo.pointer, pScreen,
+		    ScreenPriv->CurrentCursor, ScreenPriv->x, ScreenPriv->y);
+	}
         ScreenPriv->SWCursor = TRUE | XF86_FORCE_SW_CURSOR;
+    }
 
-    /* Init SW cursor */
-    return (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen);
+    return ret;
 }
 
 /**
@@ -469,7 +494,11 @@ xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
     }
 
     if (!it) /* no other sprites except VCP. restore HW rendering */
-        ScreenPriv->SWCursor = TRUE;
+    {
+	ScreenPriv->SWCursor = TRUE;
+	xf86CursorSetCursor(inputInfo.pointer, pScreen,
+		ScreenPriv->CurrentCursor, ScreenPriv->x, ScreenPriv->y);
+    }
 
     /* Clean up SW cursor */
     (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
commit b9c1a57e7a98dea63cd362f714411547e728a85a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 6 14:51:23 2008 +0930

    xfree86: switch between to SW cursors if more than 1 sprite is available.
    
    Switches back to HW cursors when sprites other than the VCP are removed.
    The current state requires the cursor to change shape once before it updates
    to SW / HW rendering (whatever is appropriate), e.g. by moving into a
    different window. Until this is done, the cursor is invisible.

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 61fb0ed..4ecb03e 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -20,6 +20,8 @@ extern InputInfo inputInfo;
 
 DevPrivateKey xf86CursorScreenKey = &xf86CursorScreenKey;
 
+#define XF86_FORCE_SW_CURSOR (1 << 7)
+
 /* sprite functions */
 
 static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
@@ -325,25 +327,29 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
 
     PointPriv = (miPointerScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
 						     miPointerScreenKey);
-    if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || ((
+    if (!(ScreenPriv->SWCursor & XF86_FORCE_SW_CURSOR))
+    {
+	if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || ((
 #ifdef ARGB_CURSOR
-	pCurs->bits->argb && infoPtr->UseHWCursorARGB &&
-	 (*infoPtr->UseHWCursorARGB) (pScreen, pCurs) ) || (
-	pCurs->bits->argb == 0 &&
+			    pCurs->bits->argb && infoPtr->UseHWCursorARGB &&
+			    (*infoPtr->UseHWCursorARGB) (pScreen, pCurs) ) || (
+			    pCurs->bits->argb == 0 &&
 #endif
-	(pCurs->bits->height <= infoPtr->MaxHeight) &&
-	(pCurs->bits->width <= infoPtr->MaxWidth) &&
-	(!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs))))))
-    {
+			    (pCurs->bits->height <= infoPtr->MaxHeight) &&
+			    (pCurs->bits->width <= infoPtr->MaxWidth) &&
+			    (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs))))))
+	{
 
 	if (ScreenPriv->SWCursor)	/* remove the SW cursor */
-	      (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y);
+	  (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y);
 
 	xf86SetCursor(pScreen, pCurs, x, y);
 	ScreenPriv->SWCursor = FALSE;
 	ScreenPriv->isUp = TRUE;
 	PointPriv->waitForUpdate = !infoPtr->pScrn->silkenMouse;
 	return;
+  }
+
     }
 
     PointPriv->waitForUpdate = TRUE;
@@ -358,10 +364,12 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs,
 	}
     }
 
-    ScreenPriv->SWCursor = TRUE;
+    if (!ScreenPriv->SWCursor)
+        ScreenPriv->SWCursor = TRUE;
 
     if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent)
 	pCurs = NullCursor;
+
     (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, pCurs, x, y);
 }
 
@@ -436,6 +444,9 @@ xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
             &pScreen->devPrivates, xf86CursorScreenKey);
 
+    if (pDev != inputInfo.pointer)
+        ScreenPriv->SWCursor = TRUE | XF86_FORCE_SW_CURSOR;
+
     /* Init SW cursor */
     return (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen);
 }
@@ -446,9 +457,20 @@ xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
 static void
 xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
 {
+    DeviceIntPtr it;
     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
             &pScreen->devPrivates, xf86CursorScreenKey);
 
+    for (it = inputInfo.devices; it; it = it->next)
+    {
+        if (it->isMaster && it != inputInfo.pointer && it !=
+                inputInfo.keyboard)
+            break;
+    }
+
+    if (!it) /* no other sprites except VCP. restore HW rendering */
+        ScreenPriv->SWCursor = TRUE;
+
     /* Clean up SW cursor */
     (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
 }
commit 3df88c17e315b5ae580096e4bc88920d1f452e83
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue May 6 11:50:20 2008 +0930

    xfree86: re-enable hardware cursor (for a single cursor)
    
    This commit enables HW rendering for cursors again, but only for a single
    cursor. Other cursors can be created, however they will not be visible.

diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index 5c909c7..61fb0ed 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -26,12 +26,18 @@ static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
 static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
 static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int);
 static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int);
+static Bool xf86DeviceCursorInitialize(DeviceIntPtr, ScreenPtr);
+static void xf86DeviceCursorCleanup(DeviceIntPtr, ScreenPtr);
+static void xf86DeviceCursorUndisplay(DeviceIntPtr, ScreenPtr);
 
 static miPointerSpriteFuncRec xf86CursorSpriteFuncs = {
    xf86CursorRealizeCursor,
    xf86CursorUnrealizeCursor,
    xf86CursorSetCursor,
-   xf86CursorMoveCursor
+   xf86CursorMoveCursor,
+   xf86DeviceCursorInitialize,
+   xf86DeviceCursorCleanup,
+   xf86DeviceCursorUndisplay
 };
 
 /* Screen functions */
@@ -420,3 +426,43 @@ xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr)
 {
     xfree(infoPtr);
 }
+
+/**
+ * New cursor has been created. Do your initalizations here.
+ */
+static Bool
+xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+    xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+            &pScreen->devPrivates, xf86CursorScreenKey);
+
+    /* Init SW cursor */
+    return (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen);
+}
+
+/**
+ * Cursor has been removed. Clean up after yourself.
+ */
+static void
+xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+    xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+            &pScreen->devPrivates, xf86CursorScreenKey);
+
+    /* Clean up SW cursor */
+    (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
+}
+
+/**
+ * Called on server shutdown to remove all cursors from the screen before
+ * bringing the server down.
+ */
+static void
+xf86DeviceCursorUndisplay(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+    xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+            &pScreen->devPrivates, xf86CursorScreenKey);
+
+    /* Undisplay SW cursor */
+    (*ScreenPriv->spriteFuncs->UndisplayCursor)(pDev, pScreen);
+}
diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c
index 4c5ef40..d10e283 100644
--- a/hw/xfree86/ramdac/xf86HWCurs.c
+++ b/hw/xfree86/ramdac/xf86HWCurs.c
@@ -73,10 +73,6 @@ static unsigned char* RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
 Bool
 xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
 {
-    /* Graphics cards cannot render multiple cursors in hardware. We have to
-       software render them. */
-    return FALSE;
-
     if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
 	return FALSE;
 
commit 6f63724b28c8b3fd85314fb95d1e4f363b610e19
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 2 14:56:58 2008 +0930

    xfree86: don't try to repaint the cursor before cursors exist.

diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 42a4eaa..73a4663 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -596,8 +596,10 @@ xf86_reload_cursors (ScreenPtr screen)
     CursorPtr		cursor;
     int			x, y;
     
-    /* initial mode setting will not have set a screen yet */
-    if (!screen)
+    /* initial mode setting will not have set a screen yet.
+       May be called before the devices are initialised.
+     */
+    if (!screen || !inputInfo.pointer)
 	return;
     scrn = xf86Screens[screen->myNum];
     xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
commit 334456952930cb3e55c02fcdada2d0c074cd0520
Merge: 8e56fd9... 3b8d534...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 2 11:00:14 2008 +0930

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	Xi/exevents.c
    	dix/devices.c

diff --cc Xi/exevents.c
index d0c10d9,641bead..b284547
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@@ -2140,7 -1279,9 +2140,9 @@@ SendEventToAllWindows(DeviceIntPtr dev
  
      for (i = 0; i < screenInfo.numScreens; i++) {
          pWin = WindowTable[i];
+         if (!pWin)
+             continue;
 -        (void)DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, dev->id);
 +        (void)DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab, dev->id);
          p1 = pWin->firstChild;
          FindInterestedChildren(dev, p1, mask, ev, count);
      }
diff --cc dix/getevents.c
index 414e27e,0229c0a..0879434
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -474,10 -407,9 +474,10 @@@ GetKeyboardValuatorEvents(EventList *ev
                            int num_valuators, int *valuators) {
      int numEvents = 0;
      CARD32 ms = 0;
-     KeySym *map = pDev->key->curKeySyms.map;
-     KeySym sym = map[key_code * pDev->key->curKeySyms.mapWidth];
+     KeySym *map;
+     KeySym sym;
      deviceKeyButtonPointer *kbp = NULL;
 +    DeviceIntPtr master;
  
      if (!events)
          return 0;
@@@ -486,29 -418,20 +486,31 @@@
      if (type != KeyPress && type != KeyRelease)
          return 0;
  
--    if (!pDev->key || !pDev->focus || !pDev->kbdfeed ||
-         (pDev->coreEvents && !inputInfo.keyboard->key))
 -        (pDev->coreEvents && !(inputInfo.keyboard && inputInfo.keyboard->key)))
++    if (!pDev->key || !pDev->focus || !pDev->kbdfeed)
          return 0;
  
 +    numEvents = 1;
 +
      if (key_code < 8 || key_code > 255)
          return 0;
 -    
 +
+     map = pDev->key->curKeySyms.map;
+     sym = map[key_code * pDev->key->curKeySyms.mapWidth];
+ 
 -    if (pDev->coreEvents)
 -        numEvents = 2;
 -    else
 -        numEvents = 1;
 +    master = pDev->u.master;
 +    if (master && master->u.lastSlave != pDev)
 +    {
 +        CreateClassesChangedEvent(events, master, pDev);
 +
 +        if (master->valuator && pDev->valuator)
 +        {
 +            pDev->lastx = master->lastx;
 +            pDev->lasty = master->lasty;
 +        }
 +        master->u.lastSlave = pDev;
 +        numEvents++;
 +        events++;
 +    }
  
      if (num_valuators) {
          if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS)
commit 8e56fd9728d63a7a48ef44503425c6e25c7c9ffb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri May 2 10:22:06 2008 +0930

    dix: continue to check for invalid valuator ranges.
    
    In an ideal world, the drivers would init all axes with NO_AXIS_LIMIT. In the
    real world, this is an ABI break, so let's just leave the old check in.

diff --git a/dix/getevents.c b/dix/getevents.c
index 6f25fe8..414e27e 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -358,7 +358,14 @@ clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
 {
     AxisInfoPtr axis = pDev->valuator->axes + axisNum;
 
-    /* InitValuatoraAxisStruct ensures that (min < max) */
+    /* InitValuatoraAxisStruct ensures that (min < max). */
+
+
+    /* FIXME: drivers need to be updated, evdev e.g. inits axes as min = 0 and
+     * max = -1. Leave this extra check until the drivers have been updated.
+     */
+    if (axis->max_value < axis->min_value)
+        return;
 
     if (axis->min_value != NO_AXIS_LIMITS &&
             *val < axis->min_value)
commit a0e6a7d4f507c5c0a0b11adb10394af58a0a6e07
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 30 17:57:48 2008 +0930

    dix: resize EQ to minimum size to avoid reallocs during SIGIO.
    
    When a new device is added, calculate the event size needed if a DCCE event is
    sent and set the EQ's event size to this minimum. This avoids reallocs when a
    event is sent (which may happen during a SIGIO).

diff --git a/dix/devices.c b/dix/devices.c
index abd3cb6..802bf79 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -249,6 +249,7 @@ EnableDevice(DeviceIntPtr dev)
     listlen = GetEventList(&evlist);
     OsBlockSignals();
     SetMinimumEventSize(evlist, listlen, evsize);
+    mieqResizeEvents(evsize);
     OsReleaseSignals();
 
     if ((*prev != dev) || !dev->inited ||
diff --git a/mi/mi.h b/mi/mi.h
index 842edf3..0af1a1b 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -153,6 +153,10 @@ extern Bool mieqInit(
     void
 );
 
+extern void mieqResize(
+    int /* min_size */
+);
+
 extern void mieqEnqueue(
     DeviceIntPtr /*pDev*/,
     xEventPtr /*e*/
diff --git a/mi/mieq.c b/mi/mieq.c
index 9f81867..3ab8936 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -102,6 +102,16 @@ mieqInit(void)
     return TRUE;
 }
 
+/* Ensure all events in the EQ are at least size bytes. */
+Bool
+mieqResizeEvents(int min_size)
+{
+    int i;
+
+    for (i = 0; i < QUEUE_SIZE; i++)
+        SetMinimumEventSize(miEventQueue.events[i].events, 7, min_size);
+}
+
 /*
  * Must be reentrant with ProcessInputEvents.  Assumption: mieqEnqueue
  * will never be interrupted.  If this is called from both signal
commit fea39c94bcc8b635d37530d8a27ee92acab484fe
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 30 13:17:14 2008 +0930

    dix: fix typo from last commit.

diff --git a/dix/getevents.c b/dix/getevents.c
index a358bb3..6f25fe8 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -356,17 +356,17 @@ acceleratePointer(DeviceIntPtr pDev, int first_valuator, int num_valuators,
 static void
 clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
 {
-    AxisInfoPtr axes = pDev->valuator->axes + axisNum;
+    AxisInfoPtr axis = pDev->valuator->axes + axisNum;
 
     /* InitValuatoraAxisStruct ensures that (min < max) */
 
-    if (axes->min_value != NO_AXIS_LIMITS &&
+    if (axis->min_value != NO_AXIS_LIMITS &&
             *val < axis->min_value)
-        *val = axes->min_value;
+        *val = axis->min_value;
 
-    if (axes->max_value != NO_AXIS_LIMITS &&
-            *val > axes->max_value)
-        *val = axes->max_value;
+    if (axis->max_value != NO_AXIS_LIMITS &&
+            *val > axis->max_value)
+        *val = axis->max_value;
 }
 
 /**
commit ffaccc2dc91f4ca4ea10da010206a0a7d2b5540c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 30 11:45:19 2008 +0930

    input: replace -1 as default axis limit with NO_AXIS_LIMIT define.
    
    This allows easier refacturing of the coordinate limit handling. Grepping for
    -1 is boring.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 761950e..d0c10d9 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1153,13 +1153,22 @@ InitProximityClassDeviceStruct(DeviceIntPtr dev)
     return TRUE;
 }
 
+/**
+ * Initialise the device's valuators. The memory must already be allocated,
+ * this function merely inits the matching axis (specified through axnum) to
+ * sane values.
+ *
+ * It is a condition that (minval < maxval).
+ *
+ * @see InitValuatorClassDeviceStruct
+ */
 _X_EXPORT void
 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
 		       int resolution, int min_res, int max_res)
 {
     AxisInfoPtr ax;
-  
-    if (!dev || !dev->valuator)
+
+    if (!dev || !dev->valuator || minval > maxval)
         return;
 
     ax = dev->valuator->axes + axnum;
diff --git a/dix/devices.c b/dix/devices.c
index 37feb34..abd3cb6 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1187,7 +1187,8 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
         AllocateMotionHistory(dev);
 
     for (i=0; i<numAxes; i++) {
-        InitValuatorAxisStruct(dev, i, -1, -1, 0, 0, 0);
+        InitValuatorAxisStruct(dev, i, NO_AXIS_LIMITS, NO_AXIS_LIMITS,
+                               0, 0, 0);
 	valc->axisVal[i]=0;
     }
     return TRUE;
@@ -1203,10 +1204,10 @@ InitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
         return FALSE;
 
     /* we don't do anything sensible with these, but should */
-    abs->min_x = -1;
-    abs->min_y = -1;
-    abs->max_x = -1;
-    abs->max_y = -1;
+    abs->min_x = NO_AXIS_LIMITS;
+    abs->min_y = NO_AXIS_LIMITS;
+    abs->max_x = NO_AXIS_LIMITS;
+    abs->max_y = NO_AXIS_LIMITS;
     abs->flip_x = 0;
     abs->flip_y = 0;
     abs->rotation = 0;
@@ -1214,8 +1215,8 @@ InitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
 
     abs->offset_x = 0;
     abs->offset_y = 0;
-    abs->width = -1;
-    abs->height = -1;
+    abs->width = NO_AXIS_LIMITS;
+    abs->height = NO_AXIS_LIMITS;
     abs->following = 0;
     abs->screen = 0;
 
diff --git a/dix/getevents.c b/dix/getevents.c
index e9c1db0..a358bb3 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -358,14 +358,15 @@ clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
 {
     AxisInfoPtr axes = pDev->valuator->axes + axisNum;
 
-    /* Don't clip if min_value and max_value are the same, or if an invalid
-       range is specified. */
-    if(axes->min_value < axes->max_value) {
-        if (*val < axes->min_value)
-            *val = axes->min_value;
-        if (*val > axes->max_value)
-            *val = axes->max_value;
-    }
+    /* InitValuatoraAxisStruct ensures that (min < max) */
+
+    if (axes->min_value != NO_AXIS_LIMITS &&
+            *val < axis->min_value)
+        *val = axes->min_value;
+
+    if (axes->max_value != NO_AXIS_LIMITS &&
+            *val > axes->max_value)
+        *val = axes->max_value;
 }
 
 /**
diff --git a/include/input.h b/include/input.h
index 10dadfe..ec6ac90 100644
--- a/include/input.h
+++ b/include/input.h
@@ -63,6 +63,8 @@ SOFTWARE.
 #define POINTER_ABSOLUTE (1 << 2)
 #define POINTER_ACCELERATE (1 << 3)
 
+#define NO_AXIS_LIMITS -1
+
 #define MAP_LENGTH	256
 #define DOWN_LENGTH	32	/* 256/8 => number of bytes to hold 256 bits */
 #define NullGrab ((GrabPtr)NULL)
commit 00acb40f2bc5bb4a1977b9b08db75630677ff787
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 30 11:29:03 2008 +0930

    dix: fix typo in clipAxis.
    
    Check needs to be (min_axis < max_axis), not (min_axis < min_axis)

diff --git a/dix/getevents.c b/dix/getevents.c
index 0a44a80..e9c1db0 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -358,8 +358,9 @@ clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
 {
     AxisInfoPtr axes = pDev->valuator->axes + axisNum;
 
-    /* No clipping if the value-range <= 0 */
-    if(axes->min_value < axes->min_value) {
+    /* Don't clip if min_value and max_value are the same, or if an invalid
+       range is specified. */
+    if(axes->min_value < axes->max_value) {
         if (*val < axes->min_value)
             *val = axes->min_value;
         if (*val > axes->max_value)
commit 18b33dd4ff46f63bad70b493b1d0b0758c961ada
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 29 15:24:55 2008 +0930

    Xi: stop excessive use of _X_EXPORT.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 68e82dd..761950e 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -107,7 +107,7 @@ RegisterOtherDevice(DeviceIntPtr device)
     device->public.realInputProc = ProcessOtherEvent;
 }
 
-_X_EXPORT Bool
+Bool
 IsPointerEvent(xEvent* xE)
 {
     switch(xE->u.u.type)
@@ -490,7 +490,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
  * Saves a few memory allocations.
  */
 
-_X_EXPORT void
+void
 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 {
     ClassesPtr classes;
@@ -778,7 +778,7 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
 #define DEFAULT 0
 #define DONT_PROCESS 1
 #define IS_REPEAT 2
-_X_EXPORT int
+int
 UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 {
     int i;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 99ace89..1d68d1e 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -966,7 +966,7 @@ IResetProc(ExtensionEntry * unused)
  *
  */
 
-_X_EXPORT Bool
+Bool
 DeviceIsPointerType(DeviceIntPtr dev)
 {
     if (dev_type[1].type == dev->type)
diff --git a/Xi/listdev.c b/Xi/listdev.c
index c484dcc..ce549da 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -93,7 +93,7 @@ SProcXListInputDevices(ClientPtr client)
  *
  */
 
-_X_EXPORT void
+void
 SizeDeviceInfo(DeviceIntPtr d, int *namesize, int *size)
 {
     int chunks;
commit 2b179c32ac40f5258d95ae16da96a79fa8eea696
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 29 15:15:16 2008 +0930

    include: add declaration for CopyGetMasterEvent to shut up compiler warning.

diff --git a/include/input.h b/include/input.h
index 0c993ee..10dadfe 100644
--- a/include/input.h
+++ b/include/input.h
@@ -512,12 +512,18 @@ extern Bool RegisterPairingClient(ClientPtr client);
 extern DeviceIntPtr GuessFreePointerDevice(void);
 extern DeviceIntPtr NextFreePointerDevice(void);
 
+extern void CopyGetMasterEvent(DeviceIntPtr mdev,
+			       xEvent* original,
+			       xEvent** master,
+			       int count);
+
 extern int AllocMasterDevice(ClientPtr client,
                              char* name,
                              DeviceIntPtr* ptr,
                              DeviceIntPtr* keybd);
 extern void DeepCopyDeviceClasses(DeviceIntPtr from,
                                   DeviceIntPtr to);
+
 extern void FreeDeviceClass(int type, pointer* class);
 extern void FreeFeedbackClass(int type, pointer* class);
 extern void FreeAllDeviceClasses(ClassesPtr classes);
commit ff36753755360aaa16ab8604a0ab78123884b57d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 29 14:53:41 2008 +0930

    mi: call the custom event handlers for both MD and SD.

diff --git a/mi/mieq.c b/mi/mieq.c
index 082ebab..9f81867 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -313,16 +313,7 @@ mieqProcessInputEvents(void)
             NewCurrentScreen (e->pDev, DequeueScreen(e->pDev), x, y);
         }
         else {
-            /* If someone's registered a custom event handler, let them
-             * steal it. */
-            if (miEventQueue.handlers[e->events->event->u.u.type]) {
-                miEventQueue.handlers[e->events->event->u.u.type](
-                                              DequeueScreen(e->pDev)->myNum,
-                                                      e->events->event,
-                                                      e->pDev,
-                                                      e->nevents);
-                return;
-            }
+            mieqHandler handler;
 
             /* FIXME: Bad hack. The only event where we actually get multiple
              * events at once is a DeviceMotionNotify followed by
@@ -350,13 +341,27 @@ mieqProcessInputEvents(void)
             } else
                 master_event = NULL;
 
-            /* process slave first, then master */
-            e->pDev->public.processInputProc(event, e->pDev, e->nevents);
-
-            if (!e->pDev->isMaster && e->pDev->u.master)
+            /* If someone's registered a custom event handler, let them
+             * steal it. */
+            if ((handler = miEventQueue.handlers[e->events->event->u.u.type]))
             {
-                e->pDev->u.master->public.processInputProc(master_event,
-                        e->pDev->u.master, e->nevents);
+                handler(DequeueScreen(e->pDev)->myNum, e->events->event,
+                        e->pDev, e->nevents);
+                if (!e->pDev->isMaster && e->pDev->u.master)
+                {
+                    handler(DequeueScreen(e->pDev->u.master)->myNum,
+                            e->events->event, e->pDev->u.master, e->nevents);
+                }
+            } else
+            {
+                /* process slave first, then master */
+                e->pDev->public.processInputProc(event, e->pDev, e->nevents);
+
+                if (!e->pDev->isMaster && e->pDev->u.master)
+                {
+                    e->pDev->u.master->public.processInputProc(master_event,
+                            e->pDev->u.master, e->nevents);
+                }
             }
 
             if (e->nevents > 1)
commit ec2fca7e6f7ce8fdf33d959b7adeaae935ec4b37
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 29 14:40:44 2008 +0930

    xfree86: DGA needs to call into Xi.
    
    Two steps: first use UpdateDeviceState() instead of replicating the device
    changing code. And emulate XI events instead of core events.

diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
index 89fdec6..9c79505 100644
--- a/hw/xfree86/common/xf86DGA.c
+++ b/hw/xfree86/common/xf86DGA.c
@@ -46,6 +46,7 @@
 #include <xkbsrv.h>
 #endif
 #include "xf86Xinput.h"
+#include "exglobals.h"
 
 #include "mi.h"
 
@@ -1025,17 +1026,12 @@ static Mask filters[] =
 static void
 DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
 {
-    int             key, bit;
-    register BYTE   *kptr;
-    register int    i;
-    register CARD8  modifiers;
-    register CARD16 mask;
     int		    coreEquiv;
-    xEvent	    core;
+    xEvent	    xi;
     KeyClassPtr	    keyc = keybd->key;
     DGAScreenPtr    pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
     DeviceIntPtr    pointer = GetPairedDevice(keybd);
-    
+
     coreEquiv = de->u.u.type - *XDGAEventBase;
 
     /*
@@ -1046,59 +1042,10 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
     de->u.event.screen = pScreen->myNum;
     de->u.event.state = keyc->state | pointer->button->state;
 
-    /*
-     * Keep the core state in sync by duplicating what
-     * CoreProcessKeyboardEvent does
-     */
-    key = de->u.u.detail;
-    kptr = &keyc->down[key >> 3];
-    bit = 1 << (key & 7);
-    modifiers = keyc->modifierMap[key];
-    switch (coreEquiv)
-    {
-    case KeyPress:
-        pointer->valuator->motionHintWindow = NullWindow;
-	*kptr |= bit;
-	keyc->prev_state = keyc->state;
-#ifdef XKB
-	if (noXkbExtension)
-#endif
-	{
-	    
-	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
-	    {
-		if (mask & modifiers)
-		{
-		    /* This key affects modifier "i" */
-		    keyc->modifierKeyCount[i]++;
-		    keyc->state |= mask;
-		    modifiers &= ~mask;
-		}
-	    }
-	}
-	break;
-    case KeyRelease:
-	pointer->valuator->motionHintWindow = NullWindow;
-	*kptr &= ~bit;
-	keyc->prev_state = keyc->state;
-#ifdef XKB
-	if (noXkbExtension)
-#endif
-	{
-	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
-	    {
-		if (mask & modifiers) {
-		    /* This key affects modifier "i" */
-		    if (--keyc->modifierKeyCount[i] <= 0) {
-			keyc->state &= ~mask;
-			keyc->modifierKeyCount[i] = 0;
-		    }
-		    modifiers &= ~mask;
-		}
-	    }
-	}
-	break;
-    }
+    de->u.u.type = (IEventBase - 1) + coreEquiv; /* change to XI event */
+    UpdateDeviceState(keybd, de);
+    de->u.u.type = *XDGAEventBase + coreEquiv; /* change back */
+
     /*
      * Deliver the DGA event
      */
@@ -1113,17 +1060,16 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
 	/* If the keyboard is actively grabbed, deliver a grabbed core event */
 	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) */
-            core.u.u.type		    = coreEquiv;
-	    core.u.u.detail		    = de->u.u.detail;
-	    core.u.keyButtonPointer.time    = de->u.event.time;
-	    core.u.keyButtonPointer.eventX  = de->u.event.dx;
-	    core.u.keyButtonPointer.eventY  = de->u.event.dy;
-	    core.u.keyButtonPointer.rootX   = de->u.event.dx;
-	    core.u.keyButtonPointer.rootY   = de->u.event.dy;
-	    core.u.keyButtonPointer.state   = de->u.event.state;
-	    DeliverGrabbedEvent (&core, keybd, FALSE, 1);
+	    xi.u.u.type                  = (IEventBase - 1) + coreEquiv;
+	    xi.u.u.detail                = de->u.u.detail;
+	    xi.u.keyButtonPointer.time   = de->u.event.time;
+	    xi.u.keyButtonPointer.eventX = de->u.event.dx;
+	    xi.u.keyButtonPointer.eventY = de->u.event.dy;
+	    xi.u.keyButtonPointer.rootX  = de->u.event.dx;
+	    xi.u.keyButtonPointer.rootY  = de->u.event.dy;
+	    xi.u.keyButtonPointer.state  = de->u.event.state;
+	    ((deviceKeyButtonPointer*)&xi)->deviceid = keybd->id;
+	    DeliverGrabbedEvent (&xi, keybd, FALSE, 1);
 	}
     }
 }
@@ -1132,9 +1078,9 @@ static void
 DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
 {
     ButtonClassPtr  butc = mouse->button;
-    int		    coreEquiv;    
+    int		    coreEquiv;
     DGAScreenPtr    pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
-    xEvent	    core;
+    xEvent	    xi;
 
     coreEquiv = de->u.u.type - *XDGAEventBase;
     /*
@@ -1142,44 +1088,11 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
      */
     de->u.event.screen = pScreen->myNum;
     de->u.event.state = butc->state | GetPairedDevice(mouse)->key->state;
-    /*
-     * Keep the core state in sync by duplicating what
-     * CoreProcessPointerEvent does
-     */
-    if (coreEquiv != MotionNotify)
-    {
-	int           key;
-	BYTE          *kptr;
-	int           bit;
-	
-	key = de->u.u.detail;
-	kptr = &butc->down[key >> 3];
-	bit = 1 << (key & 7);
-	switch (coreEquiv)
-	{
-	case ButtonPress: 
-	    mouse->valuator->motionHintWindow = NullWindow;
-	    if (!(*kptr & bit))
-		butc->buttonsDown++;
-	    butc->motionMask = ButtonMotionMask;
-	    *kptr |= bit;
-	    if (key <= 5)
-		butc->state |= (Button1Mask >> 1) << key;
-	    break;
-	case ButtonRelease: 
-	    mouse->valuator->motionHintWindow = NullWindow;
-	    if (*kptr & bit)
-		--butc->buttonsDown;
-	    if (!butc->buttonsDown)
-		butc->motionMask = 0;
-	    *kptr &= ~bit;
-	    if (key == 0)
-		return;
-	    if (key <= 5)
-		butc->state &= ~((Button1Mask >> 1) << key);
-	    break;
-	}
-    }
+
+    de->u.u.type = (IEventBase - 1) + coreEquiv; /* change to XI event */
+    UpdateDeviceState(mouse, de);
+    de->u.u.type = *XDGAEventBase + coreEquiv; /* change back */
+
     /*
      * Deliver the DGA event
      */
@@ -1194,15 +1107,15 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
 	/* If the pointer is actively grabbed, deliver a grabbed core event */
 	if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab)
 	{
-	    core.u.u.type		    = coreEquiv;
-	    core.u.u.detail		    = de->u.u.detail;
-	    core.u.keyButtonPointer.time    = de->u.event.time;
-	    core.u.keyButtonPointer.eventX  = de->u.event.dx;
-	    core.u.keyButtonPointer.eventY  = de->u.event.dy;
-	    core.u.keyButtonPointer.rootX   = de->u.event.dx;
-	    core.u.keyButtonPointer.rootY   = de->u.event.dy;
-	    core.u.keyButtonPointer.state   = de->u.event.state;
-	    DeliverGrabbedEvent (&core, mouse, FALSE, 1);
+	    xi.u.u.type                   = (IEventBase - 1 ) + coreEquiv;
+	    xi.u.u.detail                 = de->u.u.detail;
+	    xi.u.keyButtonPointer.time    = de->u.event.time;
+	    xi.u.keyButtonPointer.eventX  = de->u.event.dx;
+	    xi.u.keyButtonPointer.eventY  = de->u.event.dy;
+	    xi.u.keyButtonPointer.rootX   = de->u.event.dx;
+	    xi.u.keyButtonPointer.rootY   = de->u.event.dy;
+	    xi.u.keyButtonPointer.state   = de->u.event.state;
+	    DeliverGrabbedEvent (&xi, mouse, FALSE, 1);
 	}
     }
 }
commit 8208b842b7dd3b30bafdd74147bdfa63bc00cc40
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 29 14:19:42 2008 +0930

    Xi: add IEventBase global variable. Stores event base for X Input events.

diff --git a/Xi/exglobals.h b/Xi/exglobals.h
index 4c23d84..0b1caf9 100644
--- a/Xi/exglobals.h
+++ b/Xi/exglobals.h
@@ -37,6 +37,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define EXGLOBALS_H 1
 
 extern int IReqCode;
+extern int IEventBase;
 extern int BadDevice;
 extern int BadMode;
 extern int DeviceBusy;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index a647b9e..99ace89 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -277,6 +277,7 @@ static int (*SProcIVector[])(ClientPtr) = {
  */
 
 int IReqCode = 0;
+int IEventBase = 0;
 int BadDevice = 0;
 static int BadEvent = 1;
 int BadMode = 2;
@@ -885,6 +886,7 @@ RestoreExtensionEvents(void)
     int i, j;
 
     IReqCode = 0;
+    IEventBase = 0;
 
     for (i = 0; i < ExtEventIndex - 1; i++) {
 	if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
@@ -1122,6 +1124,7 @@ XInputExtensionInit(void)
 			    SProcIDispatch, IResetProc, StandardMinorOpcode);
     if (extEntry) {
 	IReqCode = extEntry->base;
+	IEventBase = extEntry->eventBase;
 	AllExtensionVersions[IReqCode - 128] = thisversion;
 	MakeDeviceTypeAtoms();
 	RT_INPUTCLIENT = CreateNewResourceType((DeleteType) InputClientGone);
commit 46340b740640b76b52b8e69bc67f9201c7e974c3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 29 14:17:48 2008 +0930

    Xi: change UpdateDeviceState to be _X_EXPORT.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index bbe70e4..68e82dd 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -778,7 +778,7 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
 #define DEFAULT 0
 #define DONT_PROCESS 1
 #define IS_REPEAT 2
-static int
+_X_EXPORT int
 UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 {
     int i;
diff --git a/include/exevents.h b/include/exevents.h
index 8d5d5dd..664e236 100644
--- a/include/exevents.h
+++ b/include/exevents.h
@@ -44,6 +44,12 @@ typedef struct _XIClientRec {
 extern void RegisterOtherDevice (
 	DeviceIntPtr           /* device */);
 
+extern int
+UpdateDeviceState (
+	DeviceIntPtr           /* device */,
+	xEventPtr              /*  xE    */,
+        int                    /* count  */);
+
 extern void ProcessOtherEvent (
 	xEventPtr /* FIXME deviceKeyButtonPointer * xE */,
 	DeviceIntPtr           /* other */,
commit 3a922c5d07509703a3eeda2bbec6f332e6b0ffac
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 28 17:32:54 2008 +0930

    Xi: apply ValuatorEvent data to the device's valuators.
    
    After UpdateDeviceState, the device has the current position in absolute
    coordinates, the event has the correct valuator data to be delivered to the
    client.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index a83d5ed..bbe70e4 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -823,6 +823,7 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 	if ((++xV)->type == DeviceValuator) {
 	    int *axisvals;
             int first = xV->first_valuator;
+            BOOL change = FALSE;
 
 	    if (xV->num_valuators &&
                 (!v || (xV->num_valuators &&
@@ -830,24 +831,91 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 		FatalError("Bad valuators reported for device %s\n",
 			   device->name);
 	    if (v && v->axisVal) {
+                /* The device always stores values in absolute. Only the
+                 * delivery mode changes.
+                 * If device is mode Absolute, and event is Relative
+                 *     dev += event
+                 *     event = dev
+                 * If device is mode Absolute, and event is Absolute
+                 *     dev = event
+                 * If device is mode Relative, and event is Absolute
+                 *      swap = (event - device)
+                 *      dev = event
+                 *      event = delta
+                 * If device is mode Relative, and event is Relative
+                 *      dev += event
+                 *
+                 * XXX: axis clipping for relative events?
+                 */
 		axisvals = v->axisVal;
-		switch (xV->num_valuators) {
-		case 6:
-		    *(axisvals + first + 5) = xV->valuator5;
-		case 5:
-		    *(axisvals + first + 4) = xV->valuator4;
-		case 4:
-		    *(axisvals + first + 3) = xV->valuator3;
-		case 3:
-		    *(axisvals + first + 2) = xV->valuator2;
-		case 2:
-		    *(axisvals + first + 1) = xV->valuator1;
-		case 1:
-		    *(axisvals + first) = xV->valuator0;
-		case 0:
-		default:
-		    break;
-		}
+                if (xV->sequenceNumber & Absolute) {
+                    int delta;
+                    if (v->mode == Relative) /* device reports relative */
+                    {
+                        change = TRUE;
+                        xV->sequenceNumber &= ~Absolute;
+                    }
+
+                    switch (xV->num_valuators) {
+                        case 6:
+                            if (change) delta = xV->valuator5 - *(axisvals + first + 5);
+                            *(axisvals + first + 5) = xV->valuator5;
+                            if (change) xV->valuator5 = delta;
+                        case 5:
+                            if (change) delta = xV->valuator4 - *(axisvals + first + 4);
+                            *(axisvals + first + 4) = xV->valuator4;
+                            if (change) xV->valuator4 = delta;
+                        case 4:
+                            if (change) delta = xV->valuator3 - *(axisvals + first + 3);
+                            *(axisvals + first + 3) = xV->valuator3;
+                            if (change) xV->valuator3 = delta;
+                        case 3:
+                            if (change) delta = xV->valuator2 - *(axisvals + first + 2);
+                            *(axisvals + first + 2) = xV->valuator2;
+                            if (change) xV->valuator2 = delta;
+                        case 2:
+                            if (change) delta = xV->valuator1 - *(axisvals + first + 1);
+                            *(axisvals + first + 1) = xV->valuator1;
+                            if (change) xV->valuator1 = delta;
+                        case 1:
+                            if (change) delta = xV->valuator0 - *(axisvals + first);
+                            *(axisvals + first) = xV->valuator0;
+                            if (change) xV->valuator0 = delta;
+                        case 0:
+                        default:
+                            break;
+                    }
+		} else { /* event is relative */
+                    if (v->mode == Absolute) /* device reports absolute */
+                    {
+                        change = TRUE;
+                        xV->sequenceNumber |= Absolute;
+                    }
+
+                    switch (xV->num_valuators) {
+                        case 6:
+                            *(axisvals + first + 5) += xV->valuator5;
+                            if (change) xV->valuator5 = *(axisvals + first + 5);
+                        case 5:
+                            *(axisvals + first + 4) += xV->valuator4;
+                            if (change) xV->valuator4 = *(axisvals + first + 4);
+                        case 4:
+                            *(axisvals + first + 3) += xV->valuator3;
+                            if (change) xV->valuator3 = *(axisvals + first + 3);
+                        case 3:
+                            *(axisvals + first + 2) += xV->valuator2;
+                            if (change) xV->valuator2 = *(axisvals + first + 2);
+                        case 2:
+                            *(axisvals + first + 1) += xV->valuator1;
+                            if (change) xV->valuator1 = *(axisvals + first + 1);
+                        case 1:
+                            *(axisvals + first) += xV->valuator0;
+                            if (change) xV->valuator0 = *(axisvals + first);
+                        case 0:
+                        default:
+                            break;
+                    }
+                }
 	    }
 	}
     }
diff --git a/include/inputstr.h b/include/inputstr.h
index 8c1d5fc..d117e55 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -174,7 +174,7 @@ typedef struct _ValuatorClassRec {
 
     AxisInfoPtr 	  axes;
     unsigned short	  numAxes;
-    int			  *axisVal;
+    int			  *axisVal; /* always absolute, but device-coord system */
     int                   dxremaind, dyremaind; /* for acceleration */
     CARD8	 	  mode;
 } ValuatorClassRec, *ValuatorClassPtr;
commit f2a20294fe26f4c9d245d24d065331fefd8f830d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 28 16:56:22 2008 +0930

    dix: store all valuators as they come from the device in the valuator events.
    
    The event's sequenceNumber is mis-used to determine whether the values are
    relative or absolute.

diff --git a/dix/getevents.c b/dix/getevents.c
index d352ebe..0a44a80 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -386,13 +386,15 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
  * Fills events with valuator events for pDev, as given by the other
  * parameters.
  *
+ * Note that we mis-use the sequence number to store the absolute bit.
+ *
  * FIXME: Need to fix ValuatorClassRec to store all the valuators as
  *        last posted, not just x and y; otherwise relative non-x/y
  *        valuators, though a very narrow use case, will be broken.
  */
 static EventList *
-getValuatorEvents(EventList *events, DeviceIntPtr pDev, int first_valuator,
-                  int num_valuators, int *valuators) {
+getValuatorEvents(EventList *events, DeviceIntPtr pDev, int absolute,
+        int first_valuator, int num_valuators, int *valuators) {
     deviceValuator *xv;
     int i = 0, final_valuator = first_valuator + num_valuators;
 
@@ -419,6 +421,8 @@ getValuatorEvents(EventList *events, DeviceIntPtr pDev, int first_valuator,
 
         if (i + 6 < final_valuator)
             xv->deviceid |= MORE_EVENTS;
+
+        xv->sequenceNumber = (absolute) ? Absolute : Relative;
     }
 
     return events;
@@ -561,8 +565,8 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
     if (num_valuators) {
         kbp->deviceid |= MORE_EVENTS;
         clipValuators(pDev, first_valuator, num_valuators, valuators);
-        events = getValuatorEvents(events, pDev, first_valuator,
-                                   num_valuators, valuators);
+        events = getValuatorEvents(events, pDev, FALSE /* relative */,
+                                   first_valuator, num_valuators, valuators);
     }
 
     return numEvents;
@@ -751,14 +755,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
      * to the current screen.  Right now, we only have one history buffer,
      * so we don't set this for both the device and core.*/
     miPointerSetPosition(pDev, &x, &y, ms);
-
-    /* Drop x and y back into the valuators list, if they were originally
-     * present. */
-    if (first_valuator == 0 && num_valuators >= 1)
-        valuators[0] = x;
-    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-        valuators[1 - first_valuator] = y;
-
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
     pDev->lastx = x;
@@ -791,8 +787,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     if (num_valuators) {
         kbp->deviceid |= MORE_EVENTS;
         clipValuators(pDev, first_valuator, num_valuators, valuators);
-        events = getValuatorEvents(events, pDev, first_valuator,
-                num_valuators, valuators);
+        events = getValuatorEvents(events, pDev, (flags & POINTER_ABSOLUTE),
+                first_valuator, num_valuators, valuators);
     }
 
     return num_events;
@@ -859,8 +855,8 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
         kbp->deviceid |= MORE_EVENTS;
         events++;
         clipValuators(pDev, first_valuator, num_valuators, valuators);
-        events = getValuatorEvents(events, pDev, first_valuator,
-                                   num_valuators, valuators);
+        events = getValuatorEvents(events, pDev, False /* relative */,
+                                   first_valuator, num_valuators, valuators);
     }
 
     return num_events;
commit 53dba5381fdd8f644e16aaa0ecb05df4dc615b23
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 28 11:37:52 2008 +0930

    dix: if alloc of a master keyboard fails, remove the master pointer.

diff --git a/dix/devices.c b/dix/devices.c
index b3c9efc..37feb34 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -863,6 +863,11 @@ UndisplayDevices()
  * resources.
  * Removes both enabled and disabled devices and notifies all devices about
  * the removal of the device.
+ *
+ * No PresenceNotify is sent for device that the client never saw. This can
+ * happen if a malloc fails during the addition of master devices. If
+ * dev->init is FALSE it means the client never received a DeviceAdded event,
+ * so let's not send a DeviceRemoved event either.
  */
 int
 RemoveDevice(DeviceIntPtr dev)
@@ -873,12 +878,14 @@ RemoveDevice(DeviceIntPtr dev)
     DeviceIntRec dummyDev;
     ScreenPtr screen = screenInfo.screens[0];
     int deviceid;
+    int initialized;
 
     DebugF("(dix) removing device %d\n", dev->id);
 
     if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
         return BadImplementation;
 
+    initialized = dev->inited;
     screen->UndisplayCursor(dev, screen);
 
     deviceid = dev->id;
@@ -914,7 +921,7 @@ RemoveDevice(DeviceIntPtr dev)
 	}
     }
 
-    if (ret == Success) {
+    if (ret == Success && initialized) {
         inputInfo.numDevices--;
         ev.type = DevicePresenceNotify;
         ev.time = currentTime.milliseconds;
@@ -2587,7 +2594,10 @@ AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr*
 
     keyboard = AddInputDevice(client, CoreKeyboardProc, TRUE);
     if (!keyboard)
+    {
+        RemoveDevice(pointer);
         return BadAlloc;
+    }
 
     keyboard->name = xcalloc(strlen(name) + strlen(" keyboard") + 1, sizeof(char));
     strcpy(keyboard->name, name);
commit 1fab51edfc82e1ef60dfa29fd5d93478066a3998
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 28 11:37:21 2008 +0930

    mi: guard against NULL-pointer dereference.

diff --git a/mi/misprite.c b/mi/misprite.c
index c998e55..9e4b685 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -916,12 +916,15 @@ miSpriteUndisplayCursor(pDev, pScreen)
     DeviceIntPtr pDev;
     ScreenPtr    pScreen;
 {
+    miCursorInfoPtr pCursorInfo;
+
     if (!pDev->isMaster && !pDev->u.master)
     {
         ErrorF("[mi] miSpriteUndisplayCursor called for floating device.\n");
         return;
     }
-    if (MISPRITE(pDev)->isUp)
+    pCursorInfo = MISPRITE(pDev);
+    if (pCursorInfo && pCursorInfo->isUp)
         miSpriteRemoveCursor(pDev, pScreen);
 }
 
commit b5004722a208479a4bc762ff428bf4cbeb430d53
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 28 10:26:01 2008 +0930

    Xi: Only return VCP, VCK and floating SDs to Xi 1.x clients.
    
    This is better than the approach implemented with
    8973a3f7983240407dd6da59b3643f40e6a3d83a which disabled XI altogether for 1.x.
    Instead, return a device list that resembles a traditional XI setup on pre XI
    2.0 servers. If the client tries to open a device other than a floating SD,
    return a BadDevice error.

diff --git a/Xi/listdev.c b/Xi/listdev.c
index b588c24..c484dcc 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -315,9 +315,9 @@ CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes,
  * This procedure lists the input devices available to the server.
  *
  * If this request is called by a client that has not issued a
- * GetExtensionVersion request with major/minor version set, we pretend no
- * devices are available. It's the only thing we can do to stop pre-XI 2
- * clients.
+ * GetExtensionVersion request with major/minor version set, we don't send the
+ * complete device list. Instead, we only send the VCP, the VCK and floating
+ * SDs. This resembles the setup found on XI 1.x machines.
  */
 
 int
@@ -347,34 +347,35 @@ ProcXListInputDevices(ClientPtr client)
 
     AddOtherInputDevices();
 
-    if (pXIClient->major_version >= XI_2_Major) {
-        for (d = inputInfo.devices; d; d = d->next) {
-            rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
-            if (rc != Success)
-                return rc;
-            SizeDeviceInfo(d, &namesize, &size);
-            numdevs++;
-        }
-        for (d = inputInfo.off_devices; d; d = d->next) {
-            rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
-            if (rc != Success)
-                return rc;
-            SizeDeviceInfo(d, &namesize, &size);
-            numdevs++;
+    for (d = inputInfo.devices; d; d = d->next) {
+        if (pXIClient->major_version < XI_2_Major)
+        {
+            if (d->isMaster &&
+                d != inputInfo.pointer &&
+                d != inputInfo.keyboard)
+                continue; /* don't send master devices other than VCP/VCK */
+
+            if (!d->isMaster && d->u.master)
+                continue; /* don't send attached SDs */
         }
-    } else
-    {
-        /* Pretend we don't have XI devices connected */
-        rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, DixGetAttrAccess);
+        rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
         if (rc != Success)
             return rc;
-        rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, DixGetAttrAccess);
+        SizeDeviceInfo(d, &namesize, &size);
+        numdevs++;
+    }
+
+    for (d = inputInfo.off_devices; d; d = d->next) {
+        if (pXIClient->major_version < XI_2_Major &&
+            !d->isMaster &&
+            d->u.master) /* XXX can off_devices be attached? */
+                continue; /* don't send attached SDs */
+
+        rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
         if (rc != Success)
             return rc;
-
-        SizeDeviceInfo(inputInfo.pointer, &namesize, &size);
-        SizeDeviceInfo(inputInfo.keyboard, &namesize, &size);
-        numdevs = 2;
+        SizeDeviceInfo(d, &namesize, &size);
+        numdevs++;
     }
 
     total_length = numdevs * sizeof(xDeviceInfo) + size + namesize;
@@ -384,18 +385,30 @@ ProcXListInputDevices(ClientPtr client)
     savbuf = devbuf;
 
     dev = (xDeviceInfoPtr) devbuf;
-    if (pXIClient->major_version >= XI_2_Major)
-    {
-        for (d = inputInfo.devices; d; d = d->next, dev++)
-            ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
-        for (d = inputInfo.off_devices; d; d = d->next, dev++)
-            ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
-    } else
+    for (d = inputInfo.devices; d; d = d->next)
     {
-        ListDeviceInfo(client, inputInfo.pointer, dev, &devbuf, &classbuf, &namebuf);
-        ListDeviceInfo(client, inputInfo.keyboard, dev, &devbuf, &classbuf, &namebuf);
+        if (pXIClient->major_version < XI_2_Major)
+        {
+            if (d->isMaster &&
+                    d != inputInfo.pointer &&
+                    d != inputInfo.keyboard)
+                continue; /* don't count master devices other than VCP/VCK */
+
+            if (!d->isMaster && d->u.master)
+                continue; /* don't count attached SDs */
+        }
+        ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
     }
 
+    for (d = inputInfo.off_devices; d; d = d->next)
+    {
+        if (pXIClient->major_version < XI_2_Major &&
+                !d->isMaster &&
+                d->u.master) /* XXX can off_devices be attached? */
+            continue; /* don't send attached SDs */
+
+        ListDeviceInfo(client, d, dev++, &devbuf, &classbuf, &namebuf);
+    }
     rep.ndevices = numdevs;
     rep.length = (total_length + 3) >> 2;
     WriteReplyToClient(client, sizeof(xListInputDevicesReply), &rep);
diff --git a/Xi/opendev.c b/Xi/opendev.c
index f14f848..c51bb7e 100644
--- a/Xi/opendev.c
+++ b/Xi/opendev.c
@@ -62,6 +62,7 @@ SOFTWARE.
 #include "XIstubs.h"
 #include "windowstr.h"	/* window structure  */
 #include "exglobals.h"
+#include "exevents.h"
 
 #include "opendev.h"
 
@@ -98,6 +99,7 @@ ProcXOpenDevice(ClientPtr client)
     int status = Success;
     xOpenDeviceReply rep;
     DeviceIntPtr dev;
+    XIClientPtr pXIClient;
 
     REQUEST(xOpenDeviceReq);
     REQUEST_SIZE_MATCH(xOpenDeviceReq);
@@ -113,6 +115,15 @@ ProcXOpenDevice(ClientPtr client)
     } else if (status != Success)
 	return status;
 
+    /* Don't let XI 1.x clients open devices other than floating SDs. */
+    pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+    if (pXIClient->major_version < XI_2_Major)
+    {
+        if (dev->isMaster || (!dev->isMaster && dev->u.master))
+            return BadDevice;
+    }
+
+
     OpenInputDevice(dev, client, &status);
     if (status != Success)
 	return status;
commit 684b5d8382bf0bc6cd55774226ee362e81c0adbf
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Apr 26 19:55:59 2008 +0930

    Xi: whoops, stray ! caused a bit of memory mess.

diff --git a/Xi/listdev.c b/Xi/listdev.c
index fc2748e..b588c24 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -347,7 +347,7 @@ ProcXListInputDevices(ClientPtr client)
 
     AddOtherInputDevices();
 
-    if (!pXIClient->major_version >= XI_2_Major) {
+    if (pXIClient->major_version >= XI_2_Major) {
         for (d = inputInfo.devices; d; d = d->next) {
             rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
             if (rc != Success)
commit 87071b604c4b7c3c79ab784e2c09ff691e2bc5ad
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Apr 26 19:37:57 2008 +0930

    Revert "Xi: disable XI for clients < XI 2.0"
    
    Turns out some programs don't like this change. gnome-settings-daemon crashes
    hard if you tell it that XI doesn't exist. So, tell them we have XI, but leave
    the other change (the one that pretends no devices are available).
    
    This reverts commit 8973a3f7983240407dd6da59b3643f40e6a3d83a.

diff --git a/Xi/getvers.c b/Xi/getvers.c
index daf9a02..43a1a4d 100644
--- a/Xi/getvers.c
+++ b/Xi/getvers.c
@@ -122,10 +122,7 @@ ProcXGetExtensionVersion(ClientPtr client)
     rep.RepType = X_GetExtensionVersion;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
-    if (!pXIClient->major_version < XI_2_Major) /* sorry, no XI 1.x anymore. */
-        rep.present = FALSE;
-    else
-        rep.present = TRUE;
+    rep.present = TRUE;
     rep.major_version = AllExtensionVersions[IReqCode - 128].major_version;
     rep.minor_version = AllExtensionVersions[IReqCode - 128].minor_version;
 
commit 7447a30fb27ed50a20a85b5a2de9afe7dea8cfa5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Apr 26 19:03:13 2008 +0930

    Xi: if a pre-XI2 client tries to list the devices, pretend we don't have any.
    
    XI 1.x isn't supported anymore, so let's pretend we don't have any devices.
    This stops clients from opening them and thus stops interference.

diff --git a/Xi/listdev.c b/Xi/listdev.c
index 3fb0ab3..fc2748e 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -64,6 +64,7 @@ SOFTWARE.
 #include "XIstubs.h"
 #include "extnsionst.h"
 #include "exglobals.h"	/* FIXME */
+#include "exevents.h"
 #include "xace.h"
 
 #include "listdev.h"
@@ -313,12 +314,17 @@ CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes,
  *
  * This procedure lists the input devices available to the server.
  *
+ * If this request is called by a client that has not issued a
+ * GetExtensionVersion request with major/minor version set, we pretend no
+ * devices are available. It's the only thing we can do to stop pre-XI 2
+ * clients.
  */
 
 int
 ProcXListInputDevices(ClientPtr client)
 {
     xListInputDevicesReply rep;
+    XIClientPtr pXIClient;
     int numdevs = 0;
     int namesize = 1;	/* need 1 extra byte for strcpy */
     int rc, size = 0;
@@ -337,21 +343,38 @@ ProcXListInputDevices(ClientPtr client)
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
 
+    pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+
     AddOtherInputDevices();
 
-    for (d = inputInfo.devices; d; d = d->next) {
-	rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
-	if (rc != Success)
-	    return rc;
-	SizeDeviceInfo(d, &namesize, &size);
-        numdevs++;
-    }
-    for (d = inputInfo.off_devices; d; d = d->next) {
-	rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
-	if (rc != Success)
-	    return rc;
-	SizeDeviceInfo(d, &namesize, &size);
-        numdevs++;
+    if (!pXIClient->major_version >= XI_2_Major) {
+        for (d = inputInfo.devices; d; d = d->next) {
+            rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
+            if (rc != Success)
+                return rc;
+            SizeDeviceInfo(d, &namesize, &size);
+            numdevs++;
+        }
+        for (d = inputInfo.off_devices; d; d = d->next) {
+            rc = XaceHook(XACE_DEVICE_ACCESS, client, d, DixGetAttrAccess);
+            if (rc != Success)
+                return rc;
+            SizeDeviceInfo(d, &namesize, &size);
+            numdevs++;
+        }
+    } else
+    {
+        /* Pretend we don't have XI devices connected */
+        rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, DixGetAttrAccess);
+        if (rc != Success)
+            return rc;
+        rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, DixGetAttrAccess);
+        if (rc != Success)
+            return rc;
+
+        SizeDeviceInfo(inputInfo.pointer, &namesize, &size);
+        SizeDeviceInfo(inputInfo.keyboard, &namesize, &size);
+        numdevs = 2;
     }
 
     total_length = numdevs * sizeof(xDeviceInfo) + size + namesize;
@@ -361,10 +384,17 @@ ProcXListInputDevices(ClientPtr client)
     savbuf = devbuf;
 
     dev = (xDeviceInfoPtr) devbuf;
-    for (d = inputInfo.devices; d; d = d->next, dev++)
-	ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
-    for (d = inputInfo.off_devices; d; d = d->next, dev++)
-	ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
+    if (pXIClient->major_version >= XI_2_Major)
+    {
+        for (d = inputInfo.devices; d; d = d->next, dev++)
+            ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
+        for (d = inputInfo.off_devices; d; d = d->next, dev++)
+            ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
+    } else
+    {
+        ListDeviceInfo(client, inputInfo.pointer, dev, &devbuf, &classbuf, &namebuf);
+        ListDeviceInfo(client, inputInfo.keyboard, dev, &devbuf, &classbuf, &namebuf);
+    }
 
     rep.ndevices = numdevs;
     rep.length = (total_length + 3) >> 2;
commit 8973a3f7983240407dd6da59b3643f40e6a3d83a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Apr 26 17:48:52 2008 +0930

    Xi: disable XI for clients < XI 2.0
    
    Sorry. With the huge changes in the device handling I honestly don't know how
    to support XI and XI2 alongside. So let's just pretend XI doesn't exist if a
    client doesn't request it supporting XI2.

diff --git a/Xi/getvers.c b/Xi/getvers.c
index 43a1a4d..daf9a02 100644
--- a/Xi/getvers.c
+++ b/Xi/getvers.c
@@ -122,7 +122,10 @@ ProcXGetExtensionVersion(ClientPtr client)
     rep.RepType = X_GetExtensionVersion;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
-    rep.present = TRUE;
+    if (!pXIClient->major_version < XI_2_Major) /* sorry, no XI 1.x anymore. */
+        rep.present = FALSE;
+    else
+        rep.present = TRUE;
     rep.major_version = AllExtensionVersions[IReqCode - 128].major_version;
     rep.minor_version = AllExtensionVersions[IReqCode - 128].minor_version;
 
commit b304b0a65cc57127cdea103f2c5114e4ea79af41
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Apr 26 17:38:55 2008 +0930

    Xi: add versioning support.
    
    Remember the version the client sent to us, so we can adjust our replies
    accordingly. This requires the client to use the {major|minor}Version fields
    in the GetExtensionVersion request. However, they were padding before, so we
    must assume they are garbage if nbytes is non-zero. If nbytes is zero, the
    client is probably a new client and we can handle it correctly.

diff --git a/Xi/exglobals.h b/Xi/exglobals.h
index 8cbccf2..4c23d84 100644
--- a/Xi/exglobals.h
+++ b/Xi/exglobals.h
@@ -31,6 +31,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
 #endif
+#include "privates.h"
 
 #ifndef EXGLOBALS_H
 #define EXGLOBALS_H 1
@@ -75,4 +76,5 @@ extern int DeviceLeaveNotify;
 
 extern int RT_INPUTCLIENT;
 
+extern DevPrivateKey XIClientPrivateKey;
 #endif /* EXGLOBALS_H */
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 838efdd..a647b9e 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -72,6 +72,7 @@ SOFTWARE.
 #include "exglobals.h"
 #include "swaprep.h"
 #include "registry.h"
+#include "privates.h"
 
 /* modules local to Xi */
 #include "allowev.h"
@@ -324,20 +325,43 @@ int RT_INPUTCLIENT;
 
 extern XExtensionVersion AllExtensionVersions[];
 
+
 Mask PropagateMask[MAX_DEVICES];
 
 /*****************************************************************
  *
- * Declarations of local routines.
+ * Versioning support
  *
  */
 
+DevPrivateKey XIClientPrivateKey = &XIClientPrivateKey;
+
 static XExtensionVersion thisversion = { XI_Present,
     XI_2_Major,
     XI_2_Minor
 };
 
 
+/*****************************************************************
+ *
+ * Declarations of local routines.
+ *
+ */
+
+static void
+XIClientCallback(CallbackListPtr        *list,
+                 pointer                closure,
+                 pointer                data)
+{
+    NewClientInfoRec *clientinfo = (NewClientInfoRec*)data;
+    ClientPtr pClient = clientinfo->client;
+    XIClientPtr pXIClient;
+
+    pXIClient = dixLookupPrivate(&pClient->devPrivates, XIClientPrivateKey);
+    pXIClient->major_version = 0;
+    pXIClient->minor_version = 0;
+}
+
 /*************************************************************************
  *
  * ProcIDispatch - main dispatch routine for requests to this extension.
@@ -1080,6 +1104,7 @@ XIGEEventFill(xGenericEvent* ev, DeviceIntPtr pDev,
  *
  * This extension has several events and errors.
  *
+ * XI is mandatory nowadays, so if we fail to init XI, we die.
  */
 
 void
@@ -1087,6 +1112,12 @@ XInputExtensionInit(void)
 {
     ExtensionEntry *extEntry;
 
+    if (!dixRequestPrivate(XIClientPrivateKey, sizeof(XIClientRec)))
+        FatalError("Cannot request private for XI.\n");
+
+    if (!AddCallback(&ClientStateCallback, XIClientCallback, 0))
+        FatalError("Failed to add callback to XI.\n");
+
     extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
 			    SProcIDispatch, IResetProc, StandardMinorOpcode);
     if (extEntry) {
diff --git a/Xi/getvers.c b/Xi/getvers.c
index 1e17eea..43a1a4d 100644
--- a/Xi/getvers.c
+++ b/Xi/getvers.c
@@ -59,6 +59,7 @@ SOFTWARE.
 #include "inputstr.h"	/* DeviceIntPtr      */
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
+#include "exevents.h"
 #include "exglobals.h"
 
 #include "getvers.h"
@@ -93,6 +94,7 @@ int
 ProcXGetExtensionVersion(ClientPtr client)
 {
     xGetExtensionVersionReply rep;
+    XIClientPtr pXIClient;
 
     REQUEST(xGetExtensionVersionReq);
     REQUEST_AT_LEAST_SIZE(xGetExtensionVersionReq);
@@ -101,6 +103,21 @@ ProcXGetExtensionVersion(ClientPtr client)
 			  stuff->nbytes + 3) >> 2)
 	return BadLength;
 
+    pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+
+    /* GetExtensionVersionReq before XI 2 didn't supply the client's
+     * major/minor. So we don't actually have a clue what they support.
+     * {major|minor}Version was added as part of XI, so if they are set, we
+     * know we can trust it. In this case the client must set nbytes to 0
+     * though, otherwise we have to assume that the version are padding
+     * garbage.
+     */
+    if (!stuff->nbytes) /* Client using XQueryInputVersion(). */
+    {
+        pXIClient->major_version = stuff->majorVersion;
+        pXIClient->minor_version = stuff->minorVersion;
+    } /* else version unknown, leave it at 0.0 */
+
     rep.repType = X_Reply;
     rep.RepType = X_GetExtensionVersion;
     rep.length = 0;
diff --git a/include/exevents.h b/include/exevents.h
index 0892f4d..8d5d5dd 100644
--- a/include/exevents.h
+++ b/include/exevents.h
@@ -32,6 +32,15 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #include <X11/extensions/XIproto.h>
 
+/**
+ * Attached to the devPrivates of each client. Specifies the version number as
+ * supported by the client.
+ */
+typedef struct _XIClientRec {
+        int major_version;
+        int minor_version;
+} XIClientRec, *XIClientPtr;
+
 extern void RegisterOtherDevice (
 	DeviceIntPtr           /* device */);
 
commit e251c9e75afdc5e32f2bc9801712272358934266
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 16:49:35 2008 +0930

    Remove all traces of #ifdef XINPUT and the matching bits from the configure.ac

diff --git a/configure.ac b/configure.ac
index d3a2317..166d9f6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1004,7 +1004,7 @@ DAMAGE_INC='-I$(top_srcdir)/damageext'
 MIEXT_DAMAGE_LIB='$(top_builddir)/miext/damage/libdamage.la'
 MIEXT_DAMAGE_INC='-I$(top_srcdir)/miext/damage'
 
-AC_DEFINE(XINPUT, 1, [Support X Input extension])
+# XINPUT extension is integral part of the server
 XI_LIB='$(top_builddir)/Xi/libXi.la'
 XI_INC='-I$(top_srcdir)/Xi'
 
diff --git a/hw/dmx/dmxclient.h b/hw/dmx/dmxclient.h
index 8f018d1..91ba049 100644
--- a/hw/dmx/dmxclient.h
+++ b/hw/dmx/dmxclient.h
@@ -98,9 +98,7 @@ typedef XID           KeySym64;
 #include <X11/extensions/XKBstr.h>
 #endif
 
-#ifdef XINPUT
 #include <X11/extensions/XI.h>
-#endif
 
 /* Always include these, since we query them even if we don't export XINPUT. */
 #include <X11/extensions/XInput.h> /* For XDevice */
diff --git a/hw/dmx/dmxlog.c b/hw/dmx/dmxlog.c
index 31a74cd..94b8035 100644
--- a/hw/dmx/dmxlog.c
+++ b/hw/dmx/dmxlog.c
@@ -42,10 +42,8 @@
 #include "dmx.h"
 #include "dmxlog.h"
 #include "dmxinput.h"
-#ifdef XINPUT
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
-#endif
 
 static dmxLogLevel dmxCurrentLogLevel = dmxDebug;
 
@@ -279,7 +277,6 @@ void dmxLogVisual(DMXScreenInfo *dmxScreen, XVisualInfo *vi, int defaultVisual)
     }
 }
 
-#ifdef XINPUT
 /** Translate a (normalized) XInput event \a type into a human-readable
  * string. */
 const char *dmxXInputEventName(int type)
@@ -305,7 +302,6 @@ const char *dmxXInputEventName(int type)
 }
 
 #endif
-#endif
 
 /** Translate an event \a type into a human-readable string. */
 const char *dmxEventName(int type)
diff --git a/hw/dmx/dmxlog.h b/hw/dmx/dmxlog.h
index 8a5f725..7b614bd 100644
--- a/hw/dmx/dmxlog.h
+++ b/hw/dmx/dmxlog.h
@@ -70,9 +70,7 @@ extern void dmxLogInputCont(DMXInputInfo *dmxInput, const char *format, ...);
 extern void dmxLogArgs(dmxLogLevel logLevel, int argc, char **argv);
 extern void dmxLogVisual(DMXScreenInfo *dmxScreen, XVisualInfo *vi,
                          int defaultVisual);
-#ifdef XINPUT
 extern const char *dmxXInputEventName(int type);
 #endif
-#endif
 
 #endif
diff --git a/hw/dmx/input/dmxcommon.h b/hw/dmx/input/dmxcommon.h
index 1cc935d..a9b260c 100644
--- a/hw/dmx/input/dmxcommon.h
+++ b/hw/dmx/input/dmxcommon.h
@@ -63,13 +63,9 @@
 #define DMX_COMMON_XKB      DMX_COMMON_OTHER
 #endif
 
-#ifdef XINPUT
 #define DMX_COMMON_PRIVATE                  \
     DMX_COMMON_XKB;                         \
     XDevice                 *xi
-#else
-#define DMX_COMMON_PRIVATE  DMX_COMMON_OTHER
-#endif
 
 #define GETONLYPRIVFROMPRIVATE                                          \
     myPrivate            *priv     = private
diff --git a/hw/dmx/input/dmxeq.c b/hw/dmx/input/dmxeq.c
index dff0b44..afa2b2c 100644
--- a/hw/dmx/input/dmxeq.c
+++ b/hw/dmx/input/dmxeq.c
@@ -79,10 +79,8 @@
 #include "inputstr.h"
 #include "scrnintstr.h"         /* For screenInfo */
 
-#ifdef XINPUT
 #include <X11/extensions/XIproto.h>
 #define EXTENSION_PROC_ARGS void *
-#endif
 
 #if DMX_EQ_DEBUG
 #define DMXDBG2(f,a,b)           dmxLog(dmxDebug,f,a,b)
@@ -100,9 +98,7 @@
 typedef struct _Event {
     xEvent	   event;    /**< Event. */
     ScreenPtr	   pScreen;  /**< Screen on which event occurred. */
-#ifdef XINPUT
     deviceValuator valuator; /**< XInput device valuator information. */
-#endif
 } EventRec, *EventPtr;
 
 /** Event queue. */
@@ -183,15 +179,11 @@ void dmxeqEnqueue(xEvent *e)
 
                                 /* Store the event in the queue */
     dmxEventQueue.events[oldtail].event   = *e;
-#ifdef XINPUT
-    {
-                                /* If this is an XInput event, store the
-                                 * valuator event, too */
-        deviceKeyButtonPointer *ev = (deviceKeyButtonPointer *)e;
-        if (e->u.u.type >= LASTEvent && (ev->deviceid & MORE_EVENTS))
-            dmxEventQueue.events[oldtail].valuator = *(deviceValuator *)(ev+1);
-    }
-#endif
+                            /* If this is an XInput event, store the
+                             * valuator event, too */
+    deviceKeyButtonPointer *ev = (deviceKeyButtonPointer *)e;
+    if (e->u.u.type >= LASTEvent && (ev->deviceid & MORE_EVENTS))
+        dmxEventQueue.events[oldtail].valuator = *(deviceValuator *)(ev+1);
 
                                 /* Make sure that event times don't go
                                  * backwards - this is "unnecessary",
@@ -211,7 +203,6 @@ void dmxeqSwitchScreen(ScreenPtr pScreen, Bool fromDIX)
     if (fromDIX) dmxEventQueue.pDequeueScreen = pScreen;
 }
 
-#ifdef XINPUT
 static void dmxeqProcessXInputEvent(xEvent *xe, EventRec *e)
 {
     deviceKeyButtonPointer *ev     = (deviceKeyButtonPointer *)xe;
@@ -238,7 +229,6 @@ static void dmxeqProcessXInputEvent(xEvent *xe, EventRec *e)
         pDevice->public.processInputProc(xe, pDevice, 1);
     }
 }
-#endif
 
 /**
  * This function is called from #ProcessInputEvents() to remove events
@@ -285,11 +275,8 @@ void dmxeqProcessInputEvents(void)
                                        (DeviceIntPtr)dmxEventQueue.pKbd, 1);
 	    	break;
             default:
-#ifdef XINPUT
                 dmxeqProcessXInputEvent(xe, e);
                 break;
-#endif
-                /* ifndef XINPUT, fall through */
             case ButtonPress:
             case ButtonRelease:
             case MotionNotify:
diff --git a/hw/dmx/input/dmxevents.c b/hw/dmx/input/dmxevents.c
index 26dc067..2e24ff4 100644
--- a/hw/dmx/input/dmxevents.c
+++ b/hw/dmx/input/dmxevents.c
@@ -57,9 +57,7 @@
 #include "mipointer.h"
 #include "mi.h"
 
-#ifdef XINPUT
 #include "XIstubs.h"
-#endif
 
 static int  dmxGlobalX, dmxGlobalY; /* Global cursor position */
 static int  dmxGlobalInvalid;       /* Flag indicating dmxCoreMotion
@@ -154,7 +152,6 @@ static int dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal,
     return 0;
 }
 
-#ifdef XINPUT
 static void dmxEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, xEvent *e,
                                DMXBlockType block)
 {
@@ -208,7 +205,6 @@ static void dmxEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, xEvent *e,
     if (block)
         dmxSigioUnblock();
 }
-#endif
 
 DMXScreenInfo *dmxFindFirstScreen(int x, int y)
 {
@@ -331,7 +327,6 @@ dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block)
 
 
 
-#ifdef XINPUT
 #define DMX_MAX_AXES 32         /* Max axes reported by this routine */
 static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
                          int *v, int firstAxis, int axesCount,
@@ -537,7 +532,6 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
     }
     return 0;
 }
-#endif
 
 static int dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal, int button)
 {
@@ -578,14 +572,12 @@ void dmxInvalidateGlobalPosition(void)
 void dmxMotion(DevicePtr pDev, int *v, int firstAxes, int axesCount,
                DMXMotionType type, DMXBlockType block)
 {
-#ifdef XINPUT
     GETDMXLOCALFROMPDEV;
 
     if (!dmxLocal->sendsCore) {
         dmxExtMotion(dmxLocal, v, firstAxes, axesCount, type, block);
         return;
     }
-#endif
     if (axesCount == 2) {
         switch (type) {
         case DMX_RELATIVE:
@@ -739,17 +731,13 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
                                  * control of the input device LEDs. */
         return;
     default:
-#ifdef XINPUT
         if (type == ProximityIn || type == ProximityOut) {
             if (dmxLocal->sendsCore)
                 return; /* Not a core event */
             break;
         }
-#endif
         if (type >= LASTEvent) {
-#ifdef XINPUT
             if (dmxTranslateAndEnqueueExtEvent(dmxLocal, e, block))
-#endif
                 dmxLogInput(dmxInput, "Unhandled extension event: %d\n", type);
         } else {
             dmxLogInput(dmxInput, "Unhandled event: %d (%s)\n",
@@ -764,11 +752,9 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
     xE.u.u.detail              = detail;
     xE.u.keyButtonPointer.time = GetTimeInMillis();
 
-#ifdef XINPUT
     if (!dmxLocal->sendsCore)
         dmxEnqueueExtEvent(dmxLocal, &xE, block);
     else
-#endif
         dmxeqEnqueue(&xE);
 #endif /*00*/
 }
diff --git a/hw/dmx/input/dmxinputinit.c b/hw/dmx/input/dmxinputinit.c
index fd4eeaa..7b5cc73 100644
--- a/hw/dmx/input/dmxinputinit.c
+++ b/hw/dmx/input/dmxinputinit.c
@@ -73,13 +73,11 @@
 #include "windowstr.h"
 #include "mi.h"
 
-#ifdef XINPUT
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include "exevents.h"
 #define EXTENSION_PROC_ARGS void *
 #include "extinit.h"
-#endif
 
 /* From XI.h */
 #ifndef Relative
@@ -462,9 +460,7 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
     GETDMXINPUTFROMPDEVICE;
     int              fd;
     DMXLocalInitInfo info;
-#ifdef XINPUT
     int              i;
-#endif
     
     if (dmxInput->detached) return Success;
 
@@ -504,41 +500,33 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
                                               GetMaximumEventsNum(),
 #endif
                                               Relative);
-#ifdef XINPUT
                 for (i = 0; i < info.numRelAxes; i++)
                     InitValuatorAxisStruct(pDevice, i, info.minval[0],
                                            info.maxval[0], info.res[0],
                                            info.minres[0], info.maxres[0]);
-#endif
             } else if (info.numRelAxes) {
                 InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
                                               dmxPointerGetMotionEvents,
                                               dmxPointerGetMotionBufferSize(),
                                               Relative);
-#ifdef XINPUT
                 for (i = 0; i < info.numRelAxes; i++)
                     InitValuatorAxisStruct(pDevice, i, info.minval[0],
                                            info.maxval[0], info.res[0],
                                            info.minres[0], info.maxres[0]);
-#endif
             } else if (info.numAbsAxes) {
                 InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes,
                                               dmxPointerGetMotionEvents,
                                               dmxPointerGetMotionBufferSize(),
                                               Absolute);
-#ifdef XINPUT
                 for (i = 0; i < info.numAbsAxes; i++)
                     InitValuatorAxisStruct(pDevice, i+info.numRelAxes,
                                            info.minval[i+1], info.maxval[i+1],
                                            info.res[i+1], info.minres[i+1],
                                            info.maxres[i+1]);
-#endif
             }
         }
         if (info.focusClass)       InitFocusClassDeviceStruct(pDevice);
-#ifdef XINPUT
         if (info.proximityClass)   InitProximityClassDeviceStruct(pDevice);
-#endif
         if (info.ptrFeedbackClass)
             InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl);
         if (info.kbdFeedbackClass)
@@ -759,17 +747,10 @@ static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal)
         }
     }
 
-#ifdef XINPUT
     if (!name) {
         name            = "extension";
         registerProcPtr = RegisterOtherDevice;
     }
-#else
-    if (!name)
-        dmxLog(dmxFatal,
-               "Server not build with XINPUT support (cannot add %s)\n",
-               dmxLocal->name);
-#endif
 
     if (!name || !registerProcPtr)
         dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name);
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index b6e1186..601b9bb 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -62,10 +62,8 @@
 #include "extension.h"
 #include "Pci.h"
 
-#ifdef XINPUT
 #include "xf86Xinput.h"
 extern DeviceAssocRec mouse_assoc;
-#endif
 
 #ifdef XKB
 #undef XKB_IN_SERVER
diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c
index 725fcb2..c6f6039 100644
--- a/hw/xfree86/common/xf86Cursor.c
+++ b/hw/xfree86/common/xf86Cursor.c
@@ -44,10 +44,8 @@
 #include "xf86Priv.h"
 #include "xf86_OSproc.h"
 
-#ifdef XINPUT
 #include <X11/extensions/XIproto.h>
 #include "xf86Xinput.h"
-#endif
 
 #ifdef XFreeXDGA
 #include "dgaproc.h"
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
index 0dc42c6..14bef39 100644
--- a/hw/xfree86/common/xf86Globals.c
+++ b/hw/xfree86/common/xf86Globals.c
@@ -100,9 +100,7 @@ xf86InfoRec xf86Info = {
 	FALSE,		/* vtSysreq */
 	SKWhenNeeded,	/* ddxSpecialKeys */
 	NULL,		/* pMouse */
-#ifdef XINPUT
 	NULL,		/* mouseLocal */
-#endif
 	-1,		/* lastEventTime */
 	FALSE,		/* vtRequestsPending */
 	FALSE,		/* inputPending */
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 6d5eaad..bf45d76 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -71,12 +71,8 @@
 #include "xf86Date.h"
 #include "xf86Build.h"
 #include "mipointer.h"
-#ifdef XINPUT
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
-#else
-#include "inputstr.h"
-#endif
 #include "xf86DDC.h"
 #include "xf86Xinput.h"
 #include "xf86InPriv.h"
diff --git a/hw/xfree86/common/xf86MiscExt.c b/hw/xfree86/common/xf86MiscExt.c
index 40c196a..8817b79 100644
--- a/hw/xfree86/common/xf86MiscExt.c
+++ b/hw/xfree86/common/xf86MiscExt.c
@@ -48,13 +48,9 @@
 #define XF86_OS_PRIVS
 #include "xf86_OSlib.h"
 
-#ifdef XINPUT
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include "xf86Xinput.h"
-#else
-#include "inputstr.h"
-#endif
 
 #include "xf86OSmouse.h"
 
diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h
index 8cab56e..318a59f 100644
--- a/hw/xfree86/common/xf86Privstr.h
+++ b/hw/xfree86/common/xf86Privstr.h
@@ -80,9 +80,7 @@ typedef struct {
 
     /* mouse part */
     DeviceIntPtr	pMouse;
-#ifdef XINPUT
     pointer		mouseLocal;
-#endif
 
     /* event handler part */
     int			lastEventTime;
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 9f293cc..5279306 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -52,17 +52,13 @@
 
 #include <X11/Xfuncproto.h>
 #include <X11/Xmd.h>
-#ifdef XINPUT
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
-#endif
 #include "xf86.h"
 #include "xf86Priv.h"
 #include "xf86Xinput.h"
-#ifdef XINPUT
 #include "XIstubs.h"
 #include "xf86Optrec.h"
-#endif
 #include "mipointer.h"
 #include "xf86InPriv.h"
 
@@ -193,7 +189,6 @@ xf86ActivateDevice(LocalDevicePtr local)
 }
 
 
-#ifdef XINPUT
 /***********************************************************************
  *
  * Caller:	ProcXOpenDevice
@@ -322,7 +317,6 @@ void
 AddOtherInputDevices()
 {
 }
-#endif
 
 int
 NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index d88bbbe..dd72ec7 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -57,11 +57,9 @@
 #endif
 #include "xf86str.h"
 #include "inputstr.h"
-#ifdef XINPUT
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include "XIstubs.h"
-#endif
 
 /* Input device flags */
 #define XI86_OPEN_ON_INIT       0x01 /* open the device at startup time */
@@ -89,7 +87,6 @@
 #define TS_Raw 60
 #define TS_Scaled 61
 
-#ifdef XINPUT
 /* This holds the input driver entry and module information. */
 typedef struct _InputDriverRec {
     int			    driverVersion;
@@ -103,7 +100,6 @@ typedef struct _InputDriverRec {
     pointer		    module;
     int			    refCount;
 } InputDriverRec, *InputDriverPtr;
-#endif
 
 /* This is to input devices what the ScrnInfoRec is to screens. */
 
diff --git a/hw/xfree86/loader/dixsym.c b/hw/xfree86/loader/dixsym.c
index 61dec59..a2a2390 100644
--- a/hw/xfree86/loader/dixsym.c
+++ b/hw/xfree86/loader/dixsym.c
@@ -422,9 +422,9 @@ _X_HIDDEN void *dixLookupTab[] = {
 #ifdef PANORAMIX
     SYMVAR(noPanoramiXExtension)
 #endif
-#ifdef XINPUT
+
     SYMVAR(noXInputExtension)
-#endif
+
 #ifdef XIDLE
     SYMVAR(noXIdleExtension)
 #endif
@@ -481,14 +481,12 @@ _X_HIDDEN void *dixLookupTab[] = {
     SYMVAR(XkbDfltRepeatInterval)
 #endif
 
-#ifdef XINPUT
     /* Xi */
     /* exevents.c */
     SYMFUNC(InitValuatorAxisStruct)
     SYMFUNC(InitProximityClassDeviceStruct)
     /* extinit.c */
     SYMFUNC(AssignTypeAndName)
-#endif
 
     /* xf86DGA.c */
     /* XXX This is exported from the DDX, not DIX. */
diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c
index 7f3bbe4..04719a6 100644
--- a/hw/xfree86/loader/loadmod.c
+++ b/hw/xfree86/loader/loadmod.c
@@ -59,9 +59,7 @@
 #include "misc.h"
 #include "xf86.h"
 #include "xf86Priv.h"
-#ifdef XINPUT
 #include "xf86Xinput.h"
-#endif
 #include "loader.h"
 #include "xf86Optrec.h"
 
diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c
index 1d3e639..e15b07a 100644
--- a/hw/xfree86/loader/xf86sym.c
+++ b/hw/xfree86/loader/xf86sym.c
@@ -64,9 +64,7 @@
 #include "xf86_OSproc.h"
 #include "xf86Parser.h"
 #include "xf86Config.h"
-#ifdef XINPUT
 # include "xf86Xinput.h"
-#endif
 #include "xf86OSmouse.h"
 #ifdef XV
 #include "xf86xv.h"
@@ -291,14 +289,12 @@ _X_HIDDEN void *xfree86LookupTab[] = {
     SYMFUNC(xf86UnbindGARTMemory)
     SYMFUNC(xf86EnableAGP)
     SYMFUNC(xf86GARTCloseScreen)
-#ifdef XINPUT
     SYMFUNC(XisbNew)
     SYMFUNC(XisbFree)
     SYMFUNC(XisbRead)
     SYMFUNC(XisbWrite)
     SYMFUNC(XisbTrace)
     SYMFUNC(XisbBlockDuration)
-#endif
 
     /* xf86Bus.c */
     SYMFUNC(xf86CheckPciSlot)
@@ -673,7 +669,6 @@ _X_HIDDEN void *xfree86LookupTab[] = {
     SYMFUNC(GetTimeInMillis)
 
     /* xf86Xinput.c */
-#ifdef XINPUT
     SYMFUNC(xf86ProcessCommonOptions)
     SYMFUNC(xf86PostMotionEvent)
     SYMFUNC(xf86PostProximityEvent)
@@ -684,7 +679,6 @@ _X_HIDDEN void *xfree86LookupTab[] = {
     SYMFUNC(xf86ActivateDevice)
     SYMFUNC(xf86XInputSetScreen)
     SYMFUNC(xf86ScaleAxis)
-#endif
 #ifdef DPMSExtension
     SYMFUNC(DPMSGet)
     SYMFUNC(DPMSSet)
diff --git a/hw/xgl/egl/kinput.c b/hw/xgl/egl/kinput.c
index f892dc1..6c1018c 100644
--- a/hw/xgl/egl/kinput.c
+++ b/hw/xgl/egl/kinput.c
@@ -612,7 +612,6 @@ eglInitInput(KdMouseFuncs    *pMouseFuncs,
     RegisterKeyboardDevice(pKeyboard);
     miRegisterPointerDevice(screenInfo.screens[0], pPointer);
     mieqInit(&pKeyboard->public, &pPointer->public);
-#ifdef XINPUT
     {
 	static long zero1, zero2;
 
@@ -620,7 +619,6 @@ eglInitInput(KdMouseFuncs    *pMouseFuncs,
 	ErrorF("Extended Input Devices not yet supported. Impelement it at line %d in %s\n",
 	       __LINE__, __FILE__);
     }
-#endif
 }
 
 /*
diff --git a/hw/xprint/ddxInit.c b/hw/xprint/ddxInit.c
index d744121..5cb2472 100644
--- a/hw/xprint/ddxInit.c
+++ b/hw/xprint/ddxInit.c
@@ -284,8 +284,6 @@ ddxProcessArgument (
     return(0);
 }
 
-#ifdef XINPUT
-
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #include "XIstubs.h"
@@ -373,8 +371,6 @@ SetDeviceValuators (
 }
 
 
-#endif /* XINPUT */
-
 #ifdef AIXV3
 /*
  * This is just to get the server to link on AIX, where some bits
diff --git a/hw/xquartz/darwin.c b/hw/xquartz/darwin.c
index aad55fc..7e927c8 100644
--- a/hw/xquartz/darwin.c
+++ b/hw/xquartz/darwin.c
@@ -47,12 +47,10 @@
 #include "globals.h"
 #include "dix.h"
 
-#ifdef XINPUT
 # include <X11/extensions/XI.h>
 # include <X11/extensions/XIproto.h>
 # include "exevents.h"
 # include "extinit.h"
-#endif
 
 #include <sys/types.h>
 #include <sys/time.h>
diff --git a/hw/xwin/winmouse.c b/hw/xwin/winmouse.c
index 1507dd3..be2b66a 100644
--- a/hw/xwin/winmouse.c
+++ b/hw/xwin/winmouse.c
@@ -36,7 +36,7 @@
 #endif
 #include "win.h"
 
-#if defined(XFree86Server) && defined(XINPUT)
+#if defined(XFree86Server)
 #include "inputstr.h"
 
 /* Peek the internal button mapping */
@@ -106,7 +106,7 @@ winMouseProc (DeviceIntPtr pDeviceInt, int iState)
 			       2);
       free(map);
 
-#if defined(XFree86Server) && defined(XINPUT)
+#if defined(XFree86Server)
       g_winMouseButtonMap = pDeviceInt->button->map;
 #endif
       break;
@@ -116,7 +116,7 @@ winMouseProc (DeviceIntPtr pDeviceInt, int iState)
       break;
 
     case DEVICE_CLOSE:
-#if defined(XFree86Server) && defined(XINPUT)
+#if defined(XFree86Server)
       g_winMouseButtonMap = NULL;
 #endif
     case DEVICE_OFF:
@@ -225,7 +225,7 @@ winMouseButtonsSendEvent (int iEventType, int iButton)
 
   /* Load an xEvent and enqueue the event */
   xCurrentEvent.u.u.type = iEventType;
-#if defined(XFree86Server) && defined(XINPUT)
+#if defined(XFree86Server)
   if (g_winMouseButtonMap)
     xCurrentEvent.u.u.detail = g_winMouseButtonMap[iButton];
   else
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 1779082..2d1ec91 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -371,9 +371,6 @@
 /* Support Xinerama extension */
 #undef XINERAMA
 
-/* Support X Input extension */
-#undef XINPUT
-
 /* Build XKB */
 #undef XKB
 
diff --git a/include/globals.h b/include/globals.h
index 9e5060d..e2e4804 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -151,9 +151,7 @@ extern Bool noXkbExtension;
 extern Bool noPanoramiXExtension;
 #endif
 
-#ifdef XINPUT
 extern Bool noXInputExtension;
-#endif
 
 #ifdef XIDLE
 extern Bool noXIdleExtension;
diff --git a/include/windowstr.h b/include/windowstr.h
index a895a88..0e45262 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -113,9 +113,7 @@ typedef struct _WindowOpt {
     RegionPtr		clipShape;	   /* default: NULL */
     RegionPtr		inputShape;	   /* default: NULL */
 #endif
-#ifdef XINPUT
     struct _OtherInputMasks *inputMasks;   /* default: NULL */
-#endif
     DevCursorList       deviceCursors;     /* default: NULL */
     struct _GenericClientMasks *geMasks;/* default: NULL */
     WindowAccessRec     access;
@@ -214,11 +212,7 @@ extern Mask	    DontPropagateMasks[];
 #define wDontPropagateMask(w)	wUseDefault(w, dontPropagateMask, DontPropagateMasks[(w)->dontPropagate])
 #define wOtherEventMasks(w)	wUseDefault(w, otherEventMasks, 0)
 #define wOtherClients(w)	wUseDefault(w, otherClients, NULL)
-#ifdef XINPUT
 #define wOtherInputMasks(w)	wUseDefault(w, inputMasks, NULL)
-#else
-#define wOtherInputMasks(w)	NULL
-#endif
 #define wPassiveGrabs(w)	wUseDefault(w, passiveGrabs, NULL)
 #define wUserProps(w)		wUseDefault(w, userProps, NULL)
 #define wBackingBitPlanes(w)	wUseDefault(w, backingBitPlanes, ~0L)
diff --git a/mi/miinitext.c b/mi/miinitext.c
index 4f3b92e..00f0d27 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -197,9 +197,7 @@ extern Bool noPanoramiXExtension;
 #ifdef INXQUARTZ
 extern Bool noPseudoramiXExtension;
 #endif
-#ifdef XINPUT
 extern Bool noXInputExtension;
-#endif
 #ifdef XIDLE
 extern Bool noXIdleExtension;
 #endif
@@ -262,9 +260,7 @@ extern void PanoramiXExtensionInit(INITARGS);
 #ifdef INXQUARTZ
 extern void PseudoramiXExtensionInit(INITARGS);
 #endif
-#ifdef XINPUT
 extern void XInputExtensionInit(INITARGS);
-#endif
 #ifdef XTEST
 extern void XTestExtensionInit(INITARGS);
 #endif
@@ -448,9 +444,7 @@ static ExtensionToggle ExtensionToggleList[] =
 #ifdef PANORAMIX
     { "XINERAMA", &noPanoramiXExtension },
 #endif
-#ifdef XINPUT
     { "XInputExtension", &noXInputExtension },
-#endif
 #ifdef XKB
     { "XKEYBOARD", &noXkbExtension },
 #endif
@@ -632,9 +626,7 @@ static ExtensionModule staticExtensions[] = {
 #ifdef MITSHM
     { ShmExtensionInit, SHMNAME, &noMITShmExtension, NULL, NULL },
 #endif
-#ifdef XINPUT
     { XInputExtensionInit, "XInputExtension", &noXInputExtension, NULL, NULL },
-#endif
 #ifdef XTEST
     { XTestExtensionInit, XTestExtensionName, &noTestExtensions, NULL, NULL },
 #endif
diff --git a/os/utils.c b/os/utils.c
index d1bc1a1..4bebeca 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -214,9 +214,7 @@ _X_EXPORT Bool noXFixesExtension = FALSE;
 /* Xinerama is disabled by default unless enabled via +xinerama */
 _X_EXPORT Bool noPanoramiXExtension = TRUE;
 #endif
-#ifdef XINPUT
 _X_EXPORT Bool noXInputExtension = FALSE;
-#endif
 #ifdef XIDLE
 _X_EXPORT Bool noXIdleExtension = FALSE;
 #endif
commit 1d0438de176551aaeff549664f00b8bd83d465af
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 16:28:58 2008 +0930

    Xi: remove RemoveOtherCoreGrabs()
    
    PickPointer() returns grabbed devices, so we can't get a double grab anyway.

diff --git a/dix/events.c b/dix/events.c
index 779be81..73b7fa0 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5161,9 +5161,6 @@ ProcGrabPointer(ClientPtr client)
 	if (oldCursor)
 	    FreeCursor (oldCursor, (Cursor)0);
 	rep.status = GrabSuccess;
-
-        /* guarantee only one core pointer grab at a time by this client */
-        RemoveOtherCoreGrabs(client, device);
     }
     WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
     return Success;
@@ -5345,47 +5342,6 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
 }
 
 /**
- * Deactivate any core grabs on the given client except the given device.
- *
- * This fixes race conditions where clients deal with implicit passive grabs
- * on one device, but then actively grab their client pointer, which is
- * another device.
- *
- * Grabs are only removed if the other device matches the type of device. If
- * dev is a pointer device, only other pointer grabs are removed. Likewise, if
- * dev is a keyboard device, only keyboard grabs are removed.
- *
- * If dev doesn't have a grab, do nothing and go for a beer.
- *
- * @param client The client that is to be limited.
- * @param dev The only device allowed to have a grab on the client.
- */
-
-_X_EXPORT void
-RemoveOtherCoreGrabs(ClientPtr client, DeviceIntPtr dev)
-{
-    if (!dev || !dev->deviceGrab.grab)
-        return;
-
-    DeviceIntPtr it = inputInfo.devices;
-    for (; it; it = it->next)
-    {
-        if (it == dev)
-            continue;
-        /* check for IsPointer Device */
-
-        if (it->deviceGrab.grab &&
-                it->deviceGrab.grab->coreGrab &&
-                SameClient(it->deviceGrab.grab, client))
-        {
-            if ((IsPointerDevice(dev) && IsPointerDevice(it)) ||
-                    (IsKeyboardDevice(dev) && IsKeyboardDevice(it)))
-                (*it->deviceGrab.DeactivateGrab)(it);
-        }
-    }
-}
-
-/**
  * Server-side protocol handling for GrabKeyboard request.
  *
  * Grabs the client's keyboard and returns success status to client.
@@ -5405,9 +5361,6 @@ ProcGrabKeyboard(ClientPtr client)
             stuff->ownerEvents, stuff->time,
             KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
 
-    /* ensure only one core keyboard grab by this client */
-    RemoveOtherCoreGrabs(client, keyboard);
-
     if (result != Success)
 	return result;
     rep.type = X_Reply;
diff --git a/include/dix.h b/include/dix.h
index 57ffee9..970b1d8 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -460,10 +460,6 @@ extern int GrabDevice(
     CARD8 * /* status */,
     Bool /* coreGrab */);
 
-extern void RemoveOtherCoreGrabs(
-    ClientPtr /* client */,
-    DeviceIntPtr /* dev */);
-
 extern void InitEvents(void);
 extern void InitSprite(
         DeviceIntPtr /* pDev */, 
commit be5ff2b8d8a392eb8611e1fcd6da4752d68a7f9d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 16:25:13 2008 +0930

    Xi: remove some superflous code

diff --git a/Xi/getvers.c b/Xi/getvers.c
index a4afe80..1e17eea 100644
--- a/Xi/getvers.c
+++ b/Xi/getvers.c
@@ -85,7 +85,7 @@ SProcXGetExtensionVersion(ClientPtr client)
 
 /***********************************************************************
  *
- * This procedure lists the input devices available to the server.
+ * This procedure returns the major/minor version of the X Input extension.
  *
  */
 
@@ -105,14 +105,10 @@ ProcXGetExtensionVersion(ClientPtr client)
     rep.RepType = X_GetExtensionVersion;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
-    rep.major_version = 0;
-    rep.minor_version = 0;
-
     rep.present = TRUE;
-    if (rep.present) {
-	rep.major_version = AllExtensionVersions[IReqCode - 128].major_version;
-	rep.minor_version = AllExtensionVersions[IReqCode - 128].minor_version;
-    }
+    rep.major_version = AllExtensionVersions[IReqCode - 128].major_version;
+    rep.minor_version = AllExtensionVersions[IReqCode - 128].minor_version;
+
     WriteReplyToClient(client, sizeof(xGetExtensionVersionReply), &rep);
 
     return Success;
commit b093bf3ec37367172be3b44a04f0f43890ba7d7d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 15:15:31 2008 +0930

    dix: don't search for grabbed devices, PickPointer does it for us now.
    
    Follow-up to 93ee33830778b9ec85ad81496572677a30022b09.

diff --git a/dix/events.c b/dix/events.c
index 5919e26..779be81 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1861,44 +1861,20 @@ AllowSome(ClientPtr client,
  * Server-side protocol handling for AllowEvents request.
  *
  * Release some events from a frozen device.
- *
- * In some cases, the grab the client has is not on the ClientPointer but on
- * some other device (see ProcGrabPointer comments). To cover this case, we
- * need to run through all devices to ensure we don't forget the device we
- * actually have a grab on.
  */
 int
 ProcAllowEvents(ClientPtr client)
 {
     TimeStamp		time;
-    DeviceIntPtr	mouse = NULL,
-			grabbed;
+    DeviceIntPtr	mouse = NULL;
     DeviceIntPtr	keybd = NULL;
-    GrabPtr		grab;
     REQUEST(xAllowEventsReq);
 
     REQUEST_SIZE_MATCH(xAllowEventsReq);
     time = ClientTimeToServerTime(stuff->time);
 
-    for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
-    {
-        grab = grabbed->deviceGrab.grab;
-        if (grab && grab->coreGrab && SameClient(grab, client))
-        {
-            if (IsPointerDevice(grabbed))
-                mouse = grabbed;
-            else if (IsKeyboardDevice(grabbed))
-                keybd = grabbed;
-
-	    if (mouse && keybd)
-		break;
-        }
-    }
-
-    if (!mouse)
-        mouse = PickPointer(client);
-    if (!keybd)
-        keybd = PickKeyboard(client);
+    mouse = PickPointer(client);
+    keybd = PickKeyboard(client);
 
     switch (stuff->mode)
     {
@@ -5061,12 +5037,6 @@ ProcGetInputFocus(ClientPtr client)
  *
  * Sets an active grab on the client's ClientPointer and returns success
  * status to client.
- *
- * A special case of GrabPointer is when there is already a grab on some
- * device (by the same client). In this case, this grab is overwritten, and
- * the device stays as it is. This case can happen when a client has a passive
- * grab and then grabs the pointer, or when the client already has an active
- * grab and the ClientPointer was changed since.
  */
 int
 ProcGrabPointer(ClientPtr client)
@@ -5080,7 +5050,6 @@ ProcGrabPointer(ClientPtr client)
     TimeStamp time;
     Mask access_mode = DixGrabAccess;
     int rc;
-    DeviceIntPtr grabbed = NULL;
 
     REQUEST_SIZE_MATCH(xGrabPointerReq);
     UpdateCurrentTime();
@@ -5144,20 +5113,6 @@ ProcGrabPointer(ClientPtr client)
     rep.sequenceNumber = client->sequence;
     rep.length = 0;
 
-    /* Check if a the client already has a grab on a device */
-    for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
-    {
-        if (IsPointerDevice(grabbed))
-        {
-            grab = grabbed->deviceGrab.grab;
-            if (grab && grab->coreGrab && SameClient(grab, client))
-            {
-                device = grabbed;
-                break;
-            }
-        }
-    }
-
     grab = device->deviceGrab.grab;
     /* check for
        1. other client has a grab on the device already.
@@ -5219,15 +5174,11 @@ ProcGrabPointer(ClientPtr client)
  *
  * Changes properties of the grab hold by the client. If the client does not
  * hold an active grab on the device, nothing happens.
- *
- * Works on the client's ClientPointer, but in some cases the client may have
- * a grab on a device that isn't the ClientPointer (see ProcGrabPointer
- * comments).
  */
 int
 ProcChangeActivePointerGrab(ClientPtr client)
 {
-    DeviceIntPtr device, grabbed;
+    DeviceIntPtr device;
     GrabPtr      grab;
     CursorPtr newCursor, oldCursor;
     REQUEST(xChangeActivePointerGrabReq);
@@ -5255,26 +5206,6 @@ ProcChangeActivePointerGrab(ClientPtr client)
     device = PickPointer(client);
     grab = device->deviceGrab.grab;
 
-    if (!grab || !SameClient(grab, client))
-    {
-        /* no grab on ClientPointer, or some other client has a grab on our
-         * ClientPointer, let's check if we have a pointer grab on some other
-         * device. */
-        for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
-        {
-            if (IsPointerDevice(grabbed))
-            {
-                grab = grabbed->deviceGrab.grab;
-                if (grab && grab->coreGrab && SameClient(grab, client))
-                {
-                    device = grabbed;
-                    grab = device->deviceGrab.grab;
-                    break;
-                }
-            }
-        }
-    }
-
     if (!grab)
 	return Success;
     if (!SameClient(grab, client))
@@ -5297,17 +5228,12 @@ ProcChangeActivePointerGrab(ClientPtr client)
 /**
  * Server-side protocol handling for UngrabPointer request.
  *
- * Deletes a pointer grab on a device the client has grabbed. This should be
- * the ClientPointer, but may not be. So we search the device list for a
- * device we have a pointer grab on and then ungrab this device. (see
- * ProcGrabPointer comments). We are guaranteed that the client doesn't have
- * more than one core pointer grab at a time.
+ * Deletes a pointer grab on a device the client has grabbed.
  */
 int
 ProcUngrabPointer(ClientPtr client)
 {
-    DeviceIntPtr device = PickPointer(client),
-                 grabbed;
+    DeviceIntPtr device = PickPointer(client);
     GrabPtr grab;
     TimeStamp time;
     REQUEST(xResourceReq);
@@ -5316,30 +5242,6 @@ ProcUngrabPointer(ClientPtr client)
     UpdateCurrentTime();
     grab = device->deviceGrab.grab;
 
-    if (!grab || !grab->coreGrab || !SameClient(grab, client))
-    {
-        /* No pointer grab on ClientPointer. May be a pointer grab on some
-         * other device */
-        for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
-        {
-            if (IsPointerDevice(grabbed))
-            {
-                grab = grabbed->deviceGrab.grab;
-                if (grab && grab->coreGrab && SameClient(grab, client))
-                {
-                    device = grabbed;
-                    break;
-                }
-            }
-        }
-        /* nope. no grab on any actual device */
-        if (!grabbed)
-        {
-            device = inputInfo.pointer;
-            grab = inputInfo.pointer->deviceGrab.grab;
-        }
-    }
-
     time = ClientTimeToServerTime(stuff->id);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
 	    (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
@@ -5487,15 +5389,6 @@ RemoveOtherCoreGrabs(ClientPtr client, DeviceIntPtr dev)
  * Server-side protocol handling for GrabKeyboard request.
  *
  * Grabs the client's keyboard and returns success status to client.
- *
- * In some special cases the client may already have a grab on a keyboard that
- * is not the one that is paired with the ClientPointer. This can happen when
- * the client alreay has a passive grab on some keyboard device, or when the
- * client actively grabbed the keyboard and the ClientPointer or keyboard
- * pairing was changed since.
- * Therefore, we need to run through all the keyboards available and check if
- * there's already a grab on it from our client. The client will only ever
- * have one core keyboard grab at a time.
  */
 int
 ProcGrabKeyboard(ClientPtr client)
@@ -5503,24 +5396,10 @@ ProcGrabKeyboard(ClientPtr client)
     xGrabKeyboardReply rep;
     REQUEST(xGrabKeyboardReq);
     int result;
-    DeviceIntPtr keyboard = PickKeyboard(client),
-                 grabbed;
-    GrabPtr      grab;
+    DeviceIntPtr keyboard = PickKeyboard(client);
 
     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
 
-    for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
-    {
-	if (IsKeyboardDevice(grabbed))
-	{
-	    grab = grabbed->deviceGrab.grab;
-	    if (grab && grab->coreGrab && SameClient(grab, client))
-	    {
-		keyboard = grabbed;
-		break;
-	    }
-	}
-    }
     result = GrabDevice(client, keyboard, stuff->keyboardMode,
             stuff->pointerMode, stuff->grabWindow,
             stuff->ownerEvents, stuff->time,
@@ -5542,16 +5421,11 @@ ProcGrabKeyboard(ClientPtr client)
  * Server-side protocol handling for UngrabKeyboard request.
  *
  * Deletes a possible grab on the client's keyboard.
- *
- * We may have a grab on a keyboard that isn't the ClientPointer's keyboard.
- * Thus we need to check all keyboar devices for a grab. (see ProcGrabKeyboard
- * comments)
  */
 int
 ProcUngrabKeyboard(ClientPtr client)
 {
-    DeviceIntPtr device = PickKeyboard(client),
-		 grabbed;
+    DeviceIntPtr device = PickKeyboard(client);
     GrabPtr grab;
     TimeStamp time;
     REQUEST(xResourceReq);
@@ -5561,21 +5435,6 @@ ProcUngrabKeyboard(ClientPtr client)
 
     grab = device->deviceGrab.grab;
 
-    if (!grab || !grab->coreGrab || !SameClient(grab, client))
-    {
-	for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
-	{
-	    if (IsKeyboardDevice(grabbed))
-	    {
-		grab = device->deviceGrab.grab;
-		if (grab && grab->coreGrab && SameClient(grab, client))
-		{
-		    device = grabbed;
-		    break;
-		}
-	    }
-	}
-    }
     grab = device->deviceGrab.grab;
 
     time = ClientTimeToServerTime(stuff->id);
commit 6198bad07edc51ff4a264a9361c5e9b6c74647a6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 15:02:40 2008 +0930

    dix: remove misleading (stale) comment

diff --git a/dix/events.c b/dix/events.c
index 9bf40f8..5919e26 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -6479,8 +6479,6 @@ PickPointer(ClientPtr client)
 /* PickKeyboard will pick an appropriate keyboard for the given client by
  * searching the list of devices for the keyboard device that is paired with
  * the client's pointer.
- * If no pointer is paired with the keyboard, the virtual core keyboard is
- * returned.
  */
 _X_EXPORT DeviceIntPtr
 PickKeyboard(ClientPtr client)
commit 93ee33830778b9ec85ad81496572677a30022b09
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 15:02:13 2008 +0930

    dix: let PickPointer() return devices that are core-grabbed by the client.
    
    If the client currently holds a core grab on any device, this device has
    priority, even over the ClientPointer.

diff --git a/dix/events.c b/dix/events.c
index 04342fc..9bf40f8 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -6435,10 +6435,31 @@ SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device)
     return TRUE;
 }
 
-/* PickPointer will pick an appropriate pointer for the given client.  */
+/* PickPointer will pick an appropriate pointer for the given client.
+ *
+ * An "appropriate device" is (in order of priority):
+ *  1) A device the given client has a core grab on.
+ *  2) A device set as ClientPointer for the given client.
+ *  3) The first master device.
+ */
 _X_EXPORT DeviceIntPtr
 PickPointer(ClientPtr client)
 {
+    DeviceIntPtr it = inputInfo.devices;
+
+    /* First, check if the client currently has a grab on a device. Even
+     * keyboards count. */
+    for(it = inputInfo.devices; it; it = it->next)
+    {
+        GrabPtr grab = it->deviceGrab.grab;
+        if (grab && grab->coreGrab && SameClient(grab, client))
+        {
+            if (!IsPointerDevice(it))
+                it = GetPairedDevice(it);
+            return it; /* Always return a core grabbed device */
+        }
+    }
+
     if (!client->clientPtr)
     {
         DeviceIntPtr it = inputInfo.devices;
commit f5ac98747de921d48f36d4f3f66dbe73e26a6760
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 14:50:24 2008 +0930

    Standardise copyright headers for all new files created as part of MPX.

diff --git a/COPYING b/COPYING
index 2b464e0..ddfb201 100644
--- a/COPYING
+++ b/COPYING
@@ -9,6 +9,7 @@ Stone).
 Copyright © 2000-2001 Juliusz Chroboczek
 Copyright © 2006-2007 Intel Corporation
 Copyright © 2006 Nokia Corporation
+Copyright © 2006-2008 Peter Hutterer
 Copyright © 1999 Keith Packard
 Copyright © 2005-2007 Daniel Stone
 Copyright © 2006 Luc Verhaegen
diff --git a/Xext/geext.c b/Xext/geext.c
index 29ddacd..afede22 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -1,31 +1,27 @@
 /*
-
-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.
-
-*/
-
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xext/geint.h b/Xext/geint.h
index 7747234..2e0eb09 100644
--- a/Xext/geint.h
+++ b/Xext/geint.h
@@ -1,31 +1,27 @@
 /*
-
-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.
-
-*/
-
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
 #endif
diff --git a/Xi/chaccess.c b/Xi/chaccess.c
index a58409b..3ef29fc 100644
--- a/Xi/chaccess.c
+++ b/Xi/chaccess.c
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #define	 NEED_EVENTS
 #define	 NEED_REPLIES
diff --git a/Xi/chaccess.h b/Xi/chaccess.h
index 8c2c600..090258c 100644
--- a/Xi/chaccess.h
+++ b/Xi/chaccess.h
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/chdevcur.c b/Xi/chdevcur.c
index 0a14900..867bf97 100644
--- a/Xi/chdevcur.c
+++ b/Xi/chdevcur.c
@@ -1,30 +1,27 @@
 /*
-
-Copyright 2006 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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 /***********************************************************************
  *
diff --git a/Xi/chdevcur.h b/Xi/chdevcur.h
index 92c8d4f..af86279 100644
--- a/Xi/chdevcur.h
+++ b/Xi/chdevcur.h
@@ -1,27 +1,27 @@
-/************************************************************
-
-Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au>
-
-                        All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the above listed
-copyright holder(s) not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission.
-
-THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
index 36797d9..1d57843 100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 /***********************************************************************
  *
diff --git a/Xi/chdevhier.h b/Xi/chdevhier.h
index 1853fa7..85c1a39 100644
--- a/Xi/chdevhier.h
+++ b/Xi/chdevhier.h
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 /***********************************************************************
  *
diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
index 6458404..c92c31d 100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 /***********************************************************************
  *
diff --git a/Xi/extgrbdev.h b/Xi/extgrbdev.h
index 93075b1..7e2b0ea 100644
--- a/Xi/extgrbdev.h
+++ b/Xi/extgrbdev.h
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/getcptr.c b/Xi/getcptr.c
index ba69f9c..c85fced 100644
--- a/Xi/getcptr.c
+++ b/Xi/getcptr.c
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #define	 NEED_EVENTS
 #define	 NEED_REPLIES
diff --git a/Xi/getcptr.h b/Xi/getcptr.h
index 456d1ba..cf8cd2e 100644
--- a/Xi/getcptr.h
+++ b/Xi/getcptr.h
@@ -1,27 +1,27 @@
-/************************************************************
-
-Copyright 2007 by Peter Hutterer <peter at cs.unisa.edu.au>
-
-                        All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the above listed
-copyright holder(s) not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission.
-
-THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/qryacces.c b/Xi/qryacces.c
index ab627e2..b3cc27a 100644
--- a/Xi/qryacces.c
+++ b/Xi/qryacces.c
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #define	 NEED_EVENTS
 #define	 NEED_REPLIES
diff --git a/Xi/qryacces.h b/Xi/qryacces.h
index 5fce9ae..085d93a 100644
--- a/Xi/qryacces.h
+++ b/Xi/qryacces.h
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/querydp.c b/Xi/querydp.c
index ac11025..bd0a1c5 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -1,30 +1,27 @@
 /*
-
-Copyright 2006 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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 /***********************************************************************
  *
diff --git a/Xi/querydp.h b/Xi/querydp.h
index acad548..e8c5165 100644
--- a/Xi/querydp.h
+++ b/Xi/querydp.h
@@ -1,27 +1,27 @@
-/************************************************************
-
-Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au>
-
-                        All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the above listed
-copyright holder(s) not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission.
-
-THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/setcptr.c b/Xi/setcptr.c
index 7313a9d..f73a44c 100644
--- a/Xi/setcptr.c
+++ b/Xi/setcptr.c
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 /***********************************************************************
  *
diff --git a/Xi/setcptr.h b/Xi/setcptr.h
index 0c24fd4..114623c 100644
--- a/Xi/setcptr.h
+++ b/Xi/setcptr.h
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index 21fe22c..5ea6132 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -1,30 +1,27 @@
 /*
-
-Copyright 2006 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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 /***********************************************************************
  *
diff --git a/Xi/warpdevp.h b/Xi/warpdevp.h
index 8ce5b70..7034e16 100644
--- a/Xi/warpdevp.h
+++ b/Xi/warpdevp.h
@@ -1,27 +1,27 @@
-/************************************************************
-
-Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au>
-
-                        All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the above listed
-copyright holder(s) not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission.
-
-THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
+/*
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/Xi/xiselev.c b/Xi/xiselev.c
index 2bfbd82..fc0a0f0 100644
--- a/Xi/xiselev.c
+++ b/Xi/xiselev.c
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #define	 NEED_EVENTS
 #define	 NEED_REPLIES
diff --git a/Xi/xiselev.h b/Xi/xiselev.h
index 9102815..e846407 100644
--- a/Xi/xiselev.h
+++ b/Xi/xiselev.h
@@ -1,31 +1,27 @@
 /*
-
-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.
-
-*/
-
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/dix/access.c b/dix/access.c
index dc66db8..e29ab86 100644
--- a/dix/access.c
+++ b/dix/access.c
@@ -1,30 +1,27 @@
 /*
-
-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.
-
-*/
+ * Copyright 2007-2008 Peter Hutterer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Author: Peter Hutterer, UniSA, NICTA
+ */
 
 /* This file controls the access control lists for each window. 
  * Each device can be explicitely allowed or denied access to a given window.
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 8ff31e8..9f293cc 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -46,15 +46,6 @@
  * authorization from the copyright holder(s) and author(s).
  */
 
- /* 
-  * MPX additions:
-  * Copyright © 2006 Peter Hutterer
-  * License see above.
-  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
-  *
-  */
-
-
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
 #endif
diff --git a/mi/mieq.c b/mi/mieq.c
index 1c85030..082ebab 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -24,13 +24,6 @@ in this Software without prior written authorization from The Open Group.
  *
  * Author:  Keith Packard, MIT X Consortium
  */
- /* 
-  * MPX additions:
-  * Copyright © 2006 Peter Hutterer
-  * License see above.
-  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
-  *
-  */
 
 /*
  * mieq.c
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 42d38c0..8f8086c 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -22,13 +22,6 @@ Except as contained in this notice, the name of The Open Group 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 Open Group.
 */
- /* 
-  * MPX additions:
-  * Copyright © 2006 Peter Hutterer
-  * License see above.
-  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
-  *
-  */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
diff --git a/mi/misprite.c b/mi/misprite.c
index 2be814f..c998e55 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -29,12 +29,6 @@ Except as contained in this notice, the name of The Open Group 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 Open Group.
 */
-/* 
- * MPX additions:
- * Copyright © 2006 Peter Hutterer
- * Author: Peter Hutterer <peter at cs.unisa.edu.au>
- *
- */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
commit 3fc67b4205851dcffcc431a07a885828549bd9cf
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 11:37:32 2008 +0930

    Xi: remove leftover chpkpair.h file.
    
    Used to contain declarations for ChangePointerKeyboardPairing request
    handling.

diff --git a/Xi/chpkpair.h b/Xi/chpkpair.h
deleted file mode 100644
index b0d410d..0000000
--- a/Xi/chpkpair.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/************************************************************
-
-Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au>
-
-                        All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of the above listed
-copyright holder(s) not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior
-permission.
-
-THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
-TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
-LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef CHPKPAIR_H
-#define CHPKPAIR_H 1
-
-int SProcXChangePointerKeyboardPairing(ClientPtr	/* client */
-    );
-
-int ProcXChangePointerKeyboardPairing(ClientPtr	/* client */
-    );
-
-void 
-SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify* /* from */, 
-                                           pairingChangedNotify* /* to */
-   );
-
-#endif /* WARPDEVP_H */
-
commit 89add4ee986e38b833bb58750b3e5a664efb6f4a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 11:19:12 2008 +0930

    dix: remove obsolete InitWindowPrivates().

diff --git a/dix/main.c b/dix/main.c
index f7824ee..d99cb2d 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -377,8 +377,6 @@ main(int argc, char *argv[], char *envp[])
 		FatalError("failed to create scratch GCs");
 	    if (!CreateDefaultStipple(i))
 		FatalError("failed to create default stipple");
-            if (!InitWindowPrivates(pScreen))
-                FatalError("Failed to init window privates.");
 	    if (!CreateRootWindow(pScreen))
 		FatalError("failed to create root window");
 	}
diff --git a/dix/window.c b/dix/window.c
index 98a905c..6b95068 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -3924,19 +3924,6 @@ WindowParentHasDeviceCursor(WindowPtr pWin,
     return FALSE;
 }
 
-/**
- * Initialize some mandatory devPrivates for windows. 
- *
- * At the moment, this includes only the enter/leave semaphore.
- *
- * Returns TRUE on success.
- */
-_X_EXPORT Bool
-InitWindowPrivates(ScreenPtr screen)
-{
-    /* obsolete with devPrivates rework */
-}
-
 #ifndef NOLOGOHACK
 static void
 DrawLogo(WindowPtr pWin)
diff --git a/include/window.h b/include/window.h
index 8dbef22..04cbe26 100644
--- a/include/window.h
+++ b/include/window.h
@@ -269,6 +269,4 @@ extern void DisableMapUnmapEvents(
 extern void EnableMapUnmapEvents(
     WindowPtr /* pWin */ );
 
-Bool InitWindowPrivates(
-    ScreenPtr /* screen */);
 #endif /* WINDOW_H */
commit dcdc66fcfc7957aa7875fbf74fa3a55989a9a187
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 11:14:32 2008 +0930

    dix: add mi.h include to stop compiler warning

diff --git a/dix/window.c b/dix/window.c
index 08d738e..98a905c 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -123,6 +123,7 @@ Equipment Corporation.
 #endif
 #include "dixevents.h"
 #include "globals.h"
+#include "mi.h" /* miPaintWindow */
 
 #include "privates.h"
 #include "xace.h"
commit 97552413d213337e4bff8c89b06d58a09d722b05
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 11:13:05 2008 +0930

    dix: remove "unused variable" compiler warning.

diff --git a/dix/window.c b/dix/window.c
index 33e9752..08d738e 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -367,7 +367,6 @@ CreateRootWindow(ScreenPtr pScreen)
     WindowPtr	pWin;
     BoxRec	box;
     PixmapFormatRec *format;
-    FocusSemaphoresPtr sem;
 
     pWin = (WindowPtr)xalloc(sizeof(WindowRec));
     if (!pWin)
commit d9c38e84cc492b931a2238757d438f562946e5bc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 11:04:02 2008 +0930

    dix: remove pairingClient definition.
    
    This variable was used originally to determine which client is allowed to
    change the pointer-keyboard pairing. For now, we just let anyone change it and
    see how that works out.

diff --git a/dix/devices.c b/dix/devices.c
index 656707c..b3c9efc 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -86,8 +86,6 @@ SOFTWARE.
  * This file handles input device-related stuff.
  */
 
-/* The client that is allowed to change pointer-keyboard pairings. */
-static ClientPtr pairingClient = NULL;
 DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey;
 /* Used to sture classes currently not in use by an MD */
 DevPrivateKey UnusedClassesPrivateKey = &UnusedClassesPrivateKey;
commit c14b858aeced81ff43723644f2de0f5c43f55755
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 11:02:12 2008 +0930

    Xi: fix two compiler warnings
    
    unused variable in exevents.c
    implicit declaration in warpdevp.c

diff --git a/Xi/exevents.c b/Xi/exevents.c
index a828044..a83d5ed 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -952,7 +952,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     KeyClassPtr k;
     ValuatorClassPtr v;
     deviceValuator *xV  = (deviceValuator *) xE;
-    int coretype = 0;
     int ret = 0;
 
     ret = UpdateDeviceState(device, xE, count);
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index 26081eb..21fe22c 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -48,6 +48,7 @@ from the author.
 #include "extnsionst.h"
 #include "exevents.h"
 #include "exglobals.h"
+#include "mipointer.h" /* for miPointerUpdateSprite */
 
 
 #include "warpdevp.h"
commit 6015b7a81252cd1729e6f4045f9b0c885c95b183
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 10:41:30 2008 +0930

    Xi: handle requests through a dispatch handler.
    
    Same principle as e.g. in the RandR extension, rather than having a load of
        if (type == XI_whatever)
    use an array of function pointers.

diff --git a/Xi/extinit.c b/Xi/extinit.c
index fa15478..838efdd 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -166,6 +166,109 @@ static struct dev_type
 CARD8 event_base[numInputClasses];
 XExtEventInfo EventInfo[32];
 
+/**
+ * Dispatch vector. Functions defined in here will be called when the matching
+ * request arrives.
+ */
+static int (*ProcIVector[])(ClientPtr) = {
+        NULL,                                   /*  0 */
+	ProcXGetExtensionVersion,               /*  1 */
+	ProcXListInputDevices,                  /*  2 */
+	ProcXOpenDevice,                        /*  3 */
+	ProcXCloseDevice,                       /*  4 */
+	ProcXSetDeviceMode,                     /*  5 */
+	ProcXSelectExtensionEvent,              /*  6 */
+	ProcXGetSelectedExtensionEvents,        /*  7 */
+	ProcXChangeDeviceDontPropagateList,     /*  8 */
+	ProcXGetDeviceDontPropagateList,        /*  9 */
+	ProcXGetDeviceMotionEvents,             /* 10 */
+	ProcXChangeKeyboardDevice,              /* 11 */
+	ProcXChangePointerDevice,               /* 12 */
+	ProcXGrabDevice,                        /* 13 */
+	ProcXUngrabDevice,                      /* 14 */
+	ProcXGrabDeviceKey,                     /* 15 */
+	ProcXUngrabDeviceKey,                   /* 16 */
+	ProcXGrabDeviceButton,                  /* 17 */
+	ProcXUngrabDeviceButton,                /* 18 */
+	ProcXAllowDeviceEvents,                 /* 19 */
+	ProcXGetDeviceFocus,                    /* 20 */
+	ProcXSetDeviceFocus,                    /* 21 */
+	ProcXGetFeedbackControl,                /* 22 */
+	ProcXChangeFeedbackControl,             /* 23 */
+	ProcXGetDeviceKeyMapping,               /* 24 */
+	ProcXChangeDeviceKeyMapping,            /* 25 */
+	ProcXGetDeviceModifierMapping,          /* 26 */
+	ProcXSetDeviceModifierMapping,          /* 27 */
+	ProcXGetDeviceButtonMapping,            /* 28 */
+	ProcXSetDeviceButtonMapping,            /* 29 */
+	ProcXQueryDeviceState,                  /* 30 */
+	ProcXSendExtensionEvent,                /* 31 */
+	ProcXDeviceBell,                        /* 32 */
+	ProcXSetDeviceValuators,                /* 33 */
+	ProcXGetDeviceControl,                  /* 34 */
+	ProcXChangeDeviceControl,               /* 35 */
+        ProcXQueryDevicePointer,                /* 36 */
+        ProcXWarpDevicePointer,                 /* 37 */
+        ProcXChangeDeviceCursor,                /* 38 */
+        ProcXChangeDeviceHierarchy,             /* 39 */
+        ProcXiSelectEvent,                      /* 40 */
+        ProcXChangeWindowAccess,                /* 41 */
+        ProcXQueryWindowAccess,                 /* 42 */
+        ProcXSetClientPointer,                  /* 43 */
+        ProcXGetClientPointer,                  /* 44 */
+        ProcXExtendedGrabDevice                 /* 45 */
+};
+
+/* For swapped clients */
+static int (*SProcIVector[])(ClientPtr) = {
+        NULL,                                    /*  0 */
+	SProcXGetExtensionVersion,               /*  1 */
+	SProcXListInputDevices,                  /*  2 */
+	SProcXOpenDevice,                        /*  3 */
+	SProcXCloseDevice,                       /*  4 */
+	SProcXSetDeviceMode,                     /*  5 */
+	SProcXSelectExtensionEvent,              /*  6 */
+	SProcXGetSelectedExtensionEvents,        /*  7 */
+	SProcXChangeDeviceDontPropagateList,     /*  8 */
+	SProcXGetDeviceDontPropagateList,        /*  9 */
+	SProcXGetDeviceMotionEvents,             /* 10 */
+	SProcXChangeKeyboardDevice,              /* 11 */
+	SProcXChangePointerDevice,               /* 12 */
+	SProcXGrabDevice,                        /* 13 */
+	SProcXUngrabDevice,                      /* 14 */
+	SProcXGrabDeviceKey,                     /* 15 */
+	SProcXUngrabDeviceKey,                   /* 16 */
+	SProcXGrabDeviceButton,                  /* 17 */
+	SProcXUngrabDeviceButton,                /* 18 */
+	SProcXAllowDeviceEvents,                 /* 19 */
+	SProcXGetDeviceFocus,                    /* 20 */
+	SProcXSetDeviceFocus,                    /* 21 */
+	SProcXGetFeedbackControl,                /* 22 */
+	SProcXChangeFeedbackControl,             /* 23 */
+	SProcXGetDeviceKeyMapping,               /* 24 */
+	SProcXChangeDeviceKeyMapping,            /* 25 */
+	SProcXGetDeviceModifierMapping,          /* 26 */
+	SProcXSetDeviceModifierMapping,          /* 27 */
+	SProcXGetDeviceButtonMapping,            /* 28 */
+	SProcXSetDeviceButtonMapping,            /* 29 */
+	SProcXQueryDeviceState,                  /* 30 */
+	SProcXSendExtensionEvent,                /* 31 */
+	SProcXDeviceBell,                        /* 32 */
+	SProcXSetDeviceValuators,                /* 33 */
+	SProcXGetDeviceControl,                  /* 34 */
+	SProcXChangeDeviceControl,               /* 35 */
+        SProcXQueryDevicePointer,                /* 36 */
+        SProcXWarpDevicePointer,                 /* 37 */
+        SProcXChangeDeviceCursor,                /* 38 */
+        SProcXChangeDeviceHierarchy,             /* 39 */
+        SProcXiSelectEvent,                      /* 40 */
+        SProcXChangeWindowAccess,                /* 41 */
+        SProcXQueryWindowAccess,                 /* 42 */
+        SProcXSetClientPointer,                  /* 43 */
+        SProcXGetClientPointer,                  /* 44 */
+        SProcXExtendedGrabDevice                 /* 45 */
+};
+
 /*****************************************************************
  *
  * Globals referenced elsewhere in the server.
@@ -246,100 +349,10 @@ static int
 ProcIDispatch(ClientPtr client)
 {
     REQUEST(xReq);
-    if (stuff->data == X_GetExtensionVersion)
-	return (ProcXGetExtensionVersion(client));
-    if (stuff->data == X_ListInputDevices)
-	return (ProcXListInputDevices(client));
-    else if (stuff->data == X_OpenDevice)
-	return (ProcXOpenDevice(client));
-    else if (stuff->data == X_CloseDevice)
-	return (ProcXCloseDevice(client));
-    else if (stuff->data == X_SetDeviceMode)
-	return (ProcXSetDeviceMode(client));
-    else if (stuff->data == X_SelectExtensionEvent)
-	return (ProcXSelectExtensionEvent(client));
-    else if (stuff->data == X_GetSelectedExtensionEvents)
-	return (ProcXGetSelectedExtensionEvents(client));
-    else if (stuff->data == X_ChangeDeviceDontPropagateList)
-	return (ProcXChangeDeviceDontPropagateList(client));
-    else if (stuff->data == X_GetDeviceDontPropagateList)
-	return (ProcXGetDeviceDontPropagateList(client));
-    else if (stuff->data == X_GetDeviceMotionEvents)
-	return (ProcXGetDeviceMotionEvents(client));
-    else if (stuff->data == X_ChangeKeyboardDevice)
-	return (ProcXChangeKeyboardDevice(client));
-    else if (stuff->data == X_ChangePointerDevice)
-	return (ProcXChangePointerDevice(client));
-    else if (stuff->data == X_GrabDevice)
-	return (ProcXGrabDevice(client));
-    else if (stuff->data == X_UngrabDevice)
-	return (ProcXUngrabDevice(client));
-    else if (stuff->data == X_GrabDeviceKey)
-	return (ProcXGrabDeviceKey(client));
-    else if (stuff->data == X_UngrabDeviceKey)
-	return (ProcXUngrabDeviceKey(client));
-    else if (stuff->data == X_GrabDeviceButton)
-	return (ProcXGrabDeviceButton(client));
-    else if (stuff->data == X_UngrabDeviceButton)
-	return (ProcXUngrabDeviceButton(client));
-    else if (stuff->data == X_AllowDeviceEvents)
-	return (ProcXAllowDeviceEvents(client));
-    else if (stuff->data == X_GetDeviceFocus)
-	return (ProcXGetDeviceFocus(client));
-    else if (stuff->data == X_SetDeviceFocus)
-	return (ProcXSetDeviceFocus(client));
-    else if (stuff->data == X_GetFeedbackControl)
-	return (ProcXGetFeedbackControl(client));
-    else if (stuff->data == X_ChangeFeedbackControl)
-	return (ProcXChangeFeedbackControl(client));
-    else if (stuff->data == X_GetDeviceKeyMapping)
-	return (ProcXGetDeviceKeyMapping(client));
-    else if (stuff->data == X_ChangeDeviceKeyMapping)
-	return (ProcXChangeDeviceKeyMapping(client));
-    else if (stuff->data == X_GetDeviceModifierMapping)
-	return (ProcXGetDeviceModifierMapping(client));
-    else if (stuff->data == X_SetDeviceModifierMapping)
-	return (ProcXSetDeviceModifierMapping(client));
-    else if (stuff->data == X_GetDeviceButtonMapping)
-	return (ProcXGetDeviceButtonMapping(client));
-    else if (stuff->data == X_SetDeviceButtonMapping)
-	return (ProcXSetDeviceButtonMapping(client));
-    else if (stuff->data == X_QueryDeviceState)
-	return (ProcXQueryDeviceState(client));
-    else if (stuff->data == X_SendExtensionEvent)
-	return (ProcXSendExtensionEvent(client));
-    else if (stuff->data == X_DeviceBell)
-	return (ProcXDeviceBell(client));
-    else if (stuff->data == X_SetDeviceValuators)
-	return (ProcXSetDeviceValuators(client));
-    else if (stuff->data == X_GetDeviceControl)
-	return (ProcXGetDeviceControl(client));
-    else if (stuff->data == X_ChangeDeviceControl)
-	return (ProcXChangeDeviceControl(client));
-    else if (stuff->data == X_QueryDevicePointer)
-        return (ProcXQueryDevicePointer(client));
-    else if (stuff->data == X_WarpDevicePointer)
-        return (ProcXWarpDevicePointer(client));
-    else if (stuff->data == X_ChangeDeviceCursor)
-        return (ProcXChangeDeviceCursor(client));
-    else if (stuff->data == X_ChangeDeviceHierarchy)
-        return (ProcXChangeDeviceHierarchy(client));
-    else if (stuff->data == X_XiSelectEvent)
-        return (ProcXiSelectEvent(client));
-    else if (stuff->data == X_ChangeWindowAccess)
-        return (ProcXChangeWindowAccess(client));
-    else if (stuff->data == X_QueryWindowAccess)
-        return ProcXQueryWindowAccess(client);
-    else if (stuff->data == X_SetClientPointer)
-        return ProcXSetClientPointer(client);
-    else if (stuff->data == X_GetClientPointer)
-        return ProcXGetClientPointer(client);
-    else if (stuff->data == X_ExtendedGrabDevice)
-        return ProcXExtendedGrabDevice(client);
-    else {
-	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
-    }
-    return (BadRequest);
+    if (stuff->data > IREQUESTS || !ProcIVector[stuff->data])
+        return BadRequest;
+
+    return (*ProcIVector[stuff->data])(client);
 }
 
 /*******************************************************************************
@@ -355,100 +368,10 @@ static int
 SProcIDispatch(ClientPtr client)
 {
     REQUEST(xReq);
-    if (stuff->data == X_GetExtensionVersion)
-	return (SProcXGetExtensionVersion(client));
-    if (stuff->data == X_ListInputDevices)
-	return (SProcXListInputDevices(client));
-    else if (stuff->data == X_OpenDevice)
-	return (SProcXOpenDevice(client));
-    else if (stuff->data == X_CloseDevice)
-	return (SProcXCloseDevice(client));
-    else if (stuff->data == X_SetDeviceMode)
-	return (SProcXSetDeviceMode(client));
-    else if (stuff->data == X_SelectExtensionEvent)
-	return (SProcXSelectExtensionEvent(client));
-    else if (stuff->data == X_GetSelectedExtensionEvents)
-	return (SProcXGetSelectedExtensionEvents(client));
-    else if (stuff->data == X_ChangeDeviceDontPropagateList)
-	return (SProcXChangeDeviceDontPropagateList(client));
-    else if (stuff->data == X_GetDeviceDontPropagateList)
-	return (SProcXGetDeviceDontPropagateList(client));
-    else if (stuff->data == X_GetDeviceMotionEvents)
-	return (SProcXGetDeviceMotionEvents(client));
-    else if (stuff->data == X_ChangeKeyboardDevice)
-	return (SProcXChangeKeyboardDevice(client));
-    else if (stuff->data == X_ChangePointerDevice)
-	return (SProcXChangePointerDevice(client));
-    else if (stuff->data == X_GrabDevice)
-	return (SProcXGrabDevice(client));
-    else if (stuff->data == X_UngrabDevice)
-	return (SProcXUngrabDevice(client));
-    else if (stuff->data == X_GrabDeviceKey)
-	return (SProcXGrabDeviceKey(client));
-    else if (stuff->data == X_UngrabDeviceKey)
-	return (SProcXUngrabDeviceKey(client));
-    else if (stuff->data == X_GrabDeviceButton)
-	return (SProcXGrabDeviceButton(client));
-    else if (stuff->data == X_UngrabDeviceButton)
-	return (SProcXUngrabDeviceButton(client));
-    else if (stuff->data == X_AllowDeviceEvents)
-	return (SProcXAllowDeviceEvents(client));
-    else if (stuff->data == X_GetDeviceFocus)
-	return (SProcXGetDeviceFocus(client));
-    else if (stuff->data == X_SetDeviceFocus)
-	return (SProcXSetDeviceFocus(client));
-    else if (stuff->data == X_GetFeedbackControl)
-	return (SProcXGetFeedbackControl(client));
-    else if (stuff->data == X_ChangeFeedbackControl)
-	return (SProcXChangeFeedbackControl(client));
-    else if (stuff->data == X_GetDeviceKeyMapping)
-	return (SProcXGetDeviceKeyMapping(client));
-    else if (stuff->data == X_ChangeDeviceKeyMapping)
-	return (SProcXChangeDeviceKeyMapping(client));
-    else if (stuff->data == X_GetDeviceModifierMapping)
-	return (SProcXGetDeviceModifierMapping(client));
-    else if (stuff->data == X_SetDeviceModifierMapping)
-	return (SProcXSetDeviceModifierMapping(client));
-    else if (stuff->data == X_GetDeviceButtonMapping)
-	return (SProcXGetDeviceButtonMapping(client));
-    else if (stuff->data == X_SetDeviceButtonMapping)
-	return (SProcXSetDeviceButtonMapping(client));
-    else if (stuff->data == X_QueryDeviceState)
-	return (SProcXQueryDeviceState(client));
-    else if (stuff->data == X_SendExtensionEvent)
-	return (SProcXSendExtensionEvent(client));
-    else if (stuff->data == X_DeviceBell)
-	return (SProcXDeviceBell(client));
-    else if (stuff->data == X_SetDeviceValuators)
-	return (SProcXSetDeviceValuators(client));
-    else if (stuff->data == X_GetDeviceControl)
-	return (SProcXGetDeviceControl(client));
-    else if (stuff->data == X_ChangeDeviceControl)
-	return (SProcXChangeDeviceControl(client));
-    else if (stuff->data == X_QueryDevicePointer)
-	return (SProcXQueryDevicePointer(client));
-    else if (stuff->data == X_WarpDevicePointer)
-	return (SProcXWarpDevicePointer(client));
-    else if (stuff->data == X_ChangeDeviceCursor)
-        return (SProcXChangeDeviceCursor(client));
-    else if (stuff->data == X_ChangeDeviceHierarchy)
-        return (SProcXChangeDeviceHierarchy(client));
-    else if (stuff->data == X_XiSelectEvent)
-        return (SProcXiSelectEvent(client));
-    else if (stuff->data == X_ChangeWindowAccess)
-        return (SProcXChangeWindowAccess(client));
-    else if (stuff->data == X_QueryWindowAccess)
-        return SProcXQueryWindowAccess(client);
-    else if (stuff->data == X_SetClientPointer)
-        return SProcXSetClientPointer(client);
-    else if (stuff->data == X_GetClientPointer)
-        return SProcXGetClientPointer(client);
-    else if (stuff->data == X_ExtendedGrabDevice)
-        return SProcXExtendedGrabDevice(client);
-    else {
-	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
-    }
-    return (BadRequest);
+    if (stuff->data > IREQUESTS || !SProcIVector[stuff->data])
+        return BadRequest;
+
+    return (*SProcIVector[stuff->data])(client);
 }
 
 /**********************************************************************
commit cb8cb87bc6decf75832c3724687000ecb658226e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 25 10:09:50 2008 +0930

    Xi: remove unused #define DISPATCH

diff --git a/Xi/extinit.c b/Xi/extinit.c
index f1c2824..fa15478 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -458,11 +458,6 @@ SProcIDispatch(ClientPtr client)
  *
  */
 
-/* FIXME: this would be more concise and readable in ANSI C */
-#define DISPATCH(code) \
-    if (rep->RepType == X_##code) \
-	SRepX##code (client, len, (x##code##Reply *) rep)
-
 static void
 SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
 					/* All we look at is the type field */
commit 7dc40c8eca90ec1bfab84b6f54418b64c0e62d63
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 24 12:47:29 2008 +0930

    xfree86: Don't free master devices.
    
    The previous check works in the master-branch, but doesn't work with MPX. We
    actually copy the SD's information into the MDs public.devicePrivate, so we
    need to explicitly check whether a device is a MD before freeing the module.

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 30e0e6b..8ff31e8 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -490,7 +490,7 @@ DeleteInputDeviceRequest(DeviceIntPtr pDev)
     }
     RemoveDevice(pDev);
 
-    if (!pInfo) /* VCP and VCK */
+    if (pDev->isMaster)
         return;
 
     if(drv->UnInit)
commit cc13f87cd8ac54223fdb0b3d3c043dc9b9be5a42
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 24 11:43:47 2008 +0930

    Xext: XGE: change function definition to have return value on separate line.
    
    This seems to be the common style in most parts of the server.

diff --git a/Xext/geext.c b/Xext/geext.c
index 19763a0..29ddacd 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -64,7 +64,8 @@ static void SGEGenericEvent(xEvent* from, xEvent* to);
 /*                request handlers                          */
 /************************************************************/
 
-static int ProcGEQueryVersion(ClientPtr client)
+static int
+ProcGEQueryVersion(ClientPtr client)
 {
     int n;
     GEClientInfoPtr pGEClient = GEGetClient(client);
@@ -160,9 +161,10 @@ SProcGEDispatch(ClientPtr client)
  * We alloc a simple struct to store the client's major/minor version. Can be
  * used in the furture for versioning support.
  */
-static void GEClientCallback(CallbackListPtr *list,
-        pointer closure,
-        pointer data)
+static void
+GEClientCallback(CallbackListPtr *list,
+                 pointer closure,
+                 pointer data)
 {
     NewClientInfoRec	*clientinfo = (NewClientInfoRec *) data;
     ClientPtr		pClient = clientinfo->client;
@@ -256,12 +258,11 @@ GEExtensionInit(void)
  * @param ev_fill Called for an event before delivery. The extension now has
  * the chance to fill in necessary fields for the event.
  */
-void GERegisterExtension(
-        int extension,
-        void (*ev_swap)(xGenericEvent* from, xGenericEvent* to),
-        void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev,
-                        WindowPtr pWin, GrabPtr pGrab)
-        )
+void
+GERegisterExtension(int extension,
+                    void (*ev_swap)(xGenericEvent* from, xGenericEvent* to),
+                    void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev,
+                                    WindowPtr pWin, GrabPtr pGrab))
 {
     if ((extension & 0x7F) >=  MAXEXTENSIONS)
         FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n");
@@ -275,7 +276,8 @@ void GERegisterExtension(
 /* 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)
+void
+GEInitEvent(xGenericEvent* ev, int extension)
 {
     ev->type = GenericEvent;
     ev->extension = extension;
@@ -312,8 +314,9 @@ GERecalculateWinMask(WindowPtr pWin)
 }
 
 /* Set generic event mask for given window. */
-void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
-                     WindowPtr pWin, int extension, Mask mask)
+void
+GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
+                WindowPtr pWin, int extension, Mask mask)
 {
     GenericMaskPtr cli;
 
@@ -397,8 +400,9 @@ void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
  * @param extension Extension ID
  * @param mask Event mask
  */
-BOOL GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev,
-                       int extension, Mask mask)
+BOOL
+GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev,
+                  int extension, Mask mask)
 {
     GenericMaskPtr gemask;
 
commit d0890c40b9a9c7965c08608e6950c078a29aac16
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 24 11:32:36 2008 +0930

    Xext: add a few lines of comments to XGE.

diff --git a/Xext/geext.c b/Xext/geext.c
index c6c8713..19763a0 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -178,7 +178,7 @@ static void GEClientCallback(CallbackListPtr *list,
     pGEClient->minor_version = 0;
 }
 
-/* reset extension */
+/* Reset extension. Called on server shutdown. */
 static void
 GEResetProc(ExtensionEntry *extEntry)
 {
@@ -190,7 +190,13 @@ GEResetProc(ExtensionEntry *extEntry)
     GEEventType = 0;
 }
 
-/*  Calls the registered event swap function for the extension. */
+/*  Calls the registered event swap function for the extension.
+ *
+ *  Each extension can register a swap function to handle GenericEvents being
+ *  swapped properly. The server calls SGEGenericEvent() before the event is
+ *  written on the wire, this one calls the registered swap function to do the
+ *  work.
+ */
 static void
 SGEGenericEvent(xEvent* from, xEvent* to)
 {
@@ -207,7 +213,10 @@ SGEGenericEvent(xEvent* from, xEvent* to)
         GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto);
 }
 
-/* init extension, register at server */
+/* Init extension, register at server.
+ * Since other extensions may rely on XGE (XInput does already), it is a good
+ * idea to init XGE first, before any other extension.
+ */
 void
 GEExtensionInit(void)
 {
@@ -357,8 +366,8 @@ void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
         {
             pWin->optional->geMasks->geClients = cli->next;
             xfree(cli);
-        } else 
-        { 
+        } else
+        {
             GenericMaskPtr prev = cli;
             cli = cli->next;
 
commit 745b90cde1007383ec8c887f02439a34ab427f31
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 24 11:27:22 2008 +0930

    Xext: re-do the XGE versioning handling.
    
    Basically the same approach RandR takes. Remember which one the client
    requested, send back the one the server supports. Also divide XGE server
    version (now defined in geext.c) and the client's version (still in the
    protocol definition).

diff --git a/Xext/geext.c b/Xext/geext.c
index 8347322..c6c8713 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -1,4 +1,4 @@
-/* 
+/*
 
 Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
 
@@ -36,6 +36,11 @@ from the author.
 #include "geint.h"
 #include "geext.h"
 
+/* Currently supported XGE version */
+#define SERVER_GE_MAJOR 1
+#define SERVER_GE_MINOR 0
+
+
 int GEEventBase;
 int GEErrorBase;
 DevPrivateKey GEClientPrivateKey = &GEClientPrivateKey;
@@ -73,20 +78,13 @@ static int ProcGEQueryVersion(ClientPtr client)
     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;
-    }
+    /* return the supported version by the server */
+    rep.majorVersion = SERVER_GE_MAJOR;
+    rep.minorVersion = SERVER_GE_MINOR;
 
-    pGEClient->major_version = rep.majorVersion;
-    pGEClient->minor_version = rep.minorVersion;
+    /* Remember version the client requested */
+    pGEClient->major_version = stuff->majorVersion;
+    pGEClient->minor_version = stuff->minorVersion;
 
     if (client->swapped)
     {
@@ -156,7 +154,12 @@ SProcGEDispatch(ClientPtr client)
     return (*SProcGEVector[stuff->ReqType])(client);
 }
 
-/* new client callback */
+/**
+ * Called when a new client inits a connection to the X server.
+ *
+ * We alloc a simple struct to store the client's major/minor version. Can be
+ * used in the furture for versioning support.
+ */
 static void GEClientCallback(CallbackListPtr *list,
         pointer closure,
         pointer data)
commit 5f3e5b3462bb02e828c70d0e1890b5a83d399d42
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 24 11:03:23 2008 +0930

    Xext: remove trailing whitespaces in geext.{c|h}

diff --git a/Xext/geext.c b/Xext/geext.c
index 77bb181..8347322 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -78,7 +78,7 @@ static int ProcGEQueryVersion(ClientPtr client)
         rep.minorVersion = stuff->minorVersion;
     } else {
         rep.majorVersion = GE_MAJOR;
-        if (stuff->majorVersion == GE_MAJOR && 
+        if (stuff->majorVersion == GE_MAJOR &&
                 stuff->minorVersion < GE_MINOR)
             rep.minorVersion = stuff->minorVersion;
         else
@@ -90,8 +90,8 @@ static int ProcGEQueryVersion(ClientPtr client)
 
     if (client->swapped)
     {
-    	swaps(&rep.sequenceNumber, n);
-    	swapl(&rep.length, n);
+	swaps(&rep.sequenceNumber, n);
+        swapl(&rep.length, n);
         swaps(&rep.majorVersion, n);
         swaps(&rep.minorVersion, n);
     }
@@ -132,7 +132,7 @@ int (*SProcGEVector[GENumberRequests])(ClientPtr) = {
 /************************************************************/
 
 /* dispatch requests */
-static int 
+static int
 ProcGEDispatch(ClientPtr client)
 {
     GEClientInfoPtr pGEClient = GEGetClient(client);
@@ -188,7 +188,7 @@ GEResetProc(ExtensionEntry *extEntry)
 }
 
 /*  Calls the registered event swap function for the extension. */
-static void 
+static void
 SGEGenericEvent(xEvent* from, xEvent* to)
 {
     xGenericEvent* gefrom = (xGenericEvent*)from;
@@ -215,9 +215,9 @@ GEExtensionInit(void)
         FatalError("GEExtensionInit: register client callback failed.\n");
     }
 
-    if((extEntry = AddExtension(GE_NAME, 
-                        GENumberEvents, GENumberErrors, 
-                        ProcGEDispatch, SProcGEDispatch, 
+    if((extEntry = AddExtension(GE_NAME,
+                        GENumberEvents, GENumberErrors,
+                        ProcGEDispatch, SProcGEDispatch,
                         GEResetProc, StandardMinorOpcode)) != 0)
     {
         GEEventBase = extEntry->eventBase;
@@ -239,15 +239,15 @@ GEExtensionInit(void)
 
 /* 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.  
+ * @param extension The extensions major opcode
+ * @param ev_swap The event swap function.
  * @param ev_fill Called for an event before delivery. The extension now has
  * the chance to fill in necessary fields for the event.
  */
 void GERegisterExtension(
-        int extension, 
+        int extension,
         void (*ev_swap)(xGenericEvent* from, xGenericEvent* to),
-        void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev, 
+        void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev,
                         WindowPtr pWin, GrabPtr pGrab)
         )
 {
@@ -261,8 +261,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;
@@ -271,7 +271,7 @@ void GEInitEvent(xGenericEvent* ev, int extension)
 }
 
 /* Recalculates the summary mask for the window. */
-static void 
+static void
 GERecalculateWinMask(WindowPtr pWin)
 {
     int i;
@@ -300,7 +300,7 @@ GERecalculateWinMask(WindowPtr pWin)
 }
 
 /* Set generic event mask for given window. */
-void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev, 
+void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
                      WindowPtr pWin, int extension, Mask mask)
 {
     GenericMaskPtr cli;
@@ -403,7 +403,7 @@ BOOL GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev,
 
     while(gemask)
     {
-        if ((!gemask->dev || gemask->dev == pDev) && 
+        if ((!gemask->dev || gemask->dev == pDev) &&
                 (gemask->eventMask[extension] & mask))
             return TRUE;
 
diff --git a/Xext/geext.h b/Xext/geext.h
index 577654a..84539a9 100644
--- a/Xext/geext.h
+++ b/Xext/geext.h
@@ -1,4 +1,4 @@
-/* 
+/*
 
 Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
 
@@ -46,7 +46,7 @@ typedef struct _GenericMaskRec {
     ClientPtr       client;                /* client who set the event mask */
     DeviceIntPtr    dev;
     Mask            eventMask[MAXEXTENSIONS]; /* one mask per extension */
-    struct _GenericMaskRec* next;            
+    struct _GenericMaskRec* next;
 } GenericMaskRec, *GenericMaskPtr;
 
 
@@ -57,7 +57,7 @@ typedef struct _GenericMaskRec {
  */
 typedef struct _GEExtension {
     void (*evswap)(xGenericEvent* from, xGenericEvent* to);
-    void (*evfill)(xGenericEvent* ev, 
+    void (*evfill)(xGenericEvent* ev,
                     DeviceIntPtr pDev,  /* device */
                     WindowPtr pWin,     /* event window */
                     GrabPtr pGrab       /* current grab, may be NULL */
@@ -101,12 +101,12 @@ void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
 void GERegisterExtension(
         int extension,
         void (*ev_dispatch)(xGenericEvent* from, xGenericEvent* to),
-        void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev, 
+        void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev,
                         WindowPtr pWin, GrabPtr pGrab)
         );
 
 void GEInitEvent(xGenericEvent* ev, int extension);
-BOOL GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev, 
+BOOL GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev,
                        int extension, Mask mask);
 
 void GEExtensionInit(void);
diff --git a/Xext/geint.h b/Xext/geint.h
index 57404d8..7747234 100644
--- a/Xext/geint.h
+++ b/Xext/geint.h
@@ -1,4 +1,4 @@
-/* 
+/*
 
 Copyright 2007 Peter Hutterer <peter at cs.unisa.edu.au>
 
commit 275cdc1c74b7e43ecd931d312469fecc8d998ed1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 23 16:16:15 2008 +0930

    xfree86: pass correct value to mieqEnqueue (merge detritus I guess)

diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index d1e4393..f408fc9 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -818,7 +818,7 @@ xf86ReleaseKeys(DeviceIntPtr pDev)
 		    int sigstate = xf86BlockSIGIO ();
                     nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i);
                     for (j = 0; j < nevents; j++)
-                        mieqEnqueue(pDev, xf86Events + j);
+                        mieqEnqueue(pDev, (xf86Events + j)->event);
 		    xf86UnblockSIGIO(sigstate);
                 }
                 break;
commit c3659cb414ef05da8fa09009b2b82a3deeeb4f3a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 22 21:54:02 2008 +0930

    dix: always send FocusIn events if mode is NotifyUngrab.
    
    In the case of a NotifyUngrab, the flag for the device may already be set but
    we still need to send the FocusIn event.

diff --git a/dix/events.c b/dix/events.c
index 7b503ac..04342fc 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4690,6 +4690,8 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
 
     if (!numFoci)
         sendevent = TRUE;
+    else if (mode == NotifyUngrab && FOCUS_SEMAPHORE_ISSET(pWin, dev))
+        sendevent = TRUE;
 
     if (sendevent)
     {
commit 8190ef87547b704848231bde10b1cdffc6442790
Merge: 179a082... 2ddbfd3...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 22 18:04:05 2008 +0930

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	Xext/EVI.c
    	Xext/appgroup.c
    	Xext/cup.c
    	Xext/mitmisc.c
    	Xext/sampleEVI.c
    	dix/window.c

diff --cc dix/devices.c
index fe70e78,5a726af..656707c
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -835,9 -623,8 +835,9 @@@ CloseDownDevices(void
      for (dev = inputInfo.off_devices; dev; dev = next)
      {
  	next = dev->next;
- 	CloseDevice(dev);
+         DeleteInputDeviceRequest(dev);
      }
 +
      inputInfo.devices = NULL;
      inputInfo.off_devices = NULL;
      inputInfo.keyboard = NULL;
diff --cc dix/events.c
index 0931033,aef333e..7b503ac
--- a/dix/events.c
+++ b/dix/events.c
@@@ -2664,18 -2171,24 +2664,25 @@@ XYToWindow(DeviceIntPtr pDev, int x, in
  				x - pWin->drawable.x,
  				y - pWin->drawable.y, &box))
  #endif
+ #ifdef ROOTLESS
+     /* In rootless mode windows may be offscreen, even when
+      * they're in X's stack. (E.g. if the native window system
+      * implements some form of virtual desktop system).
+      */
+ 		&& !pWin->rootlessUnhittable
+ #endif
  	    )
  	{
 -	    if (spriteTraceGood >= spriteTraceSize)
 +	    if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
  	    {
 -		spriteTraceSize += 10;
 +		pSprite->spriteTraceSize += 10;
  		Must_have_memory = TRUE; /* XXX */
 -		spriteTrace = (WindowPtr *)xrealloc(
 -		    spriteTrace, spriteTraceSize*sizeof(WindowPtr));
 +		pSprite->spriteTrace = (WindowPtr *)xrealloc(
 +		                    pSprite->spriteTrace,
 +		                    pSprite->spriteTraceSize*sizeof(WindowPtr));
  		Must_have_memory = FALSE; /* XXX */
  	    }
 -	    spriteTrace[spriteTraceGood++] = pWin;
 +	    pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
  	    pWin = pWin->firstChild;
  	}
  	else
diff --cc dix/window.c
index d3160c9,168e940..33e9752
--- a/dix/window.c
+++ b/dix/window.c
@@@ -307,9 -289,9 +304,13 @@@ SetWindowToDefaults(WindowPtr pWin
      pWin->forcedBS = FALSE;
      pWin->redirectDraw = RedirectDrawNone;
      pWin->forcedBG = FALSE;
 +
 +    sem = xcalloc(1, sizeof(FocusSemaphoresRec));
 +    dixSetPrivate(&pWin->devPrivates, FocusPrivatesKey, sem);
++
+ #ifdef ROOTLESS
+     pWin->rootlessUnhittable = FALSE;
+ #endif
  }
  
  static void
commit 179a082c26f9e562492ee2e59e7f44f949f39f9c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 18 21:13:10 2008 +0930

    Xext: route event through master if required (XTestFakeInput)

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 721dacc..e11f358 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -471,7 +471,15 @@ ProcXTestFakeInput(client)
     if (screenIsSaved == SCREEN_SAVER_ON)
         dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
     ev->u.keyButtonPointer.time = currentTime.milliseconds;
-    (*dev->public.processInputProc)(ev, dev, nev);
+    if (!dev->isMaster && dev->u.master)
+    {   /* duplicate and route through master */
+        xEvent *master_event = NULL;
+        CopyGetMasterEvent(dev->u.master, ev, &master_event, nev);
+        (*dev->public.processInputProc)(ev, dev, nev);
+        (*dev->public.processInputProc)(master_event, dev->u.master, nev);
+        xfree(master_event);
+    } else
+        (*dev->public.processInputProc)(ev, dev, nev);
     return client->noClientException;
 }
 
diff --git a/mi/mieq.c b/mi/mieq.c
index cae5516..1c85030 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -263,7 +263,7 @@ ChangeDeviceID(DeviceIntPtr dev, xEvent* event)
  * @param master The event after being copied
  * @param count Number of events in original.
  */
-static void
+void
 CopyGetMasterEvent(DeviceIntPtr mdev, xEvent* original,
                    xEvent** master, int count)
 {
commit fb784d99c521823339bf00b70b9824f735d88875
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 18 20:57:42 2008 +0930

    mi: fix typo in comment.

diff --git a/mi/mieq.c b/mi/mieq.c
index 2759d16..cae5516 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -333,7 +333,7 @@ mieqProcessInputEvents(void)
 
             /* 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
+             * DeviceValuators. For now it's safe 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)
commit 8209fdbc7c7f2dd068b30ff184b5fbf00db78686
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 18 20:53:57 2008 +0930

    Xext: Update sprite on fake input only for MDs and floating SDs.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 5f0b25e..721dacc 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -440,10 +440,14 @@ ProcXTestFakeInput(client)
                             ev->u.keyButtonPointer.rootY);
                     return client->noClientException;
                 }
-            (*root->drawable.pScreen->SetCursorPosition)
-                (dev, root->drawable.pScreen,
-                 ev->u.keyButtonPointer.rootX,
-                 ev->u.keyButtonPointer.rootY, FALSE);
+            /* Only update sprite for MDs and floating SDs */
+            if (dev->isMaster || (!dev->isMaster && !dev->u.master))
+            {
+                (*root->drawable.pScreen->SetCursorPosition)
+                    (dev, root->drawable.pScreen,
+                     ev->u.keyButtonPointer.rootX,
+                     ev->u.keyButtonPointer.rootY, FALSE);
+            }
             dev->lastx = ev->u.keyButtonPointer.rootX;
             dev->lasty = ev->u.keyButtonPointer.rootY;
             break;
commit 3b93631e59ca4d312d318eac4015e0a79ad6351f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 18 11:31:54 2008 +0930

    dix: remove coreOnly check. Core pointer must generate XI events now.
    
    This flag was only used when an event is generated by Warp[Device]Pointer.
    Since the VCP now happily generates core events, this flag is obsolete.

diff --git a/dix/getevents.c b/dix/getevents.c
index 037d68c..d352ebe 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -664,8 +664,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     deviceKeyButtonPointer *kbp = NULL;
     DeviceIntPtr master;
     int x = 0, y = 0;
-    /* The core pointer must not send Xi events. */
-    Bool coreOnly = (pDev == inputInfo.pointer);
 
     /* Sanity checks. */
     if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
@@ -700,7 +698,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     }
 
     /* Do we need to send a DeviceValuator event? */
-    if (!coreOnly && num_valuators) {
+    if (num_valuators) {
         if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
             num_valuators = MAX_VALUATOR_EVENTS * 6;
         num_events += ((num_valuators - 1) / 6) + 1;
@@ -771,33 +769,30 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         master->lasty = y;
     }
 
-    if (!coreOnly)
-    {
-        kbp = (deviceKeyButtonPointer *) events->event;
-        kbp->time = ms;
-        kbp->deviceid = pDev->id;
+    kbp = (deviceKeyButtonPointer *) events->event;
+    kbp->time = ms;
+    kbp->deviceid = pDev->id;
 
-        if (type == MotionNotify) {
-            kbp->type = DeviceMotionNotify;
-        }
-        else {
-            if (type == ButtonPress)
-                kbp->type = DeviceButtonPress;
-            else if (type == ButtonRelease)
-                kbp->type = DeviceButtonRelease;
-            kbp->detail = pDev->button->map[buttons];
-        }
+    if (type == MotionNotify) {
+        kbp->type = DeviceMotionNotify;
+    }
+    else {
+        if (type == ButtonPress)
+            kbp->type = DeviceButtonPress;
+        else if (type == ButtonRelease)
+            kbp->type = DeviceButtonRelease;
+        kbp->detail = pDev->button->map[buttons];
+    }
 
-        kbp->root_x = x;
-        kbp->root_y = y;
+    kbp->root_x = x;
+    kbp->root_y = y;
 
-        events++;
-        if (num_valuators) {
-            kbp->deviceid |= MORE_EVENTS;
-            clipValuators(pDev, first_valuator, num_valuators, valuators);
-            events = getValuatorEvents(events, pDev, first_valuator,
-                                       num_valuators, valuators);
-        }
+    events++;
+    if (num_valuators) {
+        kbp->deviceid |= MORE_EVENTS;
+        clipValuators(pDev, first_valuator, num_valuators, valuators);
+        events = getValuatorEvents(events, pDev, first_valuator,
+                num_valuators, valuators);
     }
 
     return num_events;
commit e0eaf8e5e3fa7a11c087851dff93f50f6907c4a5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 18 10:57:47 2008 +0930

    Xext: Let XTestFakeInput update the sprite for XI events.
    
    Since XI devices can have their own sprite now, we need to update the sprite
    coordinates too when processing an XI event.
    Note: This doesn't deal with the device hierarchy correctly yet.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 0c96b3c..5f0b25e 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -338,7 +338,23 @@ ProcXTestFakeInput(client)
                         values += 6;
                     }
                 }
-                break;
+                /* For XI events, the actual event is mostly unset. Since we
+                 * want to update the sprite nontheless, we need to fake up
+                 * sane values for the event. */
+
+                ev->u.keyButtonPointer.root = None;
+                dv = (deviceValuator*)(ev + 1);
+                if (dv->num_valuators && dv->first_valuator == 0)
+                    ev->u.keyButtonPointer.rootX = dv->valuator0;
+                else
+                    ev->u.keyButtonPointer.rootX = 0;
+
+                /* XXX: AFAIK, XI requires always sending _all_ valuators,
+                 * i.e. you can't just send vals 3 - 7. (whot) */
+                if (dv->num_valuators > 1 && dv->first_valuator == 0)
+                    ev->u.keyButtonPointer.rootY = dv->valuator1;
+                else
+                    ev->u.keyButtonPointer.rootY = 0;
             }
 
             if (!dev)
@@ -360,9 +376,13 @@ ProcXTestFakeInput(client)
             if (ev->u.u.detail == xTrue)
             {
                 int x, y;
-                GetSpritePosition(dev, &x, &y);
-                ev->u.keyButtonPointer.rootX += x;
-                ev->u.keyButtonPointer.rootY += y;
+                if (!extension || !dev->valuator->mode == Absolute)
+                {
+                    /* if Absolute, rootX already has the final coords. */
+                    GetSpritePosition(dev, &x, &y);
+                    ev->u.keyButtonPointer.rootX += x;
+                    ev->u.keyButtonPointer.rootY += y;
+                }
             }
             else if (ev->u.u.detail != xFalse)
             {
@@ -431,6 +451,12 @@ ProcXTestFakeInput(client)
         case ButtonRelease:
             if (!extension)
                 dev = PickPointer(client);
+            else
+            {
+                /* For XI events, the rootX/Y is unset. */
+                ev->u.keyButtonPointer.rootX = dev->lastx;
+                ev->u.keyButtonPointer.rootY = dev->lasty;
+            }
             if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
             {
                 client->errorValue = ev->u.u.detail;
commit cb0168b4ac5c59cdce6f0a6d89ddd9f30d93b5f3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 18 09:48:06 2008 +0930

    Xext: xtest.c: death to tabs+spaces indendation, remove #define XINPUT

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 8d27e16..0c96b3c 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -1,30 +1,30 @@
 /*
 
-Copyright 1992, 1998  The Open Group
+   Copyright 1992, 1998  The Open Group
 
-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.
+   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 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 OPEN GROUP 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.
+   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 OPEN GROUP 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 Open Group 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 Open Group.
+   Except as contained in this notice, the name of The Open Group 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 Open Group.
 
-*/
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -45,17 +45,13 @@ from The Open Group.
 #define _XTEST_SERVER_
 #include <X11/extensions/XTest.h>
 #include <X11/extensions/xteststr.h>
-#ifdef XINPUT
 #include <X11/extensions/XI.h>
 #include <X11/extensions/XIproto.h>
 #define EXTENSION_EVENT_BASE	64
-#endif /* XINPUT */
 
 #include "modinit.h"
 
-#ifdef XINPUT
 extern int DeviceValuator;
-#endif /* XINPUT */
 
 #ifdef PANORAMIX
 #include "panoramiX.h"
@@ -63,12 +59,12 @@ extern int DeviceValuator;
 #endif
 
 static void XTestResetProc(
-    ExtensionEntry * /* extEntry */
-);
+        ExtensionEntry * /* extEntry */
+        );
 static int XTestSwapFakeInput(
-    ClientPtr /* client */,
-    xReq * /* req */
-);
+        ClientPtr /* client */,
+        xReq * /* req */
+        );
 
 static DISPATCH_PROC(ProcXTestCompareCursor);
 static DISPATCH_PROC(ProcXTestDispatch);
@@ -85,23 +81,23 @@ void
 XTestExtensionInit(INITARGS)
 {
     AddExtension(XTestExtensionName, 0, 0,
-		 ProcXTestDispatch, SProcXTestDispatch,
-		 XTestResetProc, StandardMinorOpcode);
+            ProcXTestDispatch, SProcXTestDispatch,
+            XTestResetProc, StandardMinorOpcode);
 }
 
 /*ARGSUSED*/
 static void
 XTestResetProc (extEntry)
-ExtensionEntry	*extEntry;
+    ExtensionEntry	*extEntry;
 {
 }
 
 static int
 ProcXTestGetVersion(client)
-     ClientPtr client;
+    ClientPtr client;
 {
     xXTestGetVersionReply rep;
-     int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xXTestGetVersionReq);
     rep.type = X_Reply;
@@ -110,8 +106,8 @@ ProcXTestGetVersion(client)
     rep.majorVersion = XTestMajorVersion;
     rep.minorVersion = XTestMinorVersion;
     if (client->swapped) {
-	swaps(&rep.sequenceNumber, n);
-	swaps(&rep.minorVersion, n);
+        swaps(&rep.sequenceNumber, n);
+        swaps(&rep.minorVersion, n);
     }
     WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep);
     return(client->noClientException);
@@ -119,7 +115,7 @@ ProcXTestGetVersion(client)
 
 static int
 ProcXTestCompareCursor(client)
-     ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xXTestCompareCursorReq);
     xXTestCompareCursorReply rep;
@@ -133,24 +129,24 @@ ProcXTestCompareCursor(client)
     if (rc != Success)
         return rc;
     if (stuff->cursor == None)
-	pCursor = NullCursor;
+        pCursor = NullCursor;
     else if (stuff->cursor == XTestCurrentCursor)
-	pCursor = GetSpriteCursor(ptr);
+        pCursor = GetSpriteCursor(ptr);
     else {
-	rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
-			       client, DixReadAccess);
-	if (rc != Success)
-	{
-	    client->errorValue = stuff->cursor;
-	    return (rc == BadValue) ? BadCursor : rc;
-	}
+        rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
+                client, DixReadAccess);
+        if (rc != Success)
+        {
+            client->errorValue = stuff->cursor;
+            return (rc == BadValue) ? BadCursor : rc;
+        }
     }
     rep.type = X_Reply;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
     rep.same = (wCursor(pWin) == pCursor);
     if (client->swapped) {
-	swaps(&rep.sequenceNumber, n);
+        swaps(&rep.sequenceNumber, n);
     }
     WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep);
     return(client->noClientException);
@@ -158,298 +154,292 @@ ProcXTestCompareCursor(client)
 
 static int
 ProcXTestFakeInput(client)
-     ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xXTestFakeInputReq);
     int nev, n, type, rc;
     xEvent *ev;
     DeviceIntPtr dev = NULL;
     WindowPtr root;
-#ifdef XINPUT
     Bool extension = FALSE;
     deviceValuator *dv = NULL;
     int base;
     int *values;
-#endif /* XINPUT */
 
     nev = (stuff->length << 2) - sizeof(xReq);
     if ((nev % sizeof(xEvent)) || !nev)
-	return BadLength;
+        return BadLength;
     nev /= sizeof(xEvent);
     UpdateCurrentTime();
     ev = (xEvent *)&((xReq *)stuff)[1];
     type = ev->u.u.type & 0177;
-#ifdef XINPUT
+
     if (type >= EXTENSION_EVENT_BASE)
     {
-	type -= DeviceValuator;
-	switch (type) {
-	case XI_DeviceKeyPress:
-	case XI_DeviceKeyRelease:
-	case XI_DeviceButtonPress:
-	case XI_DeviceButtonRelease:
-	case XI_DeviceMotionNotify:
-	case XI_ProximityIn:
-	case XI_ProximityOut:
-	    break;
-	default:
-	    client->errorValue = ev->u.u.type;
-	    return BadValue;
-	}
-	if (nev == 1 && type == XI_DeviceMotionNotify)
-	    return BadLength;
-	if (type == XI_DeviceMotionNotify)
-	    base = ((deviceValuator *)(ev+1))->first_valuator;
-	else
-	    base = 0;
-	for (n = 1; n < nev; n++)
-	{
-	    dv = (deviceValuator *)(ev + n);
-	    if (dv->type != DeviceValuator)
-	    {
-		client->errorValue = dv->type;
-		return BadValue;
-	    }
-	    if (dv->first_valuator != base)
-	    {
-		client->errorValue = dv->first_valuator;
-		return BadValue;
-	    }
-	    if (!dv->num_valuators || dv->num_valuators > 6)
-	    {
-		client->errorValue = dv->num_valuators;
-		return BadValue;
-	    }
-	    base += dv->num_valuators;
-	}
-	type = type - XI_DeviceKeyPress + KeyPress;
-	extension = TRUE;
+        type -= DeviceValuator;
+        switch (type) {
+            case XI_DeviceKeyPress:
+            case XI_DeviceKeyRelease:
+            case XI_DeviceButtonPress:
+            case XI_DeviceButtonRelease:
+            case XI_DeviceMotionNotify:
+            case XI_ProximityIn:
+            case XI_ProximityOut:
+                break;
+            default:
+                client->errorValue = ev->u.u.type;
+                return BadValue;
+        }
+        if (nev == 1 && type == XI_DeviceMotionNotify)
+            return BadLength; /* DevMotion must be followed by DevValuator */
+        if (type == XI_DeviceMotionNotify)
+            base = ((deviceValuator *)(ev+1))->first_valuator;
+        else
+            base = 0;
+        for (n = 1; n < nev; n++)
+        {
+            dv = (deviceValuator *)(ev + n);
+            if (dv->type != DeviceValuator)
+            {
+                client->errorValue = dv->type;
+                return BadValue;
+            }
+            if (dv->first_valuator != base)
+            {
+                client->errorValue = dv->first_valuator;
+                return BadValue;
+            }
+            if (!dv->num_valuators || dv->num_valuators > 6)
+            {
+                client->errorValue = dv->num_valuators;
+                return BadValue;
+            }
+            base += dv->num_valuators;
+        }
+        type = type - XI_DeviceKeyPress + KeyPress;
+        extension = TRUE;
     }
     else
-#endif /* XINPUT */
     {
-	if (nev != 1)
-	    return BadLength;
-	switch (type)
-	{
-	case KeyPress:
-	case KeyRelease:
-	case MotionNotify:
-	case ButtonPress:
-	case ButtonRelease:
-	    break;
-	default:
-	    client->errorValue = ev->u.u.type;
-	    return BadValue;
-	}
+        if (nev != 1)
+            return BadLength;
+        switch (type)
+        {
+            case KeyPress:
+            case KeyRelease:
+            case MotionNotify:
+            case ButtonPress:
+            case ButtonRelease:
+                break;
+            default:
+                client->errorValue = ev->u.u.type;
+                return BadValue;
+        }
     }
+
+    /* If the event has a time set, wait for it to pass */
     if (ev->u.keyButtonPointer.time)
     {
-	TimeStamp activateTime;
-	CARD32 ms;
-
-	activateTime = currentTime;
-	ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
-	if (ms < activateTime.milliseconds)
-	    activateTime.months++;
-	activateTime.milliseconds = ms;
-	ev->u.keyButtonPointer.time = 0;
-
-	/* see mbuf.c:QueueDisplayRequest for code similar to this */
-
-	if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
-	{
-	    return BadAlloc;
-	}
-	/* swap the request back so we can simply re-execute it */
-	if (client->swapped)
-	{
-	    (void) XTestSwapFakeInput(client, (xReq *)stuff);
-	    swaps(&stuff->length, n);
-	}
-	ResetCurrentRequest (client);
-	client->sequence--;
-	return Success;
+        TimeStamp activateTime;
+        CARD32 ms;
+
+        activateTime = currentTime;
+        ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
+        if (ms < activateTime.milliseconds)
+            activateTime.months++;
+        activateTime.milliseconds = ms;
+        ev->u.keyButtonPointer.time = 0;
+
+        /* see mbuf.c:QueueDisplayRequest for code similar to this */
+
+        if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
+        {
+            return BadAlloc;
+        }
+        /* swap the request back so we can simply re-execute it */
+        if (client->swapped)
+        {
+            (void) XTestSwapFakeInput(client, (xReq *)stuff);
+            swaps(&stuff->length, n);
+        }
+        ResetCurrentRequest (client);
+        client->sequence--;
+        return Success;
     }
-#ifdef XINPUT
+
     if (extension)
     {
-	rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client,
-			     DixWriteAccess);
-	if (rc != Success)
-	{
-	    client->errorValue = stuff->deviceid & 0177;
-	    return rc;
-	}
-	if (nev > 1)
-	{
-	    dv = (deviceValuator *)(ev + 1);
-	    if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes)
-	    {
-		client->errorValue = dv->first_valuator;
-		return BadValue;
-	    }
-	    if (dv->first_valuator + dv->num_valuators >
-		dev->valuator->numAxes)
-	    {
-		client->errorValue = dv->num_valuators;
-		return BadValue;
-	    }
-	}
+        rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client,
+                DixWriteAccess);
+        if (rc != Success)
+        {
+            client->errorValue = stuff->deviceid & 0177;
+            return rc;
+        }
+        if (nev > 1)
+        {
+            dv = (deviceValuator *)(ev + 1);
+            if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes)
+            {
+                client->errorValue = dv->first_valuator;
+                return BadValue;
+            }
+            if (dv->first_valuator + dv->num_valuators >
+                    dev->valuator->numAxes)
+            {
+                client->errorValue = dv->num_valuators;
+                return BadValue;
+            }
+        }
     }
-#endif /* XINPUT */
     switch (type)
     {
-    case KeyPress:
-    case KeyRelease:
-#ifdef XINPUT
-	if (!extension)
-#endif /* XINPUT */
-	    dev = PickKeyboard(client);
-	if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
-	    ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
-	{
-	    client->errorValue = ev->u.u.detail;
-	    return BadValue;
-	}
-	break;
-    case MotionNotify:
-#ifdef XINPUT
-	if (extension)
-	{
-	    if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue)
-	    {
-		client->errorValue = ev->u.u.detail;
-		return BadValue;
-	    }
-	    if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute)
-	    {
-		values = dev->valuator->axisVal + dv->first_valuator;
-		for (n = 1; n < nev; n++)
-		{
-		    dv = (deviceValuator *)(ev + n);
-		    switch (dv->num_valuators)
-		    {
-		    case 6:
-			dv->valuator5 += values[5];
-		    case 5:
-			dv->valuator4 += values[4];
-		    case 4:
-			dv->valuator3 += values[3];
-		    case 3:
-			dv->valuator2 += values[2];
-		    case 2:
-			dv->valuator1 += values[1];
-		    case 1:
-			dv->valuator0 += values[0];
-		    }
-		    values += 6;
-		}
-	    }
-	    break;
-	}
-#endif /* XINPUT */
-        if (!dev)
-            dev = PickPointer(client);
-	if (ev->u.keyButtonPointer.root == None)
-	    root = GetCurrentRootWindow(dev);
-	else
-	{
-	    rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client,
-				 DixGetAttrAccess);
-	    if (rc != Success)
-		return rc;
-	    if (root->parent)
-	    {
-		client->errorValue = ev->u.keyButtonPointer.root;
-		return BadValue;
-	    }
-	}
-	if (ev->u.u.detail == xTrue)
-	{
-	    int x, y;
-	    GetSpritePosition(dev, &x, &y);
-	    ev->u.keyButtonPointer.rootX += x;
-	    ev->u.keyButtonPointer.rootY += y;
-	}
-	else if (ev->u.u.detail != xFalse)
-	{
-	    client->errorValue = ev->u.u.detail;
-	    return BadValue;
-	}
+        case KeyPress:
+        case KeyRelease:
+            if (!extension)
+                dev = PickKeyboard(client);
+            if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
+                    ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
+            {
+                client->errorValue = ev->u.u.detail;
+                return BadValue;
+            }
+            break;
+        case MotionNotify:
+            if (extension)
+            {
+                if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue)
+                {
+                    client->errorValue = ev->u.u.detail;
+                    return BadValue;
+                }
+                /* detail is True for relative coordinates */
+                if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute)
+                {
+                    values = dev->valuator->axisVal + dv->first_valuator;
+                    for (n = 1; n < nev; n++)
+                    {
+                        dv = (deviceValuator *)(ev + n);
+                        switch (dv->num_valuators)
+                        {
+                            case 6:
+                                dv->valuator5 += values[5];
+                            case 5:
+                                dv->valuator4 += values[4];
+                            case 4:
+                                dv->valuator3 += values[3];
+                            case 3:
+                                dv->valuator2 += values[2];
+                            case 2:
+                                dv->valuator1 += values[1];
+                            case 1:
+                                dv->valuator0 += values[0];
+                        }
+                        values += 6;
+                    }
+                }
+                break;
+            }
+
+            if (!dev)
+                dev = PickPointer(client);
+            if (ev->u.keyButtonPointer.root == None)
+                root = GetCurrentRootWindow(dev);
+            else
+            {
+                rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client,
+                        DixGetAttrAccess);
+                if (rc != Success)
+                    return rc;
+                if (root->parent)
+                {
+                    client->errorValue = ev->u.keyButtonPointer.root;
+                    return BadValue;
+                }
+            }
+            if (ev->u.u.detail == xTrue)
+            {
+                int x, y;
+                GetSpritePosition(dev, &x, &y);
+                ev->u.keyButtonPointer.rootX += x;
+                ev->u.keyButtonPointer.rootY += y;
+            }
+            else if (ev->u.u.detail != xFalse)
+            {
+                client->errorValue = ev->u.u.detail;
+                return BadValue;
+            }
 
 #ifdef PANORAMIX
-	if (!noPanoramiXExtension) {
-	    ScreenPtr pScreen = root->drawable.pScreen;
-	    BoxRec    box;
-	    int       i;
-	    int       x = ev->u.keyButtonPointer.rootX + panoramiXdataPtr[0].x;
-	    int       y = ev->u.keyButtonPointer.rootY + panoramiXdataPtr[0].y;
-	    if (!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
-				 x, y, &box)) {
-		FOR_NSCREENS(i) {
-		    if (i == pScreen->myNum) continue;
-		    if (POINT_IN_REGION(pScreen,
-					&XineramaScreenRegions[i],
-					x, y, &box)) {
-			root = WindowTable[i];
-			x   -= panoramiXdataPtr[i].x;
-			y   -= panoramiXdataPtr[i].y;
-			ev->u.keyButtonPointer.rootX = x;
-			ev->u.keyButtonPointer.rootY = y;
-			break;
-		    }
-		}
-	    }
-	}
+            if (!noPanoramiXExtension) {
+                ScreenPtr pScreen = root->drawable.pScreen;
+                BoxRec    box;
+                int       i;
+                int       x = ev->u.keyButtonPointer.rootX + panoramiXdataPtr[0].x;
+                int       y = ev->u.keyButtonPointer.rootY + panoramiXdataPtr[0].y;
+                if (!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
+                            x, y, &box)) {
+                    FOR_NSCREENS(i) {
+                        if (i == pScreen->myNum) continue;
+                        if (POINT_IN_REGION(pScreen,
+                                    &XineramaScreenRegions[i],
+                                    x, y, &box)) {
+                            root = WindowTable[i];
+                            x   -= panoramiXdataPtr[i].x;
+                            y   -= panoramiXdataPtr[i].y;
+                            ev->u.keyButtonPointer.rootX = x;
+                            ev->u.keyButtonPointer.rootY = y;
+                            break;
+                        }
+                    }
+                }
+            }
 #endif
 
-	if (ev->u.keyButtonPointer.rootX < 0)
-	    ev->u.keyButtonPointer.rootX = 0;
-	else if (ev->u.keyButtonPointer.rootX >= root->drawable.width)
-	    ev->u.keyButtonPointer.rootX = root->drawable.width - 1;
-	if (ev->u.keyButtonPointer.rootY < 0)
-	    ev->u.keyButtonPointer.rootY = 0;
-	else if (ev->u.keyButtonPointer.rootY >= root->drawable.height)
-	    ev->u.keyButtonPointer.rootY = root->drawable.height - 1;
+            if (ev->u.keyButtonPointer.rootX < 0)
+                ev->u.keyButtonPointer.rootX = 0;
+            else if (ev->u.keyButtonPointer.rootX >= root->drawable.width)
+                ev->u.keyButtonPointer.rootX = root->drawable.width - 1;
+            if (ev->u.keyButtonPointer.rootY < 0)
+                ev->u.keyButtonPointer.rootY = 0;
+            else if (ev->u.keyButtonPointer.rootY >= root->drawable.height)
+                ev->u.keyButtonPointer.rootY = root->drawable.height - 1;
 
 #ifdef PANORAMIX
-	if ((!noPanoramiXExtension
-	     && root->drawable.pScreen->myNum
-                != XineramaGetCursorScreen(dev))
-	    || (noPanoramiXExtension && root != GetCurrentRootWindow(dev)))
+            if ((!noPanoramiXExtension
+                        && root->drawable.pScreen->myNum
+                        != XineramaGetCursorScreen(dev))
+                    || (noPanoramiXExtension && root != GetCurrentRootWindow(dev)))
 
 #else
-	if (root != GetCurrentRootWindow(dev))
+                if (root != GetCurrentRootWindow(dev))
 #endif
-	{
-	    NewCurrentScreen(dev, root->drawable.pScreen,
-			     ev->u.keyButtonPointer.rootX,
-			     ev->u.keyButtonPointer.rootY);
-	    return client->noClientException;
-	}
-	(*root->drawable.pScreen->SetCursorPosition)
-	    (dev, root->drawable.pScreen,
-	     ev->u.keyButtonPointer.rootX,
-	     ev->u.keyButtonPointer.rootY, FALSE);
-        dev->lastx = ev->u.keyButtonPointer.rootX;
-        dev->lasty = ev->u.keyButtonPointer.rootY;
-	break;
-    case ButtonPress:
-    case ButtonRelease:
-#ifdef XINPUT
-	if (!extension)
-#endif /* XINPUT */
-            dev = PickPointer(client);
-	if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
-	{
-	    client->errorValue = ev->u.u.detail;
-	    return BadValue;
-	}
-	break;
+                {
+                    NewCurrentScreen(dev, root->drawable.pScreen,
+                            ev->u.keyButtonPointer.rootX,
+                            ev->u.keyButtonPointer.rootY);
+                    return client->noClientException;
+                }
+            (*root->drawable.pScreen->SetCursorPosition)
+                (dev, root->drawable.pScreen,
+                 ev->u.keyButtonPointer.rootX,
+                 ev->u.keyButtonPointer.rootY, FALSE);
+            dev->lastx = ev->u.keyButtonPointer.rootX;
+            dev->lasty = ev->u.keyButtonPointer.rootY;
+            break;
+        case ButtonPress:
+        case ButtonRelease:
+            if (!extension)
+                dev = PickPointer(client);
+            if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
+            {
+                client->errorValue = ev->u.u.detail;
+                return BadValue;
+            }
+            break;
     }
     if (screenIsSaved == SCREEN_SAVER_ON)
-	dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
+        dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
     ev->u.keyButtonPointer.time = currentTime.milliseconds;
     (*dev->public.processInputProc)(ev, dev, nev);
     return client->noClientException;
@@ -457,48 +447,48 @@ ProcXTestFakeInput(client)
 
 static int
 ProcXTestGrabControl(client)
-     ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xXTestGrabControlReq);
 
     REQUEST_SIZE_MATCH(xXTestGrabControlReq);
     if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse))
     {
-	client->errorValue = stuff->impervious;
+        client->errorValue = stuff->impervious;
         return(BadValue);
     }
     if (stuff->impervious)
-	MakeClientGrabImpervious(client);
+        MakeClientGrabImpervious(client);
     else
-	MakeClientGrabPervious(client);
+        MakeClientGrabPervious(client);
     return(client->noClientException);
 }
 
 static int
 ProcXTestDispatch (client)
-     ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
     {
-    case X_XTestGetVersion:
-	return ProcXTestGetVersion(client);
-    case X_XTestCompareCursor:
-	return ProcXTestCompareCursor(client);
-    case X_XTestFakeInput:
-	return ProcXTestFakeInput(client);
-    case X_XTestGrabControl:
-	return ProcXTestGrabControl(client);
-    default:
-	return BadRequest;
+        case X_XTestGetVersion:
+            return ProcXTestGetVersion(client);
+        case X_XTestCompareCursor:
+            return ProcXTestCompareCursor(client);
+        case X_XTestFakeInput:
+            return ProcXTestFakeInput(client);
+        case X_XTestGrabControl:
+            return ProcXTestGrabControl(client);
+        default:
+            return BadRequest;
     }
 }
 
 static int
 SProcXTestGetVersion(client)
-     ClientPtr	client;
+    ClientPtr	client;
 {
-     int n;
+    int n;
     REQUEST(xXTestGetVersionReq);
 
     swaps(&stuff->length, n);
@@ -509,9 +499,9 @@ SProcXTestGetVersion(client)
 
 static int
 SProcXTestCompareCursor(client)
-     ClientPtr	client;
+    ClientPtr	client;
 {
-     int n;
+    int n;
     REQUEST(xXTestCompareCursorReq);
 
     swaps(&stuff->length, n);
@@ -523,49 +513,49 @@ SProcXTestCompareCursor(client)
 
 static int
 XTestSwapFakeInput(client, req)
-     ClientPtr	client;
+    ClientPtr	client;
     xReq *req;
 {
-     int nev;
-     xEvent *ev;
+    int nev;
+    xEvent *ev;
     xEvent sev;
     EventSwapPtr proc;
 
     nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
     for (ev = (xEvent *)&req[1]; --nev >= 0; ev++)
     {
-	/* Swap event */
-	proc = EventSwapVector[ev->u.u.type & 0177];
-	/* no swapping proc; invalid event type? */
-	if (!proc ||  proc ==  NotImplemented) {
-	    client->errorValue = ev->u.u.type;
-	    return BadValue;
-	}
-	(*proc)(ev, &sev);
-	*ev = sev;
+        /* Swap event */
+        proc = EventSwapVector[ev->u.u.type & 0177];
+        /* no swapping proc; invalid event type? */
+        if (!proc ||  proc ==  NotImplemented) {
+            client->errorValue = ev->u.u.type;
+            return BadValue;
+        }
+        (*proc)(ev, &sev);
+        *ev = sev;
     }
     return Success;
 }
 
 static int
 SProcXTestFakeInput(client)
-     ClientPtr	client;
+    ClientPtr	client;
 {
-     int n;
+    int n;
     REQUEST(xReq);
 
     swaps(&stuff->length, n);
     n = XTestSwapFakeInput(client, stuff);
     if (n != Success)
-	return n;
+        return n;
     return ProcXTestFakeInput(client);
 }
 
 static int
 SProcXTestGrabControl(client)
-     ClientPtr	client;
+    ClientPtr	client;
 {
-     int n;
+    int n;
     REQUEST(xXTestGrabControlReq);
 
     swaps(&stuff->length, n);
@@ -575,20 +565,20 @@ SProcXTestGrabControl(client)
 
 static int
 SProcXTestDispatch (client)
-     ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
     {
-    case X_XTestGetVersion:
-	return SProcXTestGetVersion(client);
-    case X_XTestCompareCursor:
-	return SProcXTestCompareCursor(client);
-    case X_XTestFakeInput:
-	return SProcXTestFakeInput(client);
-    case X_XTestGrabControl:
-	return SProcXTestGrabControl(client);
-    default:
-	return BadRequest;
+        case X_XTestGetVersion:
+            return SProcXTestGetVersion(client);
+        case X_XTestCompareCursor:
+            return SProcXTestCompareCursor(client);
+        case X_XTestFakeInput:
+            return SProcXTestFakeInput(client);
+        case X_XTestGrabControl:
+            return SProcXTestGrabControl(client);
+        default:
+            return BadRequest;
     }
 }
commit eebdf69e9a52e071e0467a1f99de135df4d1eabc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 18 09:22:37 2008 +0930

    xkb: mixing up src and dst in a memcpy is suboptimal.

diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c
index 1ea3e11..2b8efce 100644
--- a/xkb/xkbLEDs.c
+++ b/xkb/xkbLEDs.c
@@ -638,7 +638,7 @@ XkbCopySrvLedInfo(	DeviceIntPtr		from,
     if (!sli_new)
 	goto finish;
 
-    memcpy(src, sli_new, sizeof(XkbSrvLedInfoRec));
+    memcpy(sli_new, src, sizeof(XkbSrvLedInfoRec));
     if (sli_new->class == KbdFeedbackClass)
 	sli_new->fb.kf = kf;
     else
commit aa6687322de85a2d1025a3ae851fb290a089b2d3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 15 23:03:06 2008 +0930

    Xi: when copying button classes, copy xkb_acts as well.
    
    This should be the last piece in the quest for the class copy.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f412508..a828044 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -247,8 +247,6 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
  * Copies the feedback classes from device "from" into device "to". Classes
  * are duplicated (not just flipping the pointers). All feedback classes are
  * linked lists, the full list is duplicated.
- *
- * XXX: some XKB stuff is still missing.
  */
 static void
 DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
@@ -622,8 +620,18 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
             }
         }
 #ifdef XKB
-        to->button->xkb_acts = NULL;
-        /* XXX: XkbAction needs to be copied */
+        if (from->button->xkb_acts)
+        {
+            if (!to->button->xkb_acts)
+            {
+                to->button->xkb_acts = xcalloc(1, sizeof(XkbAction));
+                if (!to->button->xkb_acts)
+                    FatalError("[Xi] not enough memory for xkb_acts.\n");
+            }
+            memcpy(to->button->xkb_acts, from->button->xkb_acts,
+                    sizeof(XkbAction));
+        } else
+            xfree(to->button->xkb_acts);
 #endif
     } else if (to->button && !from->button)
     {
commit 51c8fd69ec9292f5e18cdc7f60e1716fbd6ae61a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 15 15:09:40 2008 +0930

    dix: free the unused device classes when closing a device.
    
    This also requires to NULL-ify all pointers while we're actually using them,
    otherwise we'd try to free them twice.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 4dd9fce..f412508 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -519,7 +519,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
                 to->key = xcalloc(1, sizeof(KeyClassRec));
                 if (!to->key)
                     FatalError("[Xi] no memory for class shift.\n");
-            }
+            } else
+                classes->key = NULL;
         }
 
         oldModKeyMap    = to->key->modifierKeyMap;
@@ -562,6 +563,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
             classes = dixLookupPrivate(&to->devPrivates,
                                        UnusedClassesPrivateKey);
             to->valuator = classes->valuator;
+            if (to->valuator)
+                classes->valuator = NULL;
         }
 
         to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) +
@@ -600,7 +603,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
                 to->button = xcalloc(1, sizeof(ButtonClassRec));
                 if (!to->button)
                     FatalError("[Xi] no memory for class shift.\n");
-            }
+            } else
+                classes->button = NULL;
         }
 
         to->button->buttonsDown = 0;
@@ -650,7 +654,9 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
                 to->focus = xcalloc(1, sizeof(FocusClassRec));
                 if (!to->focus)
                     FatalError("[Xi] no memory for class shift.\n");
-            }
+            } else
+                classes->focus = NULL;
+
             oldTrace = to->focus->trace;
             memcpy(to->focus, from->focus, sizeof(FocusClassRec));
             to->focus->trace = xrealloc(oldTrace,
@@ -680,7 +686,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
                 to->proximity = xcalloc(1, sizeof(ProximityClassRec));
                 if (!to->proximity)
                     FatalError("[Xi] no memory for class shift.\n");
-            }
+            } else
+                classes->proximity = NULL;
         }
         memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
     } else if (to->proximity)
@@ -703,7 +710,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
                 to->absolute = xcalloc(1, sizeof(AbsoluteClassRec));
                 if (!to->absolute)
                     FatalError("[Xi] no memory for class shift.\n");
-            }
+            } else
+                classes->absolute = NULL;
         }
         memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
     } else if (to->absolute)
@@ -713,7 +721,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         classes->absolute = to->absolute;
         to->absolute      = NULL;
     }
-
 }
 
 /**
diff --git a/dix/devices.c b/dix/devices.c
index d445916..fe70e78 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -775,6 +775,13 @@ CloseDevice(DeviceIntPtr dev)
     classes = (ClassesPtr)&dev->key;
     FreeAllDeviceClasses(classes);
 
+    if (dev->isMaster)
+    {
+        classes = dixLookupPrivate(&dev->devPrivates, UnusedClassesPrivateKey);
+        FreeAllDeviceClasses(classes);
+    }
+
+
 #ifdef XKB
     while (dev->xkb_interest)
 	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
commit 48d33ab9b672b3b3ca308000cdbd573d1e368ff9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 15 14:29:53 2008 +0930

    dix: float attached devices _before_ disabling the master.
    
    It also helps if we're actually providing the correct argument to
    AttachDevice...

diff --git a/dix/devices.c b/dix/devices.c
index 266a66c..d445916 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -301,6 +301,16 @@ DisableDevice(DeviceIntPtr dev)
     if (*prev != dev)
 	return FALSE;
 
+    /* float attached devices */
+    if (dev->isMaster)
+    {
+        for (other = inputInfo.devices; other; other = other->next)
+        {
+            if (other->u.master == dev)
+                AttachDevice(NULL, other, NULL);
+        }
+    }
+
     if (dev->isMaster && dev->spriteInfo->sprite)
     {
         for (other = inputInfo.devices; other; other = other->next)
@@ -320,16 +330,6 @@ DisableDevice(DeviceIntPtr dev)
     dev->next = inputInfo.off_devices;
     inputInfo.off_devices = dev;
 
-    /* float attached devices */
-    if (dev->isMaster)
-    {
-        for (other = inputInfo.devices; other; other = other->next)
-        {
-            if (other->u.master == dev)
-                AttachDevice(NULL, dev, NULL);
-        }
-    }
-
     ev.type = DevicePresenceNotify;
     ev.time = currentTime.milliseconds;
     ev.devchange = DeviceDisabled;
commit 4cf9c5909d926ec322ed1c7df47f95bd872bb607
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 15 13:56:11 2008 +0930

    Xi: fix up button count.
    
    Some leftover code from the previously used alloc/free device classes left us
    with a incorrect button count. So a button release didn't come through if
    a different pointer was moved after the button press.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 4417e6c..4dd9fce 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -603,6 +603,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
             }
         }
 
+        to->button->buttonsDown = 0;
+        memset(to->button->down, 0, MAP_LENGTH);
         /* merge button states from all attached devices */
         for (sd = inputInfo.devices; sd; sd = sd->next)
         {
@@ -612,6 +614,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
             for (i = 0; i < MAP_LENGTH; i++)
             {
                 to->button->down[i] += sd->button->down[i];
+                to->button->buttonsDown++;
             }
         }
 #ifdef XKB
commit 1a9d7205cd5640eb65f019336097d86301942ea7
Merge: 90f491c... 6866e84...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 14 16:25:58 2008 +0930

    Merge whot at wombat:~/potoroo/xserver into mpx

commit 6866e84e3c607d00d88eab2249c2619d6707c1a4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 19:57:51 2008 +0930

    Xi: store feedback classes in devProviates system as well.
    
    This is a follow-up to cb48d880856fd196ab8e8de5eb1f14944a1b4fff.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index d99f609..4417e6c 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -253,9 +253,19 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
 static void
 DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 {
+    ClassesPtr classes;
+
     if (from->kbdfeed)
     {
         KbdFeedbackPtr *k, it;
+
+        if (!to->kbdfeed)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->kbdfeed = classes->kbdfeed;
+        }
+
         k = &to->kbdfeed;
         for(it = from->kbdfeed; it; it = it->next)
         {
@@ -281,12 +291,22 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         }
     } else if (to->kbdfeed && !from->kbdfeed)
     {
-        FreeFeedbackClass(KbdFeedbackClass, (pointer)&to->kbdfeed);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->kbdfeed = to->kbdfeed;
+        to->kbdfeed      = NULL;
     }
 
     if (from->ptrfeed)
     {
         PtrFeedbackPtr *p, it;
+        if (!to->ptrfeed)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->ptrfeed = classes->ptrfeed;
+        }
+
         p = &to->ptrfeed;
         for (it = from->ptrfeed; it; it = it->next)
         {
@@ -306,12 +326,23 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         }
     } else if (to->ptrfeed && !from->ptrfeed)
     {
-        FreeFeedbackClass(PtrFeedbackClass, (pointer)&to->ptrfeed);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->ptrfeed = to->ptrfeed;
+        to->ptrfeed      = NULL;
     }
 
     if (from->intfeed)
     {
         IntegerFeedbackPtr *i, it;
+
+        if (!to->intfeed)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->intfeed = classes->intfeed;
+        }
+
         i = &to->intfeed;
         for (it = from->intfeed; it; it = it->next)
         {
@@ -331,12 +362,23 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         }
     } else if (to->intfeed && !from->intfeed)
     {
-        FreeFeedbackClass(IntegerFeedbackClass, (pointer)&to->intfeed);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->intfeed = to->intfeed;
+        to->intfeed      = NULL;
     }
 
     if (from->stringfeed)
     {
         StringFeedbackPtr *s, it;
+
+        if (!to->stringfeed)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->stringfeed = classes->stringfeed;
+        }
+
         s = &to->stringfeed;
         for (it = from->stringfeed; it; it = it->next)
         {
@@ -356,12 +398,23 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         }
     } else if (to->stringfeed && !from->stringfeed)
     {
-        FreeFeedbackClass(StringFeedbackClass, (pointer)&to->stringfeed);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->stringfeed = to->stringfeed;
+        to->stringfeed      = NULL;
     }
 
     if (from->bell)
     {
         BellFeedbackPtr *b, it;
+
+        if (!to->bell)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->bell = classes->bell;
+        }
+
         b = &to->bell;
         for (it = from->bell; it; it = it->next)
         {
@@ -382,12 +435,23 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         }
     } else if (to->bell && !from->bell)
     {
-        FreeFeedbackClass(BellFeedbackClass, (pointer)&to->bell);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->bell = to->bell;
+        to->bell      = NULL;
     }
 
     if (from->leds)
     {
         LedFeedbackPtr *l, it;
+
+        if (!to->leds)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->leds = classes->leds;
+        }
+
         l = &to->leds;
         for (it = from->leds; it; it = it->next)
         {
@@ -412,7 +476,10 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         }
     } else if (to->leds && !from->leds)
     {
-        FreeFeedbackClass(LedFeedbackClass, (pointer)&to->leds);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->leds = to->leds;
+        to->leds      = NULL;
     }
 }
 
commit cb48d880856fd196ab8e8de5eb1f14944a1b4fff
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 19:48:28 2008 +0930

    Xi: store unused classes in devPrivates.
    
    Rather than freeing/allocing classes each time the device capabilities need to
    swap, store them in the devPrivates system.
    When a class is unused, it is pushed into the devPrivates, and later recovered
    when needed again. This saves us a lot of memory allocations/frees, admittedly
    on the cost of some memory.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 2a7afa9..d99f609 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -96,6 +96,9 @@ Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
 static Bool MakeInputMasks(WindowPtr	/* pWin */
     );
 
+/* Used to sture classes currently not in use by an MD */
+extern DevPrivateKey UnusedClassesPrivateKey;
+
 
 void
 RegisterOtherDevice(DeviceIntPtr device)
@@ -416,28 +419,22 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 /**
  * Copies the CONTENT of the classes of device from into the classes in device
  * to. From and to are identical after finishing.
+ *
+ * If to does not have classes from currenly has, the classes are stored in
+ * to's devPrivates system. Later, we recover it again from there if needed.
+ * Saves a few memory allocations.
  */
 
 _X_EXPORT void
 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 {
+    ClassesPtr classes;
+
     /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
      * kbdfeed to be set up properly, so let's do the feedback classes first.
      */
     DeepCopyFeedbackClasses(from, to);
 
-#define ALLOC_COPY_CLASS_IF(field, type) \
-    if (from->field)\
-    { \
-        if (!to->field) \
-        { \
-            to->field = xcalloc(1, sizeof(type)); \
-            if (!to->field) \
-            FatalError("[Xi] no memory for class shift.\n"); \
-        } \
-        memcpy(to->field, from->field, sizeof(type)); \
-    }
-
     if (from->key)
     {
         KeyCode             *oldModKeyMap;
@@ -445,15 +442,19 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 #ifdef XKB
         struct _XkbSrvInfo  *oldXkbInfo;
 #endif
-
         if (!to->key)
         {
-            to->key = xcalloc(1, sizeof(KeyClassRec));
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->key = classes->key;
             if (!to->key)
-                FatalError("[Xi] no memory for class shift.\n");
+            {
+                to->key = xcalloc(1, sizeof(KeyClassRec));
+                if (!to->key)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
         }
 
-
         oldModKeyMap    = to->key->modifierKeyMap;
         oldMap          = to->key->curKeySyms.map;
 #ifdef XKB
@@ -480,14 +481,22 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         CopyKeyClass(from, to);
     } else if (to->key && !from->key)
     {
-        FreeDeviceClass(KeyClass, (pointer)&to->key);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->key = to->key;
+        to->key      = NULL;
     }
 
     if (from->valuator)
     {
         ValuatorClassPtr v;
-        if (to->valuator)
-            xfree(to->valuator->motion);
+        if (!to->valuator)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->valuator = classes->valuator;
+        }
+
         to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) +
                 from->valuator->numAxes * sizeof(AxisInfo) +
                 from->valuator->numAxes * sizeof(unsigned int));
@@ -504,14 +513,28 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         v->axisVal = (int*)(v->axes + from->valuator->numAxes);
     } else if (to->valuator && !from->valuator)
     {
-        FreeDeviceClass(ValuatorClass, (pointer)&to->valuator);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->valuator = to->valuator;
+        to->valuator      = NULL;
     }
 
-    ALLOC_COPY_CLASS_IF(button, ButtonClassRec);
-    if (to->button)
+    if (from->button)
     {
         int i;
         DeviceIntPtr sd;
+        if (!to->button)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->button = classes->button;
+            if (!to->button)
+            {
+                to->button = xcalloc(1, sizeof(ButtonClassRec));
+                if (!to->button)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+        }
 
         /* merge button states from all attached devices */
         for (sd = inputInfo.devices; sd; sd = sd->next)
@@ -530,7 +553,10 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 #endif
     } else if (to->button && !from->button)
     {
-        FreeDeviceClass(ButtonClass, (pointer)&to->button);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->button = to->button;
+        to->button      = NULL;
     }
 
 
@@ -544,29 +570,78 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     {
         if (!to->focus)
         {
-            to->focus = xcalloc(1, sizeof(FocusClassRec));
+            WindowPtr *oldTrace;
+
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->focus = classes->focus;
             if (!to->focus)
-                FatalError("[Xi] no memory for class shift.\n");
+            {
+                to->focus = xcalloc(1, sizeof(FocusClassRec));
+                if (!to->focus)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+            oldTrace = to->focus->trace;
+            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
+            to->focus->trace = xrealloc(oldTrace,
+                                  to->focus->traceSize * sizeof(WindowPtr));
+            if (!to->focus->trace && to->focus->traceSize)
+                FatalError("[Xi] no memory for trace.\n");
             memcpy(to->focus->trace, from->focus->trace,
                     from->focus->traceSize * sizeof(WindowPtr));
         }
     } else if (to->focus)
     {
-        /* properly freeing the class would also free the sprite trace, which
-         * is still in use by the SD. just xfree the struct. */
-        xfree(to->focus);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->focus = to->focus;
+        to->focus      = NULL;
     }
 
-    ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
-    if (to->proximity && !from->proximity)
+    if (from->proximity)
+    {
+        if (!to->proximity)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->proximity = classes->proximity;
+            if (!to->proximity)
+            {
+                to->proximity = xcalloc(1, sizeof(ProximityClassRec));
+                if (!to->proximity)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+        }
+        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
+    } else if (to->proximity)
     {
-        FreeDeviceClass(ProximityClass, (pointer)&to->proximity);
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->proximity = to->proximity;
+        to->proximity      = NULL;
     }
-    ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
-    if (to->absolute && !from->absolute)
+
+    if (from->absolute)
+    {
+        if (!to->absolute)
+        {
+            classes = dixLookupPrivate(&to->devPrivates,
+                                       UnusedClassesPrivateKey);
+            to->absolute = classes->absolute;
+            if (!to->absolute)
+            {
+                to->absolute = xcalloc(1, sizeof(AbsoluteClassRec));
+                if (!to->absolute)
+                    FatalError("[Xi] no memory for class shift.\n");
+            }
+        }
+        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
+    } else if (to->absolute)
     {
-        xfree(to->absolute);
-        to->absolute = NULL;
+        ClassesPtr classes;
+        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
+        classes->absolute = to->absolute;
+        to->absolute      = NULL;
     }
 
 }
diff --git a/dix/devices.c b/dix/devices.c
index a78a125..266a66c 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -89,6 +89,8 @@ SOFTWARE.
 /* The client that is allowed to change pointer-keyboard pairings. */
 static ClientPtr pairingClient = NULL;
 DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey;
+/* Used to sture classes currently not in use by an MD */
+DevPrivateKey UnusedClassesPrivateKey = &UnusedClassesPrivateKey;
 
 /**
  * Create a new input device and init it to sane values. The device is added
@@ -2550,6 +2552,7 @@ AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr*
 {
     DeviceIntPtr pointer;
     DeviceIntPtr keyboard;
+    ClassesPtr classes;
     *ptr = *keybd = NULL;
 
     pointer = AddInputDevice(client, CorePointerProc, TRUE);
@@ -2602,6 +2605,13 @@ AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr*
     keyboard->u.lastSlave = NULL;
     keyboard->isMaster = TRUE;
 
+
+    /* The ClassesRec stores the device classes currently not used. */
+    classes = xcalloc(1, sizeof(ClassesRec));
+    dixSetPrivate(&pointer->devPrivates, UnusedClassesPrivateKey, classes);
+    classes = xcalloc(1, sizeof(ClassesRec));
+    dixSetPrivate(&keyboard->devPrivates, UnusedClassesPrivateKey, classes);
+
     *ptr = pointer;
     *keybd = keyboard;
 
commit fde3c836628b6cdec3e5d107d6b1b99bc8b86912
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 17:08:51 2008 +0930

    Xi: copy the KeySyms.map over from the source.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index aee78c6..2a7afa9 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -462,6 +462,15 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 
         memcpy(to->key, from->key, sizeof(KeyClassRec));
 
+        if (!oldMap) /* newly created key struct */
+        {
+            int bytes = (to->key->curKeySyms.maxKeyCode -
+                         to->key->curKeySyms.minKeyCode + 1) *
+                         to->key->curKeySyms.mapWidth;
+            oldMap = (KeySym *)xcalloc(sizeof(KeySym), bytes);
+            memcpy(oldMap, from->key->curKeySyms.map, bytes);
+        }
+
         to->key->modifierKeyMap = oldModKeyMap;
         to->key->curKeySyms.map = oldMap;
 #ifdef XKB
commit 3c4c9938f31755c5a59995fdcfa138c99db76bbf
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 16:52:14 2008 +0930

    Xi: Fix pointer handling in KeyClassRec copy.
    
    We don't free the class anymore, so just store the previous pointers, do the
    memcpy from the SD and then restore the pointers.
    Plugs a memleak too, before xkbInfo was never freed.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index cf0e898..aee78c6 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -438,13 +438,36 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         memcpy(to->field, from->field, sizeof(type)); \
     }
 
-    ALLOC_COPY_CLASS_IF(key, KeyClassRec);
-    if (to->key && from->key)
+    if (from->key)
     {
+        KeyCode             *oldModKeyMap;
+        KeySym              *oldMap;
 #ifdef XKB
-        to->key->xkbInfo = NULL;
+        struct _XkbSrvInfo  *oldXkbInfo;
 #endif
-        to->key->curKeySyms.map = NULL;
+
+        if (!to->key)
+        {
+            to->key = xcalloc(1, sizeof(KeyClassRec));
+            if (!to->key)
+                FatalError("[Xi] no memory for class shift.\n");
+        }
+
+
+        oldModKeyMap    = to->key->modifierKeyMap;
+        oldMap          = to->key->curKeySyms.map;
+#ifdef XKB
+        oldXkbInfo      = to->key->xkbInfo;
+#endif
+
+        memcpy(to->key, from->key, sizeof(KeyClassRec));
+
+        to->key->modifierKeyMap = oldModKeyMap;
+        to->key->curKeySyms.map = oldMap;
+#ifdef XKB
+        to->key->xkbInfo        = oldXkbInfo;
+#endif
+
         CopyKeyClass(from, to);
     } else if (to->key && !from->key)
     {
commit 755f9e5d7898056cf3bead69ce25a10e23995582
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 16:49:25 2008 +0930

    dix: Ignore focus for passive grabs if the event is a pointer event.

diff --git a/dix/events.c b/dix/events.c
index 1b62db0..e25ec30 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3546,7 +3546,7 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
 {
     int i;
     WindowPtr pWin = NULL;
-    FocusClassPtr focus = device->focus;
+    FocusClassPtr focus = IsPointerEvent(xE) ? NULL : device->focus;
     xEvent core;
     BOOL sendCore = (device->isMaster && device->coreEvents);
 
commit 6faf5b97b92953c331d6540ceb18fd0a77197fea
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 15:42:33 2008 +0930

    Xi: fix up modifierKeyMap copying.
    
    Setting it to NULL isn't correct either. The correct behaviour is to realloc
    it to the size necessary (or newly alloc it/free it).  Otherwise we have a
    memleak.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 6fa08d1..cf0e898 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -176,11 +176,16 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
 
         if (dk->maxKeysPerModifier)
         {
-            mk->modifierKeyMap = xcalloc(8, dk->maxKeysPerModifier);
+            mk->modifierKeyMap = xrealloc(mk->modifierKeyMap,
+                                          8 * dk->maxKeysPerModifier);
             if (!mk->modifierKeyMap)
                 FatalError("[Xi] no memory for class shift.\n");
             memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
                     (8 * dk->maxKeysPerModifier));
+        } else
+        {
+            xfree(mk->modifierKeyMap);
+            mk->modifierKeyMap = NULL;
         }
 
         mk->maxKeysPerModifier = dk->maxKeysPerModifier;
@@ -439,7 +444,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 #ifdef XKB
         to->key->xkbInfo = NULL;
 #endif
-        to->key->modifierKeyMap = NULL;
         to->key->curKeySyms.map = NULL;
         CopyKeyClass(from, to);
     } else if (to->key && !from->key)
commit 3106ba1116e3b9d893f66a93e4a91cc61e23226a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 11:48:06 2008 +0930

    xkb: two fixes to avoid server crashes.
    
    - map can be NULL in some cases, so don't try to dereference it.
    - don't default to inputInfo.keyboard
    
    This is firefighting, I presume something in the class copy may have gone
    wrong to get a NULL map in the first instance?

diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c
index d7ada57..1ea3e11 100644
--- a/xkb/xkbLEDs.c
+++ b/xkb/xkbLEDs.c
@@ -447,7 +447,7 @@ XkbIndicatorMapPtr	map;
 XkbDescPtr		xkb;
 
     if ((sli->flags&XkbSLI_HasOwnState)==0)
-	dev= inputInfo.keyboard;
+        return;
 
     sli->usesBase&=	 ~which;
     sli->usesLatched&=	 ~which;
@@ -462,7 +462,7 @@ XkbDescPtr		xkb;
 	if (which&bit) {
 	    CARD8		what;
 
-	    if (!XkbIM_InUse(map)) 
+	    if (!map || !XkbIM_InUse(map))
 		continue;
 	    sli->mapsPresent|= bit;
 
commit 415c6df0da1197d487456b4c48e2e28e7ded8b8e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 11:46:44 2008 +0930

    Xi: copy feedback classes first, in some cases xkb relies on kbdfeed.
    
    XkbInitIndicatorMap (in XkbInitDevice) calls XkbFindSrvLedInfo. This accesses
    the devices kbdfeed struct, which is all nice and dandy if it is NULL. When
    copying the device classes however, kbdfeed may not be NULL and thus
    XkbFindSrvLedInfo goes on its merry way to do whatever it does.
    
    By copying kbdfeed first, we avoid XkbFSLI to reference the "old" kbdfeed
    struct of the previous SD.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 1d4dc51..6fa08d1 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -416,6 +416,11 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 _X_EXPORT void
 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 {
+    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
+     * kbdfeed to be set up properly, so let's do the feedback classes first.
+     */
+    DeepCopyFeedbackClasses(from, to);
+
 #define ALLOC_COPY_CLASS_IF(field, type) \
     if (from->field)\
     { \
@@ -528,7 +533,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         to->absolute = NULL;
     }
 
-    DeepCopyFeedbackClasses(from, to);
 }
 
 /**
commit 961f6660902163e99727c2dcc1a039f32b083859
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 09:31:16 2008 +0930

    Xi: modifierKeyMap needs to be set to NULL when copying classes.
    
    Otherwise we have a double reference to the same memory area.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 815eb7c..1d4dc51 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -434,6 +434,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 #ifdef XKB
         to->key->xkbInfo = NULL;
 #endif
+        to->key->modifierKeyMap = NULL;
         to->key->curKeySyms.map = NULL;
         CopyKeyClass(from, to);
     } else if (to->key && !from->key)
commit bf6679cba40a936d46008c886d204ed521a4971a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 08:28:07 2008 +0930

    Xi: copy the XkbSrvLedInfo too when copying device classes.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index a93fef4..815eb7c 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -263,7 +263,11 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
             (*k)->BellProc = it->BellProc;
             (*k)->CtrlProc = it->CtrlProc;
             (*k)->ctrl     = it->ctrl;
-            /* XXX: xkb_sli needs to be copied */
+#ifdef XKB
+            if ((*k)->xkb_sli)
+                XkbFreeSrvLedInfo((*k)->xkb_sli);
+            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
+#endif
 
             k = &(*k)->next;
         }
@@ -289,7 +293,6 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
             }
             (*p)->CtrlProc = it->CtrlProc;
             (*p)->ctrl     = it->ctrl;
-            /* XXX: xkb_sli needs to be copied */
 
             p = &(*p)->next;
         }
@@ -391,7 +394,11 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
             }
             (*l)->CtrlProc = it->CtrlProc;
             (*l)->ctrl     = it->ctrl;
-            /* XXX: xkb_sli needs to be copied */
+#ifdef XKB
+            if ((*l)->xkb_sli)
+                XkbFreeSrvLedInfo((*l)->xkb_sli);
+            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
+#endif
 
             l = &(*l)->next;
         }
commit 4219e94c2f7d431be433eceddfe79760a1ee31a1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Apr 13 08:27:31 2008 +0930

    xkb: Add XkbCopySrvLedInfo, deep-copies a XkbSrvLedInfoRec.

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index fef341a..7db9eef 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -576,6 +576,14 @@ extern XkbSrvLedInfoPtr XkbAllocSrvLedInfo(
     unsigned int		/* needed_parts */
 );
 
+extern XkbSrvLedInfoPtr XkbCopySrvLedInfo(
+    DeviceIntPtr		/* dev */,
+    XkbSrvLedInfoPtr		/* src */,
+    KbdFeedbackPtr		/* kf */,
+    LedFeedbackPtr		/* lf */
+);
+
+
 extern XkbSrvLedInfoPtr XkbFindSrvLedInfo(
     DeviceIntPtr		/* dev */,
     unsigned int		/* class */,
diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c
index 55ce12a..d7ada57 100644
--- a/xkb/xkbLEDs.c
+++ b/xkb/xkbLEDs.c
@@ -615,6 +615,45 @@ XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
     return;
 }
 
+/*
+ * XkbSrvLedInfoPtr
+ * XkbCopySrvLedInfo(dev,src,kf,lf)
+ *
+ * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made,
+ * thus the new copy behaves like the original one and can be freed with
+ * XkbFreeSrvLedInfo.
+ */
+XkbSrvLedInfoPtr
+XkbCopySrvLedInfo(	DeviceIntPtr		from,
+			XkbSrvLedInfoPtr	src,
+			KbdFeedbackPtr		kf,
+			LedFeedbackPtr		lf)
+{
+    XkbSrvLedInfoPtr sli_new;
+
+    if (!src)
+	goto finish;
+
+    sli_new = _XkbTypedCalloc(1, XkbSrvLedInfoRec);
+    if (!sli_new)
+	goto finish;
+
+    memcpy(src, sli_new, sizeof(XkbSrvLedInfoRec));
+    if (sli_new->class == KbdFeedbackClass)
+	sli_new->fb.kf = kf;
+    else
+	sli_new->fb.lf = lf;
+
+    if (sli_new->flags & XkbSLI_IsDefault) {
+	sli_new->names= _XkbTypedCalloc(XkbNumIndicators,Atom);
+	sli_new->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec);
+    } /* else sli_new->names/maps is pointing to
+	dev->key->xkbInfo->desc->names->indicators;
+	dev->key->xkbInfo->desc->names->indicators; */
+
+finish:
+    return sli_new;
+}
 
 /***====================================================================***/
 
commit 90f491cf8eb869f27c4278b26c1bb84432b12d63
Merge: cbe01b3... b4380d8...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 11 08:29:52 2008 +0930

    Merge whot at wombat:~/potoroo/xserver into mpx

commit b4380d8030927c940ddaea83c4cf24e0b9eb7b96
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 19:25:43 2008 +0930

    dix: don't free MDs classes on init.
    
    The device classes aren't deleted anymore on a class change, so there's no
    need to store the MD's original classes. We should however restore the MD to
    sane defaults when disconnecting the last device, consider this as TODO item.

diff --git a/dix/devices.c b/dix/devices.c
index 2d7885e..a78a125 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -88,8 +88,6 @@ SOFTWARE.
 
 /* The client that is allowed to change pointer-keyboard pairings. */
 static ClientPtr pairingClient = NULL;
-
-DevPrivateKey MasterDevClassesPrivateKey = &MasterDevClassesPrivateKey;
 DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey;
 
 /**
@@ -409,7 +407,6 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
     XkbComponentNamesRec names;
 #endif
     ClassesPtr classes;
-    DeviceIntRec dummy;
 
     switch (what) {
     case DEVICE_INIT:
@@ -419,8 +416,6 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
             return BadAlloc;
         }
 
-        dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, NULL);
-
         keySyms.minKeyCode = 8;
         keySyms.maxKeyCode = 255;
         keySyms.mapWidth = 4;
@@ -459,53 +454,9 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
 
         xfree(keySyms.map);
         xfree(modMap);
-
-        classes->key = pDev->key;
-        classes->valuator = pDev->valuator;
-        classes->button = pDev->button;
-        classes->focus = pDev->focus;
-        classes->proximity = pDev->proximity;
-        classes->absolute = pDev->absolute;
-        classes->kbdfeed = pDev->kbdfeed;
-        classes->ptrfeed = pDev->ptrfeed;
-        classes->intfeed = pDev->intfeed;
-        classes->stringfeed = pDev->stringfeed;
-        classes->bell = pDev->bell;
-        classes->leds = pDev->leds;
-
-        /* Each time we switch classes we free the MD's classes and copy the
-         * SD's classes into the MD. We mustn't lose the first set of classes
-         * though as we need it to restore them when the last SD disconnects.
-         *
-         * So we create a fake device, seem to copy from the fake to the real
-         * one, thus ending up with a copy of the original ones in our MD.
-         *
-         * If we don't do that, we're in SIGABRT territory (double-frees, etc)
-         */
-        memcpy(&dummy, pDev, sizeof(DeviceIntRec));
-        /* Need to set them to NULL. Otherwise, Xkb does some weird stuff and
-         * the dev->key->xkbInfo->kbdProc starts calling itself. This can
-         * probably be fixed in a better way, but I don't know how. (whot) */
-        pDev->key        = NULL;
-        pDev->valuator   = NULL;
-        pDev->button     = NULL;
-        pDev->focus      = NULL;
-        pDev->proximity  = NULL;
-        pDev->absolute   = NULL;
-        pDev->kbdfeed    = NULL;
-        pDev->ptrfeed    = NULL;
-        pDev->intfeed    = NULL;
-        pDev->stringfeed = NULL;
-        pDev->bell       = NULL;
-        pDev->leds       = NULL;
-        DeepCopyDeviceClasses(&dummy, pDev);
-
-        dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey,
-                      classes);
         break;
 
     case DEVICE_CLOSE:
-	dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL);
         break;
 
     default:
@@ -526,16 +477,12 @@ CorePointerProc(DeviceIntPtr pDev, int what)
     BYTE map[33];
     int i = 0;
     ClassesPtr classes;
-    DeviceIntRec dummy;
-
 
     switch (what) {
     case DEVICE_INIT:
         if (!(classes = xcalloc(1, sizeof(ClassesRec))))
             return BadAlloc;
 
-        dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, NULL);
-
         for (i = 1; i <= 32; i++)
             map[i] = i;
         InitPointerDeviceStruct((DevicePtr)pDev, map, 32,
@@ -545,43 +492,9 @@ CorePointerProc(DeviceIntPtr pDev, int what)
         pDev->lastx = pDev->valuator->axisVal[0];
         pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
         pDev->lasty = pDev->valuator->axisVal[1];
-
-        classes->key = pDev->key;
-        classes->valuator = pDev->valuator;
-        classes->button = pDev->button;
-        classes->focus = pDev->focus;
-        classes->proximity = pDev->proximity;
-        classes->absolute = pDev->absolute;
-        classes->kbdfeed = pDev->kbdfeed;
-        classes->ptrfeed = pDev->ptrfeed;
-        classes->intfeed = pDev->intfeed;
-        classes->stringfeed = pDev->stringfeed;
-        classes->bell = pDev->bell;
-        classes->leds = pDev->leds;
-
-        /* See comment in CoreKeyboardProc. */
-        memcpy(&dummy, pDev, sizeof(DeviceIntRec));
-        /* Need to set them to NULL for the VCK (see CoreKeyboardProc). Not
-         * sure if also necessary for the VCP, but it doesn't seem to hurt */
-        pDev->key        = NULL;
-        pDev->valuator   = NULL;
-        pDev->button     = NULL;
-        pDev->focus      = NULL;
-        pDev->proximity  = NULL;
-        pDev->absolute   = NULL;
-        pDev->kbdfeed    = NULL;
-        pDev->ptrfeed    = NULL;
-        pDev->intfeed    = NULL;
-        pDev->stringfeed = NULL;
-        pDev->bell       = NULL;
-        pDev->leds       = NULL;
-        DeepCopyDeviceClasses(&dummy, pDev);
-
-        dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, classes);
         break;
 
     case DEVICE_CLOSE:
-	dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL);
         break;
 
     default:
@@ -857,13 +770,6 @@ CloseDevice(DeviceIntPtr dev)
 
     xfree(dev->name);
 
-    if (dev->isMaster)
-    {
-        classes = (ClassesPtr)dixLookupPrivate(&dev->devPrivates,
-                MasterDevClassesPrivateKey);
-        FreeAllDeviceClasses(classes);
-    }
-
     classes = (ClassesPtr)&dev->key;
     FreeAllDeviceClasses(classes);
 
@@ -2543,16 +2449,9 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 
         if (!it)  /* no dev is paired with old master */
         {
-            ClassesPtr classes;
+            /* XXX: reset to defaults */
             EventList event = { NULL, 0};
             char* classbuf;
-            DeviceIntRec dummy;
-
-            FreeAllDeviceClasses((ClassesPtr)&oldmaster->key);
-            classes = (ClassesPtr)dixLookupPrivate(&oldmaster->devPrivates,
-                                        MasterDevClassesPrivateKey);
-            memcpy(&dummy.key, classes, sizeof(ClassesRec));
-            DeepCopyDeviceClasses(&dummy, oldmaster);
 
             /* Send event to clients */
             CreateClassesChangedEvent(&event, oldmaster, oldmaster);
commit 04dff74ffdf727015e3721aae4ea13acc498cd1c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 19:22:59 2008 +0930

    dix: Rework Enter/Leave semaphore system.
    
    Instead of a simple counter, use bits to keep track of which device is where
    etc. When device enters a window (or sets focus), the bit matching the device
    is set, when it leaves again, it is unset. If there are 0 bits set, then
    Leave/Enter/Focus events may be sent to the client.
    
    Same theory as before, but this should get around the insanity with
    Grab/Ungrab special cases. Those cases are basically untested though.

diff --git a/dix/devices.c b/dix/devices.c
index df194de..2d7885e 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -224,8 +224,7 @@ EnableDevice(DeviceIntPtr dev)
             if (dev->spriteInfo->spriteOwner)
             {
                 InitializeSprite(dev, WindowTable[0]);
-                ((FocusSemaphoresPtr)dixLookupPrivate(&(WindowTable[0])->devPrivates,
-                    FocusPrivatesKey))->enterleave++;
+                ENTER_LEAVE_SEMAPHORE_SET(WindowTable[0], dev);
             }
             else if ((other = NextFreePointerDevice()) == NULL)
             {
diff --git a/dix/events.c b/dix/events.c
index 1445914..1b62db0 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4393,7 +4393,7 @@ EnterLeaveEvent(
     GrabPtr	        grab = mouse->deviceGrab.grab;
     GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
-    int*                inWindow; /* no of sprites inside pWin */
+    int                 inWindow; /* zero if no sprites are in window */
     Bool                sendevent = FALSE;
 
     deviceEnterNotify   *devEnterLeave;
@@ -4446,7 +4446,6 @@ EnterLeaveEvent(
              IsParent(focus, pWin)))
         event.u.enterLeave.flags |= ELFlagFocus;
 
-    inWindow = &((FocusSemaphoresPtr)dixLookupPrivate(&pWin->devPrivates, FocusPrivatesKey))->enterleave;
 
     /*
      * Sending multiple core enter/leave events to the same window confuse the
@@ -4472,16 +4471,15 @@ EnterLeaveEvent(
      * NotifyNonlinearVirtual to C and nothing to B.
      */
 
-    if (event.u.u.detail != NotifyVirtual &&
-            event.u.u.detail != NotifyNonlinearVirtual)
-    {
-        if (((*inWindow) == (LeaveNotify - type)))
-            sendevent = TRUE;
-    } else
-    {
-        if (!(*inWindow))
-            sendevent = TRUE;
-    }
+    /* Clear bit for device, but don't worry about SDs. */
+    if (mouse->isMaster && type == LeaveNotify &&
+            (mode != NotifyVirtual && mode != NotifyNonlinearVirtual))
+        ENTER_LEAVE_SEMAPHORE_UNSET(pWin, mouse);
+
+    inWindow = EnterLeaveSemaphoresIsset(pWin);
+
+    if (!inWindow)
+        sendevent = TRUE;
 
     if ((mask & filters[mouse->id][type]) && sendevent)
     {
@@ -4493,6 +4491,10 @@ EnterLeaveEvent(
                                   filters[mouse->id][type], NullGrab, 0);
     }
 
+    if (mouse->isMaster && type == EnterNotify &&
+            (mode != NotifyVirtual && mode != NotifyNonlinearVirtual))
+        ENTER_LEAVE_SEMAPHORE_SET(pWin, mouse);
+
     /* 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;
@@ -4582,25 +4584,6 @@ LeaveNotifies(DeviceIntPtr pDev,
     }
 }
 
-/* welcome to insanity */
-#define FOCUS_SEMAPHORE_MODIFY(win, field, mode, val) \
-{ \
-    FocusSemaphoresPtr sem;\
-    sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \
-    if (mode != NotifyGrab && mode != NotifyUngrab) { \
-        sem->field += val; \
-    } else if (mode == NotifyUngrab) { \
-        if (sem->field == 0 && val > 0) \
-            sem->field += val; \
-        else if (sem->field == 1 && val < 0) \
-            sem->field += val; \
-    } \
-}
-#define ENTER_LEAVE_SEMAPHORE_UP(win, mode)  \
-        FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode, 1);
-
-#define ENTER_LEAVE_SEMAPHORE_DOWN(win, mode) \
-        FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode,  -1);
 
 
 /**
@@ -4620,33 +4603,27 @@ DoEnterLeaveEvents(DeviceIntPtr pDev,
 	return;
     if (IsParent(fromWin, toWin))
     {
-        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
         EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin,
                         None);
         EnterNotifies(pDev, fromWin, toWin, mode,
                       NotifyVirtual);
-        ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
         EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None);
     }
     else if (IsParent(toWin, fromWin))
     {
-        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
 	EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin,
                         None);
 	LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual);
-        ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
 	EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None);
     }
     else
     { /* neither fromWin nor toWin is descendent of the other */
 	WindowPtr common = CommonAncestor(toWin, fromWin);
 	/* common == NullWindow ==> different screens */
-        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
         EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin,
                         None);
         LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual);
 	EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual);
-        ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
         EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin,
                         None);
     }
@@ -4656,7 +4633,7 @@ static void
 FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
 {
     xEvent event;
-    int* numFoci; /* no of foci the window has already */
+    int numFoci; /* zero if no device has focus on window */
     Bool sendevent = FALSE;
 
     if (dev != inputInfo.keyboard)
@@ -4690,25 +4667,18 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
      * NotifyNonlinearVirtual to C and nothing to B.
      */
 
-    numFoci =
-        &((FocusSemaphoresPtr)dixLookupPrivate(&pWin->devPrivates,
-                    FocusPrivatesKey))->focusinout;
-    if (mode == NotifyGrab || mode == NotifyUngrab)
+    if (dev->isMaster && type == FocusOut &&
+            (detail != NotifyVirtual &&
+             detail != NotifyNonlinearVirtual &&
+             detail != NotifyPointer &&
+             detail != NotifyPointerRoot &&
+             detail != NotifyDetailNone))
+       FOCUS_SEMAPHORE_UNSET(pWin, dev);
+
+    numFoci = FocusSemaphoresIsset(pWin);
+
+    if (!numFoci)
         sendevent = TRUE;
-    else if (detail != NotifyVirtual &&
-            detail != NotifyNonlinearVirtual &&
-            detail != NotifyPointer &&
-            detail != NotifyPointerRoot &&
-            detail != NotifyDetailNone)
-    {
-        (type == FocusIn) ? (*numFoci)++ : (*numFoci)--;
-        if (((*numFoci) == (FocusOut - type)))
-            sendevent = TRUE;
-    } else
-    {
-        if (!(*numFoci))
-            sendevent = TRUE;
-    }
 
     if (sendevent)
     {
@@ -4733,6 +4703,14 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
                                         KeymapStateMask, NullGrab, 0);
         }
     }
+
+    if (dev->isMaster && type == FocusIn &&
+            (detail != NotifyVirtual &&
+             detail != NotifyNonlinearVirtual &&
+             detail != NotifyPointer &&
+             detail != NotifyPointerRoot &&
+             detail != NotifyDetailNone))
+        FOCUS_SEMAPHORE_SET(pWin, dev);
 }
 
  /*
@@ -6616,3 +6594,37 @@ ExtGrabDevice(ClientPtr client,
     return GrabSuccess;
 }
 
+/*
+ * @return Zero if no device is currently in window, non-zero otherwise.
+ */
+int
+EnterLeaveSemaphoresIsset(WindowPtr win)
+{
+    FocusSemaphoresPtr sem;
+    int set = 0;
+    int i;
+
+    sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey);
+    for (i = 0; i < (MAX_DEVICES + 7)/8; i++)
+        set += sem->enterleave[i];
+
+    return set;
+}
+
+/*
+ * @return Zero if no devices has focus on the window, non-zero otherwise.
+ */
+int
+FocusSemaphoresIsset(WindowPtr win)
+{
+    FocusSemaphoresPtr sem;
+    int set = 0;
+    int i;
+
+    sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey);
+    for (i = 0; i < (MAX_DEVICES + 7)/8; i++)
+        set += sem->focusinout[i];
+
+    return set;
+}
+
diff --git a/dix/window.c b/dix/window.c
index ee4c756..d3160c9 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -366,6 +366,7 @@ CreateRootWindow(ScreenPtr pScreen)
     WindowPtr	pWin;
     BoxRec	box;
     PixmapFormatRec *format;
+    FocusSemaphoresPtr sem;
 
     pWin = (WindowPtr)xalloc(sizeof(WindowRec));
     if (!pWin)
@@ -484,6 +485,7 @@ CreateRootWindow(ScreenPtr pScreen)
 		
     if (disableSaveUnders)
 	pScreen->saveUnderSupport = NotUseful;
+
     return TRUE;
 }
 
diff --git a/include/input.h b/include/input.h
index 9ba12db..0c993ee 100644
--- a/include/input.h
+++ b/include/input.h
@@ -80,6 +80,39 @@ SOFTWARE.
 #define RevertToFollowKeyboard	3
 #endif
 
+/* Used for enter/leave and focus in/out semaphores */
+#define SEMAPHORE_FIELD_SET(win, dev, field) \
+{ \
+    FocusSemaphoresPtr sem; \
+    sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \
+    sem->field[dev->id/8] |= (1 << (dev->id % 8)); \
+}
+
+#define SEMAPHORE_FIELD_UNSET(win, dev, field) \
+{ \
+    FocusSemaphoresPtr sem; \
+    sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \
+    sem->field[dev->id/8] &= ~(1 << (dev->id % 8)); \
+}
+
+#define ENTER_LEAVE_SEMAPHORE_SET(win, dev) \
+        SEMAPHORE_FIELD_SET(win, dev, enterleave);
+
+#define ENTER_LEAVE_SEMAPHORE_UNSET(win, dev) \
+        SEMAPHORE_FIELD_UNSET(win, dev, enterleave);
+
+#define ENTER_LEAVE_SEMAPHORE_ISSET(win, dev) \
+    ((FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey))->enterleave[dev->id/8] & (1 << (dev->id % 8))
+
+#define FOCUS_SEMAPHORE_SET(win, dev) \
+        SEMAPHORE_FIELD_SET(win, dev, focusinout);
+
+#define FOCUS_SEMAPHORE_UNSET(win, dev) \
+        SEMAPHORE_FIELD_UNSET(win, dev, focusinout);
+
+#define FOCUS_SEMAPHORE_ISSET(win, dev) \
+    ((FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey))->focusinout[dev->id/8] & (1 << (dev->id % 8))
+
 typedef unsigned long Leds;
 typedef struct _OtherClients *OtherClientsPtr;
 typedef struct _InputClients *InputClientsPtr;
@@ -488,6 +521,8 @@ extern void DeepCopyDeviceClasses(DeviceIntPtr from,
 extern void FreeDeviceClass(int type, pointer* class);
 extern void FreeFeedbackClass(int type, pointer* class);
 extern void FreeAllDeviceClasses(ClassesPtr classes);
+extern int EnterLeaveSemaphoresIsset(WindowPtr win);
+extern int FocusSemaphoresIsset(WindowPtr win);
 
 /* Window/device based access control */
 extern Bool ACRegisterClient(ClientPtr client);
diff --git a/include/windowstr.h b/include/windowstr.h
index 406087e..a36dc29 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -59,6 +59,7 @@ SOFTWARE.
 #include "miscstruct.h"
 #include <X11/Xprotostr.h>
 #include "opaque.h"
+#include "inputstr.h"
 
 #define GuaranteeNothing	0
 #define GuaranteeVisBack	1
@@ -257,11 +258,14 @@ extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
 extern DevPrivateKey FocusPrivatesKey;
 
 /* Used to maintain semantics of core protocol for Enter/LeaveNotifies and
- * FocusIn/Out events for multiple pointers/keyboards. 
- */ 
+ * FocusIn/Out events for multiple pointers/keyboards.
+ *
+ * Each device ID corresponds to one bit. If set, the device is in the
+ * window/has focus.
+ */
 typedef struct _FocusSemaphores {
-    int                 enterleave;
-    int                 focusinout;
+    char                enterleave[(MAX_DEVICES + 7)/8];
+    char                focusinout[(MAX_DEVICES + 7)/8];
 } FocusSemaphoresRec, *FocusSemaphoresPtr;
 
 /*
commit a88386ee277d136caaaeec305f8753f23f9b6274
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 14:36:57 2008 +0930

    Xi: only DeliverFocusedEvents if the event is not a pointer event.
    
    A pointer device may have a focus class, but even if so, pointer events must
    be delivered to the sprite window, not the focus window.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index ba7f3b2..a93fef4 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -104,6 +104,32 @@ RegisterOtherDevice(DeviceIntPtr device)
     device->public.realInputProc = ProcessOtherEvent;
 }
 
+_X_EXPORT Bool
+IsPointerEvent(xEvent* xE)
+{
+    switch(xE->u.u.type)
+    {
+        case ButtonPress:
+        case ButtonRelease:
+        case MotionNotify:
+        case EnterNotify:
+        case LeaveNotify:
+            return TRUE;
+        default:
+            if (xE->u.u.type == DeviceButtonPress ||
+                xE->u.u.type == DeviceButtonRelease ||
+                xE->u.u.type == DeviceMotionNotify ||
+                xE->u.u.type == DeviceEnterNotify ||
+                xE->u.u.type == DeviceLeaveNotify ||
+                xE->u.u.type == ProximityIn ||
+                xE->u.u.type == ProximityOut)
+            {
+                return TRUE;
+            }
+    }
+    return FALSE;
+}
+
 /**
  * Copy the device->key into master->key and send a mapping notify to the
  * clients if appropriate.
@@ -830,7 +856,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 
     if (grab)
         DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
-    else if (device->focus)
+    else if (device->focus && !IsPointerEvent(xE))
 	DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
     else
 	DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
diff --git a/dix/events.c b/dix/events.c
index 305502a..1445914 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1397,7 +1397,7 @@ ComputeFreezes(void)
 		replayDev->spriteInfo->sprite->spriteTrace[i])
 	    {
 		if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
-		    if (replayDev->focus)
+		    if (replayDev->focus && !IsPointerEvent(xE))
 			DeliverFocusedEvent(replayDev, xE, w, count);
 		    else
 			DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
@@ -1407,7 +1407,7 @@ ComputeFreezes(void)
 	    }
 	}
 	/* must not still be in the same stack */
-	if (replayDev->focus)
+	if (replayDev->focus && !IsPointerEvent(xE))
 	    DeliverFocusedEvent(replayDev, xE, w, count);
 	else
 	    DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
diff --git a/include/dix.h b/include/dix.h
index e00df29..57ffee9 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -615,6 +615,7 @@ extern int XItoCoreType(int xi_type);
 extern Bool DevHasCursor(DeviceIntPtr pDev);
 extern Bool IsPointerDevice( DeviceIntPtr dev);
 extern Bool IsKeyboardDevice(DeviceIntPtr dev);
+extern Bool IsPointerEvent(xEvent* xE);
 
 /*
  * These are deprecated compatibility functions and will be removed soon!
commit 48249425275cc90242497aee9968e5f1ffc86698
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 14:36:10 2008 +0930

    Xi: dont copy FocusClassRec if the master already has one.
    
    Blindly copying will override the focus setting of the master. If there's XI
    applications running, they may set the SD focus, while leaving the
    MD's focus as it was. In this case, after a class swap we still want to get
    the MD's events to the same window as before.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 38f6cb5..ba7f3b2 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -459,11 +459,29 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     }
 
 
-    ALLOC_COPY_CLASS_IF(focus, FocusClassRec);
-    if (to->focus && !from->focus)
+    /* We can't just copy over the focus class. When an app sets the focus,
+     * it'll do so on the master device. Copying the SDs focus means losing
+     * the focus.
+     * So we only copy the focus class if the device didn't have one,
+     * otherwise we leave it as it is.
+     */
+    if (from->focus)
+    {
+        if (!to->focus)
+        {
+            to->focus = xcalloc(1, sizeof(FocusClassRec));
+            if (!to->focus)
+                FatalError("[Xi] no memory for class shift.\n");
+            memcpy(to->focus->trace, from->focus->trace,
+                    from->focus->traceSize * sizeof(WindowPtr));
+        }
+    } else if (to->focus)
     {
-        FreeDeviceClass(FocusClass, (pointer)&to->focus);
+        /* properly freeing the class would also free the sprite trace, which
+         * is still in use by the SD. just xfree the struct. */
+        xfree(to->focus);
     }
+
     ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
     if (to->proximity && !from->proximity)
     {
commit bce6091c6b04ff2db704ae4f161179d21dcbec59
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 09:59:45 2008 +0930

    dix: Extend IsKeyboardDevice() to not include pointer devices.
    
    If a pointer devices has key classes as well, don't register it as a keyboard
    device. Let's see how much that change will break.

diff --git a/dix/events.c b/dix/events.c
index a2a0c1a..305502a 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -331,11 +331,14 @@ IsPointerDevice(DeviceIntPtr dev)
 /*
  * Return true if a device is a keyboard, check is the same as used by XI to
  * fill the 'use' field.
+ *
+ * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
+ * count them as keyboard devices.
  */
 _X_EXPORT Bool
 IsKeyboardDevice(DeviceIntPtr dev)
 {
-    return (dev->key && dev->kbdfeed);
+    return (dev->key && dev->kbdfeed) && !IsPointerDevice(dev);;
 }
 
 #ifdef XEVIE
commit cc7dab2d04da4ca164eeec1a3296df1706585466
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 09:58:50 2008 +0930

    dix: Dont deliver grabbed pointer events to a focus window.
    
    If an pointer event is being processed during a device grab, don't deliver it
    to the focus window, even if the device has a focus class. Reason being that
    some pointers may have a focus class, thus killing drag-and-drop.

diff --git a/dix/events.c b/dix/events.c
index 6ecd90c..a2a0c1a 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3686,7 +3686,18 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
     {
 	WindowPtr focus;
 
-	if (thisDev->focus)
+        /* Hack: Some pointer device have a focus class. So we need to check
+         * for the type of event, to see if we really want to deliver it to
+         * the focus window. For pointer events, the answer is no.
+         */
+        if (xE->u.u.type == DeviceButtonPress ||
+                xE->u.u.type == DeviceButtonRelease ||
+                xE->u.u.type == DeviceMotionNotify ||
+                xE->u.u.type == ProximityIn ||
+                xE->u.u.type == ProximityOut)
+        {
+            focus = PointerRootWin;
+        } else if (thisDev->focus)
 	{
 	    focus = thisDev->focus->win;
 	    if (focus == FollowKeyboardWin)
commit df2545b98d888924209cb889a68737c15f1aa209
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 08:50:43 2008 +0930

    xfree86: Sanity check before retrieving the paired device.
    
    Some pointer devices send key events [1], blindly getting the paired device
    crashes the server. So let's check if the device is a pointer before we try to
    get the paired device.
    
    [1] The MS Wireless Optical Desktop 2000's multimedia keys are sent through
    the pointer device, not through the keyboard device.

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index d8e23ee..c2dd600 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -722,7 +722,10 @@ xf86PostKeyboardEvent(DeviceIntPtr      device,
     int index;
 
 #if XFreeXDGA
-    DeviceIntPtr pointer = GetPairedDevice(device);
+    DeviceIntPtr pointer;
+
+    /* Some pointers send key events, paired device is wrong then. */
+    pointer = IsPointerDevice(device) ? device : GetPairedDevice(device);
 
     if (miPointerGetScreen(pointer)) {
         index = miPointerGetScreen(pointer)->myNum;
commit 5a4c6621aaf4e886f2c3b633e837ba359fedf921
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 08:29:05 2008 +0930

    Xi: some extra checks for validity of kbd and mouse.
    
    Floating SDs are paired with themselves, so the paired device may not be a
    proper keyboard or mouse. Put some extra checks in to avoid dereferencing a
    nullpointer later.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f28952f..38f6cb5 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -730,11 +730,15 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
         {
             kbd = GetPairedDevice(device);
             mouse = device;
+            if (!kbd->key) /* can happen with floating SDs */
+                kbd = NULL;
         }
         else
         {
             mouse = GetPairedDevice(device);
             kbd = device;
+            if (!mouse->valuator || !mouse->button) /* may be float. SDs */
+                mouse = NULL;
         }
         xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0;
         xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0;
commit 8e0a6529303a52acc10905dd47c72a0d60979676
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 08:25:36 2008 +0930

    dix: When floating, set sprite to NULL before calling InitializeSprite.
    
    InitializeSprite won't create a new one if it already exists, with the result
    of overwriting the master's sprite. This master sprite is then assigned to the
    floating slave, and freed when the slave is reattached later.
    Setting the sprite to NULL forces InitializeSprite to alloc a new one, and
    this one can be freed without further repercussions.

diff --git a/dix/devices.c b/dix/devices.c
index c4cde26..df194de 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2506,7 +2506,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         return Success;
 
     /* free the existing sprite. */
-    if (!dev->u.master && dev->spriteInfo->sprite)
+    if (!dev->u.master && dev->spriteInfo->paired == dev)
         xfree(dev->spriteInfo->sprite);
 
     oldmaster = dev->u.master;
@@ -2515,15 +2515,22 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
     /* If device is set to floating, we need to create a sprite for it,
      * otherwise things go bad. However, we don't want to render the cursor,
      * so we reset spriteOwner.
+     * Sprite has to be forced to NULL first, otherwise InitializeSprite won't
+     * alloc new memory but overwrite the previous one.
      */
     if (!master)
     {
-                              /* current root window */
-        InitializeSprite(dev, dev->spriteInfo->sprite->spriteTrace[0]);
+        WindowPtr currentRoot = dev->spriteInfo->sprite->spriteTrace[0];
+        dev->spriteInfo->sprite = NULL;
+        InitializeSprite(dev, currentRoot);
         dev->spriteInfo->spriteOwner = FALSE;
-
+        dev->spriteInfo->paired = dev;
     } else
+    {
         dev->spriteInfo->sprite = master->spriteInfo->sprite;
+        dev->spriteInfo->paired = master;
+        dev->spriteInfo->spriteOwner = FALSE;
+    }
 
     /* If we were connected to master device before, this MD may need to
      * change back to it's original classes.
commit e7211eb0b3d10323dab681bcb18580405ea18ab2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 10 08:08:54 2008 +0930

    Xi: When attaching, check for ptr -> ptr and keybd -> keybd.
    
    Some pointer devices have key classes (e.g. MS Optical Desktop 2000). The
    previous test was performed as Error if ptr -> keybd or keybd -> ptr. This
    doesnt work with such devices. New test is Succeed if ptr->ptr or
    keybd->keybd.

diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
index e9a5076..36797d9 100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@ -272,10 +272,10 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                             goto unwind;
                         }
 
-                        if ((IsPointerDevice(newmaster) &&
-                                    !IsPointerDevice(ptr)) ||
+                        if (!((IsPointerDevice(newmaster) &&
+                                    IsPointerDevice(ptr)) ||
                                 (IsKeyboardDevice(newmaster) &&
-                                 !IsKeyboardDevice(ptr)))
+                                 IsKeyboardDevice(ptr))))
                         {
                             rc = BadDevice;
                             goto unwind;
commit cbe01b3083eb65c9d4259b1071683febebf11600
Merge: 5ffbcfe... 389dae7...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 9 10:46:46 2008 +0930

    Merge whot at wombat:~/potoroo/xserver into mpx

commit 389dae73cc0f3693f49807fd2de146c454ba9783
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 9 08:26:00 2008 +0930

    Xi: If device "to" has a class but "from" doesn't, free the class in "to".

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 4c967b2..f28952f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -241,6 +241,9 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 
             k = &(*k)->next;
         }
+    } else if (to->kbdfeed && !from->kbdfeed)
+    {
+        FreeFeedbackClass(KbdFeedbackClass, (pointer)&to->kbdfeed);
     }
 
     if (from->ptrfeed)
@@ -264,6 +267,9 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 
             p = &(*p)->next;
         }
+    } else if (to->ptrfeed && !from->ptrfeed)
+    {
+        FreeFeedbackClass(PtrFeedbackClass, (pointer)&to->ptrfeed);
     }
 
     if (from->intfeed)
@@ -286,6 +292,9 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 
             i = &(*i)->next;
         }
+    } else if (to->intfeed && !from->intfeed)
+    {
+        FreeFeedbackClass(IntegerFeedbackClass, (pointer)&to->intfeed);
     }
 
     if (from->stringfeed)
@@ -308,6 +317,9 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 
             s = &(*s)->next;
         }
+    } else if (to->stringfeed && !from->stringfeed)
+    {
+        FreeFeedbackClass(StringFeedbackClass, (pointer)&to->stringfeed);
     }
 
     if (from->bell)
@@ -331,6 +343,9 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 
             b = &(*b)->next;
         }
+    } else if (to->bell && !from->bell)
+    {
+        FreeFeedbackClass(BellFeedbackClass, (pointer)&to->bell);
     }
 
     if (from->leds)
@@ -354,6 +369,9 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 
             l = &(*l)->next;
         }
+    } else if (to->leds && !from->leds)
+    {
+        FreeFeedbackClass(LedFeedbackClass, (pointer)&to->leds);
     }
 }
 
@@ -385,6 +403,9 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 #endif
         to->key->curKeySyms.map = NULL;
         CopyKeyClass(from, to);
+    } else if (to->key && !from->key)
+    {
+        FreeDeviceClass(KeyClass, (pointer)&to->key);
     }
 
     if (from->valuator)
@@ -406,6 +427,9 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
 
         v->axisVal = (int*)(v->axes + from->valuator->numAxes);
+    } else if (to->valuator && !from->valuator)
+    {
+        FreeDeviceClass(ValuatorClass, (pointer)&to->valuator);
     }
 
     ALLOC_COPY_CLASS_IF(button, ButtonClassRec);
@@ -429,10 +453,28 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         to->button->xkb_acts = NULL;
         /* XXX: XkbAction needs to be copied */
 #endif
+    } else if (to->button && !from->button)
+    {
+        FreeDeviceClass(ButtonClass, (pointer)&to->button);
     }
+
+
     ALLOC_COPY_CLASS_IF(focus, FocusClassRec);
+    if (to->focus && !from->focus)
+    {
+        FreeDeviceClass(FocusClass, (pointer)&to->focus);
+    }
     ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
+    if (to->proximity && !from->proximity)
+    {
+        FreeDeviceClass(ProximityClass, (pointer)&to->proximity);
+    }
     ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
+    if (to->absolute && !from->absolute)
+    {
+        xfree(to->absolute);
+        to->absolute = NULL;
+    }
 
     DeepCopyFeedbackClasses(from, to);
 }
commit 60c38d248c1a89392c2c6695c3802f4b54e4c00b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 9 07:46:53 2008 +0930

    Xi: plug memory leak, free previous motion history before allocating new.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 757d57a..4c967b2 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -390,6 +390,8 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     if (from->valuator)
     {
         ValuatorClassPtr v;
+        if (to->valuator)
+            xfree(to->valuator->motion);
         to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) +
                 from->valuator->numAxes * sizeof(AxisInfo) +
                 from->valuator->numAxes * sizeof(unsigned int));
commit ea05cf0813b2b7c8cd2151cb935820753ae7997a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 8 22:09:11 2008 +0930

    Xi: check if source has a key class before copying.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 225d3e5..757d57a 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -378,7 +378,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     }
 
     ALLOC_COPY_CLASS_IF(key, KeyClassRec);
-    if (to->key)
+    if (to->key && from->key)
     {
 #ifdef XKB
         to->key->xkbInfo = NULL;
commit 5ffbcfec3d37d3b627a78acfa00dbafc5948df82
Author: Magnus Vigerlöf <Magnus.Vigerlof at ipbo.se>
Date:   Tue Apr 8 14:42:00 2008 +0930

    dix: Ensure Proximity events don't kill the server.
    
    Add Prox events to the if-clauses with the other events
    that are usually sent from the input devices.
    Ensure that the event deliverers won't try to deliver
    events of type '0' (some extended events doesn't have
    an equivalent core-type)
    
    Small modification by Peter Hutterer.
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/dix/events.c b/dix/events.c
index 6ecd90c..42ae3f1 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2513,7 +2513,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
             core = *xE;
             core.u.u.type = XItoCoreType(xE->u.u.type);
 
-            if (filter & pWin->deliverableEvents)
+            if (core.u.u.type && filter & pWin->deliverableEvents)
             {
                 if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
                 {
@@ -3562,6 +3562,8 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
     {
         core = *xE;
         core.u.u.type = XItoCoreType(xE->u.u.type);
+        if(!core.u.u.type) /* probably a Proximity event, can't grab for those */
+            return FALSE;
     }
 
     i = checkFirst;
@@ -3651,7 +3653,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
     if (deliveries > 0)
         return;
 
-    if (sendCore)
+    if (sendCore && core.u.u.type)
     {
         FixUpEventFromWindow(keybd, &core, focus, None, FALSE);
         deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
@@ -3734,20 +3736,22 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                 {
                     core = *xE;
                     core.u.u.type = XItoCoreType(xE->u.u.type);
-                    FixUpEventFromWindow(thisDev, &core, grab->window,
-                                         None, TRUE);
-                    if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
-                                 grab->window, &core, 1) ||
-                            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
-                                     grab->window, &count, 1))
-                        deliveries = 1; /* don't send, but pretend we did */
-                    else if (!IsInterferingGrab(rClient(grab), thisDev,
-                                &core))
-                    {
-                        deliveries = TryClientEvents(rClient(grab), thisDev,
-                                                     &core, 1, mask,
-                                                     filters[thisDev->id][core.u.u.type],
-                                                     grab);
+                    if(core.u.u.type) {
+                        FixUpEventFromWindow(thisDev, &core, grab->window,
+                                             None, TRUE);
+                        if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
+                                     grab->window, &core, 1) ||
+                                XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
+                                         grab->window, &count, 1))
+                            deliveries = 1; /* don't send, but pretend we did */
+                        else if (!IsInterferingGrab(rClient(grab), thisDev,
+                                    &core))
+                        {
+                            deliveries = TryClientEvents(rClient(grab), thisDev,
+                                                         &core, 1, mask,
+                                                         filters[thisDev->id][core.u.u.type],
+                                                         grab);
+                        }
                     }
                 }
 
diff --git a/dix/getevents.c b/dix/getevents.c
index b735318..037d68c 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -816,7 +816,8 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
                    int first_valuator, int num_valuators, int *valuators)
 {
     int num_events = 1;
-    deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events->event;
+    deviceKeyButtonPointer *kbp;
+    DeviceIntPtr master;
 
     /* Sanity checks. */
     if (type != ProximityIn && type != ProximityOut)
@@ -840,6 +841,20 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
         (num_valuators + first_valuator) > pDev->valuator->numAxes)
         return 0;
 
+    master = pDev->u.master;
+    if (master && master->u.lastSlave != pDev)
+    {
+        CreateClassesChangedEvent(events, master, pDev);
+
+        pDev->lastx = master->lastx;
+        pDev->lasty = master->lasty;
+        master->u.lastSlave = pDev;
+
+        num_events++;
+        events++;
+    }
+
+    kbp = (deviceKeyButtonPointer *) events->event;
     kbp->type = type;
     kbp->deviceid = pDev->id;
     kbp->detail = 0;
diff --git a/mi/mieq.c b/mi/mieq.c
index a15b24f..2759d16 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -239,7 +239,8 @@ ChangeDeviceID(DeviceIntPtr dev, xEvent* event)
 
     if (type == DeviceKeyPress || type == DeviceKeyRelease ||
             type == DeviceButtonPress || type == DeviceButtonRelease ||
-            type == DeviceMotionNotify)
+            type == DeviceMotionNotify || type == ProximityIn ||
+            type == ProximityOut)
         ((deviceKeyButtonPointer*)event)->deviceid = dev->id;
     else if (type == DeviceValuator)
         ((deviceValuator*)event)->deviceid = dev->id;
commit 32e4a88ae613c7200d84d5621344b418b656346b
Author: Peter Hutterer <whot at potoroo.wearablelab.ml.unisa.edu.au>
Date:   Tue Apr 8 08:42:58 2008 +0930

    xkb: don't overwrite CtrlProc in the second run of XkbFinishDeviceInit.
    
    XkbFinishDeviceInit is called once when the device is initialised, but also
    when a class copy causes the key class of a device to change. In this case,
    overwriting the CtrlProc of the KeybdFeedbackClass with XkbDDXKeybdCtrlProc
    sets up a nice recursive loop of XkbDDXKeybdCtrlProc calling itself until the
    cows come home.

diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index ce5de07..0d5d15e 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -726,7 +726,10 @@ XkbSrvLedInfoPtr	sli;
     if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) {
 	xkbi= pXDev->key->xkbInfo;
 	xkb= xkbi->desc;
-	if (pXDev->kbdfeed) {
+        /* If we come from DeepCopyDeviceClasses, the CtrlProc was already set
+         * to XkbDDXKeybdCtrlProc, overwriting it leads to happy recursion.
+         */
+	if (pXDev->kbdfeed && pXDev->kbdfeed->CtrlProc != XkbDDXKeybdCtrlProc) {
 	    xkbi->kbdProc= pXDev->kbdfeed->CtrlProc;
 	    pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc;
 	}
commit 6271df6953bea462be7e9e01744e5dd46841e867
Author: Peter Hutterer <whot at potoroo.wearablelab.ml.unisa.edu.au>
Date:   Tue Apr 8 08:42:58 2008 +0930

    xkb: don't overwrite CtrlProc in the second run of XkbFinishDeviceInit.
    
    XkbFinishDeviceInit is called once when the device is initialised, but also
    when a class copy causes the key class of a device to change. In this case, overwriting the CtrlProc of the KeybdFeedbackClass with XkbDDXKeybdCtrlProc sets up a nice recursive loop of XkbDDXKeybdCtrlProc calling itself until the cows come home.

diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index ce5de07..0d5d15e 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -726,7 +726,10 @@ XkbSrvLedInfoPtr	sli;
     if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) {
 	xkbi= pXDev->key->xkbInfo;
 	xkb= xkbi->desc;
-	if (pXDev->kbdfeed) {
+        /* If we come from DeepCopyDeviceClasses, the CtrlProc was already set
+         * to XkbDDXKeybdCtrlProc, overwriting it leads to happy recursion.
+         */
+	if (pXDev->kbdfeed && pXDev->kbdfeed->CtrlProc != XkbDDXKeybdCtrlProc) {
 	    xkbi->kbdProc= pXDev->kbdfeed->CtrlProc;
 	    pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc;
 	}
commit fd06e8f8c1d82a9d91931e8532bee0fd9c9ca9ab
Merge: b46a009... 6c0cfe3...
Author: Peter Hutterer <whot at potoroo.wearablelab.ml.unisa.edu.au>
Date:   Mon Apr 7 07:56:41 2008 +0930

    Merge branch 'master' into dcdc_rework
    
    Conflicts:
    
    	Xext/xevie.c
    	dix/dispatch.c

diff --cc Xext/dpms.c
index 0723c46,e3204fe..54871c5
--- a/Xext/dpms.c
+++ b/Xext/dpms.c
@@@ -186,9 -186,9 +186,9 @@@ ProcDPMSSetTimeouts(client
  
  static int
  ProcDPMSEnable(client)
 -    register ClientPtr client;
 +    ClientPtr client;
  {
-     /* REQUEST(xDPMSEnableReq); */
+     Bool was_enabled = DPMSEnabled;
  
      REQUEST_SIZE_MATCH(xDPMSEnableReq);
  
diff --cc Xext/panoramiX.c
index 086de46,f924147..5fcaeb3
--- a/Xext/panoramiX.c
+++ b/Xext/panoramiX.c
@@@ -916,10 -916,10 +916,10 @@@ ProcPanoramiXGetState(ClientPtr client
  	REQUEST(xPanoramiXGetStateReq);
      	WindowPtr			pWin;
  	xPanoramiXGetStateReply		rep;
 -	register int			n, rc;
 +	int			n, rc;
  	
  	REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
- 	rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+ 	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
  	if (rc != Success)
  	    return rc;
  
@@@ -943,10 -943,10 +943,10 @@@ ProcPanoramiXGetScreenCount(ClientPtr c
  	REQUEST(xPanoramiXGetScreenCountReq);
      	WindowPtr			pWin;
  	xPanoramiXGetScreenCountReply	rep;
 -	register int			n, rc;
 +	int			n, rc;
  
  	REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
- 	rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+ 	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
  	if (rc != Success)
  	    return rc;
  
@@@ -969,10 -969,10 +969,10 @@@ ProcPanoramiXGetScreenSize(ClientPtr cl
  	REQUEST(xPanoramiXGetScreenSizeReq);
      	WindowPtr			pWin;
  	xPanoramiXGetScreenSizeReply	rep;
 -	register int			n, rc;
 +	int			n, rc;
  	
  	REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
- 	rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+ 	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
  	if (rc != Success)
  	    return rc;
  
diff --cc Xext/xevie.c
index ff3a628,5e20bd9..277b93b
--- a/Xext/xevie.c
+++ b/Xext/xevie.c
@@@ -158,7 -153,7 +153,7 @@@ void XevieResetProc (ExtensionEntry *ex
  }
  
  static 
- int ProcQueryVersion (ClientPtr client)
 -int ProcXevieQueryVersion (register ClientPtr client)
++int ProcXevieQueryVersion (ClientPtr client)
  {
      xXevieQueryVersionReply rep;
  
@@@ -173,7 -168,7 +168,7 @@@
  }
  
  static
- int ProcStart (ClientPtr client)
 -int ProcXevieStart (register ClientPtr client)
++int ProcXevieStart (ClientPtr client)
  {
      xXevieStartReply rep;
  
@@@ -214,7 -209,7 +209,7 @@@
  }
  
  static
- int ProcEnd (ClientPtr client)
 -int ProcXevieEnd (register ClientPtr client)
++int ProcXevieEnd (ClientPtr client)
  {
      xXevieEndReply rep;
  
@@@ -233,7 -230,7 +230,7 @@@
  }
  
  static
- int ProcSend (ClientPtr client)
 -int ProcXevieSend (register ClientPtr client)
++int ProcXevieSend (ClientPtr client)
  {
      REQUEST (xXevieSendReq);
      xXevieSendReply rep;
@@@ -279,7 -278,7 +278,7 @@@
  }
  
  static
- int ProcSelectInput (ClientPtr client)
 -int ProcXevieSelectInput (register ClientPtr client)
++int ProcXevieSelectInput (ClientPtr client)
  {
      REQUEST (xXevieSelectInputReq);
      xXevieSelectInputReply rep;
@@@ -295,7 -296,7 +296,7 @@@
  }
  
  static 
- int ProcDispatch (ClientPtr client)
 -int ProcXevieDispatch (register ClientPtr client)
++int ProcXevieDispatch (ClientPtr client)
  {
      REQUEST (xReq);
      switch (stuff->data)
@@@ -316,19 -317,22 +317,22 @@@
  }
  
  static 
- int SProcQueryVersion (ClientPtr client)
 -int SProcXevieQueryVersion (register ClientPtr client)
++int SProcXevieQueryVersion (ClientPtr client)
  {
 -    register int n;
 +    int n;
  
      REQUEST(xXevieQueryVersionReq);
-     swaps(&stuff->length, n);
-     return ProcQueryVersion(client);
+     swaps (&stuff->length, n);
+     REQUEST_SIZE_MATCH (xXevieQueryVersionReq);
+     swaps (&stuff->client_major_version, n);
+     swaps (&stuff->client_minor_version, n);
+     return ProcXevieQueryVersion(client);
  }
  
  static 
- int SProcStart (ClientPtr client)
+ int SProcXevieStart (ClientPtr client)
  {
 -    register int n;
 +    int n;
  
      REQUEST (xXevieStartReq);
      swaps (&stuff->length, n);
@@@ -338,9 -342,9 +342,9 @@@
  }
  
  static 
- int SProcEnd (ClientPtr client)
+ int SProcXevieEnd (ClientPtr client)
  {
 -    register int n;
 +    int n;
  
      REQUEST (xXevieEndReq);
      swaps (&stuff->length, n);
@@@ -350,9 -354,11 +354,11 @@@
  }
  
  static
- int SProcSend (ClientPtr client)
+ int SProcXevieSend (ClientPtr client)
  {
 -    register int n;
 +    int n;
+     xEvent eventT;
+     EventSwapPtr proc;
  
      REQUEST (xXevieSendReq);
      swaps (&stuff->length, n);
@@@ -362,9 -376,9 +376,9 @@@
  }
  
  static
- int SProcSelectInput (ClientPtr client)
+ int SProcXevieSelectInput (ClientPtr client)
  {
 -    register int n;
 +    int n;
  
      REQUEST (xXevieSelectInputReq);
      swaps (&stuff->length, n);
@@@ -375,7 -389,7 +389,7 @@@
  
  
  static 
- int SProcDispatch (ClientPtr client)
 -int SProcXevieDispatch (register ClientPtr client)
++int SProcXevieDispatch (ClientPtr client)
  {
      REQUEST(xReq);
      switch (stuff->data)
diff --cc dix/getevents.c
index b2be9bd,bf9331e..b735318
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -390,17 -340,16 +390,17 @@@ clipValuators(DeviceIntPtr pDev, int fi
   *        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 - i) > 6) ? 6 : (num_valuators - i);
+         xv->num_valuators = ((final_valuator - i) > 6) ? 6 : (final_valuator - i);
          xv->deviceid = pDev->id;
          switch (final_valuator - i) {
          case 6:
diff --cc dix/selection.c
index 0000000,6a9198e..c5427e0
mode 000000,100644..100644
--- a/dix/selection.c
+++ b/dix/selection.c
@@@ -1,0 -1,311 +1,311 @@@
+ /************************************************************
+ 
+ Copyright 1987, 1989, 1998  The Open Group
+ 
+ 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
+ OPEN GROUP 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 Open Group 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 Open Group.
+ 
+ 
+ Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+ 
+                         All Rights Reserved
+ 
+ Permission to use, copy, modify, and distribute this software and its 
+ documentation for any purpose and without fee is hereby granted, 
+ provided that the above copyright notice appear in all copies and that
+ both that copyright notice and this permission notice appear in 
+ supporting documentation, and that the name of Digital not be
+ used in advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.  
+ 
+ DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ SOFTWARE.
+ 
+ ********************************************************/
+ 
+ #ifdef HAVE_DIX_CONFIG_H
+ #include <dix-config.h>
+ #endif
+ 
+ #include "windowstr.h"
+ #include "dixstruct.h"
+ #include "dispatch.h"
+ #include "selection.h"
+ #include "xace.h"
+ 
+ /*****************************************************************
+  * Selection Stuff
+  *
+  *    dixLookupSelection
+  *
+  *   Selections are global to the server.  The list of selections should
+  *   not be traversed directly.  Instead, use the functions listed above.
+  *
+  *****************************************************************/
+ 
+ _X_EXPORT Selection *CurrentSelections;
+ CallbackListPtr SelectionCallback;
+ 
+ _X_EXPORT int
+ dixLookupSelection(Selection **result, Atom selectionName,
+ 		   ClientPtr client, Mask access_mode)
+ {
+     Selection *pSel;
+     int rc = BadMatch;
+     client->errorValue = selectionName;
+ 
+     for (pSel = CurrentSelections; pSel; pSel = pSel->next)
+ 	if (pSel->selection == selectionName)
+ 	    break;
+ 
+     if (pSel)
+ 	rc = XaceHookSelectionAccess(client, &pSel, access_mode);
+     *result = pSel;
+     return rc;
+ }
+ 
+ void
+ InitSelections(void)
+ {
+     Selection *pSel, *pNextSel;
+ 
+     pSel = CurrentSelections;
+     while (pSel) {
+ 	pNextSel = pSel->next;
+ 	dixFreePrivates(pSel->devPrivates);
+ 	xfree(pSel);
+ 	pSel = pNextSel;
+     }
+ 
+     CurrentSelections = NULL;
+ }
+ 
+ static _X_INLINE void
+ CallSelectionCallback(Selection *pSel, ClientPtr client,
+ 		      SelectionCallbackKind kind)
+ {
+     SelectionInfoRec info = { pSel, client, kind };
+     CallCallbacks(&SelectionCallback, &info);
+ }
+ 
+ void
+ DeleteWindowFromAnySelections(WindowPtr pWin)
+ {
+     Selection *pSel;
+ 
+     for (pSel = CurrentSelections; pSel; pSel = pSel->next)
+         if (pSel->pWin == pWin) {
+ 	    CallSelectionCallback(pSel, NULL, SelectionWindowDestroy);
+ 
+             pSel->pWin = (WindowPtr)NULL;
+             pSel->window = None;
+ 	    pSel->client = NullClient;
+ 	}
+ }
+ 
+ void
+ DeleteClientFromAnySelections(ClientPtr client)
+ {
+     Selection *pSel;
+ 
+     for (pSel = CurrentSelections; pSel; pSel = pSel->next)
+         if (pSel->client == client) {
+ 	    CallSelectionCallback(pSel, NULL, SelectionClientClose);
+ 
+             pSel->pWin = (WindowPtr)NULL;
+             pSel->window = None;
+ 	    pSel->client = NullClient;
+ 	}
+ }
+ 
+ int
+ ProcSetSelectionOwner(ClientPtr client)
+ {
+     WindowPtr pWin = NULL;
+     TimeStamp time;
+     Selection *pSel;
+     int rc;
+ 
+     REQUEST(xSetSelectionOwnerReq);
+     REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
+ 
+     UpdateCurrentTime();
+     time = ClientTimeToServerTime(stuff->time);
+ 
+     /* If the client's time stamp is in the future relative to the server's
+ 	time stamp, do not set the selection, just return success. */
+     if (CompareTimeStamps(time, currentTime) == LATER)
+     	return Success;
+ 
+     if (stuff->window != None) {
+ 	rc = dixLookupWindow(&pWin, stuff->window, client, DixSetAttrAccess);
+         if (rc != Success)
+             return rc;
+     }
+     if (!ValidAtom(stuff->selection)) {
+ 	client->errorValue = stuff->selection;
+         return BadAtom;
+     }
+ 
+     /*
+      * First, see if the selection is already set...
+      */
+     rc = dixLookupSelection(&pSel, stuff->selection, client, DixSetAttrAccess);
+ 
+     if (rc == Success) {
+ 	xEvent event;
+ 
+ 	/* If the timestamp in client's request is in the past relative
+ 	   to the time stamp indicating the last time the owner of the
+ 	   selection was set, do not set the selection, just return 
+ 	   success. */
+ 	if (CompareTimeStamps(time, pSel->lastTimeChanged) == EARLIER)
+ 	    return Success;
+ 	if (pSel->client && (!pWin || (pSel->client != client)))
+ 	{
+ 	    event.u.u.type = SelectionClear;
+ 	    event.u.selectionClear.time = time.milliseconds;
+ 	    event.u.selectionClear.window = pSel->window;
+ 	    event.u.selectionClear.atom = pSel->selection;
 -	    TryClientEvents(pSel->client, &event, 1, NoEventMask,
++	    TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask,
+ 			    NoEventMask /* CantBeFiltered */, NullGrab);
+ 	}
+     }
+     else if (rc == BadMatch)
+     {
+ 	/*
+ 	 * It doesn't exist, so add it...
+ 	 */
+ 	pSel = xalloc(sizeof(Selection));
+ 	if (!pSel)
+ 	    return BadAlloc;
+ 
+ 	pSel->selection = stuff->selection;
+ 	pSel->devPrivates = NULL;
+ 
+ 	/* security creation/labeling check */
+ 	rc = XaceHookSelectionAccess(client, &pSel,
+ 				     DixCreateAccess|DixSetAttrAccess);
+ 	if (rc != Success) {
+ 	    xfree(pSel);
+ 	    return rc;
+ 	}
+ 
+ 	pSel->next = CurrentSelections;
+ 	CurrentSelections = pSel;
+     }
+     else
+ 	return rc;
+ 
+     pSel->lastTimeChanged = time;
+     pSel->window = stuff->window;
+     pSel->pWin = pWin;
+     pSel->client = (pWin ? client : NullClient);
+ 
+     CallSelectionCallback(pSel, client, SelectionSetOwner);
+     return client->noClientException;
+ }
+ 
+ int
+ ProcGetSelectionOwner(ClientPtr client)
+ {
+     int rc;
+     Selection *pSel;
+     xGetSelectionOwnerReply reply;
+ 
+     REQUEST(xResourceReq);
+     REQUEST_SIZE_MATCH(xResourceReq);
+ 
+     if (!ValidAtom(stuff->id)) {
+ 	client->errorValue = stuff->id;
+         return BadAtom;
+     }
+ 
+     reply.type = X_Reply;
+     reply.length = 0;
+     reply.sequenceNumber = client->sequence;
+ 
+     rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess);
+     if (rc == Success)
+ 	reply.owner = pSel->window;
+     else if (rc == BadMatch)
+ 	reply.owner = None;
+     else
+ 	return rc;
+ 
+     WriteReplyToClient(client, sizeof(xGetSelectionOwnerReply), &reply);
+     return client->noClientException;
+ }
+ 
+ int
+ ProcConvertSelection(ClientPtr client)
+ {
+     Bool paramsOkay;
+     xEvent event;
+     WindowPtr pWin;
+     Selection *pSel;
+     int rc;
+ 
+     REQUEST(xConvertSelectionReq);
+     REQUEST_SIZE_MATCH(xConvertSelectionReq);
+ 
+     rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
+     if (rc != Success)
+         return rc;
+ 
+     paramsOkay = ValidAtom(stuff->selection) && ValidAtom(stuff->target);
+     paramsOkay &= (stuff->property == None) || ValidAtom(stuff->property);
+     if (!paramsOkay) {
+ 	client->errorValue = stuff->property;
+         return BadAtom;
+     }
+ 
+     rc = dixLookupSelection(&pSel, stuff->selection, client, DixReadAccess);
+ 
+     if (rc != Success && rc != BadMatch)
+ 	return rc;
+     else if (rc == Success && pSel->window != None) {
+ 	event.u.u.type = SelectionRequest;
+ 	event.u.selectionRequest.owner = pSel->window;
+ 	event.u.selectionRequest.time = stuff->time;
+ 	event.u.selectionRequest.requestor = stuff->requestor;
+ 	event.u.selectionRequest.selection = stuff->selection;
+ 	event.u.selectionRequest.target = stuff->target;
+ 	event.u.selectionRequest.property = stuff->property;
 -	if (TryClientEvents(pSel->client, &event, 1, NoEventMask,
++	if (TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask,
+ 			    NoEventMask /* CantBeFiltered */, NullGrab))
+ 	    return client->noClientException;
+     }
+ 
+     event.u.u.type = SelectionNotify;
+     event.u.selectionNotify.time = stuff->time;
+     event.u.selectionNotify.requestor = stuff->requestor;
+     event.u.selectionNotify.selection = stuff->selection;
+     event.u.selectionNotify.target = stuff->target;
+     event.u.selectionNotify.property = None;
 -    TryClientEvents(client, &event, 1, NoEventMask,
++    TryClientEvents(client, NULL, &event, 1, NoEventMask,
+ 		    NoEventMask /* CantBeFiltered */, NullGrab);
+     return client->noClientException;
+ }
diff --cc os/utils.c
index 3f4355f,d785d46..d2b5674
--- a/os/utils.c
+++ b/os/utils.c
@@@ -235,9 -239,10 +239,12 @@@ _X_EXPORT int selinuxEnforcingState = S
  #ifdef XV
  _X_EXPORT Bool noXvExtension = FALSE;
  #endif
+ #ifdef DRI2
+ _X_EXPORT Bool noDRI2Extension = FALSE;
+ #endif
  
 +_X_EXPORT Bool noGEExtension = FALSE;
 +
  #define X_INCLUDE_NETDB_H
  #include <X11/Xos_r.h>
  
diff --cc xkb/xkbInit.c
index 09317e9,3b47396..ce5de07
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@@ -219,11 -219,11 +219,11 @@@ char *			pval
      }
      pval[out++]= '\0';
      if (out!=len) {
 -	ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
 +	ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
  								out,len);
      }
-     ChangeWindowProperty(WindowTable[0],name,XA_STRING,8,PropModeReplace,
- 							len,pval,True);
+     dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8,
+ 			    PropModeReplace, len, pval, True);
      xfree(pval);
      return True;
  }
commit b46a00918691cbd5ca80b6d3acae7614f93e073b
Author: Peter Hutterer <whot at potoroo.wearablelab.ml.unisa.edu.au>
Date:   Sun Apr 6 09:02:57 2008 +0930

    dix: sprite may be NULL, don't dereference it then.
    
    In some rare cases (e.g. when the init fails) a device's sprite is NULL,
    dereferencing it to xfree the spriteTrace is a bad idea then.

diff --git a/dix/devices.c b/dix/devices.c
index 61b3b66..c4cde26 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -873,7 +873,7 @@ CloseDevice(DeviceIntPtr dev)
 	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
 #endif
 
-    if (DevHasCursor(dev)) {
+    if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
         xfree(dev->spriteInfo->sprite->spriteTrace);
         xfree(dev->spriteInfo->sprite);
     }
commit 638a50552e3e2190eac9721deb72e7365bdd52e4
Author: Peter Hutterer <whot at potoroo.wearablelab.ml.unisa.edu.au>
Date:   Sun Apr 6 08:36:21 2008 +0930

    dix: remove debug error message about XI->core type conversion.

diff --git a/dix/events.c b/dix/events.c
index 0b9b768..6ecd90c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -305,8 +305,6 @@ XItoCoreType(int xitype)
     else if (xitype == DeviceKeyRelease)
         coretype = KeyRelease;
 
-    if (coretype == 0)
-        ErrorF("[dix] Cannot convert type %d to core.\n", xitype);
     return coretype;
 }
 
commit 8f38feb3e464986dc523dabd3447ba13263a3a4a
Author: Peter Hutterer <whot at potoroo.wearablelab.ml.unisa.edu.au>
Date:   Sat Apr 5 20:37:09 2008 +1030

    Xi: add comments for DeepCopyDeviceClasses, ChangeMasterDeviceClasses.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 5e72bae..252256a 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -357,6 +357,11 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
     }
 }
 
+/**
+ * Copies the CONTENT of the classes of device from into the classes in device
+ * to. From and to are identical after finishing.
+ */
+
 _X_EXPORT void
 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 {
@@ -430,6 +435,12 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     DeepCopyFeedbackClasses(from, to);
 }
 
+/**
+ * Change MD to look like SD by copying all classes over. An event is sent to
+ * all interested clients.
+ * @param device The slave device
+ * @param dcce Pointer to the event struct.
+ */
 static void
 ChangeMasterDeviceClasses(DeviceIntPtr device,
                           deviceClassesChangedEvent *dcce)
commit d0395a753079f291a78d9ab86810b5f84f237491
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 4 15:05:26 2008 +1030

    Xi: realloc to->valuator instead of allocing it blindly.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index c16b0c8..5e72bae 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -385,7 +385,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     if (from->valuator)
     {
         ValuatorClassPtr v;
-        to->valuator = xalloc(sizeof(ValuatorClassRec) +
+        to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) +
                 from->valuator->numAxes * sizeof(AxisInfo) +
                 from->valuator->numAxes * sizeof(unsigned int));
         v = to->valuator;
commit 502689847b86be5619da7134646d55a1ac322a2c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 4 15:01:53 2008 +1030

    Xi: ALLOC_COPY_CLASS_IF should only alloc if to->field doesn't exist.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index b2403bc..c16b0c8 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -363,9 +363,12 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 #define ALLOC_COPY_CLASS_IF(field, type) \
     if (from->field)\
     { \
-        to->field = xcalloc(1, sizeof(type)); \
         if (!to->field) \
+        { \
+            to->field = xcalloc(1, sizeof(type)); \
+            if (!to->field) \
             FatalError("[Xi] no memory for class shift.\n"); \
+        } \
         memcpy(to->field, from->field, sizeof(type)); \
     }
 
commit 035b1b6995e670ce5593e8aceb08f9ec812c70ea
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 4 15:00:06 2008 +1030

    Xi: remove duplicate copying of kbdfeed and ptrfeed.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 9c771a4..b2403bc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -424,22 +424,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
     ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
 
-    ALLOC_COPY_CLASS_IF(kbdfeed, KbdFeedbackClassRec);
-#ifdef XKB
-    if (to->kbdfeed)
-    {
-        to->kbdfeed->xkb_sli = NULL;
-        /* XXX: XkbSrvLedInfo needs to be copied*/
-        to->kbdfeed->next = NULL;
-    }
-#endif
-    ALLOC_COPY_CLASS_IF(ptrfeed, PtrFeedbackClassRec);
-    if (to->ptrfeed)
-    {
-        to->ptrfeed->next = NULL;
-    }
-
-
     DeepCopyFeedbackClasses(from, to);
 }
 
commit 52fc7aed18930fc9e6bcfdd5dbc28ae559978288
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 4 14:47:23 2008 +1030

    Xi: only alloc memory for feedback classes if it doesn't already exist.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index b21c73d..9c771a4 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -225,7 +225,15 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         k = &to->kbdfeed;
         for(it = from->kbdfeed; it; it = it->next)
         {
-            *k = xcalloc(1, sizeof(KbdFeedbackClassRec));
+            if (!(*k))
+            {
+                *k = xcalloc(1, sizeof(KbdFeedbackClassRec));
+                if (!*k)
+                {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
             (*k)->BellProc = it->BellProc;
             (*k)->CtrlProc = it->CtrlProc;
             (*k)->ctrl     = it->ctrl;
@@ -241,7 +249,15 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         p = &to->ptrfeed;
         for (it = from->ptrfeed; it; it = it->next)
         {
-            *p = xcalloc(1, sizeof(PtrFeedbackClassRec));
+            if (!(*p))
+            {
+                *p = xcalloc(1, sizeof(PtrFeedbackClassRec));
+                if (!*p)
+                {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
             (*p)->CtrlProc = it->CtrlProc;
             (*p)->ctrl     = it->ctrl;
             /* XXX: xkb_sli needs to be copied */
@@ -256,7 +272,15 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         i = &to->intfeed;
         for (it = from->intfeed; it; it = it->next)
         {
-            *i = xcalloc(1, sizeof(IntegerFeedbackClassRec));
+            if (!(*i))
+            {
+                *i = xcalloc(1, sizeof(IntegerFeedbackClassRec));
+                if (!(*i))
+                {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
             (*i)->CtrlProc = it->CtrlProc;
             (*i)->ctrl     = it->ctrl;
 
@@ -270,7 +294,15 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         s = &to->stringfeed;
         for (it = from->stringfeed; it; it = it->next)
         {
-            *s = xcalloc(1, sizeof(StringFeedbackClassRec));
+            if (!(*s))
+            {
+                *s = xcalloc(1, sizeof(StringFeedbackClassRec));
+                if (!(*s))
+                {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
             (*s)->CtrlProc = it->CtrlProc;
             (*s)->ctrl     = it->ctrl;
 
@@ -284,7 +316,15 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         b = &to->bell;
         for (it = from->bell; it; it = it->next)
         {
-            *b = xcalloc(1, sizeof(BellFeedbackClassRec));
+            if (!(*b))
+            {
+                *b = xcalloc(1, sizeof(BellFeedbackClassRec));
+                if (!(*b))
+                {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
             (*b)->BellProc = it->BellProc;
             (*b)->CtrlProc = it->CtrlProc;
             (*b)->ctrl     = it->ctrl;
@@ -299,7 +339,15 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
         l = &to->leds;
         for (it = from->leds; it; it = it->next)
         {
-            *l = xcalloc(1, sizeof(LedFeedbackClassRec));
+            if (!(*l))
+            {
+                *l = xcalloc(1, sizeof(LedFeedbackClassRec));
+                if (!(*l))
+                {
+                    ErrorF("[Xi] Cannot alloc memory for class copy.");
+                    return;
+                }
+            }
             (*l)->CtrlProc = it->CtrlProc;
             (*l)->ctrl     = it->ctrl;
             /* XXX: xkb_sli needs to be copied */
commit 4eb87c8693b57d9354832c76417797394656333e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 4 14:20:18 2008 +1030

    Xi: don't free device classes before copying them.
    
    First commit in a series to come.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index fe7f8dc..b21c73d 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -413,7 +413,6 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
 
     master->public.devicePrivate = device->public.devicePrivate;
 
-    FreeAllDeviceClasses((ClassesPtr)&master->key);
     DeepCopyDeviceClasses(device, master);
 
     /* event is already correct size, see comment in GetPointerEvents */
commit 8e562fe26ff77c03be0855afb08e43f3ed0bd4b9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Mar 5 15:11:41 2008 +1030

    Xi: remove false memset from DeepCopyDeviceClasses.
    
    It's wrong, needs to be different, but I haven't had enough coffee to figure
    out what it needs to do yet.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 46ee66d..fe7f8dc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -356,7 +356,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         int i;
         DeviceIntPtr sd;
 
-        memset(to->button, 0, MAP_LENGTH);
         /* merge button states from all attached devices */
         for (sd = inputInfo.devices; sd; sd = sd->next)
         {
commit 7b4f3616f75a541b819d99c28bb6cb73761b6066
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Mar 4 18:29:15 2008 +1030

    Xi: add deviceid to QueryDevicePointer request.
    
    Why not, we had the padding anyway.
    Suggested by Jim Gettys on the X.Org mailing list.

diff --git a/Xi/querydp.c b/Xi/querydp.c
index 3103346..ac11025 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -113,6 +113,7 @@ ProcXQueryDevicePointer(ClientPtr client)
     rep.rootX = pSprite->hot.x;
     rep.rootY = pSprite->hot.y;
     rep.child = None;
+    rep.deviceid = pDev->id;
 
     if (pSprite->hot.pScreen == pWin->drawable.pScreen)
     {
commit 4f2cd0ed96d3b10c78774c721c2ffbfb0556dddd
Merge: 23ae68a... 453661a...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Mar 4 18:11:10 2008 +1030

    Merge branch 'master' into mpx
    
    This merge reverts Magnus' device coorindate scaling changes. MPX core event
    generation is very different, so we can't scale in GetPointerEvents.
    
    Conflicts:
    
    	Xi/opendev.c
    	dix/devices.c
    	dix/dixfonts.c
    	dix/getevents.c
    	dix/resource.c
    	dix/window.c
    	hw/xfree86/common/xf86Xinput.c
    	mi/mipointer.c
    	xkb/ddxBeep.c
    	xkb/ddxCtrls.c
    	xkb/ddxKeyClick.c
    	xkb/ddxList.c
    	xkb/ddxLoad.c
    	xkb/xkb.c
    	xkb/xkbAccessX.c
    	xkb/xkbEvents.c
    	xkb/xkbInit.c
    	xkb/xkbPrKeyEv.c
    	xkb/xkbUtils.c

diff --cc Xi/opendev.c
index f4c0066,acda385..f14f848
--- a/Xi/opendev.c
+++ b/Xi/opendev.c
@@@ -102,7 -102,11 +102,8 @@@ ProcXOpenDevice(ClientPtr client
      REQUEST(xOpenDeviceReq);
      REQUEST_SIZE_MATCH(xOpenDeviceReq);
  
-     status = dixLookupDevice(&dev, stuff->deviceid, client, DixReadAccess);
 -    if (stuff->deviceid == inputInfo.pointer->id ||
 -	stuff->deviceid == inputInfo.keyboard->id)
 -	return BadDevice;
 -
+     status = dixLookupDevice(&dev, stuff->deviceid, client, DixUseAccess);
++
      if (status == BadDevice) {  /* not open */
  	for (dev = inputInfo.off_devices; dev; dev = dev->next)
  	    if (dev->id == stuff->deviceid)
diff --cc dix/devices.c
index f036985,4b20655..61b3b66
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -663,212 -498,104 +663,211 @@@ InitAndStartDevices(WindowPtr root
      return Success;
  }
  
 -/**
 - * Close down a device and free all resources. 
 - * Once closed down, the driver will probably not expect you that you'll ever
 - * enable it again and free associated structs. If you want the device to just
 - * be disabled, DisableDevice().
 - * Don't call this function directly, use RemoveDevice() instead.
 - */
 -static void
 -CloseDevice(DeviceIntPtr dev)
 +_X_EXPORT void
 +FreeAllDeviceClasses(ClassesPtr classes)
  {
 -    KbdFeedbackPtr k, knext;
 -    PtrFeedbackPtr p, pnext;
 -    IntegerFeedbackPtr i, inext;
 -    StringFeedbackPtr s, snext;
 -    BellFeedbackPtr b, bnext;
 -    LedFeedbackPtr l, lnext;
 +    if (!classes)
 +        return;
 +
 +    FreeDeviceClass(KeyClass, (pointer)&classes->key);
 +    FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
 +    FreeDeviceClass(ButtonClass, (pointer)&classes->button);
 +    FreeDeviceClass(FocusClass, (pointer)&classes->focus);
 +    FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
 +
 +    FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed);
 +    FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed);
 +    FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed);
 +    FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed);
 +    FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell);
 +    FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds);
  
 -    if (dev->inited)
 -	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
 +}
  
 -    xfree(dev->name);
 +/**
 + * Free the given device class and reset the pointer to NULL.
 + */
 +_X_EXPORT void
 +FreeDeviceClass(int type, pointer *class)
 +{
 +    if (!(*class))
 +        return;
  
 -    if (dev->key) {
 +    switch(type)
 +    {
 +        case KeyClass:
 +            {
 +                KeyClassPtr* k = (KeyClassPtr*)class;
 +#ifdef XKB
 +                if ((*k)->xkbInfo)
 +                {
 +                    XkbFreeInfo((*k)->xkbInfo);
 +                    (*k)->xkbInfo = NULL;
 +                }
 +#endif
 +                xfree((*k)->curKeySyms.map);
 +                xfree((*k)->modifierKeyMap);
 +                xfree((*k));
 +                break;
 +            }
 +        case ButtonClass:
 +            {
 +                ButtonClassPtr *b = (ButtonClassPtr*)class;
  #ifdef XKB
 -	if (dev->key->xkbInfo)
 -	    XkbFreeInfo(dev->key->xkbInfo);
 +                if ((*b)->xkb_acts)
 +                    xfree((*b)->xkb_acts);
  #endif
 -        dev->key->xkbInfo = NULL;
 -	xfree(dev->key->curKeySyms.map);
 -	xfree(dev->key->modifierKeyMap);
 -	xfree(dev->key);
 -        dev->key = NULL;
 -    }
 -
 -    if (dev->valuator) {
 -        /* Counterpart to 'biggest hack ever' in init. */
 -        if (dev->valuator->motion &&
 -            dev->valuator->GetMotionProc == GetMotionHistory)
 -            xfree(dev->valuator->motion);
 -        xfree(dev->valuator);
 +                xfree((*b));
 +                break;
 +            }
 +        case ValuatorClass:
 +            {
 +                ValuatorClassPtr *v = (ValuatorClassPtr*)class;
 +
 +                /* Counterpart to 'biggest hack ever' in init. */
 +                if ((*v)->motion && (*v)->GetMotionProc == GetMotionHistory)
 +                    xfree((*v)->motion);
 +                xfree((*v));
 +                break;
 +            }
 +        case FocusClass:
 +            {
 +                FocusClassPtr *f = (FocusClassPtr*)class;
 +                xfree((*f)->trace);
 +                xfree((*f));
 +                break;
 +            }
 +        case ProximityClass:
 +            {
 +                ProximityClassPtr *p = (ProximityClassPtr*)class;
 +                xfree((*p));
 +                break;
 +            }
- 
      }
 +    *class = NULL;
 +}
 +_X_EXPORT void
 +FreeFeedbackClass(int type, pointer *class)
 +{
 +    if (!(*class))
 +        return;
  
 -    if (dev->button) {
 +    switch(type)
 +    {
 +        case KbdFeedbackClass:
 +            {
 +                KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class;
 +                KbdFeedbackPtr k, knext;
 +                for (k = (*kbdfeed); k; k = knext) {
 +                    knext = k->next;
  #ifdef XKB
 -        if (dev->button->xkb_acts)
 -            xfree(dev->button->xkb_acts);
 +                    if (k->xkb_sli)
 +                        XkbFreeSrvLedInfo(k->xkb_sli);
  #endif
 -        xfree(dev->button);
 -    }
 -
 -    if (dev->focus) {
 -	xfree(dev->focus->trace);
 -	xfree(dev->focus);
 -    }
 -
 -    if (dev->proximity)
 -        xfree(dev->proximity);
 +                    xfree(k);
 +                }
 +                break;
 +            }
 +        case PtrFeedbackClass:
 +            {
 +                PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class;
 +                PtrFeedbackPtr p, pnext;
 +
 +                for (p = (*ptrfeed); p; p = pnext) {
 +                    pnext = p->next;
 +                    xfree(p);
 +                }
 +                break;
 +            }
 +        case IntegerFeedbackClass:
 +            {
 +                IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class;
 +                IntegerFeedbackPtr i, inext;
 +
 +                for (i = (*intfeed); i; i = inext) {
 +                    inext = i->next;
 +                    xfree(i);
 +                }
 +                break;
 +            }
 +        case StringFeedbackClass:
 +            {
 +                StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class;
 +                StringFeedbackPtr s, snext;
 +
 +                for (s = (*stringfeed); s; s = snext) {
 +                    snext = s->next;
 +                    xfree(s->ctrl.symbols_supported);
 +                    xfree(s->ctrl.symbols_displayed);
 +                    xfree(s);
 +                }
 +                break;
 +            }
 +        case BellFeedbackClass:
 +            {
 +                BellFeedbackPtr *bell = (BellFeedbackPtr*)class;
 +                BellFeedbackPtr b, bnext;
 +
 +                for (b = (*bell); b; b = bnext) {
 +                    bnext = b->next;
 +                    xfree(b);
 +                }
 +                break;
 +            }
 +        case LedFeedbackClass:
 +            {
 +                LedFeedbackPtr *leds = (LedFeedbackPtr*)class;
 +                LedFeedbackPtr l, lnext;
  
 -    for (k = dev->kbdfeed; k; k = knext) {
 -	knext = k->next;
 +                for (l = (*leds); l; l = lnext) {
 +                    lnext = l->next;
  #ifdef XKB
 -	if (k->xkb_sli)
 -	    XkbFreeSrvLedInfo(k->xkb_sli);
 +                    if (l->xkb_sli)
 +                        XkbFreeSrvLedInfo(l->xkb_sli);
  #endif
 -	xfree(k);
 +                    xfree(l);
 +                }
 +                break;
 +            }
      }
 +    *class = NULL;
 +}
 +/**
 + * Close down a device and free all resources.
 + * Once closed down, the driver will probably not expect you that you'll ever
 + * enable it again and free associated structs. If you want the device to just
 + * be disabled, DisableDevice().
 + * Don't call this function directly, use RemoveDevice() instead.
 + */
 +static void
 +CloseDevice(DeviceIntPtr dev)
 +{
 +    ScreenPtr screen = screenInfo.screens[0];
 +    ClassesPtr classes;
 +    int j;
  
 -    for (p = dev->ptrfeed; p; p = pnext) {
 -	pnext = p->next;
 -	xfree(p);
 -    }
 -    
 -    for (i = dev->intfeed; i; i = inext) {
 -	inext = i->next;
 -	xfree(i);
 -    }
 +    if (!dev)
 +        return;
  
 -    for (s = dev->stringfeed; s; s = snext) {
 -	snext = s->next;
 -	xfree(s->ctrl.symbols_supported);
 -	xfree(s->ctrl.symbols_displayed);
 -	xfree(s);
 -    }
 +    if (dev->inited)
 +	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
  
 -    for (b = dev->bell; b; b = bnext) {
 -	bnext = b->next;
 -	xfree(b);
 -    }
 +    /* free sprite memory */
 +    if (dev->isMaster && dev->spriteInfo->sprite)
 +        screen->DeviceCursorCleanup(dev, screen);
  
 -    for (l = dev->leds; l; l = lnext) {
 -	lnext = l->next;
 -#ifdef XKB
 -	if (l->xkb_sli)
 -	    XkbFreeSrvLedInfo(l->xkb_sli);
 -#endif
 -	xfree(l);
 +    xfree(dev->name);
 +
 +    if (dev->isMaster)
 +    {
 +        classes = (ClassesPtr)dixLookupPrivate(&dev->devPrivates,
 +                MasterDevClassesPrivateKey);
 +        FreeAllDeviceClasses(classes);
      }
  
 +    classes = (ClassesPtr)&dev->key;
 +    FreeAllDeviceClasses(classes);
 +
  #ifdef XKB
      while (dev->xkb_interest)
  	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
diff --cc dix/getevents.c
index 7537906,3e6fe5a..b2be9bd
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -659,14 -528,10 +662,10 @@@ GetPointerEvents(EventList *events, Dev
      int num_events = 0, final_valuator = 0;
      CARD32 ms = 0;
      deviceKeyButtonPointer *kbp = NULL;
 -    DeviceIntPtr cp = inputInfo.pointer;
 +    DeviceIntPtr master;
- 
-     /* Thanks to a broken lib, we _always_ have to chase DeviceMotionNotifies
-      * with DeviceValuators. */
-     Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
      int x = 0, y = 0;
 +    /* The core pointer must not send Xi events. */
      Bool coreOnly = (pDev == inputInfo.pointer);
 -    ScreenPtr scr = miPointerGetScreen(pDev);
  
      /* Sanity checks. */
      if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
@@@ -683,25 -548,13 +682,25 @@@
 -    if (!coreOnly && pDev->coreEvents)
 -        num_events = 2;
 -    else
 -        num_events = 1;
 -
      if (type == MotionNotify && num_valuators <= 0)
          return 0;
  
 +    ms = GetTimeInMillis();
 +
 +    num_events = 1;
 +
 +    master = pDev->u.master;
 +    if (master && master->u.lastSlave != pDev)
 +    {
 +        CreateClassesChangedEvent(events, master, pDev);
 +
 +        pDev->lastx = master->lastx;
 +        pDev->lasty = master->lasty;
 +        master->u.lastSlave = pDev;
 +
 +        num_events++;
 +        events++;
 +    }
 +
      /* Do we need to send a DeviceValuator event? */
-     if (!coreOnly && sendValuators) {
+     if (!coreOnly && num_valuators) {
          if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
              num_valuators = MAX_VALUATOR_EVENTS * 6;
          num_events += ((num_valuators - 1) / 6) + 1;
@@@ -789,11 -757,11 +788,11 @@@
              kbp->detail = pDev->button->map[buttons];
          }
  
 -        kbp->root_x = pDev->valuator->lastx;
 -        kbp->root_y = pDev->valuator->lasty;
 +        kbp->root_x = x;
 +        kbp->root_y = y;
  
          events++;
-         if (sendValuators) {
+         if (num_valuators) {
              kbp->deviceid |= MORE_EVENTS;
              clipValuators(pDev, first_valuator, num_valuators, valuators);
              events = getValuatorEvents(events, pDev, first_valuator,
diff --cc dix/window.c
index a941dac,9975b5e..ee4c756
--- a/dix/window.c
+++ b/dix/window.c
@@@ -305,12 -290,8 +305,11 @@@ SetWindowToDefaults(WindowPtr pWin
      pWin->deliverableEvents = 0;
      pWin->dontPropagate = 0;
      pWin->forcedBS = FALSE;
- #ifdef COMPOSITE
      pWin->redirectDraw = RedirectDrawNone;
- #endif
+     pWin->forcedBG = FALSE;
 +
 +    sem = xcalloc(1, sizeof(FocusSemaphoresRec));
 +    dixSetPrivate(&pWin->devPrivates, FocusPrivatesKey, sem);
  }
  
  static void
diff --cc hw/xfree86/common/xf86Xinput.c
index d2c0531,eafc0e9..d8e23ee
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@@ -606,9 -583,8 +620,8 @@@ xf86PostProximityEvent(DeviceIntPtr	dev
                                   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);
  }
  
  _X_EXPORT void
@@@ -632,8 -608,12 +645,12 @@@ xf86PostButtonEvent(DeviceIntPtr	device
              return;
      }
  #endif
-     valuators = xcalloc(sizeof(int), num_valuators);
+     if (num_valuators > MAX_VALUATORS) {
+ 	xf86Msg(X_ERROR, "xf86PostMotionEvent: num_valuator %d"
+ 	    " is greater than MAX_VALUATORS\n", num_valuators);
+ 	return;
+     }
 -    
 +
      va_start(var, num_valuators);
      for (i = 0; i < num_valuators; i++)
          valuators[i] = va_arg(var, int);
@@@ -646,9 -629,7 +663,8 @@@
                                 first_valuator, num_valuators, valuators);
  
      for (i = 0; i < nevents; i++)
 -        mieqEnqueue(device, xf86Events + i);
 +        mieqEnqueue(device, (xf86Events + i)->event);
 +
-     xfree(valuators);
  }
  
  _X_EXPORT void
@@@ -668,8 -650,16 +685,13 @@@ xf86PostKeyEvent(DeviceIntPtr	device
             "badly south after this message, then xf86PostKeyEvent is "
             "broken.\n");
  
+     if (num_valuators > MAX_VALUATORS) {
+ 	xf86Msg(X_ERROR, "xf86PostMotionEvent: num_valuator %d"
+ 	    " is greater than MAX_VALUATORS\n", num_valuators);
+ 	return;
+     }
+ 
 -    if (!xf86Events)
 -        FatalError("Didn't allocate event store\n");
 -
      if (is_absolute) {
-         valuators = xcalloc(sizeof(int), num_valuators);
          va_start(var, num_valuators);
          for (i = 0; i < num_valuators; i++)
              valuators[i] = va_arg(var, int);
diff --cc include/misc.h
index e6a5e9e,a1cbe86..0107a30
--- a/include/misc.h
+++ b/include/misc.h
@@@ -87,10 -87,7 +87,8 @@@ extern unsigned long serverGeneration
  #define MAXSCREENS	16
  #endif
  #define MAXCLIENTS	256
- #define MAXDITS		1
- #define MAXEXTENSIONS	128
++#define MAXEXTENSIONS   128
  #define MAXFORMATS	8
- #define MAXVISUALS_PER_SCREEN 50
  
  typedef unsigned long PIXEL;
  typedef unsigned long ATOM;
diff --cc mi/mipointer.c
index 5706ef4,b55e68b..42d38c0
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@@ -341,22 -227,16 +341,22 @@@ miPointerDeviceCleanup(pDev, pScreen
  /* Once signals are ignored, the WarpCursor function can call this */
  
  _X_EXPORT void
 -miPointerWarpCursor (pScreen, x, y)
 -    ScreenPtr	pScreen;
 -    int		x, y;
 +miPointerWarpCursor (pDev, pScreen, x, y)
 +    DeviceIntPtr pDev;
 +    ScreenPtr	 pScreen;
 +    int	   	 x, y;
  {
 +    miPointerPtr pPointer;
      BOOL changedScreen = FALSE;
-     
++
 +    if (!pDev->isMaster && !pDev->u.master)
 +        return;
 +    pPointer = MIPOINTER(pDev);
      SetupScreen (pScreen);
  
 -    if (miPointer.pScreen != pScreen)
 +    if (pPointer->pScreen != pScreen)
      {
 -	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
 +	(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
          changedScreen = TRUE;
      }
  
@@@ -368,19 -248,20 +368,20 @@@
      {
  	/* everything from miPointerMove except the event and history */
  
 -    	if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
 +    	if (!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
      	{
 -	    miPointer.devx = x;
 -	    miPointer.devy = y;
 -	    if(!miPointer.pCursor->bits->emptyMask)
 -		(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
 +	    pPointer->devx = x;
 +	    pPointer->devy = y;
 +	    if(!pPointer->pCursor->bits->emptyMask)
 +		(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
      	}
 -	miPointer.x = x;
 -	miPointer.y = y;
 -	miPointer.pScreen = pScreen;
 +	pPointer->x = x;
 +	pPointer->y = y;
 +	pPointer->pScreen = pScreen;
      }
+ 
      if (changedScreen)
 -        UpdateSpriteForScreen (pScreen) ;
 +        UpdateSpriteForScreen (pDev, pScreen) ;
  }
  
  /*
diff --cc xkb/ddxList.c
index 2baf652,80e0505..ae3a7f7
--- a/xkb/ddxList.c
+++ b/xkb/ddxList.c
@@@ -199,11 -191,10 +191,10 @@@ char	tmpname[PATH_MAX]
  #ifndef WIN32
  	in= Popen(buf,"r");
  #else
- #ifdef DEBUG_CMD
- 	ErrorF("[xkb] xkb executes: %s\n",buf);
- #endif
+         if (xkbDebugFlags)
 -            DebugF("xkbList executes: %s\n",buf);
++            DebugF("[xkb] xkbList executes: %s\n",buf);
  	if (System(buf) < 0)
 -	    ErrorF("Could not invoke keymap compiler\n");
 +	    ErrorF("[xkb] Could not invoke keymap compiler\n");
  	else
  	    in= fopen(tmpname, "r");
  #endif
diff --cc xkb/ddxLoad.c
index a0fa606,d80ce62..ee64c3b
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@@ -360,23 -252,19 +252,19 @@@ char tmpname[PATH_MAX]
      if (out!=NULL) {
  #ifdef DEBUG
      if (xkbDebugFlags) {
 -       ErrorF("XkbDDXCompileKeymapByNames compiling keymap:\n");
 +       ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
-        XkbWriteXKBKeymapForNames(stderr,names,NULL,xkb,want,need);
+        XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need);
      }
  #endif
- 	XkbWriteXKBKeymapForNames(out,names,NULL,xkb,want,need);
+ 	XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
  #ifndef WIN32
  	if (Pclose(out)==0)
  #else
  	if (fclose(out)==0 && System(buf) >= 0)
  #endif
  	{
- #ifdef DEBUG_CMD
- 	    ErrorF("[xkb] xkb executes: %s\n",buf);
- 	    ErrorF("[xkb] xkbcomp input:\n");
- 	    XkbWriteXKBKeymapForNames(stderr,names,NULL,xkb,want,need);
- 	    ErrorF("[xkb] end xkbcomp input\n");
- #endif
+             if (xkbDebugFlags)
 -                DebugF("xkb executes: %s\n",buf);
++                DebugF("[xkb] xkb executes: %s\n",buf);
  	    if (nameRtrn) {
  		strncpy(nameRtrn,keymap,nameRtrnLen);
  		nameRtrn[nameRtrnLen-1]= '\0';
@@@ -385,24 -273,20 +273,20 @@@
                  xfree (buf);
  	    return True;
  	}
- #ifdef DEBUG
  	else
- 	    ErrorF("[xkb] Error compiling keymap (%s)\n",keymap);
- #endif
 -	    DebugF("Error compiling keymap (%s)\n",keymap);
++	    DebugF("[xkb] Error compiling keymap (%s)\n",keymap);
  #ifdef WIN32
          /* remove the temporary file */
          unlink(tmpname);
  #endif
      }
- #ifdef DEBUG
      else {
  #ifndef WIN32
- 	ErrorF("[xkb] Could not invoke keymap compiler\n");
 -	DebugF("Could not invoke keymap compiler\n");
++	DebugF("[xkb] Could not invoke keymap compiler\n");
  #else
- 	ErrorF("[xkb] Could not open file %s\n", tmpname);
 -	DebugF("Could not open file %s\n", tmpname);
++	DebugF("[xkb] Could not open file %s\n", tmpname);
  #endif
      }
- #endif
      if (nameRtrn)
  	nameRtrn[0]= '\0';
      if (buf != NULL)
@@@ -466,28 -350,11 +350,11 @@@ unsigned	missing
      if ((names->keycodes==NULL)&&(names->types==NULL)&&
  	(names->compat==NULL)&&(names->symbols==NULL)&&
  	(names->geometry==NULL)) {
- 	if (names->keymap==NULL) {
- 	    bzero(finfoRtrn,sizeof(XkbFileInfo));
- 	    if (xkb && XkbDetermineFileType(finfoRtrn,XkbXKMFile,NULL) &&
- 	   				((finfoRtrn->defined&need)==need) ) {
- 		finfoRtrn->xkb= xkb;
- 		nameRtrn[0]= '\0';
- 		return finfoRtrn->defined;
- 	    }
- 	    return 0;
- 	}
- 	else if (!XkbDDXCompileNamedKeymap(xkb,names,nameRtrn,nameRtrnLen)) {
- #ifdef NOISY
- 	    ErrorF("[xkb] Couldn't compile keymap file\n");
- #endif
- 	    return 0;
- 	}
+         return 0;
      }
      else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need,
- 						nameRtrn,nameRtrnLen)){
- #ifdef NOISY
- 	ErrorF("[xkb] Couldn't compile keymap file\n");
- #endif
+                                          nameRtrn,nameRtrnLen)){
 -	DebugF("Couldn't compile keymap file\n");
++	DebugF("[xkb] Couldn't compile keymap file\n");
  	return 0;
      }
      file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX);
@@@ -502,11 -369,9 +369,9 @@@
  	(void) unlink (fileName);
  	return 0;
      }
- #ifdef DEBUG
      else if (xkbDebugFlags) {
- 	ErrorF("[xkb] Loaded %s, defined=0x%x\n",fileName,finfoRtrn->defined);
 -	DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined);
++	DebugF("[xkb] Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined);
      }
- #endif
      fclose(file);
      (void) unlink (fileName);
      return (need|want)&(~missing);
diff --cc xkb/xkb.c
index 835b613,07f57a7..9b3d78e
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@@ -5784,10 -5778,8 +5778,8 @@@ char *			str
  	    return status;
      }
      else if (length!=0)  {
- #ifdef DEBUG
 -	ErrorF("Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
 -	ErrorF("                 Wrote %d fewer bytes than expected\n",length);
 +	ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
 +	ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",length);
- #endif
  	return BadLength;
      }
      if (stuff->wanted&(~supported)) {
diff --cc xkb/xkbAccessX.c
index 975b2eb,75b8c5a..28107d0
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@@ -130,11 -130,9 +130,9 @@@ xEvent		xE
      xE.u.u.type = type;
      xE.u.u.detail = keyCode;
      xE.u.keyButtonPointer.time = GetTimeInMillis();	    
- #ifdef DEBUG
      if (xkbDebugFlags&0x8) {
- 	ErrorF("[xkb] AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up"));
 -	DebugF("AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up"));
++	DebugF("[xkb] AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up"));
      }
- #endif
  
      if (_XkbIsPressEvent(type))
  	XkbDDXKeyClick(keybd,keyCode,TRUE);
diff --cc xkb/xkbEvents.c
index 351a328,49725d0..6389b90
--- a/xkb/xkbEvents.c
+++ b/xkb/xkbEvents.c
@@@ -818,18 -817,17 +817,17 @@@ XkbSrvInfoPtr	xkbi
  		((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
                   (xE[0].u.u.type==DeviceKeyPress)||
                   (xE[0].u.u.type == DeviceKeyRelease))) {
- 	    ErrorF("[xkb] XKbFilterWriteEvents:\n");
- 	    ErrorF("[xkb]    Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
- 	    ErrorF("[xkb]    XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
 -	    DebugF("XKbFilterWriteEvents:\n");
 -	    DebugF("   Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
 -	    DebugF("   XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
++	    DebugF("[xkb] XKbFilterWriteEvents:\n");
++	    DebugF("[xkb]    Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
++	    DebugF("[xkb]    XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
  			XkbLastRepeatEvent,xE,
  			((XkbLastRepeatEvent!=(pointer)xE)?"True":"False"));
- 	    ErrorF("[xkb]    (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n",
 -	    DebugF("   (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n",
++	    DebugF("[xkb]   (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n",
  		pClient->xkbClientFlags,
  		(_XkbWantsDetectableAutoRepeat(pClient)?"True":"False"));
- 	    ErrorF("[xkb]    !IsRelease(%d) %s\n",xE[0].u.u.type,
 -	    DebugF("   !IsRelease(%d) %s\n",xE[0].u.u.type,
++	    DebugF("[xkb]   !IsRelease(%d) %s\n",xE[0].u.u.type,
  			(!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False");
  	}
- #endif /* DEBUG */
  	if (	(XkbLastRepeatEvent==(pointer)xE) &&
  	     	(_XkbWantsDetectableAutoRepeat(pClient)) &&
  	     	(_XkbIsReleaseEvent(xE[0].u.u.type)) ) {
@@@ -872,8 -868,7 +869,7 @@@
  	     * when the mouse is released, the server does not behave properly.
  	     * Faking a release of the button here solves the problem.
  	     */
- 	    ErrorF("[xkb] Faking release of button %d\n", xE[0].u.u.detail);
- #endif
 -	    DebugF("Faking release of button %d\n", xE[0].u.u.detail);
++	    DebugF("[xkb] Faking release of button %d\n", xE[0].u.u.detail);
  	    XkbDDXFakePointerButton(ButtonRelease, xE[0].u.u.detail);
          }
      }
@@@ -888,11 -882,11 +883,11 @@@
                   (xE[i].u.u.type==DeviceKeyPress)||
                   (xE[i].u.u.type == DeviceKeyRelease))) {
  		XkbStatePtr s= &xkbi->state;
- 		ErrorF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
- 		ErrorF("[xkb] event= 0x%04x\n",xE[i].u.keyButtonPointer.state);
- 		ErrorF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods,
 -		DebugF("XKbFilterWriteEvents (non-XKB):\n");
 -		DebugF("event= 0x%04x\n",xE[i].u.keyButtonPointer.state);
 -		DebugF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods,
++		DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
++		DebugF("[xkb] event= 0x%04x\n",xE[i].u.keyButtonPointer.state);
++		DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods,
  							s->grab_mods);
- 		ErrorF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
 -		DebugF("compat lookup= 0x%02x, grab= 0x%02x\n",
++		DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
  							s->compat_lookup_mods,
  							s->compat_grab_mods);
  	    }
@@@ -929,16 -918,12 +923,12 @@@
  	    if (type == ButtonPress &&
  		((xE[i].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
  		(xkbi->lockedPtrButtons & button_mask) == button_mask) {
- #ifdef DEBUG
- 		ErrorF("[xkb] Faking release of button %d\n", xE[i].u.u.detail);
- #endif
 -		DebugF("Faking release of button %d\n", xE[i].u.u.detail);
++		DebugF("[xkb] Faking release of button %d\n", xE[i].u.u.detail);
  		XkbDDXFakePointerButton(ButtonRelease, xE[i].u.u.detail);
  	    } else if (type == DeviceButtonPress &&
                      ((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask &&
                      (xkbi->lockedPtrButtons & button_mask) == button_mask) {
- #ifdef DEBUG
- 		ErrorF("[xkb] Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
- #endif
 -		DebugF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
++		DebugF("[xkb] Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
  		XkbDDXFakePointerButton(DeviceButtonRelease, ((deviceKeyButtonPointer*)&xE[i])->state);
              }
  	}
diff --cc xkb/xkbInit.c
index 0682cc4,2b5f1fb..09317e9
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@@ -771,9 -742,7 +742,7 @@@ XkbSrvLedInfoPtr	sli
      sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0);
      if (sli && xkbi)
  	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
- #ifdef DEBUG
-     else ErrorF("[xkb] No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
- #endif
 -    else DebugF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
++    else DebugF("[xkb] No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
      return softRepeat;
  }
  
diff --cc xkb/xkbPrKeyEv.c
index f007f75,69c218c..74d02c6
--- a/xkb/xkbPrKeyEv.c
+++ b/xkb/xkbPrKeyEv.c
@@@ -56,11 -56,9 +56,9 @@@ int             xiEvent
      xkbi= keyc->xkbInfo;
      key= xE->u.u.detail;
      xiEvent= (xE->u.u.type & EXTENSION_EVENT_BASE);
- #ifdef DEBUG
      if (xkbDebugFlags&0x8) {
- 	ErrorF("[xkb] XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
 -	DebugF("XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
++	DebugF("[xkb] XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
      }
- #endif
  
      if ( (xkbi->repeatKey==key) && (xE->u.u.type==KeyRelease) &&
  	 ((xkbi->desc->ctrls->enabled_ctrls&XkbRepeatKeysMask)==0) ) {
commit 23ae68a4c74a2ec90b4130c37b0d0aec3f4082ce
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Feb 26 15:12:36 2008 +1030

    dix: before copying the classes the first time, set the VCK's classes to NULL.
    
    XkbFinishDeviceInit does the following:
      xkbi->kbdProc= pXDev->kbdfeed->CtrlProc;
      pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc;
    
    If we directly copy the device classes for the VCK, pXDev->kbdfeed->CtrlProc
    at the time of copying is still XbkDDXKeybdCtrlProc. So at some point
    XkbDDXKeybdCtrlProc is called, and calls itself, and calls itself, and...
    
    Setting the device's classes to NULL seems to fix things. The memory isn't
    lost, it gets stored into the devPrivates and freed at device closing time.

diff --git a/dix/devices.c b/dix/devices.c
index 38466f8..f036985 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -484,6 +484,21 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
          * If we don't do that, we're in SIGABRT territory (double-frees, etc)
          */
         memcpy(&dummy, pDev, sizeof(DeviceIntRec));
+        /* Need to set them to NULL. Otherwise, Xkb does some weird stuff and
+         * the dev->key->xkbInfo->kbdProc starts calling itself. This can
+         * probably be fixed in a better way, but I don't know how. (whot) */
+        pDev->key        = NULL;
+        pDev->valuator   = NULL;
+        pDev->button     = NULL;
+        pDev->focus      = NULL;
+        pDev->proximity  = NULL;
+        pDev->absolute   = NULL;
+        pDev->kbdfeed    = NULL;
+        pDev->ptrfeed    = NULL;
+        pDev->intfeed    = NULL;
+        pDev->stringfeed = NULL;
+        pDev->bell       = NULL;
+        pDev->leds       = NULL;
         DeepCopyDeviceClasses(&dummy, pDev);
 
         dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey,
@@ -547,6 +562,20 @@ CorePointerProc(DeviceIntPtr pDev, int what)
 
         /* See comment in CoreKeyboardProc. */
         memcpy(&dummy, pDev, sizeof(DeviceIntRec));
+        /* Need to set them to NULL for the VCK (see CoreKeyboardProc). Not
+         * sure if also necessary for the VCP, but it doesn't seem to hurt */
+        pDev->key        = NULL;
+        pDev->valuator   = NULL;
+        pDev->button     = NULL;
+        pDev->focus      = NULL;
+        pDev->proximity  = NULL;
+        pDev->absolute   = NULL;
+        pDev->kbdfeed    = NULL;
+        pDev->ptrfeed    = NULL;
+        pDev->intfeed    = NULL;
+        pDev->stringfeed = NULL;
+        pDev->bell       = NULL;
+        pDev->leds       = NULL;
         DeepCopyDeviceClasses(&dummy, pDev);
 
         dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, classes);
commit ce9fb2f8c4610016e49321018fc9b24729380afc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Feb 26 13:19:54 2008 +1030

    Xi: MDs return the paired device's ID in attached field of ListInputDevices.

diff --git a/Xi/listdev.c b/Xi/listdev.c
index 50f34e4..3fb0ab3 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -188,6 +188,8 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
 	dev->use = IsXExtensionDevice;
     if (!d->isMaster)
         dev->attached = (d->u.master) ? d->u.master->id : IsFloating;
+    else
+        dev->attached = GetPairedDevice(d)->id;
 
     if (client->swapped) {
 	swapl(&dev->type, n);	/* macro - braces are required */
commit d61f481a4455dd2a94674d2b7b26429cf9dcece3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Feb 25 17:52:45 2008 +1030

    Xi: remove GetPairedPointer handling.
    
    obsolete, ListInputDevices provides this information now.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 7804c51..2af1940 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -46,8 +46,6 @@ libXi_la_SOURCES =	\
 	getkmap.h \
 	getmmap.c \
 	getmmap.h \
-	getpairp.c \
-	getpairp.h \
 	getprop.c \
 	getprop.h \
 	getselev.c \
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 0cf429f..f1c2824 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -94,7 +94,6 @@ SOFTWARE.
 #include "getfocus.h"
 #include "getkmap.h"
 #include "getmmap.h"
-#include "getpairp.h"
 #include "getprop.h"
 #include "getselev.h"
 #include "getvers.h"
@@ -335,8 +334,6 @@ ProcIDispatch(ClientPtr client)
         return ProcXSetClientPointer(client);
     else if (stuff->data == X_GetClientPointer)
         return ProcXGetClientPointer(client);
-    else if (stuff->data == X_GetPairedPointer)
-        return ProcXGetPairedPointer(client);
     else if (stuff->data == X_ExtendedGrabDevice)
         return ProcXExtendedGrabDevice(client);
     else {
@@ -446,8 +443,6 @@ SProcIDispatch(ClientPtr client)
         return SProcXSetClientPointer(client);
     else if (stuff->data == X_GetClientPointer)
         return SProcXGetClientPointer(client);
-    else if (stuff->data == X_GetPairedPointer)
-        return SProcXGetPairedPointer(client);
     else if (stuff->data == X_ExtendedGrabDevice)
         return SProcXExtendedGrabDevice(client);
     else {
@@ -530,8 +525,6 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
                                (xQueryWindowAccessReply*) rep);
     else if (rep->RepType == X_GetClientPointer)
         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 {
diff --git a/Xi/getpairp.c b/Xi/getpairp.c
deleted file mode 100644
index 59ed189..0000000
--- a/Xi/getpairp.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-
-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 <X11/X.h>	/* for inputstr.h    */
-#include <X11/Xproto.h>	/* Request macro     */
-#include "inputstr.h"	/* DeviceIntPtr      */
-#include "windowstr.h"	/* window structure  */
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "extnsionst.h"
-#include "exevents.h"
-#include "exglobals.h"
-
-#ifdef PANORAMIX
-#include "panoramiXsrv.h"
-#endif
-
-#include "getpairp.h"
-
-/***********************************************************************
- *
- * This procedure allows a client to query the paired pointer for a keyboard
- * device.
- *
- */
-
-int
-SProcXGetPairedPointer(ClientPtr client)
-{
-    char n;
-    REQUEST(xGetPairedPointerReq);
-    swaps(&stuff->length, n);
-    return (ProcXGetPairedPointer(client));
-}
-
-int 
-ProcXGetPairedPointer(ClientPtr client)
-{
-    xGetPairedPointerReply rep;
-    DeviceIntPtr kbd, ptr;
-    int rc;
-
-    REQUEST(xGetPairedPointerReq);
-    REQUEST_SIZE_MATCH(xGetPairedPointerReq);
-
-    rc = dixLookupDevice(&kbd, stuff->deviceid, client, DixReadAccess);
-    if (rc != Success)
-        return rc;
-    else if (!kbd->key || !kbd->isMaster) {
-        client->errorValue = stuff->deviceid;
-        return BadDevice;
-    }
-
-    ptr = GetPairedDevice(kbd);
-
-    rep.repType = X_Reply;
-    rep.RepType = X_GetPairedPointer;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-    rep.paired = TRUE;
-    rep.deviceid = ptr->id;
-    WriteReplyToClient(client, sizeof(xGetPairedPointerReply), &rep);
-    return Success;
-}
-
-void
-SRepXGetPairedPointer(ClientPtr client, int size,
-        xGetPairedPointerReply* rep)
-{
-    char n;
-
-    swaps(&rep->sequenceNumber, n);
-    swapl(&rep->length, n);
-    WriteToClient(client, size, (char *)rep);
-}
diff --git a/Xi/getpairp.h b/Xi/getpairp.h
deleted file mode 100644
index 9b4759e..0000000
--- a/Xi/getpairp.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-
-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 GETPAIRP_H
-#define GETPAIRP_H 1
-
-int SProcXGetPairedPointer(ClientPtr /* client */
-        );
-int ProcXGetPairedPointer(ClientPtr /* client */
-        );
-void SRepXGetPairedPointer(ClientPtr /* client */,
-        int /* size */,
-        xGetPairedPointerReply* /* rep */
-        );
-
-#endif /* GETPAIRP_H */
commit 27b21278939a06ab6a22c9902f202eae6c5fae72
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Feb 25 17:00:42 2008 +1030

    Xi: remove ungrab handling of ExtendedUngrabDevice request.
    
    This can be done by UngrabDevice, no need for separate codepaths.

diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
index 72f8879..6458404 100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@ -107,19 +107,13 @@ ProcXExtendedGrabDevice(ClientPtr client)
     REQUEST(xExtendedGrabDeviceReq);
     REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq);
 
-    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))
+    if (stuff->length != (sizeof(xExtendedGrabDeviceReq) >> 2) +
+            stuff->event_count + 2 * stuff->generic_event_count)
     {
         errval = 0;
         rc = BadLength;
@@ -131,13 +125,6 @@ ProcXExtendedGrabDevice(ClientPtr client)
 	goto cleanup;
     }
 
-
-    if (stuff->ungrab)
-    {
-        ExtUngrabDevice(client, dev);
-        goto cleanup;
-    }
-
     rc = dixLookupWindow(&grab_window,
                           stuff->grab_window,
                           client,
diff --git a/dix/events.c b/dix/events.c
index bf2df9f..0b9b768 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -6604,15 +6604,3 @@ ExtGrabDevice(ClientPtr client,
     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 079645d..1ed4af0 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -698,7 +698,4 @@ extern int ExtGrabDevice(ClientPtr client,
                          CursorPtr cursor, 
                          Mask xi_mask,
                          GenericMaskPtr ge_masks);
-extern int ExtUngrabDevice(ClientPtr client,
-                         DeviceIntPtr dev);
-
 #endif /* DIX_H */
commit f14a62f823e257f92745bbcde11838f2ddd32ac8
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Feb 19 21:44:10 2008 +1030

    dix: set evlen to the size of the reallocated memory.
    
    What a good idea this is... I'm very proud of myself.

diff --git a/dix/getevents.c b/dix/getevents.c
index 15b7dc3..7537906 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -613,6 +613,7 @@ SetMinimumEventSize(EventListPtr list, int num_events, int min_size)
     {
         if (list[num_events].evlen < min_size)
         {
+            list[num_events].evlen = min_size;
             list[num_events].event = realloc(list[num_events].event, min_size);
             if (!list[num_events].event)
             {
commit 750d70267679ddee10590c80ec621d890bd3d4a7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Feb 3 10:25:15 2008 +1030

    dix: Ensure enough memory for ClassesChangedEvent for a new device.
    
    Before we enable the device through the driver, we size it up and make sure
    that the events in the event list contain enough bytes for a possible
    ClassesChangedEvent lateron.

diff --git a/dix/devices.c b/dix/devices.c
index 0ffc798..38466f8 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -206,6 +206,10 @@ EnableDevice(DeviceIntPtr dev)
     DeviceIntRec dummyDev;
     DeviceIntPtr other;
     devicePresenceNotify ev;
+    int namelen = 0; /* dummy */
+    int evsize  = sizeof(xEvent);
+    int listlen;
+    EventListPtr evlist;
 
     for (prev = &inputInfo.off_devices;
 	 *prev && (*prev != dev);
@@ -238,6 +242,18 @@ EnableDevice(DeviceIntPtr dev)
         }
     }
 
+    /* Before actually enabling the device, we need to make sure the event
+     * list's events have enough memory for a ClassesChangedEvent from the
+     * device
+     */
+
+    SizeDeviceInfo(dev, &namelen, &evsize);
+
+    listlen = GetEventList(&evlist);
+    OsBlockSignals();
+    SetMinimumEventSize(evlist, listlen, evsize);
+    OsReleaseSignals();
+
     if ((*prev != dev) || !dev->inited ||
 	((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
         ErrorF("[dix] couldn't enable device %d\n", dev->id);
commit 74628d639719815c1beff4cac84662fa41c55925
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Feb 3 10:15:40 2008 +1030

    dix: change GetEventList to return length of list and set parameter in place.
    
    Changing DDXs to use new prototype too.

diff --git a/dix/getevents.c b/dix/getevents.c
index 407ac58..15b7dc3 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -77,10 +77,11 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
 EventListPtr InputEventList = NULL;
 int InputEventListLen = 0;
 
-_X_EXPORT EventListPtr
-GetEventList()
+_X_EXPORT int
+GetEventList(EventListPtr* list)
 {
-    return InputEventList;
+    *list = InputEventList;
+    return InputEventListLen;
 }
 
 /**
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 78b4419..62a8261 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -65,7 +65,7 @@ static struct KdConfigDevice *kdConfigPointers    = NULL;
 static KdKeyboardDriver *kdKeyboardDrivers = NULL;
 static KdPointerDriver  *kdPointerDrivers  = NULL;
 
-static EventListPtr     *kdEvents = NULL;
+static EventListPtr     kdEvents = NULL;
 
 static Bool		kdInputEnabled;
 static Bool		kdOffScreen;
@@ -1979,7 +1979,7 @@ KdReleaseAllKeys (void)
              key++) {
             if (IsKeyDown(ki, key)) {
                 KdHandleKeyboardEvent(ki, KeyRelease, key);
-                kdEvents = GetEventList();
+                GetEventList(&kdEvents);
                 nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key);
                 for (i = 0; i < nEvents; i++)
                     KdQueueEvent (ki->dixdev, kdEvents + i);
@@ -2044,7 +2044,7 @@ KdEnqueueKeyboardEvent(KdKeyboardInfo   *ki,
             KdHandleKeyboardEvent(ki, type, key_code);
 	}
 	
-        kdEvents = GetEventList();
+        GetEventList(&kdEvents);
         nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code);
         for (i = 0; i < nEvents; i++)
             KdQueueEvent(ki->dixdev, kdEvents);
@@ -2145,7 +2145,7 @@ _KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z,
     if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
         return;
 
-    kdEvents = GetEventList();
+    GetEventList(&kdEvents);
     nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel,
                                0, 3, valuators);
     for (i = 0; i < nEvents; i++)
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index a928b4c..d2c0531 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -569,7 +569,7 @@ xf86PostMotionEventP(DeviceIntPtr	device,
     }
 #endif
 
-    xf86Events = GetEventList();
+    GetEventList(&xf86Events);
     nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0,
                                flags, first_valuator, num_valuators,
                                valuators);
@@ -601,7 +601,7 @@ xf86PostProximityEvent(DeviceIntPtr	device,
         valuators[i] = va_arg(var, int);
     va_end(var);
 
-    xf86Events = GetEventList();
+    GetEventList(&xf86Events);
     nevents = GetProximityEvents(xf86Events, device,
                                  is_in ? ProximityIn : ProximityOut, 
                                  first_valuator, num_valuators, valuators);
@@ -639,7 +639,7 @@ xf86PostButtonEvent(DeviceIntPtr	device,
         valuators[i] = va_arg(var, int);
     va_end(var);
 
-    xf86Events = GetEventList();
+    GetEventList(&xf86Events);
     nevents = GetPointerEvents(xf86Events, device,
                                is_down ? ButtonPress : ButtonRelease, button,
                                (is_absolute) ? POINTER_ABSOLUTE : POINTER_RELATIVE,
@@ -675,7 +675,7 @@ xf86PostKeyEvent(DeviceIntPtr	device,
             valuators[i] = va_arg(var, int);
         va_end(var);
 
-        xf86Events = GetEventList();
+        GetEventList(&xf86Events);
         nevents = GetKeyboardValuatorEvents(xf86Events, device,
                                             is_down ? KeyPress : KeyRelease,
                                             key_code, first_valuator,
@@ -710,7 +710,7 @@ xf86PostKeyboardEvent(DeviceIntPtr      device,
     }
 #endif
 
-    xf86Events = GetEventList();
+    GetEventList(&xf86Events);
     nevents = GetKeyboardEvents(xf86Events, device,
                                 is_down ? KeyPress : KeyRelease, key_code);
 
diff --git a/include/input.h b/include/input.h
index af330a7..9ba12db 100644
--- a/include/input.h
+++ b/include/input.h
@@ -399,7 +399,7 @@ extern void InitInput(
 
 extern int GetMaximumEventsNum(void);
 
-extern EventListPtr GetEventList();
+extern int GetEventList(EventListPtr* list);
 extern EventListPtr InitEventList(int num_events);
 extern void SetMinimumEventSize(EventListPtr list,
                                 int num_events,
commit 77dba004a9aaf35f183f61ff6875a491a52aa030
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Feb 3 10:10:46 2008 +1030

    dix: add InputEventListLen and SetMinimumEventSize
    
    The latter is used to increase the amount of allocated memory for the event
    list. This will be needed for ClassesChangedEvents that can be of more or less
    arbitrary size (larger than 32 anyway).

diff --git a/dix/events.c b/dix/events.c
index 1155178..bf2df9f 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5712,7 +5712,8 @@ InitEvents(void)
 	DontPropagateRefCnts[i] = 0;
     }
 
-    InputEventList = InitEventList(GetMaximumEventsNum());
+    InputEventListLen = GetMaximumEventsNum();
+    InputEventList = InitEventList(InputEventListLen);
     if (!InputEventList)
         FatalError("[dix] Failed to allocate input event list.\n");
 }
diff --git a/dix/getevents.c b/dix/getevents.c
index 2a9df0f..407ac58 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -75,6 +75,7 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
  * Get{Pointer|Keyboard}Events.
  */
 EventListPtr InputEventList = NULL;
+int InputEventListLen = 0;
 
 _X_EXPORT EventListPtr
 GetEventList()
@@ -599,6 +600,29 @@ InitEventList(int num_events)
 }
 
 /**
+ * Allocs min_size memory for each event in the list.
+ */
+_X_EXPORT void
+SetMinimumEventSize(EventListPtr list, int num_events, int min_size)
+{
+    if (!list)
+        return;
+
+    while(num_events--)
+    {
+        if (list[num_events].evlen < min_size)
+        {
+            list[num_events].event = realloc(list[num_events].event, min_size);
+            if (!list[num_events].event)
+            {
+                FatalError("[dix] Failed to set event list's "
+                        "min_size to %d.\n", min_size);
+            }
+        }
+    }
+}
+
+/**
  * Free an event list.
  *
  * @param list The list to be freed.
diff --git a/include/input.h b/include/input.h
index fb24e76..af330a7 100644
--- a/include/input.h
+++ b/include/input.h
@@ -96,6 +96,7 @@ typedef struct _EventList {
 
 /* The DIX stores incoming input events in this list */
 extern EventListPtr InputEventList;
+extern int InputEventListLen;
 
 typedef int (*DeviceProc)(
     DeviceIntPtr /*device*/,
@@ -400,6 +401,9 @@ extern int GetMaximumEventsNum(void);
 
 extern EventListPtr GetEventList();
 extern EventListPtr InitEventList(int num_events);
+extern void SetMinimumEventSize(EventListPtr list,
+                                int num_events,
+                                int min_size);
 extern void FreeEventList(EventListPtr list, int num_events);
 
 extern void CreateClassesChangedEvent(EventListPtr event, 
commit 3fe64d8d271aea0863bf01b0376f3eceec0c90b5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Feb 3 09:56:19 2008 +1030

    Move input event list initialisation and storage from DDX to DIX.
    
    Rather than letting the DDX allocate the events, allocate them once in the DIX
    and just pass it around when needed.
    
    DDX should call GetEventList() to obtain this list and then pass it into
    Get{Pointer|Keyboard}Events.

diff --git a/dix/events.c b/dix/events.c
index 2928554..1155178 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5711,6 +5711,10 @@ InitEvents(void)
 	DontPropagateMasks[i] = 0;
 	DontPropagateRefCnts[i] = 0;
     }
+
+    InputEventList = InitEventList(GetMaximumEventsNum());
+    if (!InputEventList)
+        FatalError("[dix] Failed to allocate input event list.\n");
 }
 
 /**
diff --git a/dix/getevents.c b/dix/getevents.c
index 840fa2b..2a9df0f 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -70,6 +70,17 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
 /* Number of motion history events to store. */
 #define MOTION_HISTORY_SIZE 256
 
+/* InputEventList is the container list for all input events generated by the
+ * DDX. The DDX is expected to call GetEventList() and then pass the list into
+ * Get{Pointer|Keyboard}Events.
+ */
+EventListPtr InputEventList = NULL;
+
+_X_EXPORT EventListPtr
+GetEventList()
+{
+    return InputEventList;
+}
 
 /**
  * Pick some arbitrary size for Xi motion history.
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 5b1dc5c..78b4419 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -65,7 +65,7 @@ static struct KdConfigDevice *kdConfigPointers    = NULL;
 static KdKeyboardDriver *kdKeyboardDrivers = NULL;
 static KdPointerDriver  *kdPointerDrivers  = NULL;
 
-static xEvent           *kdEvents = NULL;
+static EventListPtr     *kdEvents = NULL;
 
 static Bool		kdInputEnabled;
 static Bool		kdOffScreen;
@@ -1391,11 +1391,6 @@ KdInitInput (void)
             ErrorF("Failed to add keyboard!\n");
     }
 
-    if (!kdEvents)
-        kdEvents = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
-    if (!kdEvents)
-        FatalError("Couldn't allocate event buffer\n");
-
     mieqInit();
 }
 
@@ -1984,6 +1979,7 @@ KdReleaseAllKeys (void)
              key++) {
             if (IsKeyDown(ki, key)) {
                 KdHandleKeyboardEvent(ki, KeyRelease, key);
+                kdEvents = GetEventList();
                 nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key);
                 for (i = 0; i < nEvents; i++)
                     KdQueueEvent (ki->dixdev, kdEvents + i);
@@ -2048,9 +2044,10 @@ KdEnqueueKeyboardEvent(KdKeyboardInfo   *ki,
             KdHandleKeyboardEvent(ki, type, key_code);
 	}
 	
+        kdEvents = GetEventList();
         nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code);
         for (i = 0; i < nEvents; i++)
-            KdQueueEvent(ki->dixdev, kdEvents + i);
+            KdQueueEvent(ki->dixdev, kdEvents);
     }
     else {
         ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n",
@@ -2148,8 +2145,9 @@ _KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z,
     if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
         return;
 
-    nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, 0, 3,
-                               valuators);
+    kdEvents = GetEventList();
+    nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel,
+                               0, 3, valuators);
     for (i = 0; i < nEvents; i++)
         KdQueueEvent(pi->dixdev, kdEvents + i);
 }
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index f99e540..a928b4c 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -569,11 +569,7 @@ xf86PostMotionEventP(DeviceIntPtr	device,
     }
 #endif
 
-    if (!xf86Events)
-        xf86Events = InitEventList(GetMaximumEventsNum());
-    if (!xf86Events)
-        FatalError("Couldn't allocate event store\n");
-
+    xf86Events = GetEventList();
     nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0,
                                flags, first_valuator, num_valuators,
                                valuators);
@@ -605,11 +601,7 @@ xf86PostProximityEvent(DeviceIntPtr	device,
         valuators[i] = va_arg(var, int);
     va_end(var);
 
-    if (!xf86Events)
-        xf86Events = InitEventList(GetMaximumEventsNum());
-    if (!xf86Events)
-        FatalError("Couldn't allocate event store\n");
-
+    xf86Events = GetEventList();
     nevents = GetProximityEvents(xf86Events, device,
                                  is_in ? ProximityIn : ProximityOut, 
                                  first_valuator, num_valuators, valuators);
@@ -647,11 +639,7 @@ xf86PostButtonEvent(DeviceIntPtr	device,
         valuators[i] = va_arg(var, int);
     va_end(var);
 
-    if (!xf86Events)
-        xf86Events = InitEventList(GetMaximumEventsNum());
-    if (!xf86Events)
-        FatalError("Couldn't allocate event store\n");
-
+    xf86Events = GetEventList();
     nevents = GetPointerEvents(xf86Events, device,
                                is_down ? ButtonPress : ButtonRelease, button,
                                (is_absolute) ? POINTER_ABSOLUTE : POINTER_RELATIVE,
@@ -680,11 +668,6 @@ xf86PostKeyEvent(DeviceIntPtr	device,
            "badly south after this message, then xf86PostKeyEvent is "
            "broken.\n");
 
-    if (!xf86Events)
-        xf86Events = InitEventList(GetMaximumEventsNum());
-    if (!xf86Events)
-        FatalError("Couldn't allocate event store\n");
-
     if (is_absolute) {
         valuators = xcalloc(sizeof(int), num_valuators);
         va_start(var, num_valuators);
@@ -692,6 +675,7 @@ xf86PostKeyEvent(DeviceIntPtr	device,
             valuators[i] = va_arg(var, int);
         va_end(var);
 
+        xf86Events = GetEventList();
         nevents = GetKeyboardValuatorEvents(xf86Events, device,
                                             is_down ? KeyPress : KeyRelease,
                                             key_code, first_valuator,
@@ -726,11 +710,7 @@ xf86PostKeyboardEvent(DeviceIntPtr      device,
     }
 #endif
 
-    if (!xf86Events)
-        xf86Events = InitEventList(GetMaximumEventsNum());
-    if (!xf86Events)
-        FatalError("Couldn't allocate event store\n");
-
+    xf86Events = GetEventList();
     nevents = GetKeyboardEvents(xf86Events, device,
                                 is_down ? KeyPress : KeyRelease, key_code);
 
diff --git a/include/input.h b/include/input.h
index 1863676..fb24e76 100644
--- a/include/input.h
+++ b/include/input.h
@@ -94,6 +94,8 @@ typedef struct _EventList {
                   ((xGenericEvent*)event)->length * 4 for GenericEvents */
 } EventList, *EventListPtr;
 
+/* The DIX stores incoming input events in this list */
+extern EventListPtr InputEventList;
 
 typedef int (*DeviceProc)(
     DeviceIntPtr /*device*/,
@@ -396,6 +398,7 @@ extern void InitInput(
 
 extern int GetMaximumEventsNum(void);
 
+extern EventListPtr GetEventList();
 extern EventListPtr InitEventList(int num_events);
 extern void FreeEventList(EventListPtr list, int num_events);
 
commit 09a8fc5c7a79ca22fc23224bb544f2e709681f3f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Feb 3 07:47:18 2008 +1030

    Xi: make SizeDeviceInfo public and re-use from CreateClassesChangedEvent.

diff --git a/Xi/listdev.c b/Xi/listdev.c
index 4aa2688..50f34e4 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -92,7 +92,7 @@ SProcXListInputDevices(ClientPtr client)
  *
  */
 
-static void
+_X_EXPORT void
 SizeDeviceInfo(DeviceIntPtr d, int *namesize, int *size)
 {
     int chunks;
diff --git a/Xi/listdev.h b/Xi/listdev.h
index 22a0d91..39ea2d6 100644
--- a/Xi/listdev.h
+++ b/Xi/listdev.h
@@ -49,4 +49,9 @@ CopySwapClasses(ClientPtr /* client */,
                 CARD8* /* num_classes */,
                 char** /* classbuf */);
 
+void
+SizeDeviceInfo(DeviceIntPtr /* dev */,
+               int* /* namesize */,
+               int* /* size */);
+
 #endif /* LISTDEV_H */
diff --git a/dix/getevents.c b/dix/getevents.c
index 1f8f0e0..840fa2b 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -113,6 +113,7 @@ CreateClassesChangedEvent(EventList* event,
     deviceClassesChangedEvent *dcce;
     int len = sizeof(xEvent);
     CARD32 ms = GetTimeInMillis();
+    int namelen = 0; /* dummy */
 
     /* XXX: ok, this is a bit weird. We need to alloc enough size for the
      * event so it can be filled in in POE lateron. Reason being that if
@@ -120,19 +121,9 @@ CreateClassesChangedEvent(EventList* event,
      * or realloc the original pointer.
      * We can only do it here as we don't have the EventList in the event
      * processing any more.
-     *
-     * Code is basically same as in Xi/listdev.c
      */
-    if (slave->key)
-        len += sizeof(xKeyInfo);
-    if (slave->button)
-        len += sizeof(xButtonInfo);
-    if (slave->valuator)
-    {
-        int chunks = ((int)slave->valuator->numAxes + 19) / VPC;
-        len += (chunks * sizeof(xValuatorInfo) +
-                slave->valuator->numAxes * sizeof(xAxisInfo));
-    }
+    SizeDeviceInfo(slave, &namelen, &len);
+
     if (event->evlen < len)
     {
         event->event = realloc(event->event, len);
commit 6d9d18bf7708eb9e640ef732b5dc4c99aa6d5feb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Feb 18 17:25:15 2008 +1030

    dix: add support for WindowAccessAllowAll in device access checking.
    
    AllowAll is the last check before the parent window is checked. This allows
    to override a DenyAll in the parent window in a simpler way than before (the
    previous method required all devices to be in the permit list).

diff --git a/dix/access.c b/dix/access.c
index e7d39b4..dc66db8 100644
--- a/dix/access.c
+++ b/dix/access.c
@@ -254,6 +254,7 @@ ACQueryWindowAccess(WindowPtr win,
  * If the device is explicitely permitted, allow.
  * If the window has a default of DenyAll, do not allow.
  * If the device is explicitely denied, do not allow.
+ * If the window has a default of AllowAll, allow.
  * Check parent window. Rinse, wash, repeat.
  * If no rule could be found, allow.
  */
@@ -309,6 +310,9 @@ ACDeviceAllowed(WindowPtr win, DeviceIntPtr dev, xEvent* xE)
             return False;
     }
 
+    if (win->optional->access.defaultRule == WindowAccessAllowAll)
+        return True;
+
     return ACDeviceAllowed(win->parent, dev, xE);
 }
 
commit 088067c891a78670d9509f48f56bf3ff9c16a30d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Feb 18 16:46:07 2008 +1030

    Xi: even if ChangeDeviceHierarchy fails, we may need to send an event.
    
    Changes are committed instantly, so if at least one change was successful, we
    must send an event to the client, even if subsequent ones fail.

diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
index b749567..e9a5076 100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@ -84,6 +84,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
     int required_len = sizeof(xChangeDeviceHierarchyReq);
     char n;
     int rc;
+    int nchanges = 0;
     deviceHierarchyChangedEvent ev;
 
     REQUEST(xChangeDeviceHierarchyReq);
@@ -115,7 +116,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                     if (rc != Success)
                     {
                         xfree(name);
-                        return rc;
+                        goto unwind;
                     }
 
                     if (!c->sendCore)
@@ -130,6 +131,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                         EnableDevice(keybd);
                     }
                     xfree(name);
+                    nchanges++;
                 }
                 break;
             case CH_RemoveMasterDevice:
@@ -143,18 +145,22 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                     rc = dixLookupDevice(&ptr, r->deviceid, client,
                                          DixDestroyAccess);
                     if (rc != Success)
-                        return rc;
+                        goto unwind;
 
                     if (!ptr->isMaster)
                     {
                         client->errorValue = r->deviceid;
-                        return BadDevice;
+                        rc = BadDevice;
+                        goto unwind;
                     }
 
                     /* XXX: For now, don't allow removal of VCP, VCK */
                     if (ptr == inputInfo.pointer ||
                             ptr == inputInfo.keyboard)
-                        return BadDevice;
+                    {
+                        rc = BadDevice;
+                        goto unwind;
+                    }
 
                     /* disable keyboards first */
                     if (IsPointerDevice(ptr))
@@ -164,7 +170,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                                              client,
                                              DixDestroyAccess);
                         if (rc != Success)
-                            return rc;
+                            goto unwind;
                     }
                     else
                     {
@@ -174,7 +180,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                                              client,
                                              DixDestroyAccess);
                         if (rc != Success)
-                            return rc;
+                            goto unwind;
                     }
 
 
@@ -189,23 +195,25 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                         rc = dixLookupDevice(&newptr, r->returnPointer,
                                              client, DixWriteAccess);
                         if (rc != Success)
-                            return rc;
+                            goto unwind;
 
                         if (!newptr->isMaster)
                         {
                             client->errorValue = r->returnPointer;
-                            return BadDevice;
+                            rc = BadDevice;
+                            goto unwind;
                         }
 
                         rc = dixLookupDevice(&newkeybd, r->returnKeyboard,
                                              client, DixWriteAccess);
                         if (rc != Success)
-                            return rc;
+                            goto unwind;
 
                         if (!newkeybd->isMaster)
                         {
                             client->errorValue = r->returnKeyboard;
-                            return BadDevice;
+                            rc = BadDevice;
+                            goto unwind;
                         }
 
                         for (attached = inputInfo.devices;
@@ -229,6 +237,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
 
                     RemoveDevice(keybd);
                     RemoveDevice(ptr);
+                    nchanges++;
                 }
                 break;
             case CH_ChangeAttachment:
@@ -238,12 +247,13 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                     rc = dixLookupDevice(&ptr, c->deviceid, client,
                                           DixWriteAccess);
                     if (rc != Success)
-                        return rc;
+                       goto unwind;
 
                     if (ptr->isMaster)
                     {
                         client->errorValue = c->deviceid;
-                        return BadDevice;
+                        rc = BadDevice;
+                        goto unwind;
                     }
 
                     if (c->changeMode == Floating)
@@ -254,21 +264,25 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                         rc = dixLookupDevice(&newmaster, c->newMaster,
                                              client, DixWriteAccess);
                         if (rc != Success)
-                            return rc;
+                            goto unwind;
                         if (!newmaster->isMaster)
                         {
                             client->errorValue = c->newMaster;
-                            return BadDevice;
+                            rc = BadDevice;
+                            goto unwind;
                         }
 
                         if ((IsPointerDevice(newmaster) &&
                                     !IsPointerDevice(ptr)) ||
                                 (IsKeyboardDevice(newmaster) &&
                                  !IsKeyboardDevice(ptr)))
-                                return BadDevice;
+                        {
+                            rc = BadDevice;
+                            goto unwind;
+                        }
                         AttachDevice(client, ptr, newmaster);
                     }
-
+                    nchanges++;
                 }
                 break;
         }
@@ -276,14 +290,20 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
         any = (xAnyHierarchyChangeInfo*)((char*)any + any->length);
     }
 
-    ev.type = GenericEvent;
-    ev.extension = IReqCode;
-    ev.length = 0;
-    ev.evtype = XI_DeviceHierarchyChangedNotify;
-    ev.time = GetTimeInMillis();
+unwind:
 
-    SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask,
-            (xEvent*)&ev, 1);
-    return Success;
+    if (nchanges > 0) /* even if an error occured, we need to send an event if
+                       we changed anything in the hierarchy. */
+    {
+        ev.type = GenericEvent;
+        ev.extension = IReqCode;
+        ev.length = 0;
+        ev.evtype = XI_DeviceHierarchyChangedNotify;
+        ev.time = GetTimeInMillis();
+
+        SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask,
+                (xEvent*)&ev, 1);
+    }
+    return rc;
 }
 
commit 660739c6bc84cb74f43a277052ce163fae654417
Author: Benjamin Close <Benjamin.Close at clearchain.com>
Date:   Fri Feb 15 13:36:34 2008 +1030

    dix: Handle the case where a device cursor was removed correctly
    
    In the case that the device cursor was the first in the list of cursors
    the window knew about, unsetting the cursor could lead to a segfault
    due to pPrev being NULL. Instead catch the condition and correctly remove
    the node from the list. Since there is no cursor now set on the device,
    we simply return success as the parent windows cursor will propogate
    down later.
    
    Signed-off-by: Peter Hutterer <peter at cs.unisa.edu.au>

diff --git a/dix/window.c b/dix/window.c
index 3b69e45..a941dac 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -3823,8 +3823,14 @@ ChangeWindowDeviceCursor(WindowPtr pWin,
 
         if (!pCursor) /* remove from list */
         {
-            pPrev->next = pNode->next;
+                if(pPrev)
+                    pPrev->next = pNode->next;
+                else
+                    /* first item in list */
+                    pWin->optional->deviceCursors = pNode->next;
+
             xfree(pNode);
+            return Success;
         }
 
     } else
commit 24db28230120ecc2b65b25164b6e7b407970f9e2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Feb 18 16:16:19 2008 +1030

    dix: set num_events to 1 by default. (no RawDeviceEvents anymore)
    
    This should have been part of acb412d5399f865b5048fdd683147cea0f19f0c1.

diff --git a/dix/getevents.c b/dix/getevents.c
index ee58f02..1f8f0e0 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -657,7 +657,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     ms = GetTimeInMillis();
 
-    num_events = 2;
+    num_events = 1;
 
     master = pDev->u.master;
     if (master && master->u.lastSlave != pDev)
commit 921c298c4cdd2c879403ebdacbef48129058cad4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 14 09:48:19 2008 +1030

    Xi: QueryDevicePointer doesn't have a shared field anymore.

diff --git a/Xi/querydp.c b/Xi/querydp.c
index 629d8ef..3103346 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -113,7 +113,6 @@ ProcXQueryDevicePointer(ClientPtr client)
     rep.rootX = pSprite->hot.x;
     rep.rootY = pSprite->hot.y;
     rep.child = None;
-    rep.shared = (pDev->spriteInfo->spriteOwner) ? xFalse : xTrue;
 
     if (pSprite->hot.pScreen == pWin->drawable.pScreen)
     {
commit b885588756450e2fa25fdd191e300e1c5dd37ec3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 14 09:47:31 2008 +1030

    Xi: remove FakeDeviceData calls. And one leftover from GrabAccessControl.
    
    FakeDeviceData needs more thoughtful integration.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 0406638..7804c51 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -32,8 +32,6 @@ libXi_la_SOURCES =	\
         extgrbdev.c \
         extgrbdev.h \
 	extinit.c \
-	fakedevdata.c \
-	fakedevdata.h \
 	getbmap.c \
 	getbmap.h \
 	getcptr.c \
diff --git a/Xi/extinit.c b/Xi/extinit.c
index f8c9927..0cf429f 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -86,7 +86,6 @@ SOFTWARE.
 #include "closedev.h"
 #include "extgrbdev.h"
 #include "devbell.h"
-#include "fakedevdata.h"
 #include "getbmap.h"
 #include "getbmap.h"
 #include "getcptr.h"
@@ -338,8 +337,6 @@ 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 if (stuff->data == X_ExtendedGrabDevice)
         return ProcXExtendedGrabDevice(client);
     else {
@@ -451,8 +448,6 @@ 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 if (stuff->data == X_ExtendedGrabDevice)
         return SProcXExtendedGrabDevice(client);
     else {
@@ -530,9 +525,6 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
     else if (rep->RepType == X_QueryDevicePointer)
 	SRepXQueryDevicePointer(client, len,
 				(xQueryDevicePointerReply *) rep);
-    else if (rep->RepType == X_GrabAccessControl)
-        SRepXGrabAccessControl(client, len,
-                                  (xGrabAccessControlReply*) rep);
     else if (rep->RepType == X_QueryWindowAccess)
         SRepXQueryWindowAccess(client, len,
                                (xQueryWindowAccessReply*) rep);
diff --git a/Xi/fakedevdata.c b/Xi/fakedevdata.c
deleted file mode 100644
index 92ee8ee..0000000
--- a/Xi/fakedevdata.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-
-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 "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;
-    int rc;
-
-    REQUEST(xFakeDeviceDataReq);
-    REQUEST_AT_LEAST_SIZE(xFakeDeviceDataReq);
-
-    if (stuff->length != (sizeof(xFakeDeviceDataReq) >> 2) + stuff->num_valuators)
-    {
-        return BadLength;
-    }
-
-    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixWriteAccess);
-    if (rc != Success)
-        return rc;
-
-    if (!fake_events && !(fake_events = InitEventList(GetMaximumEventsNum())))
-    {
-        return BadAlloc;
-    }
-    if (stuff->num_valuators)
-    {
-        CARD32* valptr = (CARD32*)&stuff[1];
-
-        valuators = xcalloc(stuff->num_valuators, sizeof(int));
-        if (!valuators)
-        {
-            return BadAlloc;
-        }
-        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
deleted file mode 100644
index 28dd729..0000000
--- a/Xi/fakedevdata.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-
-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 */
commit c99a9a97290c51bf2843f42d5683888cea8a3ff6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 14 09:43:49 2008 +1030

    Xi: remove raw device events.
    
    Need to be better refined.

diff --git a/Xi/extinit.c b/Xi/extinit.c
index 9c42a5d..f8c9927 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -138,7 +138,6 @@ Mask ExtExclusiveMasks[EMASKSIZE];
 static Mask xi_filters[4] = {
     XI_DeviceHierarchyChangedMask,
     XI_DeviceClassesChangedMask,
-    XI_RawDeviceEventMask,
 };
 
 static struct dev_type
@@ -676,23 +675,6 @@ SDeviceLeaveNotifyEvent (deviceLeaveNotify *from, deviceLeaveNotify *to)
 }
 
 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);
-}
-
-static void
 SDeviceClassesChangedEvent(deviceClassesChangedEvent* from,
                            deviceClassesChangedEvent* to)
 {
@@ -1169,9 +1151,6 @@ XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
     swaps(&from->sequenceNumber, n);
     switch(from->evtype)
     {
-        case XI_RawDeviceEvent:
-            SRawDeviceEvent((rawDeviceEvent*)from, (rawDeviceEvent*)to);
-            break;
         case XI_DeviceClassesChangedNotify:
             SDeviceClassesChangedEvent((deviceClassesChangedEvent*)from,
                                        (deviceClassesChangedEvent*)to);
commit b35a9efa16d9e14378a95c11fa39171b78710996
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 14 09:41:49 2008 +1030

    Xi: Remove files for GrabAccessControl.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 9c5658d..0406638 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -56,8 +56,6 @@ libXi_la_SOURCES =	\
 	getselev.h \
 	getvers.c \
 	getvers.h \
-        grabacc.c \
-        grabacc.h \
 	grabdev.c \
 	grabdev.h \
 	grabdevb.c \
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 6aa1ece..9c42a5d 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -100,7 +100,6 @@ SOFTWARE.
 #include "getselev.h"
 #include "getvers.h"
 #include "getvers.h"
-#include "grabacc.h"
 #include "grabdev.h"
 #include "grabdevb.h"
 #include "grabdevk.h"
@@ -330,8 +329,6 @@ ProcIDispatch(ClientPtr client)
         return (ProcXChangeDeviceHierarchy(client));
     else if (stuff->data == X_XiSelectEvent)
         return (ProcXiSelectEvent(client));
-    else if (stuff->data == X_GrabAccessControl)
-        return (ProcXGrabAccessControl(client));
     else if (stuff->data == X_ChangeWindowAccess)
         return (ProcXChangeWindowAccess(client));
     else if (stuff->data == X_QueryWindowAccess)
@@ -445,8 +442,6 @@ SProcIDispatch(ClientPtr client)
         return (SProcXChangeDeviceHierarchy(client));
     else if (stuff->data == X_XiSelectEvent)
         return (SProcXiSelectEvent(client));
-    else if (stuff->data == X_GrabAccessControl)
-        return (SProcXGrabAccessControl(client));
     else if (stuff->data == X_ChangeWindowAccess)
         return (SProcXChangeWindowAccess(client));
     else if (stuff->data == X_QueryWindowAccess)
diff --git a/Xi/grabacc.c b/Xi/grabacc.c
deleted file mode 100644
index 83b8736..0000000
--- a/Xi/grabacc.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-
-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/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 "grabacc.h"
-
-/***********************************************************************
- *
- * This procedure allows a client to register as the global client to control
- * any window access.
- *
- */
-int
-SProcXGrabAccessControl(ClientPtr client)
-{
-    char n;
-    REQUEST(xGrabAccessControlReq);
-
-    swaps(&stuff->length, n);
-    return ProcXGrabAccessControl(client);
-}
-
-int
-ProcXGrabAccessControl(ClientPtr client)
-{
-    xGrabAccessControlReply rep;
-    REQUEST(xGrabAccessControlReq);
-    REQUEST_SIZE_MATCH(xGrabAccessControlReq);
-
-    if (stuff->ungrab)
-        ACUnregisterClient(client);
-
-    rep.repType = X_Reply;
-    rep.RepType = X_GrabAccessControl;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-    rep.success = stuff->ungrab || ACRegisterClient(client);
-
-    WriteReplyToClient(client, sizeof(xGrabAccessControlReply), &rep);
-    return Success;
-}
-
-/***********************************************************************
- *
- * This procedure writes the reply for the XGrabAccessControl function,
- * if the client and server have a different byte ordering.
- *
- */
-
-void
-SRepXGrabAccessControl(ClientPtr client, int size,
-        xGrabAccessControlReply* rep)
-{
-    char n;
-
-    swaps(&rep->sequenceNumber, n);
-    swapl(&rep->length, n);
-    WriteToClient(client, size, (char *)rep);
-}
-
diff --git a/Xi/grabacc.h b/Xi/grabacc.h
deleted file mode 100644
index 6dcbcad..0000000
--- a/Xi/grabacc.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-
-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 GRABACC_H
-#define GRABACC_H 1
-
-int SProcXGrabAccessControl(ClientPtr /* client */);
-
-int ProcXGrabAccessControl(ClientPtr /* client */);
-void SRepXGrabAccessControl(ClientPtr client, int size, 
-        xGrabAccessControlReply* rep);
-#endif /* GRABACC_H */
commit b81c330f70c4a4c8f37216aa4856c7f8db93a375
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 14 09:32:54 2008 +1030

    mi: remove RawDeviceEvent's ID changing.

diff --git a/mi/mieq.c b/mi/mieq.c
index a1a434a..a15b24f 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -246,11 +246,7 @@ ChangeDeviceID(DeviceIntPtr dev, xEvent* event)
     else if (type == GenericEvent)
     {
         /* FIXME: need to put something into XGE to make this saner */
-        if (GEIsType(event, IReqCode, XI_RawDeviceEvent))
-        {
-            rawDeviceEvent* raw = (rawDeviceEvent*)event;
-            raw->deviceid = dev->id;
-        } else if (GEIsType(event, IReqCode, XI_DeviceClassesChangedNotify))
+        if (GEIsType(event, IReqCode, XI_DeviceClassesChangedNotify))
         {
             // do nothing or drink a beer. your choice.
         } else
commit acb412d5399f865b5048fdd683147cea0f19f0c1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 14 09:27:51 2008 +1030

    dix: Don't generate RawDeviceEvents anymore.
    
    These events have been removed from the protocol pending some more refinement
    and more thoughtful integration.

diff --git a/dix/getevents.c b/dix/getevents.c
index b704371..ee58f02 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -258,9 +258,9 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
  */
 _X_EXPORT int
 GetMaximumEventsNum(void) {
-    /* Three base events -- raw event and device, plus valuator events.
+    /* One base event -- device, plus valuator events.
      *  Multiply by two if we're doing non-XKB key repeats. */
-    int ret = 2 + MAX_VALUATOR_EVENTS;
+    int ret = 1 + MAX_VALUATOR_EVENTS;
 
 #ifdef XKB
     if (noXkbExtension)
@@ -628,11 +628,9 @@ _X_EXPORT int
 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, i;
+    int num_events = 0, final_valuator = 0;
     CARD32 ms = 0;
-    CARD32* valptr;
     deviceKeyButtonPointer *kbp = NULL;
-    rawDeviceEvent* ev;
     DeviceIntPtr master;
 
     /* Thanks to a broken lib, we _always_ have to chase DeviceMotionNotifies
@@ -687,35 +685,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes)
         return 0;
 
-    /* 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->event_type = type;
-    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++;
-
     /* Set x and y based on whether this is absolute or relative, and
      * accelerate if we need to. */
     if (flags & POINTER_ABSOLUTE) {
commit 0b0a09797302ac2171db5df20fc5110aafc8efbb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 7 15:48:04 2008 +1030

    xkb: when copying the keymap, make sure the structs default to 0/NULL.
    
    It actually does help if a pointer is NULL rather than pointing to nirvana
    when you're trying to free it lateron. Who would have thought?
    (cherry picked from commit 7a97ca667405a42d008265c3a870210cc1da97dd)

diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index 740bc7d..91aee18 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -1733,9 +1733,8 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
         else {
             if (dst->geom->sz_shapes) {
                 xfree(dst->geom->shapes);
-                dst->geom->shapes = NULL;
             }
-            
+            dst->geom->shapes = NULL;
             dst->geom->num_shapes = 0;
             dst->geom->sz_shapes = 0;
         }
@@ -1784,6 +1783,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
             }
 
             dst->geom->num_sections = 0;
+            dst->geom->sections = NULL;
         }
 
         if (src->geom->num_sections) {
@@ -1795,6 +1795,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
                 tmp = xalloc(src->geom->num_sections * sizeof(XkbSectionRec));
             if (!tmp)
                 return FALSE;
+            memset(tmp, 0, src->geom->num_sections * sizeof(XkbSectionRec));
             dst->geom->sections = tmp;
             dst->geom->num_sections = src->geom->num_sections;
 
@@ -1831,6 +1832,10 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
                         return FALSE;
                     dsection->doodads = tmp;
                 }
+                else {
+                    dsection->doodads = NULL;
+                }
+
                 for (k = 0,
                       sdoodad = ssection->doodads,
                       ddoodad = dsection->doodads;
@@ -1858,9 +1863,9 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
         else {
             if (dst->geom->sz_sections) {
                 xfree(dst->geom->sections);
-                dst->geom->sections = NULL;
             }
 
+            dst->geom->sections = NULL;
             dst->geom->num_sections = 0;
             dst->geom->sz_sections = 0;
         }
@@ -1889,6 +1894,8 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
                     }
                 }
             }
+            dst->geom->num_doodads = 0;
+            dst->geom->doodads = NULL;
         }
 
         if (src->geom->num_doodads) {
@@ -1901,7 +1908,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
                               sizeof(XkbDoodadRec));
             if (!tmp)
                 return FALSE;
-            bzero(tmp, src->geom->num_doodads * sizeof(XkbDoodadRec));
+            memset(tmp, 0, src->geom->num_doodads * sizeof(XkbDoodadRec));
             dst->geom->doodads = tmp;
 
             dst->geom->sz_doodads = src->geom->num_doodads;
@@ -1930,9 +1937,9 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
         else {
             if (dst->geom->sz_doodads) {
                 xfree(dst->geom->doodads);
-                dst->geom->doodads = NULL;
             }
 
+            dst->geom->doodads = NULL;
             dst->geom->num_doodads = 0;
             dst->geom->sz_doodads = 0;
         }
@@ -1960,10 +1967,10 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
             dst->geom->num_key_aliases = dst->geom->sz_key_aliases;
         }
         else {
-            if (dst->geom->sz_key_aliases && dst->geom->key_aliases) {
+            if (dst->geom->key_aliases) {
                 xfree(dst->geom->key_aliases);
-                dst->geom->key_aliases = NULL;
             }
+            dst->geom->key_aliases = NULL;
             dst->geom->num_key_aliases = 0;
             dst->geom->sz_key_aliases = 0;
         }
@@ -1994,8 +2001,8 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
         else {
             if (dst->geom->label_font) {
                 xfree(dst->geom->label_font);
-                dst->geom->label_font = NULL;
             }
+            dst->geom->label_font = NULL;
             dst->geom->label_color = NULL;
             dst->geom->base_color = NULL;
         }
commit 9d5edebe9664f4ac35b82830e000a72d5ca9cbe4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 7 21:22:50 2008 +1030

    Xi: finish XKB initialisation before copying the keymap.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index faf391f..46ee66d 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -184,7 +184,10 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
 #ifdef XKB
         if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) {
             if (!mk->xkbInfo || !mk->xkbInfo->desc)
+            {
                 XkbInitDevice(master);
+                XkbFinishDeviceInit(master);
+            }
             if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True))
                 FatalError("Couldn't pivot keymap from device to core!\n");
         }
commit 96eafa3d4f05997dac8be6a8d66a92410511824c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Feb 5 16:01:56 2008 +1030

    xkb: when copying sections, make sure num_rows is set too.
    (cherry picked from commit 41991fb991313202e8e6b513fe928ba14f8fcb87)

diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index 68ecb32..740bc7d 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -1809,6 +1809,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
                         return FALSE;
                     dsection->rows = tmp;
                 }
+                dsection->num_rows = ssection->num_rows;
                 for (j = 0, srow = ssection->rows, drow = dsection->rows;
                      j < ssection->num_rows;
                      j++, srow++, drow++) {
commit e5e531ce96264518f278f572a4d0bfcd345aa618
Merge: 6c38682... 1692dcf...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 31 16:36:17 2008 +1030

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	dix/events.c

commit 6c38682084e24b18bac0ea75729b1183aeb01600
Author: Benjamin Tissoires <tissoire at cena.fr>
Date:   Thu Jan 31 15:51:32 2008 +1030

    kdrive: AddInputClient takes a ClientPtr.

diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index c7c10e4..5b1dc5c 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -1015,7 +1015,7 @@ KdAddKeyboard (KdKeyboardInfo *ki)
     if (!ki)
         return !Success;
     
-    ki->dixdev = AddInputDevice(KdKeyboardProc, TRUE);
+    ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE);
     if (!ki->dixdev) {
         ErrorF("Couldn't register keyboard device %s\n",
                ki->name ? ki->name : "(unnamed)");
@@ -1084,7 +1084,7 @@ KdAddPointer (KdPointerInfo *pi)
     pi->mouseState = start;
     pi->eventHeld = FALSE;
 
-    pi->dixdev = AddInputDevice(KdPointerProc, TRUE);
+    pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE);
     if (!pi->dixdev) {
         ErrorF("Couldn't add pointer device %s\n",
                pi->name ? pi->name : "(unnamed)");
commit 0ac175597712edfeae676f536746a4d26d625e30
Merge: 210eeef... e915a26...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Jan 26 13:55:07 2008 +1030

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	Xext/sampleEVI.c

diff --cc Xext/sampleEVI.c
index 5dd6e45,b871bfd..a389efe
--- a/Xext/sampleEVI.c
+++ b/Xext/sampleEVI.c
@@@ -42,14 -49,16 +49,16 @@@ static int sampleGetVisualInfo
      VisualID32 **conflict_rn,
      int *n_conflict_rn)
  {
-     int max_sz_evi = n_visual * sz_xExtendedVisualInfo * screenInfo.numScreens;
+     unsigned int max_sz_evi;
      VisualID32 *temp_conflict;
      xExtendedVisualInfo *evi;
-     int max_visuals = 0, max_sz_conflict, sz_conflict = 0;
-     int visualI, scrI, sz_evi = 0, conflictI, n_conflict;
-     *evi_rn = evi = (xExtendedVisualInfo *)xalloc(max_sz_evi);
-     if (!*evi_rn)
-          return BadAlloc;
+     unsigned int max_visuals = 0, max_sz_conflict, sz_conflict = 0;
+     register int visualI, scrI, sz_evi = 0, conflictI, n_conflict;
+ 
+     if (n_visual > UINT32_MAX/(sz_xExtendedVisualInfo * screenInfo.numScreens))
+ 	return BadAlloc;
+     max_sz_evi = n_visual * sz_xExtendedVisualInfo * screenInfo.numScreens;
 -    
++
      for (scrI = 0; scrI < screenInfo.numScreens; scrI++) {
          if (screenInfo.screens[scrI]->numVisuals > max_visuals)
              max_visuals = screenInfo.screens[scrI]->numVisuals;
diff --cc Xext/shm.c
index 1ee3bd1,a7a1ecf..3e40713
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@@ -1083,9 -1100,11 +1100,11 @@@ ProcShmCreatePixmap(client
      PixmapPtr pMap;
      DrawablePtr pDraw;
      DepthPtr pDepth;
 -    register int i, rc;
 +    int i, rc;
      ShmDescPtr shmdesc;
      REQUEST(xShmCreatePixmapReq);
+     unsigned int width, height, depth;
+     unsigned long size;
  
      REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
      client->errorValue = stuff->pid;
commit 210eeef495770c1883c842ff003c28ce25f279d4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Jan 26 09:39:54 2008 +1030

    config: don't reset connection info on disconnect.
    
    If dbus is restarted, we try to connect again and this is difficult if the
    busname and/or busobject is not set.

diff --git a/config/dbus.c b/config/dbus.c
index f6ac4c1..0be42af 100644
--- a/config/dbus.c
+++ b/config/dbus.c
@@ -396,9 +396,6 @@ err_start:
 static void
 disconnect_hook(void *data)
 {
-    struct connection_info *info = data;
-
-    reset_info(info);
 }
 
 #if 0
@@ -440,4 +437,6 @@ void
 config_dbus_fini(void)
 {
     config_dbus_core_remove_hook(&core_hook);
+    connection_data.busname[0] = '\0';
+    connection_data.busobject[0] = '\0';
 }
commit d23266522390a4ef7203ae7c062b2b920e45f9d7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 25 13:54:47 2008 +1030

    config: check connection != NULL before getting dbus' dispatch status.

diff --git a/config/dbus-core.c b/config/dbus-core.c
index 9cf1530..b349c6e 100644
--- a/config/dbus-core.c
+++ b/config/dbus-core.c
@@ -56,8 +56,9 @@ wakeup_handler(pointer data, int err, pointer read_mask)
     if (info->connection && FD_ISSET(info->fd, (fd_set *) read_mask)) {
         do {
             dbus_connection_read_write_dispatch(info->connection, 0);
-        } while (dbus_connection_get_dispatch_status(info->connection) ==
-                  DBUS_DISPATCH_DATA_REMAINS);
+        } while (info->connection &&
+                 dbus_connection_get_is_connected(info->connection) &&
+                 dbus_connection_get_dispatch_status(info->connection) == DBUS_DISPATCH_DATA_REMAINS);
     }
 }
 
commit fb07fab2c07e7b0834724541dc47bfba02ba8574
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 25 13:45:22 2008 +1030

    config: only shutdown libhal if the connection is valid.
    
    Thanks to libdbus' extensive use of assert we won't just get an error, it'll
    bring the whole server down for us.

diff --git a/config/hal.c b/config/hal.c
index 52a0113..1575422 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -283,12 +283,14 @@ disconnect_hook(void *data)
     struct config_hal_info *info = data;
 
     if (info->hal_ctx) {
-        dbus_error_init(&error);
-        if (!libhal_ctx_shutdown(info->hal_ctx, &error))
-            DebugF("[config/hal] couldn't shut down context: %s (%s)\n",
-                   error.name, error.message);
+        if (dbus_connection_get_is_connected(info->system_bus)) {
+            dbus_error_init(&error);
+            if (!libhal_ctx_shutdown(info->hal_ctx, &error))
+                DebugF("[config/hal] couldn't shut down context: %s (%s)\n",
+                        error.name, error.message);
+            dbus_error_free(&error);
+        }
         libhal_ctx_free(info->hal_ctx);
-        dbus_error_free(&error);
     }
 
     info->hal_ctx = NULL;
commit 7732898aaa70e076000f6e6aa9420482896ed996
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 25 11:48:13 2008 +1030

    config: add a debug message, fix a whitespace error.

diff --git a/config/hal.c b/config/hal.c
index 4ab2961..52a0113 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -105,7 +105,7 @@ get_prop_string(LibHalContext *hal_ctx, const char *udi, const char *name)
     char *prop, *ret;
 
     prop = libhal_device_get_property_string(hal_ctx, udi, name, NULL);
-    DebugF(" [config/hal] getting %s on %s returned %s\n", name, udi, prop);
+    DebugF("[config/hal] getting %s on %s returned %s\n", name, udi, prop);
     if (prop) {
         ret = xstrdup(prop);
         libhal_free_string(prop);
@@ -234,8 +234,9 @@ device_added(LibHalContext *hal_ctx, const char *udi)
     if (xkb_options)
         add_option(&options, "xkb_options", xkb_options);
 
+    DebugF("[config/hal] Adding device %s\n", name);
     if (NewInputDeviceRequest(options, &dev) != Success) {
-        DebugF("[config/hal] NewInputDeviceRequest failed\n");
+        ErrorF("[config/hal] NewInputDeviceRequest failed\n");
         dev = NULL;
         goto unwind;
     }
commit 466f6552190d1b83d66ebfd71e07921ed6210ee2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Jan 23 16:11:31 2008 +1030

    Xi: if deviceid is > 127 assume GE mask is for all devices (XiSelectEvent).

diff --git a/Xi/xiselev.c b/Xi/xiselev.c
index f24dd36..2bfbd82 100644
--- a/Xi/xiselev.c
+++ b/Xi/xiselev.c
@@ -69,9 +69,13 @@ ProcXiSelectEvent(ClientPtr client)
     if (rc != Success)
         return rc;
 
-    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
-    if (rc != Success)
-        return rc;
+    if (stuff->deviceid & (0x1 << 7)) /* all devices */
+        pDev = NULL;
+    else {
+        rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
+        if (rc != Success)
+            return rc;
+    }
 
     GEWindowSetMask(client, pDev, pWin, IReqCode, stuff->mask);
 
commit 379f057646588fa3211d7ba0ec8d77d2fc0ad246
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Jan 23 16:08:37 2008 +1030

    Xext: add GEDeviceMaskIsSet (GE mask checking per device)
    
    If a mask was set for the NULL device, then we pretend the mask is set for all
    devices.

diff --git a/Xext/geext.c b/Xext/geext.c
index 0127a05..77bb181 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -378,4 +378,38 @@ void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
     GERecalculateWinMask(pWin);
 }
 
+/**
+ * Return TRUE if the mask for the given device is set.
+ * @param pWin Window the event may be delivered to.
+ * @param pDev Device the device originating the event. May be NULL.
+ * @param extension Extension ID
+ * @param mask Event mask
+ */
+BOOL GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev,
+                       int extension, Mask mask)
+{
+    GenericMaskPtr gemask;
+
+    if (!pWin->optional || !pWin->optional->geMasks)
+        return FALSE;
+
+    extension &= 0x7F;
+
+    if (!pWin->optional->geMasks->eventMasks[extension] & mask)
+        return FALSE;
+
+
+    gemask = pWin->optional->geMasks->geClients;
+
+    while(gemask)
+    {
+        if ((!gemask->dev || gemask->dev == pDev) && 
+                (gemask->eventMask[extension] & mask))
+            return TRUE;
+
+        gemask = gemask->next;
+    }
+
+    return FALSE;
+}
 
diff --git a/Xext/geext.h b/Xext/geext.h
index a902127..577654a 100644
--- a/Xext/geext.h
+++ b/Xext/geext.h
@@ -106,7 +106,8 @@ void GERegisterExtension(
         );
 
 void GEInitEvent(xGenericEvent* ev, int extension);
-
+BOOL GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev, 
+                       int extension, Mask mask);
 
 void GEExtensionInit(void);
 
diff --git a/dix/events.c b/dix/events.c
index f955d81..2928554 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2151,7 +2151,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 
             /* 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))
+            if (!GEDeviceMaskIsSet(pWin, pDev, GEEXT(pEvents), filter))
                 return 0;
 
             /* run through all clients, deliver event */
@@ -2471,7 +2471,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
 
         while(win)
         {
-            if (GEMaskIsSet(win, GEEXT(xE), filter))
+            if (GEDeviceMaskIsSet(win, dev, GEEXT(xE), filter))
             {
                 if (GEExtensions[GEEXTIDX(xE)].evfill)
                     GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, win, grab);
commit 91dc8c43d2343e494c59023484883f4683bdc639
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Jan 23 15:45:02 2008 +1030

    Xi: Change window access right check to RecieveAccess in XiSelectEvent.

diff --git a/Xi/xiselev.c b/Xi/xiselev.c
index 601b10c..f24dd36 100644
--- a/Xi/xiselev.c
+++ b/Xi/xiselev.c
@@ -65,7 +65,7 @@ ProcXiSelectEvent(ClientPtr client)
     REQUEST(xXiSelectEventReq);
     REQUEST_SIZE_MATCH(xXiSelectEventReq);
 
-    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
+    rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess);
     if (rc != Success)
         return rc;
 
commit 94a6a65ae7414c8247aa1741ec5c7561e6f4bbe0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Jan 23 15:43:48 2008 +1030

    Xext: allow per-device GE masks.
    
    Instead of a single mask per client we allow the storage of a mask per client
    per device.

diff --git a/Xext/geext.c b/Xext/geext.c
index 8f48e44..0127a05 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -300,7 +300,8 @@ GERecalculateWinMask(WindowPtr pWin)
 }
 
 /* Set generic event mask for given window. */
-void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask)
+void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev, 
+                     WindowPtr pWin, int extension, Mask mask)
 {
     GenericMaskPtr cli;
 
@@ -326,13 +327,13 @@ void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask
         cli = evmasks->geClients;
         while(cli)
         {
-            if (cli->client == pClient)
+            if (cli->client == pClient && cli->dev == pDev)
                 break;
             cli = cli->next;
         }
         if (!cli)
         {
-            /* new client */
+            /* new client and/or new device */
             cli  = (GenericMaskPtr)xcalloc(1, sizeof(GenericMaskRec));
             if (!cli)
             {
@@ -341,6 +342,7 @@ void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask
             }
             cli->next = evmasks->geClients;
             cli->client = pClient;
+            cli->dev = pDev;
             evmasks->geClients = cli;
         }
         cli->eventMask[extension] = mask;
@@ -348,7 +350,7 @@ void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask
     {
         /* remove client. */
         cli = pWin->optional->geMasks->geClients;
-        if (cli->client == pClient)
+        if (cli->client == pClient && cli->dev == pDev)
         {
             pWin->optional->geMasks->geClients = cli->next;
             xfree(cli);
@@ -359,7 +361,7 @@ void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask
 
             while(cli)
             {
-                if (cli->client == pClient)
+                if (cli->client == pClient && cli->dev == pDev)
                 {
                     prev->next = cli->next;
                     xfree(cli);
diff --git a/Xext/geext.h b/Xext/geext.h
index 1ba71e0..a902127 100644
--- a/Xext/geext.h
+++ b/Xext/geext.h
@@ -39,12 +39,13 @@ from the author.
  * This struct is used both in the window and by grabs to determine the event
  * mask for a client.
  * A window will have a linked list of these structs, with one entry per
- * client, null-terminated.
+ * client per device, null-terminated.
  * A grab has only one instance of this struct.
  */
 typedef struct _GenericMaskRec {
-    ClientPtr   client;                   /* client who set the event mask */
-    Mask        eventMask[MAXEXTENSIONS]; /* one mask per extension */
+    ClientPtr       client;                /* client who set the event mask */
+    DeviceIntPtr    dev;
+    Mask            eventMask[MAXEXTENSIONS]; /* one mask per extension */
     struct _GenericMaskRec* next;            
 } GenericMaskRec, *GenericMaskPtr;
 
@@ -94,7 +95,9 @@ extern GEExtension GEExtensions[MAXEXTENSIONS];
 
 
 /* Interface for other extensions */
-void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask);
+void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev,
+                     WindowPtr pWin, int extension, Mask mask);
+
 void GERegisterExtension(
         int extension,
         void (*ev_dispatch)(xGenericEvent* from, xGenericEvent* to),
diff --git a/Xi/xiselev.c b/Xi/xiselev.c
index 3c85032..601b10c 100644
--- a/Xi/xiselev.c
+++ b/Xi/xiselev.c
@@ -61,16 +61,19 @@ ProcXiSelectEvent(ClientPtr client)
 {
     int rc;
     WindowPtr pWin;
+    DeviceIntPtr pDev;
     REQUEST(xXiSelectEventReq);
     REQUEST_SIZE_MATCH(xXiSelectEventReq);
 
     rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
     if (rc != Success)
-    {
         return rc;
-    }
 
-    GEWindowSetMask(client, pWin, IReqCode, stuff->mask);
+    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
+    if (rc != Success)
+        return rc;
+
+    GEWindowSetMask(client, pDev, pWin, IReqCode, stuff->mask);
 
     return Success;
 }
commit ba315ae5ddd00763147a4b0cdcacba7691793dfc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jan 21 23:43:53 2008 +1030

    Xi: add XACE hooks for device creation (ChangeDeviceHierarchy)
    
    AddInputDevice checks for permissions already, so all we do is modify a few
    callers to let AID sort it out.

diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
index 65ff387..b749567 100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@ -52,6 +52,7 @@ from the author.
 #include "exevents.h"
 #include "exglobals.h"
 #include "geext.h"
+#include "xace.h"
 
 #include "chdevhier.h"
 
@@ -104,20 +105,17 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                 {
                     xCreateMasterInfo* c = (xCreateMasterInfo*)any;
                     char* name;
-                    int ret;
-
-                    /* XXX: check for creation permission */
 
                     SWAPIF(swaps(&c->namelen, n));
                     name = xcalloc(c->namelen + 1, sizeof(char));
                     strncpy(name, (char*)&c[1], c->namelen);
 
 
-                    ret = AllocMasterDevice(name, &ptr, &keybd);
-                    if (ret != Success)
+                    rc = AllocMasterDevice(client, name, &ptr, &keybd);
+                    if (rc != Success)
                     {
                         xfree(name);
-                        return ret;
+                        return rc;
                     }
 
                     if (!c->sendCore)
diff --git a/dix/devices.c b/dix/devices.c
index e78c1e7..0ffc798 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -100,7 +100,7 @@ DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey;
  * @return The newly created device.
  */
 DeviceIntPtr
-AddInputDevice(DeviceProc deviceProc, Bool autoStart)
+AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
 {
     DeviceIntPtr dev, *prev; /* not a typo */
     DeviceIntPtr devtmp;
@@ -562,9 +562,9 @@ CorePointerProc(DeviceIntPtr pDev, int what)
 void
 InitCoreDevices(void)
 {
-    if (AllocMasterDevice("Virtual core",
+    if (AllocMasterDevice(serverClient, "Virtual core",
                           &inputInfo.pointer,
-                          &inputInfo.keyboard) == BadAlloc)
+                          &inputInfo.keyboard) != Success)
         FatalError("Failed to allocate core devices");
 }
 
@@ -2597,13 +2597,13 @@ NextFreePointerDevice()
  * EnableDevice() manually.
  */
 int
-AllocMasterDevice(char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
+AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
 {
     DeviceIntPtr pointer;
     DeviceIntPtr keyboard;
     *ptr = *keybd = NULL;
 
-    pointer = AddInputDevice(CorePointerProc, TRUE);
+    pointer = AddInputDevice(client, CorePointerProc, TRUE);
     if (!pointer)
         return BadAlloc;
 
@@ -2628,7 +2628,7 @@ AllocMasterDevice(char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
     pointer->u.lastSlave = NULL;
     pointer->isMaster = TRUE;
 
-    keyboard = AddInputDevice(CoreKeyboardProc, TRUE);
+    keyboard = AddInputDevice(client, CoreKeyboardProc, TRUE);
     if (!keyboard)
         return BadAlloc;
 
diff --git a/hw/vfb/InitInput.c b/hw/vfb/InitInput.c
index 99cf56c..393698f 100644
--- a/hw/vfb/InitInput.c
+++ b/hw/vfb/InitInput.c
@@ -318,8 +318,8 @@ void
 InitInput(int argc, char *argv[])
 {
     DeviceIntPtr p, k;
-    p = AddInputDevice(vfbMouseProc, TRUE);
-    k = AddInputDevice(vfbKeybdProc, TRUE);
+    p = AddInputDevice(serverClient, vfbMouseProc, TRUE);
+    k = AddInputDevice(serverClient, vfbKeybdProc, TRUE);
     RegisterPointerDevice(p);
     RegisterKeyboardDevice(k);
     (void)mieqInit();
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 92298e1..a3b19e9 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -158,7 +158,7 @@ xf86ActivateDevice(LocalDevicePtr local)
     DeviceIntPtr	dev;
 
     if (local->flags & XI86_CONFIGURED) {
-        dev = AddInputDevice(local->device_control, TRUE);
+        dev = AddInputDevice(serverClient, local->device_control, TRUE);
 
         if (dev == NULL)
             FatalError("Too many input devices");
diff --git a/hw/xnest/Init.c b/hw/xnest/Init.c
index 7b344e2..de80cb5 100644
--- a/hw/xnest/Init.c
+++ b/hw/xnest/Init.c
@@ -89,8 +89,8 @@ InitOutput(ScreenInfo *screenInfo, int argc, char *argv[])
 void
 InitInput(int argc, char *argv[])
 {
-  xnestPointerDevice = AddInputDevice(xnestPointerProc, TRUE);
-  xnestKeyboardDevice = AddInputDevice(xnestKeyboardProc, TRUE);
+  xnestPointerDevice = AddInputDevice(serverClient, xnestPointerProc, TRUE);
+  xnestKeyboardDevice = AddInputDevice(serverClient, xnestKeyboardProc, TRUE);
 
   if (!xnestEvents)
       xnestEvents = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum());
diff --git a/include/input.h b/include/input.h
index da02aea..1863676 100644
--- a/include/input.h
+++ b/include/input.h
@@ -180,6 +180,7 @@ typedef struct _InputOption {
 extern void InitCoreDevices(void);
 
 extern DeviceIntPtr AddInputDevice(
+    ClientPtr /*client*/,
     DeviceProc /*deviceProc*/,
     Bool /*autoStart*/);
 
@@ -471,7 +472,8 @@ extern Bool RegisterPairingClient(ClientPtr client);
 extern DeviceIntPtr GuessFreePointerDevice(void);
 extern DeviceIntPtr NextFreePointerDevice(void);
 
-extern int AllocMasterDevice(char* name,
+extern int AllocMasterDevice(ClientPtr client,
+                             char* name,
                              DeviceIntPtr* ptr,
                              DeviceIntPtr* keybd);
 extern void DeepCopyDeviceClasses(DeviceIntPtr from,
diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c
index 2877af0..55ce12a 100644
--- a/xkb/xkbLEDs.c
+++ b/xkb/xkbLEDs.c
@@ -63,6 +63,9 @@ XkbSrvLedInfoPtr	sli;
 
     sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
 
+    if (!sli)
+        return update;
+
     if (state_changes&(XkbModifierStateMask|XkbGroupStateMask))
 	update|= sli->usesEffective;
     if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask))
commit 6492d513c0022d70f838d1b2561442c7a41e401f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 18 21:44:22 2008 +1030

    dix: if a client has a core grab, return the grab device on QueryPointer.
    
    The correct thing would be to return the ClientPointer. However, if the client
    for some reason has a core grab on another device (e.g. as result of a passive
    grab), return the coordinates of the grabbed device instead.
    
    This makes the use of nautilus a bit saner.

diff --git a/dix/events.c b/dix/events.c
index f4925e4..f955d81 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5595,7 +5595,8 @@ ProcQueryPointer(ClientPtr client)
     xQueryPointerReply rep;
     WindowPtr pWin, t;
     DeviceIntPtr mouse = PickPointer(client);
-    SpritePtr pSprite = mouse->spriteInfo->sprite;
+    DeviceIntPtr dev;
+    SpritePtr pSprite;
     int rc;
     REQUEST(xResourceReq);
     REQUEST_SIZE_MATCH(xResourceReq);
@@ -5607,6 +5608,19 @@ ProcQueryPointer(ClientPtr client)
     if (rc != Success)
 	return rc;
 
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+    {
+        if (dev->isMaster && IsPointerDevice(dev) &&
+                dev->deviceGrab.grab && dev->deviceGrab.grab->coreGrab &&
+                SameClient(dev->deviceGrab.grab, client))
+        {
+            /* special case, we have a grab on the device so we need to return
+             * this one */
+            mouse = dev;
+        }
+    }
+
+    pSprite = mouse->spriteInfo->sprite;
     if (mouse->valuator->motionHintWindow)
 	MaybeStopHint(mouse, client);
     rep.type = X_Reply;
commit cd2ad4c2ed58b49cee085174e77c242048159321
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 18 20:11:55 2008 +1030

    dix: remove some superfluous lines in ProcChangeActivePointerGrab.

diff --git a/dix/events.c b/dix/events.c
index de68b57..f4925e4 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5265,16 +5265,11 @@ ProcChangeActivePointerGrab(ClientPtr client)
                 if (grab && grab->coreGrab && SameClient(grab, client))
                 {
                     device = grabbed;
+                    grab = device->deviceGrab.grab;
                     break;
                 }
             }
         }
-        /* nope. no grab on any actual device */
-        if (!grabbed)
-        {
-            device = inputInfo.pointer;
-            grab = inputInfo.pointer->deviceGrab.grab;
-        }
     }
 
     if (!grab)
commit 8a925d201efac52ef663ea3ff46acc5046178666
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 18 20:06:29 2008 +1030

    dix: free the genericMasks when ungrabbing.
    
    This finally plugs a memory hole created by grabs registering for generic
    events.

diff --git a/dix/events.c b/dix/events.c
index c3697da..de68b57 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1627,6 +1627,14 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
     mouse->deviceGrab.grab = NullGrab;
     mouse->deviceGrab.sync.state = NOT_GRABBED;
     mouse->deviceGrab.fromPassiveGrab = FALSE;
+
+    /* make sure the potential XGE event mask is freed too*/
+    if (grab->genericMasks)
+    {
+        xfree(grab->genericMasks);
+        grab->genericMasks = NULL;
+    }
+
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
 	if (dev->deviceGrab.sync.other == grab)
@@ -1704,6 +1712,12 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
     keybd->deviceGrab.grab = NullGrab;
     keybd->deviceGrab.sync.state = NOT_GRABBED;
     keybd->deviceGrab.fromPassiveGrab = FALSE;
+    if (grab->genericMasks)
+    {
+        xfree(grab->genericMasks);
+        grab->genericMasks = NULL;
+    }
+
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
 	if (dev->deviceGrab.sync.other == grab)
@@ -2226,9 +2240,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
         inputMasks = wOtherInputMasks(pWin);
         tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
 
-        /* get the XGE event mask.
-         * FIXME: needs to be freed somewhere too.
-         */
+        /* get the XGE event mask. */
         tempGrab.genericMasks = NULL;
         if (pWin->optional && pWin->optional->geMasks)
         {
commit 8949d81a3c79eef351d7c018c76692dcca74b63e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 18 19:45:54 2008 +1030

    include: mark CoreProcessPointerEvent, CoreProcessKeyboardEvent as deprecated.
    
    ProcessOtherEvent does all the work now.

diff --git a/include/input.h b/include/input.h
index 6384716..da02aea 100644
--- a/include/input.h
+++ b/include/input.h
@@ -375,12 +375,12 @@ extern void ProcessKeyboardEvent(
 extern void CoreProcessPointerEvent(
     xEventPtr /*xE*/,
     DeviceIntPtr /*mouse*/,
-    int /*count*/);
+    int /*count*/) _X_DEPRECATED;
 
-extern void CoreProcessKeyboardEvent(
+extern _X_DEPRECATED void CoreProcessKeyboardEvent(
     xEventPtr /*xE*/,
     DeviceIntPtr /*keybd*/,
-    int /*count*/);
+    int /*count*/) _X_DEPRECATED;
 #endif
 
 extern Bool LegalModifier(
commit d323fd64206ddb4221daa7cf7504daf62c5e7d90
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 18 19:17:42 2008 +1030

    dix: remove inputInfo.pointer refernce in EventSelectForWindow
    
    If the window being changed is set as the motion hint window for any device,
    the device's motion hint window is set to NULL. Which is kinda what the old
    code did, except that it did it with only the VCP.

diff --git a/dix/events.c b/dix/events.c
index c91e73b..c3697da 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4202,6 +4202,7 @@ EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
 {
     Mask check;
     OtherClients * others;
+    DeviceIntPtr dev;
     int rc;
 
     if (mask & ~AllEventMasks)
@@ -4268,11 +4269,14 @@ EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
 	    return BadAlloc;
     }
 maskSet:
-    if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
-	(mask & PointerMotionHintMask) &&
-	!(check & PointerMotionHintMask) &&
-	!inputInfo.pointer->deviceGrab.grab) /* VCP shouldn't have deviceGrab */
-	inputInfo.pointer->valuator->motionHintWindow = NullWindow;
+    if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
+    {
+        for (dev = inputInfo.devices; dev; dev = dev->next)
+        {
+            if (dev->valuator && dev->valuator->motionHintWindow == pWin)
+                dev->valuator->motionHintWindow = NullWindow;
+        }
+    }
     RecalculateDeliverableEvents(pWin);
     return Success;
 }
commit 883811c2bed9c6fcb706effbf83ddc97518b6f0c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 18 18:48:46 2008 +1030

    dix: remove inputInfo.pointer reference in TryClientEvents.
    
    Unfortunately, this requires a change in the TCE API, and thus a change in all
    callers. Tough luck.

diff --git a/Xext/xvmain.c b/Xext/xvmain.c
index 9834fcf..e92a248 100644
--- a/Xext/xvmain.c
+++ b/Xext/xvmain.c
@@ -541,8 +541,8 @@ int reason;
 	  event.u.videoNotify.drawable = pDraw->id;
 	  event.u.videoNotify.port = pPort->id;
 	  event.u.videoNotify.reason = reason;
-	  (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask,
-				 NoEventMask, NullGrab);
+	  TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
+                          NoEventMask, NoEventMask, NullGrab);
 	}
       pn = pn->next;
     }
@@ -573,8 +573,8 @@ XvdiSendPortNotify(
 	  event.u.portNotify.port = pPort->id;
 	  event.u.portNotify.attribute = attribute;
 	  event.u.portNotify.value = value;
-	  (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask,
-				 NoEventMask, NullGrab);
+	  TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1,
+                          NoEventMask, NoEventMask, NullGrab);
 	}
       pn = pn->next;
     }
diff --git a/dix/dispatch.c b/dix/dispatch.c
index b3816a5..a555aa1 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -1023,7 +1023,8 @@ ProcSetSelectionOwner(ClientPtr client)
 		event.u.selectionClear.time = time.milliseconds;
 		event.u.selectionClear.window = CurrentSelections[i].window;
 		event.u.selectionClear.atom = CurrentSelections[i].selection;
-		(void) TryClientEvents (CurrentSelections[i].client, &event, 1,
+		TryClientEvents (CurrentSelections[i].client, NULL,
+                                &event, 1,
 				NoEventMask, NoEventMask /* CantBeFiltered */,
 				NullGrab);
 	    }
@@ -1158,7 +1159,7 @@ ProcConvertSelection(ClientPtr client)
 	    event.u.selectionRequest.target = stuff->target;
 	    event.u.selectionRequest.property = stuff->property;
 	    if (TryClientEvents(
-		CurrentSelections[i].client, &event, 1, NoEventMask,
+		CurrentSelections[i].client, NULL, &event, 1, NoEventMask,
 		NoEventMask /* CantBeFiltered */, NullGrab))
 		return (client->noClientException);
 	}
@@ -1168,8 +1169,8 @@ ProcConvertSelection(ClientPtr client)
 	event.u.selectionNotify.selection = stuff->selection;
 	event.u.selectionNotify.target = stuff->target;
 	event.u.selectionNotify.property = None;
-	(void) TryClientEvents(client, &event, 1, NoEventMask,
-			       NoEventMask /* CantBeFiltered */, NullGrab);
+	TryClientEvents(client, NULL, &event, 1, NoEventMask,
+			NoEventMask /* CantBeFiltered */, NullGrab);
 	return (client->noClientException);
     }
     else 
diff --git a/dix/events.c b/dix/events.c
index 59688c7..c91e73b 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1968,6 +1968,7 @@ ReleaseActiveGrabs(ClientPtr client)
  *
  *
  * @param client The target client to deliver to.
+ * @param dev The device the event came from. May be NULL.
  * @param pEvents The events to be delivered.
  * @param count Number of elements in pEvents.
  * @param mask Event mask as set by the window.
@@ -1978,8 +1979,8 @@ ReleaseActiveGrabs(ClientPtr client)
  * client.
  */
 _X_EXPORT int
-TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
-                 Mask filter, GrabPtr grab)
+TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
+                 int count, Mask mask, Mask filter, GrabPtr grab)
 {
     int i;
     int type;
@@ -1998,7 +1999,7 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
 	{
 	    if (mask & PointerMotionHintMask)
 	    {
-		if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
+		if (WID(dev->valuator->motionHintWindow) ==
 		    pEvents->u.keyButtonPointer.event)
 		{
 #ifdef DEBUG_EVENTS
@@ -2108,8 +2109,9 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 
 	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
 	    /* do nothing */;
-        else if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
-				      pWin->eventMask, filter, grab)) )
+        else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents,
+                                             count, pWin->eventMask,
+                                             filter, grab)) )
 	{
 	    if (attempt > 0)
 	    {
@@ -2146,8 +2148,10 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
                     if (XaceHook(XACE_RECEIVE_ACCESS, pClient->client, pWin,
                                 pEvents, count))
                         /* do nothing */;
-                    else if (TryClientEvents(pClient->client, pEvents, count,
-                            pClient->eventMask[GEEXTIDX(pEvents)], filter, grab) > 0)
+                    else if (TryClientEvents(pClient->client, pDev,
+                             pEvents, count,
+                             pClient->eventMask[GEEXTIDX(pEvents)],
+                             filter, grab) > 0)
                     {
                         deliveries++;
                     } else
@@ -2179,8 +2183,10 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
                 if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
                              pEvents, count))
                     /* do nothing */;
-                else if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
-                                other->mask[mskidx], filter, grab)) )
+                else if ( (attempt = TryClientEvents(rClient(other), pDev,
+                                                     pEvents, count,
+                                                     other->mask[mskidx],
+                                                     filter, grab)) )
                 {
                     if (attempt > 0)
                     {
@@ -2308,7 +2314,7 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
 #endif
 	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
 	    return 1; /* don't send, but pretend we did */
-	return TryClientEvents(wClient(pWin), pEvents, count,
+	return TryClientEvents(wClient(pWin), NULL, pEvents, count,
 			       pWin->eventMask, filter, NullGrab);
     }
     for (other = wOtherClients(pWin); other; other = other->next)
@@ -2325,7 +2331,7 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
 	    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
 			 count))
 		return 1; /* don't send, but pretend we did */
-	    return TryClientEvents(rClient(other), pEvents, count,
+	    return TryClientEvents(rClient(other), NULL, pEvents, count,
 				   other->mask, filter, NullGrab);
 	}
     }
@@ -3469,7 +3475,7 @@ CheckPassiveGrabsOnWindow(
 
 	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
 
-	    (void) TryClientEvents(rClient(grab), xE, count,
+	    (void) TryClientEvents(rClient(grab), device, xE, count,
 				   filters[device->id][xE->u.u.type],
 				   filters[device->id][xE->u.u.type],  grab);
 
@@ -3704,8 +3710,8 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
 
                 if (GEEventFill(xE))
                     GEEventFill(xE)(ge, thisDev, grab->window, grab);
-                deliveries = TryClientEvents(rClient(grab), xE, count,
-                        gemask->eventMask[GEEXTIDX(ge)],
+                deliveries = TryClientEvents(rClient(grab), thisDev, xE,
+                        count, gemask->eventMask[GEEXTIDX(ge)],
                         generic_filters[GEEXTIDX(ge)][ge->evtype],
                         grab);
             } else
@@ -3728,8 +3734,8 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                     else if (!IsInterferingGrab(rClient(grab), thisDev,
                                 &core))
                     {
-                        deliveries = TryClientEvents(rClient(grab), &core, 1,
-                                                     mask,
+                        deliveries = TryClientEvents(rClient(grab), thisDev,
+                                                     &core, 1, mask,
                                                      filters[thisDev->id][core.u.u.type],
                                                      grab);
                     }
@@ -3754,7 +3760,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                     else
                     {
                         deliveries =
-                            TryClientEvents(rClient(grab),
+                            TryClientEvents(rClient(grab), thisDev,
                                            xE, count,
                                            mask,
                                            filters[thisDev->id][xE->u.u.type],
@@ -4452,10 +4458,10 @@ EnterLeaveEvent(
     if ((mask & filters[mouse->id][type]) && sendevent)
     {
         if (grab)
-            (void)TryClientEvents(rClient(grab), &event, 1, mask,
+            TryClientEvents(rClient(grab), mouse, &event, 1, mask,
                                   filters[mouse->id][type], grab);
         else
-            (void)DeliverEventsToWindow(mouse, pWin, &event, 1,
+            DeliverEventsToWindow(mouse, pWin, &event, 1,
                                   filters[mouse->id][type], NullGrab, 0);
     }
 
@@ -4475,7 +4481,8 @@ EnterLeaveEvent(
             inputMasks->deliverableEvents[mskidx]))
     {
         if (devgrab)
-            (void)TryClientEvents(rClient(devgrab), (xEvent*)devEnterLeave, 1,
+            (void)TryClientEvents(rClient(devgrab), mouse,
+                                (xEvent*)devEnterLeave, 1,
                                 mask, filters[mouse->id][devEnterLeave->type],
                                 devgrab);
 	else
@@ -4496,8 +4503,8 @@ EnterLeaveEvent(
 
 	ke.type = KeymapNotify;
 	if (grab)
-	    (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
-				  KeymapStateMask, grab);
+	    (void)TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
+                                  mask, KeymapStateMask, grab);
 	else
 	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
 					KeymapStateMask, NullGrab, 0);
diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
index dfec4b1..89fdec6 100644
--- a/hw/xfree86/common/xf86DGA.c
+++ b/hw/xfree86/common/xf86DGA.c
@@ -1105,7 +1105,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
     if (pScreenPriv->client)
     {
 	/* If the DGA client has selected input, then deliver based on the usual filter */
-	TryClientEvents (pScreenPriv->client, (xEvent *) de, 1, 
+	TryClientEvents (pScreenPriv->client, keybd, (xEvent *) de, 1,
 			 filters[coreEquiv], pScreenPriv->input, 0);
     }
     else
@@ -1186,7 +1186,7 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
     if (pScreenPriv->client)
     {
 	/* If the DGA client has selected input, then deliver based on the usual filter */
-	TryClientEvents (pScreenPriv->client, (xEvent *) de, 1, 
+	TryClientEvents (pScreenPriv->client, mouse, (xEvent *) de, 1,
 			 filters[coreEquiv], pScreenPriv->input, 0);
     }
     else
diff --git a/include/dix.h b/include/dix.h
index fc862df..079645d 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -502,6 +502,7 @@ extern void WriteEventsToClient(
 
 extern int TryClientEvents(
     ClientPtr /*client*/,
+    DeviceIntPtr /* device */,
     xEventPtr /*pEvents*/,
     int /*count*/,
     Mask /*mask*/,
diff --git a/mi/miexpose.c b/mi/miexpose.c
index 2d3b0d5..ebf73e7 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -385,7 +385,7 @@ miSendGraphicsExpose (client, pRgn, drawable, major, minor)
 	    pe->u.graphicsExposure.majorEvent = major;
 	    pe->u.graphicsExposure.minorEvent = minor;
 	}
-	TryClientEvents(client, pEvent, numRects,
+	TryClientEvents(client, NULL, pEvent, numRects,
 			    (Mask)0, NoEventMask, NullGrab);
 	xfree(pEvent);
     }
@@ -396,7 +396,7 @@ miSendGraphicsExpose (client, pRgn, drawable, major, minor)
 	event.u.noExposure.drawable = drawable;
 	event.u.noExposure.majorEvent = major;
 	event.u.noExposure.minorEvent = minor;
-	TryClientEvents(client, &event, 1,
+	TryClientEvents(client, NULL, &event, 1,
 	    (Mask)0, NoEventMask, NullGrab);
     }
 }
commit 6e17184486c4309ec8b47c7cfd11fef60bb360ac
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 18 17:52:38 2008 +1030

    Xi: Check for DestroyAccess when trying to delete a master device.

diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
index 0b2e3f1..65ff387 100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@ -88,9 +88,6 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
     REQUEST(xChangeDeviceHierarchyReq);
     REQUEST_AT_LEAST_SIZE(xChangeDeviceHierarchyReq);
 
-    /* XXX: check if client is allowed to change hierarch */
-
-
     any = (xAnyHierarchyChangeInfo*)&stuff[1];
     while(stuff->num_changes--)
     {
@@ -109,10 +106,13 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                     char* name;
                     int ret;
 
+                    /* XXX: check for creation permission */
+
                     SWAPIF(swaps(&c->namelen, n));
                     name = xcalloc(c->namelen + 1, sizeof(char));
                     strncpy(name, (char*)&c[1], c->namelen);
 
+
                     ret = AllocMasterDevice(name, &ptr, &keybd);
                     if (ret != Success)
                     {
@@ -143,7 +143,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                         return BadValue;
 
                     rc = dixLookupDevice(&ptr, r->deviceid, client,
-                                         DixWriteAccess);
+                                         DixDestroyAccess);
                     if (rc != Success)
                         return rc;
 
@@ -160,13 +160,26 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
 
                     /* disable keyboards first */
                     if (IsPointerDevice(ptr))
-                        keybd = ptr->spriteInfo->paired;
+                    {
+                        rc = dixLookupDevice(&keybd,
+                                             ptr->spriteInfo->paired->id,
+                                             client,
+                                             DixDestroyAccess);
+                        if (rc != Success)
+                            return rc;
+                    }
                     else
                     {
                         keybd = ptr;
-                        ptr = keybd->spriteInfo->paired;
+                        rc = dixLookupDevice(&ptr,
+                                             keybd->spriteInfo->paired->id,
+                                             client,
+                                             DixDestroyAccess);
+                        if (rc != Success)
+                            return rc;
                     }
 
+
                     /* Disabling sends the devices floating, reattach them if
                      * desired. */
                     if (r->returnMode == AttachToMaster)
commit b0bf4308acb706abc87c51658c2251fa86231c35
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jan 15 19:15:09 2008 +1030

    dix: print out an error when core type can't be converted.
    
    Helps a bit in tracking down bugs.

diff --git a/dix/events.c b/dix/events.c
index 4006c29..59688c7 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -304,6 +304,9 @@ XItoCoreType(int xitype)
         coretype = KeyPress;
     else if (xitype == DeviceKeyRelease)
         coretype = KeyRelease;
+
+    if (coretype == 0)
+        ErrorF("[dix] Cannot convert type %d to core.\n", xitype);
     return coretype;
 }
 
commit 2a988ed75b7634d7cb6e83bb7aa89bc8768d3a58
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jan 15 19:14:46 2008 +1030

    xkb: don't do core key repeats, XI only is the path to light.

diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index a035d8d..975b2eb 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -318,9 +318,8 @@ BOOL            is_core;
 
     is_core = (dev == inputInfo.keyboard);
     key = xkbi->repeatKey;
-    AccessXKeyboardEvent(dev, is_core ? KeyRelease : DeviceKeyRelease, key,
-                         True);
-    AccessXKeyboardEvent(dev, is_core ? KeyPress : DeviceKeyPress, key, True);
+    AccessXKeyboardEvent(dev, DeviceKeyRelease, key, True);
+    AccessXKeyboardEvent(dev, DeviceKeyPress, key, True);
     return xkbi->desc->ctrls->repeat_interval;
 }
 
commit 4fd0885978be286a68b689824f1d910f929a52b0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jan 15 18:58:42 2008 +1030

    Xi: remove some leftovers from ProcessOtherEvents.
    
    Core handling not needed anymore here.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 23d0c47..faf391f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -595,10 +595,7 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 /**
  * Main device event processing function.
  * Called from when processing the events from the event queue.
- * Generates core events for XI events as needed.
  *
- * Note that these core events are then delivered first. For passive grabs, XI
- * events have preference over core.
  */
 void
 ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
@@ -612,8 +609,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     KeyClassPtr k;
     ValuatorClassPtr v;
     deviceValuator *xV  = (deviceValuator *) xE;
-    BOOL sendCore = FALSE;
-    xEvent core;
     int coretype = 0;
     int ret = 0;
 
@@ -625,10 +620,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     b = device->button;
     k = device->key;
 
-    coretype = XItoCoreType(xE->u.u.type);
-    if (device->isMaster && device->coreEvents && coretype)
-        sendCore = TRUE;
-
     if (device->isMaster)
         CheckMotion(xE, device);
 
commit 32aa252e988be8cbfd4f7e373fb7b7736ef1f5f2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jan 15 15:22:39 2008 +1030

    dix: Process an input event as a single event, instead of two separate ones.
    
    This is a significant shift in how input events are perceived. The common
    approach was to treat a core event as a different entity than the XI event.
    This could result in the XI event being delivered to a different client than
    the core event. This doesn't work nicely if they come from the same device.
    
    Instead, we treat an input event as a single event, that is delivered through
    two separate APIs. So when delivering an event, we first try the XI event,
    then the core event. If the window want's neither, we go to the parent and
    repeat. Once either core or XI has been delivered, the processing stops.
    
    Important: Different to the previous method, if a client registers for core
    button events, the parent window will not get XI events. This should only
    cause problems when you're mixing core and XI events, so don't do that!
    
    Generic events don't fit into this yet, they cause me headaches.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index d32a55f..23d0c47 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -724,32 +724,13 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
             deactivateDeviceGrab = TRUE;
     }
 
-    if (sendCore)
-    {
-        core = *xE;
-        core.u.u.type = coretype;
-    }
-
     if (grab)
-    {
-        if (sendCore)                      /* never deactivate from core */
-            DeliverGrabbedEvent(&core, device, FALSE , 1);
         DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
-    }
     else if (device->focus)
-    {
-        if (sendCore)
-            DeliverFocusedEvent(device, &core, GetSpriteWindow(device), 1);
 	DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
-    }
     else
-    {
-        if (sendCore)
-            DeliverDeviceEvents(GetSpriteWindow(device), &core, NullGrab,
-                                NullWindow, device, 1);
 	DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
 			    device, count);
-    }
 
     if (deactivateDeviceGrab == TRUE)
 	(*device->deviceGrab.DeactivateGrab) (device);
diff --git a/dix/events.c b/dix/events.c
index 4de3b01..4006c29 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1369,11 +1369,10 @@ ComputeFreezes(void)
     DeviceIntPtr replayDev = syncEvents.replayDev;
     int i;
     WindowPtr w;
-    xEvent *xE, core;
+    xEvent *xE;
     int count;
     GrabPtr grab;
     DeviceIntPtr dev;
-    BOOL sendCore;
 
     for (dev = inputInfo.devices; dev; dev = dev->next)
 	FreezeThaw(dev, dev->deviceGrab.sync.other ||
@@ -1394,24 +1393,11 @@ ComputeFreezes(void)
 		replayDev->spriteInfo->sprite->spriteTrace[i])
 	    {
 		if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
-                    sendCore = (replayDev->coreEvents && replayDev->isMaster);
-                    core = *xE;
-                    core.u.u.type = XItoCoreType(xE->u.u.type);
-
 		    if (replayDev->focus)
-                    {
-                        if (sendCore)
-                            DeliverFocusedEvent(replayDev, &core, w, 1);
 			DeliverFocusedEvent(replayDev, xE, w, count);
-                    }
 		    else
-                    {
-                        if (sendCore)
-                            DeliverDeviceEvents(w, &core, NullGrab,
-                                                NullWindow, replayDev, 1);
 			DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
 					        replayDev, count);
-                    }
 		}
 		goto playmore;
 	    }
@@ -2439,92 +2425,97 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
     int type = xE->u.u.type;
     Mask filter = filters[dev->id][type];
     int deliveries = 0;
+    OtherInputMasks *inputMasks;
+    int mskidx = dev->id;
+    xEvent core;
 
     if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count))
 	return 0;
 
-    if (type & EXTENSION_EVENT_BASE)
+    /* handle generic events */
+    /* XXX: Generic events aren't quite handled correctly yet. They should
+     * eventually fit in with the rest of the stuff
+     */
+    if (type == GenericEvent)
     {
-	OtherInputMasks *inputMasks;
-	int mskidx = dev->id;
+        WindowPtr win = pWin;
+        xGenericEvent* ge = (xGenericEvent*)xE;
 
-	inputMasks = wOtherInputMasks(pWin);
-	if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
-	    return 0;
-	while (pWin)
-	{
-	    if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
-	    {
-		FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
-		deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter,
-						   grab, mskidx);
-		if (deliveries > 0)
-		    return deliveries;
-	    }
-	    if ((deliveries < 0) ||
-		(pWin == stopAt) ||
-		(inputMasks &&
-		 (filter & inputMasks->dontPropagateMask[mskidx])))
-		return 0;
-	    child = pWin->drawable.id;
-	    pWin = pWin->parent;
-	    if (pWin)
-		inputMasks = wOtherInputMasks(pWin);
-	}
-    }
-    else
-    {
-        /* handle generic events */
-        if (type == GenericEvent)
+        if (count > 1)
         {
-            xGenericEvent* ge = (xGenericEvent*)xE;
+            ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
+            return 0;
+        }
+        filter = generic_filters[GEEXTIDX(xE)][ge->evtype];
 
-            if (count > 1)
+        while(win)
+        {
+            if (GEMaskIsSet(win, GEEXT(xE), filter))
             {
-                ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
-                return 0;
+                if (GEExtensions[GEEXTIDX(xE)].evfill)
+                    GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, win, grab);
+                deliveries = DeliverEventsToWindow(dev, win, xE, count,
+                        filter, grab, 0);
+                if (deliveries > 0)
+                    return deliveries;
             }
-            filter = generic_filters[GEEXTIDX(xE)][ge->evtype];
 
-            while(pWin)
-            {
-                if (GEMaskIsSet(pWin, GEEXT(xE), filter))
-                {
-                    if (GEExtensions[GEEXTIDX(xE)].evfill)
-                        GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, pWin, grab);
-                    deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
-                                                        filter, grab, 0);
-                    if (deliveries > 0)
-                        return deliveries;
-                }
+            win = win->parent;
+        }
+    }
+
+    while (pWin && type != GenericEvent)
+    {
+        /* First try XI event delivery */
+        inputMasks = wOtherInputMasks(pWin);
+        if (inputMasks && (filter & inputMasks->deliverableEvents[mskidx]))
+        {
 
-                pWin = pWin->parent;
+            if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
+            {
+                FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
+                deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
+                                                   filter, grab, mskidx);
+                if (deliveries > 0)
+                    return deliveries;
             }
+
+            if ((deliveries < 0) ||
+                    (pWin == stopAt) ||
+                    (inputMasks &&
+                     (filter & inputMasks->dontPropagateMask[mskidx])))
+                return 0;
         }
-        else
+
+        if (dev->isMaster && dev->coreEvents)
         {
-            /* core protocol events */
-            if (!(filter & pWin->deliverableEvents))
-                return 0;
-            while (pWin)
+
+            /* no XI event delivered. Try core event */
+            core = *xE;
+            core.u.u.type = XItoCoreType(xE->u.u.type);
+
+            if (filter & pWin->deliverableEvents)
             {
                 if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
                 {
-                    FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
-                    deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter,
-                            grab, 0);
+                    FixUpEventFromWindow(dev, &core, pWin, child, FALSE);
+                    deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
+                            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;
             }
-	}
+        }
+
+        child = pWin->drawable.id;
+        pWin = pWin->parent;
     }
+
     return 0;
 }
 
@@ -3604,7 +3595,10 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
 {
     DeviceIntPtr pointer;
     WindowPtr focus = keybd->focus->win;
-    int mskidx = 0;
+    BOOL sendCore = (keybd->isMaster && keybd->coreEvents);
+    xEvent core;
+    int deliveries = 0;
+
     if (focus == FollowKeyboardWin)
 	focus = inputInfo.keyboard->focus->win;
     if (!focus)
@@ -3622,13 +3616,29 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
     pointer = GetPairedDevice(keybd);
     if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count))
 	return;
+
+    if (sendCore)
+    {
+        core = *xE;
+        core.u.u.type = XItoCoreType(xE->u.u.type);
+    }
+
     /* just deliver it to the focus window */
     FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
-    if (xE->u.u.type & EXTENSION_EVENT_BASE)
-	mskidx = keybd->id;
-    (void)DeliverEventsToWindow(keybd, focus, xE, count,
-                                filters[keybd->id][xE->u.u.type],
-				NullGrab, mskidx);
+    deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
+                                       filters[keybd->id][xE->u.u.type],
+                                       NullGrab, keybd->id);
+
+    if (deliveries > 0)
+        return;
+
+    if (sendCore)
+    {
+        FixUpEventFromWindow(keybd, &core, focus, None, FALSE);
+        deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
+                                           filters[keybd->id][xE->u.u.type],
+                                           NullGrab, 0);
+    }
 }
 
 /**
@@ -3646,8 +3656,9 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
     GrabInfoPtr grabinfo;
     int deliveries = 0;
     DeviceIntPtr dev;
-    xEvent *dxE;
+    xEvent *dxE, core;
     SpritePtr pSprite = thisDev->spriteInfo->sprite;
+    BOOL sendCore = FALSE;
 
     grabinfo = &thisDev->deviceGrab;
     grab = grabinfo->grab;
@@ -3697,23 +3708,56 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
             } else
             {
                 Mask mask = grab->eventMask;
-                if (grabinfo->fromPassiveGrab  &&
-                        grabinfo->implicitGrab &&
-                        (xE->u.u.type & EXTENSION_EVENT_BASE))
-                    mask = grab->deviceMask;
-
-                FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
-
-                if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xE,
-                            count) ||
-                    XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), grab->window,
-                             xE, count))
-                    deliveries = 1; /* don't send, but pretend we did */
-                else if (!(!(xE->u.u.type & EXTENSION_EVENT_BASE) &&
-                        IsInterferingGrab(rClient(grab), thisDev, xE)))
+
+                sendCore = (thisDev->isMaster && thisDev->coreEvents);
+                /* try core event */
+                if (sendCore && grab->coreGrab)
                 {
-                    deliveries = TryClientEvents(rClient(grab), xE, count,
-                            mask, filters[thisDev->id][xE->u.u.type], grab);
+                    core = *xE;
+                    core.u.u.type = XItoCoreType(xE->u.u.type);
+                    FixUpEventFromWindow(thisDev, &core, grab->window,
+                                         None, TRUE);
+                    if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
+                                 grab->window, &core, 1) ||
+                            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
+                                     grab->window, &count, 1))
+                        deliveries = 1; /* don't send, but pretend we did */
+                    else if (!IsInterferingGrab(rClient(grab), thisDev,
+                                &core))
+                    {
+                        deliveries = TryClientEvents(rClient(grab), &core, 1,
+                                                     mask,
+                                                     filters[thisDev->id][core.u.u.type],
+                                                     grab);
+                    }
+                }
+
+                if (!deliveries)
+                {
+                    /* try XI event */
+                    if (grabinfo->fromPassiveGrab  &&
+                            grabinfo->implicitGrab &&
+                            (xE->u.u.type & EXTENSION_EVENT_BASE))
+                        mask = grab->deviceMask;
+                    FixUpEventFromWindow(thisDev, xE, grab->window,
+                                         None, TRUE);
+
+                    if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
+                                 grab->window, xE, count) ||
+                            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
+                                     grab->window,
+                                xE, count))
+                        deliveries = 1; /* don't send, but pretend we did */
+                    else
+                    {
+                        deliveries =
+                            TryClientEvents(rClient(grab),
+                                           xE, count,
+                                           mask,
+                                           filters[thisDev->id][xE->u.u.type],
+                                           grab);
+                    }
+
                 }
             }
             if (deliveries && (xE->u.u.type == MotionNotify
commit 0969a9f7497e10794a6534321c10a0e1ac680ad7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jan 15 11:31:12 2008 +1030

    dix: Emulate core events within CheckDeviceGrabs and ComputeFreezes.
    
    This should restore the correct passive grab processing. When checking for
    passive grabs, the core event is emulated and we check first for XI grabs on
    the window, then for core grabs. Regardless of which event activates the grab,
    the XI event is stored in the device's EQ.
    
    When replaying the event, we take the XI event and replay it on the next
    window, again including the emulation of the core event.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index fa39565..d32a55f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -697,12 +697,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	    }
 	    return;
 	}
-        /* XI grabs have priority */
-        core = *xE;
-        core.u.u.type = coretype;
-	if (!grab &&
-              (CheckDeviceGrabs(device, xE, 0, count) ||
-                 (sendCore && CheckDeviceGrabs(device, &core, 0, 1)))) {
+	if (!grab && CheckDeviceGrabs(device, xE, 0, count)) {
 	    device->deviceGrab.activatingKey = key;
 	    return;
 	}
@@ -714,17 +709,11 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	xE->u.u.detail = key;
 	if (xE->u.u.detail == 0)
 	    return;
-        if (!grab)
+        if (!grab && CheckDeviceGrabs(device, xE, 0, count))
         {
-            core = *xE;
-            core.u.u.type = coretype;
-            if (CheckDeviceGrabs(device, xE, 0, count) ||
-                    (sendCore && CheckDeviceGrabs(device, &core, 0, 1)))
-            {
-                /* if a passive grab was activated, the event has been sent
-                 * already */
-                return;
-            }
+            /* if a passive grab was activated, the event has been sent
+             * already */
+            return;
         }
 
     } else if (xE->u.u.type == DeviceButtonRelease) {
diff --git a/dix/events.c b/dix/events.c
index ca5bae5..4de3b01 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1359,6 +1359,9 @@ FreezeThaw(DeviceIntPtr dev, Bool frozen)
  * runs up the sprite tree (spriteTrace) and searches for the window to replay
  * the events from. If it is found, it checks for passive grabs one down from
  * the window or delivers the events.
+ *
+ * Since the events in the EQ are always XI events, we need to emulate core
+ * events here.
  */
 static void
 ComputeFreezes(void)
@@ -1391,30 +1394,10 @@ ComputeFreezes(void)
 		replayDev->spriteInfo->sprite->spriteTrace[i])
 	    {
 		if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
-                    /* There is no other client that gets a passive grab on
-                     * the event anymore. Emulate core event if necessary and
-                     * deliver it too.
-                     * However, we might get here with a core event, in which
-                     * case we mustn't emulate a core event.
-                     */
-                    sendCore = (replayDev->coreEvents &&
-                        (xE->u.u.type & EXTENSION_EVENT_BASE &&
-                         XItoCoreType(xE->u.u.type)));
-
-
-                    if (sendCore)
-                    {
-                        core = *xE;
-                        core.u.u.type = XItoCoreType(xE->u.u.type);
-                        /* * XXX: Not sure if this is correct: we need to
-                         * check inferior windows for core passive grabs.
-                         */
-                        if (CheckDeviceGrabs(replayDev, &core, i+1, 1))
-                        {
-                            syncEvents.playingEvents = FALSE;
-                            return;
-                        }
-                    }
+                    sendCore = (replayDev->coreEvents && replayDev->isMaster);
+                    core = *xE;
+                    core.u.u.type = XItoCoreType(xE->u.u.type);
+
 		    if (replayDev->focus)
                     {
                         if (sendCore)
@@ -3367,7 +3350,9 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
  * @param pWin The window that may be subject to a passive grab.
  * @param device Device that caused the event.
  * @param xE List of events (multiple ones for DeviceMotionNotify)
- * @count number of elements in xE.
+ * @param count number of elements in xE.
+ * @param store The event that will be stored on the device (always XI)
+ * @param scount number of elements in store.
  */
 
 static Bool
@@ -3375,7 +3360,9 @@ CheckPassiveGrabsOnWindow(
     WindowPtr pWin,
     DeviceIntPtr device,
     xEvent *xE,
-    int count)
+    int count,
+    xEvent *store,
+    int scount)
 {
     GrabPtr grab = wPassiveGrabs(pWin);
     GrabRec tempGrab;
@@ -3494,17 +3481,18 @@ CheckPassiveGrabsOnWindow(
 
 	    if (grabinfo->sync.state == FROZEN_NO_EVENT)
 	    {
-		if (grabinfo->sync.evcount < count)
+		if (grabinfo->sync.evcount < scount)
 		{
 		    Must_have_memory = TRUE; /* XXX */
 		    grabinfo->sync.event = (xEvent *)xrealloc(grabinfo->sync.event,
-							    count*
+							    scount*
 							    sizeof(xEvent));
 		    Must_have_memory = FALSE; /* XXX */
 		}
-		grabinfo->sync.evcount = count;
-		for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++)
-		    *dxE = *xE;
+		grabinfo->sync.evcount = scount;
+                /* we always store the XI event, never the core event */
+		for (dxE = grabinfo->sync.event; --scount >= 0; dxE++, store++)
+		    *dxE = *store;
 		grabinfo->sync.state = FROZEN_WITH_EVENT;
             }
 	    return TRUE;
@@ -3530,8 +3518,11 @@ CheckPassiveGrabsOnWindow(
  *
  * If a grab is activated, the event has been sent to the client already!
  *
+ * The event we pass in must always be an XI event. From this, we then emulate
+ * the core event and then check for grabs.
+ *
  * @param device The device that caused the event.
- * @param xE The event to handle (most likely {Device}ButtonPress).
+ * @param xE The event to handle (Device{Button|Key}Press).
  * @param count Number of events in list.
  * @return TRUE if a grab has been activated or false otherwise.
 */
@@ -3543,11 +3534,26 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
     int i;
     WindowPtr pWin = NULL;
     FocusClassPtr focus = device->focus;
+    xEvent core;
+    BOOL sendCore = (device->isMaster && device->coreEvents);
 
-    if (((xE->u.u.type == ButtonPress) || (xE->u.u.type == DeviceButtonPress))
+    if ((xE->u.u.type == DeviceButtonPress)
             && (device->button->buttonsDown != 1))
 	return FALSE;
 
+    if (xE->u.u.type < EXTENSION_EVENT_BASE)
+    {
+        ErrorF("[dix] Core event passed into CheckDeviceGrabs.\n");
+        return FALSE;
+    }
+
+
+    if (sendCore)
+    {
+        core = *xE;
+        core.u.u.type = XItoCoreType(xE->u.u.type);
+    }
+
     i = checkFirst;
 
     if (focus)
@@ -3555,8 +3561,11 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
 	for (; i < focus->traceGood; i++)
 	{
 	    pWin = focus->trace[i];
+            /* XI grabs have precendence */
 	    if (pWin->optional &&
-		CheckPassiveGrabsOnWindow(pWin, device, xE, count))
+	       (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count)
+                || (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core,
+                        1, xE, count))))
 		return TRUE;
 	}
 
@@ -3571,7 +3580,9 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
     {
 	pWin = device->spriteInfo->sprite->spriteTrace[i];
 	if (pWin->optional &&
-	    CheckPassiveGrabsOnWindow(pWin, device, xE, count))
+	    (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) ||
+             (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, 1,
+                                                    xE, count))))
 	    return TRUE;
     }
 
commit a83a0c5a144da67dab96a857b849a5692b73245d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Jan 13 16:14:29 2008 +1030

    dix: remove obsolete comment.
    
    Pairings don't exist anymore and the documented issue is a non-issue now.

diff --git a/dix/events.c b/dix/events.c
index 0ce07d5..ca5bae5 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3446,10 +3446,8 @@ CheckPassiveGrabsOnWindow(
                than it is assigned to at this point in time.
                Update the grab's device and modifier device to reflect the
                current state.
-               XXX: Since XGrabDeviceButton requires to specify the
+               Since XGrabDeviceButton requires to specify the
                modifierDevice explicitly, we don't override this choice.
-               This essentially requires a client to re-create all
-               passiveGrabs when the pairing changes... oh well.
              */
             if (xE->u.u.type < LASTEvent)
             {
commit 38bf01bd1c925614a6e67a38aa3cefc7b8fe3bca
Merge: 4e85c7c... 0883e83...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 10 13:38:46 2008 +1030

    Merge branch 'master' into mpx

diff --cc dix/devices.c
index a784637,534a0b9..e78c1e7
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -587,25 -469,9 +587,26 @@@ InitAndStartDevices(WindowPtr root
  
      for (dev = inputInfo.off_devices; dev; dev = dev->next) {
          DebugF("(dix) initialising device %d\n", dev->id);
- 	ActivateDevice(dev);
+         if (!dev->inited)
+             ActivateDevice(dev);
      }
 +
 +    if (!inputInfo.keyboard) { /* In theory, this cannot happen */
 +	ErrorF("[dix] No core keyboard\n");
 +	return BadImplementation;
 +    }
 +    if (!inputInfo.pointer) { /* In theory, this cannot happen */
 +	ErrorF("[dix] No core pointer\n");
 +	return BadImplementation;
 +    }
 +
 +    /* Now enable all devices */
 +    if (inputInfo.pointer->inited && inputInfo.pointer->startup)
 +        EnableDevice(inputInfo.pointer);
 +    if (inputInfo.keyboard->inited && inputInfo.keyboard->startup)
 +        EnableDevice(inputInfo.keyboard);
 +
 +    /* enable real devices */
      for (dev = inputInfo.off_devices; dev; dev = next)
      {
          DebugF("(dix) enabling device %d\n", dev->id);
commit 4e85c7c322faf14c14e4229fa294b8e3d3a4d304
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Jan 9 17:36:39 2008 +1030

    Xi: keep a counter of buttons down to avoid duplicate press/release events.
    
    If two devices are attached to the same master device, pressing button 1 on
    each of them leads to two button presses from the same device. Some apps
    really don't like that.
    
    So we just put a counter in place and only send the first press and the last
    release.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e577e3b..fa39565 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -348,13 +348,28 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     }
 
     ALLOC_COPY_CLASS_IF(button, ButtonClassRec);
-#ifdef XKB
     if (to->button)
     {
+        int i;
+        DeviceIntPtr sd;
+
+        memset(to->button, 0, MAP_LENGTH);
+        /* merge button states from all attached devices */
+        for (sd = inputInfo.devices; sd; sd = sd->next)
+        {
+            if (sd->isMaster || sd->u.master != to)
+                continue;
+
+            for (i = 0; i < MAP_LENGTH; i++)
+            {
+                to->button->down[i] += sd->button->down[i];
+            }
+        }
+#ifdef XKB
         to->button->xkb_acts = NULL;
         /* XXX: XkbAction needs to be copied */
-    }
 #endif
+    }
     ALLOC_COPY_CLASS_IF(focus, FocusClassRec);
     ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
     ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
@@ -541,8 +556,8 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
         if (!b)
             return DONT_PROCESS;
 
-	kptr = &b->down[key >> 3];
-	*kptr |= bit;
+        if (b->down[key]++ > 0)
+            return DONT_PROCESS;
 	if (device->valuator)
 	    device->valuator->motionHintWindow = NullWindow;
         b->buttonsDown++;
@@ -556,10 +571,10 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
         if (!b)
             return DONT_PROCESS;
 
-	kptr = &b->down[key >> 3];
-        if (!(*kptr & bit))
+        if (b->down[key] == 0)
+            return DONT_PROCESS;
+        if (--b->down[key] > 0)
             return DONT_PROCESS;
-	*kptr &= ~bit;
 	if (device->valuator)
 	    device->valuator->motionHintWindow = NullWindow;
         if (b->buttonsDown >= 1 && !--b->buttonsDown)
diff --git a/dix/devices.c b/dix/devices.c
index 74212b2..a784637 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1178,7 +1178,7 @@ InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons,
     butc->buttonsDown = 0;
     butc->state = 0;
     butc->motionMask = 0;
-    bzero((char *)butc->down, DOWN_LENGTH);
+    bzero((char *)butc->down, MAP_LENGTH);
 #ifdef XKB
     butc->xkb_acts=	NULL;
 #endif
diff --git a/include/inputstr.h b/include/inputstr.h
index 9011ba2..8c1d5fc 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -184,7 +184,7 @@ typedef struct _ButtonClassRec {
     CARD8		buttonsDown;	/* number of buttons currently down */
     unsigned short	state;
     Mask		motionMask;
-    CARD8		down[DOWN_LENGTH];
+    CARD8		down[MAP_LENGTH];
     CARD8		map[MAP_LENGTH];
 #ifdef XKB
     union _XkbAction    *xkb_acts;
commit 20ace6321ac464d821c67a82c7023f74ae038176
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jan 7 20:08:56 2008 +1030

    dix: don't try to confine cursor on screen restructure if there is no cursor.
    
    Stops segfaulting when using xrandr. Yay.

diff --git a/dix/events.c b/dix/events.c
index 2872bf8..0ce07d5 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1481,6 +1481,8 @@ ScreenRestructured (ScreenPtr pScreen)
 
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
+        if (!DevHasCursor(pDev))
+            continue;
 
         /* GrabDevice doesn't have a confineTo field, so we don't need to
          * worry about it. */
commit 57a491e6d3ebec464c0c861b02c9ddcb1cc62c3c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jan 7 20:06:32 2008 +1030

    dix: init GrabPrivateKey to correct value.
    
    Merge detritus from last pull.

diff --git a/dix/events.c b/dix/events.c
index d2309eb..2872bf8 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1538,7 +1538,7 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
 }
 
 /* Only ever used if a grab is called on an attached slave device. */
-static DevPrivateKey GrabPrivateKey = -1;
+static DevPrivateKey GrabPrivateKey = &GrabPrivateKey;
 typedef struct _GrabMemoryRec {
     DeviceIntPtr oldmaster;
 } GrabMemoryRec, *GrabMemoryPtr;
commit 249b9b30c11e03bb113b37cf4712bf88debf6f05
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 4 13:49:48 2008 +1030

    Xi: remove file for the obsolete ChangePointerKeyboardPairing request handling.

diff --git a/Xi/chpkpair.c b/Xi/chpkpair.c
deleted file mode 100644
index c44a263..0000000
--- a/Xi/chpkpair.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-
-Copyright 2006 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 change pairing between pointer and keyboard 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/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"
-
-/***********************************************************************
- *
- * This procedure allows a client to change the pairing of a pointer with a
- * a keyboard.
- *
- */
-
-int SProcXChangePointerKeyboardPairing(ClientPtr client)
-{
-    char n;
-
-    REQUEST(xChangePointerKeyboardPairingReq);
-    swaps(&stuff->length, n);
-    return (ProcXChangePointerKeyboardPairing(client));
-}
-
-int
-ProcXChangePointerKeyboardPairing(ClientPtr client)
-{
-    DeviceIntPtr pPointer, pKeyboard;
-    int ret;
-    pairingChangedNotify ev;
-
-    REQUEST(xChangePointerKeyboardPairingReq);
-    REQUEST_SIZE_MATCH(xChangePointerKeyboardPairingReq);
-
-    /* check if client is registered */
-
-    pPointer = LookupDeviceIntRec(stuff->pointer);
-    if (pPointer == NULL)
-    {
-        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing,
-                stuff->pointer, BadDevice);
-        return Success;
-    }
-
-    pKeyboard = LookupDeviceIntRec(stuff->keyboard);
-    if (pKeyboard == NULL)
-    {
-        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing,
-                stuff->keyboard, BadDevice);
-        return Success;
-    }
-
-    ret = PairDevices(client, pPointer, pKeyboard);
-    if (ret != Success)
-    {
-        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing,
-                0, ret);
-        return Success;
-    }
-
-
-    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->length, n);
-    swapl(&to->evtype, n);
-    swapl(&to->time, n);
-}
commit e4a214e40d35aa957c83b86b4e4abc86c22fbde0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 4 13:32:53 2008 +1030

    dix: don't free device's devPrivates manually, dixFreePrivates does it.
    
    Merge detritus from last pull.

diff --git a/dix/devices.c b/dix/devices.c
index 8d98f13..74212b2 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -843,9 +843,6 @@ CloseDevice(DeviceIntPtr dev)
         }
     }
 
-    if (dev->devPrivates)
-	xfree(dev->devPrivates);
-
     xfree(dev->deviceGrab.sync.event);
     dixFreePrivates(dev->devPrivates);
     xfree(dev);
commit b2da44c76d68a76f20e90bccb268ebf65e132b49
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 3 18:51:44 2008 +1030

    dix: DoChangeKeyboardControl shouldn't be using inputInfo.keyboard.

diff --git a/dix/devices.c b/dix/devices.c
index f1a7595..8d98f13 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2016,8 +2016,8 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
 	case KBKey:
 	    key = (KeyCode)*vlist;
 	    vlist++;
-	    if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode ||
-		(KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) {
+	    if ((KeyCode)key < keybd->key->curKeySyms.minKeyCode ||
+		(KeyCode)key > keybd->key->curKeySyms.maxKeyCode) {
 		client->errorValue = key;
 		return BadValue;
 	    }
commit 9cc41b88dfebb3f1e0a7cb5c224146e651a2cda4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 3 18:47:28 2008 +1030

    Xi: ProcXSetClientPointer should directly check for the client from the id.
    
    The window ID includes the client ID anyway, so we might as well just look up
    the client directly instead of trying to get the window first and the client
    from the window.
    
    This also fixes a possible issue with XACE. If the client had permission to
    write on the client but not on the window, the previous approach would have
    failed.

diff --git a/Xi/setcptr.c b/Xi/setcptr.c
index 968e5cd..7313a9d 100644
--- a/Xi/setcptr.c
+++ b/Xi/setcptr.c
@@ -68,7 +68,6 @@ int
 ProcXSetClientPointer(ClientPtr client)
 {
     DeviceIntPtr pDev;
-    WindowPtr pWin;
     ClientPtr targetClient;
     int rc;
 
@@ -88,21 +87,12 @@ ProcXSetClientPointer(ClientPtr client)
 
     if (stuff->win != None)
     {
-        rc = dixLookupWindow(&pWin, stuff->win, client, DixWriteAccess);
+        rc = dixLookupClient(&targetClient, stuff->win, client,
+                DixWriteAccess);
+
         if (rc != Success)
-        {
-            /* window could not be found. maybe the window ID given was a pure
-               client id? */
-            /* XXX: Needs to be fixed for XACE */
-            rc = dixLookupClient(&targetClient, stuff->win,
-                                  client, DixWriteAccess);
-            if (rc != Success)
-            {
-                client->errorValue = stuff->win;
-                return rc;
-            }
-        } else
-            targetClient= wClient(pWin);
+            return rc;
+
     } else
         targetClient = client;
 
commit 521fdc28d86d091495da3558d26ab4a938250ffe
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 3 18:43:18 2008 +1030

    xfixes: switch a few inputInfo.pointer to PickPointer

diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index a804a89..fd75df7 100755
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -355,7 +355,7 @@ ProcXFixesGetCursorImage (ClientPtr client)
 		  pCursor, RT_NONE, NULL, DixReadAccess);
     if (rc != Success)
 	return rc;
-    GetSpritePosition (inputInfo.pointer, &x, &y);
+    GetSpritePosition (PickPointer(client), &x, &y);
     width = pCursor->bits->width;
     height = pCursor->bits->height;
     npixels = width * height;
@@ -507,7 +507,7 @@ ProcXFixesGetCursorImageAndName (ClientPtr client)
 		  pCursor, RT_NONE, NULL, DixReadAccess|DixGetAttrAccess);
     if (rc != Success)
 	return rc;
-    GetSpritePosition (inputInfo.pointer, &x, &y);
+    GetSpritePosition (PickPointer(client), &x, &y);
     width = pCursor->bits->width;
     height = pCursor->bits->height;
     npixels = width * height;
@@ -879,7 +879,7 @@ ProcXFixesHideCursor (ClientPtr client)
     ret = createCursorHideCount(client, pWin->drawable.pScreen);
 
     if (ret == Success) {
-        (void) CursorDisplayCursor(inputInfo.pointer, pWin->drawable.pScreen, CursorCurrent);
+        (void) CursorDisplayCursor(PickPointer(client), pWin->drawable.pScreen, CursorCurrent);
     }
 
     return ret;
commit 37194b13554f0d36343cf73324b128b15bb6a338
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 3 18:36:33 2008 +1030

    Xi: switch to using "rc" (instead of "err") as returncode.
    
    All the rest of XI uses rc and returns rc in case of error, so make
    mpx-related stuff comply. This stops the rest of XI sending the error
    manually.
    This is just a cosmetic change to be in line with the rest.

diff --git a/Xi/chaccess.c b/Xi/chaccess.c
index 872612e..a58409b 100644
--- a/Xi/chaccess.c
+++ b/Xi/chaccess.c
@@ -63,7 +63,7 @@ SProcXChangeWindowAccess(ClientPtr client)
 int
 ProcXChangeWindowAccess(ClientPtr client)
 {
-    int padding, err, i;
+    int padding, rc, i;
     XID* deviceids = NULL;
     WindowPtr win;
     DeviceIntPtr* perm_devices = NULL;
@@ -77,27 +77,21 @@ ProcXChangeWindowAccess(ClientPtr client)
     if (stuff->length != ((sizeof(xChangeWindowAccessReq)  +
             (((stuff->npermit + stuff->ndeny) * sizeof(XID)) + padding)) >> 2))
     {
-        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
-                0, BadLength);
-        return Success;
+        return BadLength;
     }
 
 
-    err = dixLookupWindow(&win, stuff->win, client, DixWriteAccess);
-    if (err != Success)
+    rc = dixLookupWindow(&win, stuff->win, client, DixWriteAccess);
+    if (rc != Success)
     {
-        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
-                          stuff->win, err);
-        return Success;
+        return rc;
     }
 
     /* Are we clearing? if so, ignore the rest */
     if (stuff->clear)
     {
-        err = ACClearWindowAccess(client, win, stuff->clear);
-        if (err != Success)
-            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, err);
-        return Success;
+        rc = ACClearWindowAccess(client, win, stuff->clear);
+        return rc;
     }
 
     if (stuff->npermit || stuff->ndeny)
@@ -110,20 +104,18 @@ ProcXChangeWindowAccess(ClientPtr client)
         if (!perm_devices)
         {
             ErrorF("[Xi] ProcXChangeWindowAccess: alloc failure.\n");
-            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0,
-                    BadImplementation);
-            return Success;
+            return BadImplementation;
         }
 
         /* if one of the devices cannot be accessed, we don't do anything.*/
         for (i = 0; i < stuff->npermit; i++)
         {
-            err = dixLookupDevice(&perm_devices[i], deviceids[i], client,
+            rc = dixLookupDevice(&perm_devices[i], deviceids[i], client,
                                   DixWriteAccess);
-            if (err != Success)
+            if (rc != Success)
             {
                 xfree(perm_devices);
-                return err;
+                return rc;
             }
         }
     }
@@ -135,36 +127,31 @@ ProcXChangeWindowAccess(ClientPtr client)
         if (!deny_devices)
         {
             ErrorF("[Xi] ProcXChangeWindowAccecss: alloc failure.\n");
-            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0,
-                    BadImplementation);
-
             xfree(perm_devices);
-            return Success;
+            return BadImplementation;
         }
 
         for (i = 0; i < stuff->ndeny; i++)
         {
-            err = dixLookupDevice(&deny_devices[i],
+            rc = dixLookupDevice(&deny_devices[i],
                                   deviceids[i+stuff->npermit],
                                   client,
                                   DixWriteAccess);
-            if (err != Success)
+            if (rc != Success)
             {
                 xfree(perm_devices);
                 xfree(deny_devices);
-                return err;
+                return rc;
             }
         }
     }
 
-    err = ACChangeWindowAccess(client, win, stuff->defaultRule,
+    rc = ACChangeWindowAccess(client, win, stuff->defaultRule,
                                perm_devices, stuff->npermit,
                                deny_devices, stuff->ndeny);
-    if (err != Success)
+    if (rc != Success)
     {
-        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
-                          stuff->win, err);
-        return Success;
+        return rc;
     }
 
     xfree(perm_devices);
diff --git a/Xi/chdevcur.c b/Xi/chdevcur.c
index 0baee58..0a14900 100644
--- a/Xi/chdevcur.c
+++ b/Xi/chdevcur.c
@@ -71,7 +71,7 @@ SProcXChangeDeviceCursor(ClientPtr client)
 
 int ProcXChangeDeviceCursor(ClientPtr client)
 {
-    int err;
+    int rc;
     WindowPtr pWin    = NULL;
     DeviceIntPtr pDev = NULL;
     CursorPtr pCursor = NULL;
@@ -79,15 +79,15 @@ int ProcXChangeDeviceCursor(ClientPtr client)
     REQUEST(xChangeDeviceCursorReq);
     REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
 
-    err = dixLookupDevice(&pDev, stuff->deviceid, client, DixSetAttrAccess);
-    if (err != Success)
-        return err;
+    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixSetAttrAccess);
+    if (rc != Success)
+        return rc;
 
     if (stuff->win != None)
     {
-        err = dixLookupWindow(&pWin, stuff->win, client, DixSetAttrAccess);
-        if (err != Success)
-            return err;
+        rc = dixLookupWindow(&pWin, stuff->win, client, DixSetAttrAccess);
+        if (rc != Success)
+            return rc;
     }
 
     if (stuff->cursor == None)
@@ -103,9 +103,7 @@ int ProcXChangeDeviceCursor(ClientPtr client)
                                 RT_CURSOR, DixReadAccess);
         if (!pCursor)
         {
-            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor,
-                    stuff->cursor, BadCursor);
-            return Success;
+            return BadCursor;
         }
     }
 
diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
index 7738f15..72f8879 100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@ -93,7 +93,7 @@ ProcXExtendedGrabDevice(ClientPtr client)
 {
     xExtendedGrabDeviceReply rep;
     DeviceIntPtr             dev;
-    int                      err = Success,
+    int                      rc = Success,
                              errval = 0,
                              i;
     WindowPtr                grab_window,
@@ -122,12 +122,12 @@ ProcXExtendedGrabDevice(ClientPtr client)
             stuff->event_count + 2 * stuff->generic_event_count))
     {
         errval = 0;
-        err = BadLength;
+        rc = BadLength;
         goto cleanup;
     }
 
-    err = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
-    if (err != Success) {
+    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
+    if (rc != Success) {
 	goto cleanup;
     }
 
@@ -138,11 +138,11 @@ ProcXExtendedGrabDevice(ClientPtr client)
         goto cleanup;
     }
 
-    err = dixLookupWindow(&grab_window,
+    rc = dixLookupWindow(&grab_window,
                           stuff->grab_window,
                           client,
                           DixReadAccess);
-    if (err != Success)
+    if (rc != Success)
     {
         errval = stuff->grab_window;
         goto cleanup;
@@ -150,11 +150,11 @@ ProcXExtendedGrabDevice(ClientPtr client)
 
     if (stuff->confine_to)
     {
-        err = dixLookupWindow(&confineTo,
+        rc = dixLookupWindow(&confineTo,
                               stuff->confine_to,
                               client,
                               DixReadAccess);
-        if (err != Success)
+        if (rc != Success)
         {
             errval = stuff->confine_to;
             goto cleanup;
@@ -170,7 +170,7 @@ ProcXExtendedGrabDevice(ClientPtr client)
         if (!cursor)
         {
             errval = stuff->cursor;
-            err = BadCursor;
+            rc = BadCursor;
             goto cleanup;
         }
     }
@@ -205,7 +205,7 @@ ProcXExtendedGrabDevice(ClientPtr client)
                   cursor, tmp[stuff->deviceid].mask,
                   gemasks);
 
-    if (err != Success) {
+    if (rc != Success) {
         errval = 0;
         goto cleanup;
     }
@@ -215,13 +215,13 @@ cleanup:
     if (gemasks)
         xfree(gemasks);
 
-    if (err == Success)
+    if (rc == Success)
     {
         WriteReplyToClient(client, sizeof(xGrabDeviceReply), &rep);
     }
     else
     {
-        return err;
+        return rc;
     }
     return Success;
 }
diff --git a/Xi/fakedevdata.c b/Xi/fakedevdata.c
index 7f2d3ec..92ee8ee 100644
--- a/Xi/fakedevdata.c
+++ b/Xi/fakedevdata.c
@@ -86,8 +86,7 @@ ProcXFakeDeviceData(ClientPtr client)
 
     if (stuff->length != (sizeof(xFakeDeviceDataReq) >> 2) + stuff->num_valuators)
     {
-        SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadLength);
-        return Success;
+        return BadLength;
     }
 
     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixWriteAccess);
@@ -96,8 +95,7 @@ ProcXFakeDeviceData(ClientPtr client)
 
     if (!fake_events && !(fake_events = InitEventList(GetMaximumEventsNum())))
     {
-        SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadAlloc);
-        return Success;
+        return BadAlloc;
     }
     if (stuff->num_valuators)
     {
@@ -106,8 +104,7 @@ ProcXFakeDeviceData(ClientPtr client)
         valuators = xcalloc(stuff->num_valuators, sizeof(int));
         if (!valuators)
         {
-            SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadAlloc);
-            return Success;
+            return BadAlloc;
         }
         for (i = 0; i < stuff->num_valuators; i++, valptr++)
             valuators[i] = (int)(*valptr);
diff --git a/Xi/qryacces.c b/Xi/qryacces.c
index 673028c..ab627e2 100644
--- a/Xi/qryacces.c
+++ b/Xi/qryacces.c
@@ -64,7 +64,7 @@ SProcXQueryWindowAccess(ClientPtr client)
 int
 ProcXQueryWindowAccess(ClientPtr client)
 {
-    int err;
+    int rc;
     WindowPtr win;
     DeviceIntPtr *perm, *deny;
     int nperm, ndeny, i;
@@ -75,12 +75,10 @@ ProcXQueryWindowAccess(ClientPtr client)
     REQUEST(xQueryWindowAccessReq);
     REQUEST_SIZE_MATCH(xQueryWindowAccessReq);
 
-    err = dixLookupWindow(&win, stuff->win, client, DixReadAccess);
-    if (err != Success)
+    rc = dixLookupWindow(&win, stuff->win, client, DixReadAccess);
+    if (rc != Success)
     {
-        SendErrorToClient(client, IReqCode, X_QueryWindowAccess,
-                          stuff->win, err);
-        return Success;
+        return rc;
     }
 
     ACQueryWindowAccess(win, &defaultRule, &perm, &nperm, &deny, &ndeny);
@@ -100,9 +98,7 @@ ProcXQueryWindowAccess(ClientPtr client)
         if (!deviceids)
         {
             ErrorF("[Xi] ProcXQueryWindowAccess: xalloc failure.\n");
-            SendErrorToClient(client, IReqCode, X_QueryWindowAccess,
-                    0, BadImplementation);
-            return Success;
+            return BadImplementation;
         }
 
         for (i = 0; i < nperm; i++)
diff --git a/Xi/setcptr.c b/Xi/setcptr.c
index 8dd7181..968e5cd 100644
--- a/Xi/setcptr.c
+++ b/Xi/setcptr.c
@@ -70,15 +70,15 @@ ProcXSetClientPointer(ClientPtr client)
     DeviceIntPtr pDev;
     WindowPtr pWin;
     ClientPtr targetClient;
-    int err;
+    int rc;
 
     REQUEST(xSetClientPointerReq);
     REQUEST_SIZE_MATCH(xSetClientPointerReq);
 
 
-    err = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
-    if (err != Success)
-        return err;
+    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
+    if (rc != Success)
+        return rc;
 
     if (!IsPointerDevice(pDev) || !pDev->isMaster)
     {
@@ -88,18 +88,18 @@ ProcXSetClientPointer(ClientPtr client)
 
     if (stuff->win != None)
     {
-        err = dixLookupWindow(&pWin, stuff->win, client, DixWriteAccess);
-        if (err != Success)
+        rc = dixLookupWindow(&pWin, stuff->win, client, DixWriteAccess);
+        if (rc != Success)
         {
             /* window could not be found. maybe the window ID given was a pure
                client id? */
             /* XXX: Needs to be fixed for XACE */
-            err = dixLookupClient(&targetClient, stuff->win,
+            rc = dixLookupClient(&targetClient, stuff->win,
                                   client, DixWriteAccess);
-            if (err != Success)
+            if (rc != Success)
             {
                 client->errorValue = stuff->win;
-                return err;
+                return rc;
             }
         } else
             targetClient= wClient(pWin);
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index 24661d0..26081eb 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -70,7 +70,7 @@ SProcXWarpDevicePointer(ClientPtr client)
 int
 ProcXWarpDevicePointer(ClientPtr client)
 {
-    int err;
+    int rc;
     int x, y;
     WindowPtr dest = NULL;
     DeviceIntPtr pDev;
@@ -82,19 +82,17 @@ ProcXWarpDevicePointer(ClientPtr client)
 
     /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */
 
-    err = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
+    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
 
-    if (err != Success)
-        return err;
+    if (rc != Success)
+        return rc;
 
     if (stuff->dst_win != None)
     {
-        err = dixLookupWindow(&dest, stuff->dst_win, client, DixReadAccess);
-        if (err != Success)
+        rc = dixLookupWindow(&dest, stuff->dst_win, client, DixReadAccess);
+        if (rc != Success)
         {
-            SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
-                    stuff->dst_win, err);
-            return Success;
+            return rc;
         }
     }
 
@@ -107,12 +105,10 @@ ProcXWarpDevicePointer(ClientPtr client)
         int winX, winY;
         WindowPtr src;
 
-        err = dixLookupWindow(&src, stuff->src_win, client, DixReadAccess);
-        if (err != Success)
+        rc = dixLookupWindow(&src, stuff->src_win, client, DixReadAccess);
+        if (rc != Success)
         {
-            SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
-                    stuff->src_win, err);
-            return Success;
+            return rc;
         }
 
         winX = src->drawable.x;
diff --git a/Xi/xiselev.c b/Xi/xiselev.c
index 59f75b5..3c85032 100644
--- a/Xi/xiselev.c
+++ b/Xi/xiselev.c
@@ -59,16 +59,15 @@ SProcXiSelectEvent(ClientPtr client)
 int
 ProcXiSelectEvent(ClientPtr client)
 {
-    int ret;
+    int rc;
     WindowPtr pWin;
     REQUEST(xXiSelectEventReq);
     REQUEST_SIZE_MATCH(xXiSelectEventReq);
 
-    ret = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
-    if (ret != Success)
+    rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
+    if (rc != Success)
     {
-        SendErrorToClient(client, IReqCode, X_XiSelectEvent, 0, ret);
-        return Success;
+        return rc;
     }
 
     GEWindowSetMask(client, pWin, IReqCode, stuff->mask);
commit c7e9b67c547c97b2c943eab555b4fe2844e8a91f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 3 18:09:56 2008 +1030

    dix: free ClassesRec when a BadAlloc occurs during CoreKeyboardProc.

diff --git a/dix/devices.c b/dix/devices.c
index ed69cb8..f1a7595 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -415,12 +415,14 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
                                         keySyms.mapWidth);
         if (!keySyms.map) {
             ErrorF("[dix] Couldn't allocate core keymap\n");
+            xfree(classes);
             return BadAlloc;
         }
 
         modMap = (CARD8 *)xalloc(MAP_LENGTH);
         if (!modMap) {
             ErrorF("[dix] Couldn't allocate core modifier map\n");
+            xfree(classes);
             return BadAlloc;
         }
         bzero((char *)modMap, MAP_LENGTH);
commit 8da83836b60f7cdb75d08482f4311fa0e2ab4e1d
Merge: eace889... ae869fc...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 3 17:04:54 2008 +1030

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	XTrap/xtrapddmi.c
    	Xext/security.c
    	Xext/xprint.c
    	Xext/xtest.c
    	Xext/xvdisp.c
    	Xi/exevents.c
    	Xi/grabdevb.c
    	Xi/grabdevk.c
    	Xi/opendev.c
    	Xi/ungrdev.c
    	Xi/ungrdevb.c
    	Xi/ungrdevk.c
    	dix/cursor.c
    	dix/devices.c
    	dix/dixutils.c
    	dix/events.c
    	dix/getevents.c
    	dix/main.c
    	dix/window.c
    	hw/xfree86/ramdac/xf86Cursor.c
    	include/dix.h
    	include/input.h
    	include/inputstr.h
    	mi/midispcur.c
    	mi/miinitext.c
    	mi/misprite.c
    	render/animcur.c
    	xfixes/cursor.c
    	xkb/xkbAccessX.c

diff --cc Xext/geext.c
index 0c5fcab,0000000..8f48e44
mode 100644,000000..100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@@ -1,381 -1,0 +1,379 @@@
 +/* 
 +
 +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;
++DevPrivateKey GEClientPrivateKey = &GEClientPrivateKey;
 +int GEEventType; /* The opcode for all GenericEvents will have. */
 +
 +
 +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);
 +
++    if (pGEClient == NULL)
++    {
++        pGEClient = xcalloc(1, sizeof(GEClientInfoRec));
++        dixSetPrivate(&pClient->devPrivates, GEClientPrivateKey, pGEClient);
++    }
++
 +    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 
++void
 +GEExtensionInit(void)
 +{
 +    ExtensionEntry *extEntry;
 +
-     GEClientPrivateIndex = AllocateClientPrivateIndex(); 
-     if (!AllocateClientPrivate(GEClientPrivateIndex, 
-                                sizeof(GenericMaskRec)))
-     {
-         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[X_GenericEvent] = (EventSwapPtr) SGEGenericEvent;
++        EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent;
 +    } else {
 +        FatalError("GEInit: AddExtensions failed.\n");
 +    }
 +
 +}
 +
 +/************************************************************/
 +/*                interface for extensions                  */
 +/************************************************************/
 +
 +/* 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.  
 + * @param ev_fill Called for an event before delivery. The extension now has
 + * the chance to fill in necessary fields for the event.
 + */
 +void GERegisterExtension(
 +        int extension, 
 +        void (*ev_swap)(xGenericEvent* from, xGenericEvent* to),
 +        void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev, 
 +                        WindowPtr pWin, GrabPtr pGrab)
 +        )
 +{
 +    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;
 +    GEExtensions[extension & 0x7f].evfill = ev_fill;
 +}
 +
 +
 +/* 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;
 +    GenericMaskPtr it;
 +    GenericClientMasksPtr 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)
 +{
 +    GenericMaskPtr 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)
 +    {
 +        GenericClientMasksPtr 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  = (GenericMaskPtr)xcalloc(1, sizeof(GenericMaskRec));
 +            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 
 +        { 
 +            GenericMaskPtr 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 --cc Xext/geint.h
index 9e131d3,0000000..57404d8
mode 100644,000000..100644
--- a/Xext/geint.h
+++ b/Xext/geint.h
@@@ -1,60 -1,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;
++extern DevPrivateKey GEClientPrivateKey;
 +
 +typedef struct _GEClientInfo {
 +    CARD32  major_version;
 +    CARD32  minor_version;
 +} GEClientInfoRec, *GEClientInfoPtr;
 +
- #define GEGetClient(pClient)    ((GEClientInfoPtr) (pClient)->devPrivates[GEClientPrivateIndex].ptr)
++#define GEGetClient(pClient)    ((GEClientInfoPtr)(dixLookupPrivate(&((pClient)->devPrivates), GEClientPrivateKey)))
 +
 +extern int (*ProcGEVector[/*GENumRequests*/])(ClientPtr);
 +extern int (*SProcGEVector[/*GENumRequests*/])(ClientPtr);
 +
 +#endif /* _GEINT_H_ */
diff --cc Xext/security.c
index 231ea51,6aab3a3..914cec2
--- a/Xext/security.c
+++ b/Xext/security.c
@@@ -633,7 -649,7 +649,7 @@@ SProcSecurityQueryVersion
      ClientPtr client)
  {
      REQUEST(xSecurityQueryVersionReq);
-     char 	n;
 -    register char 	n;
++    char	n;
  
      swaps(&stuff->length, n);
      REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
@@@ -648,7 -664,7 +664,7 @@@ SProcSecurityGenerateAuthorization
      ClientPtr client)
  {
      REQUEST(xSecurityGenerateAuthorizationReq);
-     char 	n;
 -    register char 	n;
++    char	n;
      CARD32 *values;
      unsigned long nvalues;
  
@@@ -671,7 -687,7 +687,7 @@@ SProcSecurityRevokeAuthorization
      ClientPtr client)
  {
      REQUEST(xSecurityRevokeAuthorizationReq);
-     char 	n;
 -    register char 	n;
++    char	n;
  
      swaps(&stuff->length, n);
      REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
@@@ -1227,595 -860,168 +860,168 @@@ SecurityServer(CallbackListPtr *pcbl, p
      }
  }
  
- CALLBACK(SecurityDeclareExtSecure)
- {
-     XaceDeclareExtSecureRec *rec = (XaceDeclareExtSecureRec*)calldata;
- 
-     /* security state for extensions is simply a boolean trust value */
-     STATEVAL(rec->ext) = rec->secure;
- }
- 
- /**********************************************************************/
- 
- typedef struct _PropertyAccessRec {
-     ATOM name;
-     ATOM mustHaveProperty;
-     char *mustHaveValue;
-     char windowRestriction;
- #define SecurityAnyWindow          0
- #define SecurityRootWindow         1
- #define SecurityWindowWithProperty 2
-     char readAction;
-     char writeAction;
-     char destroyAction;
-     struct _PropertyAccessRec *next;
- } PropertyAccessRec, *PropertyAccessPtr;
- 
- static PropertyAccessPtr PropertyAccessList = NULL;
- static char SecurityDefaultAction = XaceErrorOperation;
- static char *SecurityPolicyFile = DEFAULTPOLICYFILE;
- static ATOM SecurityMaxPropertyName = 0;
- 
- static char *SecurityKeywords[] = {
- #define SecurityKeywordComment 0
-     "#",
- #define SecurityKeywordProperty 1
-     "property",
- #define SecurityKeywordSitePolicy 2
-     "sitepolicy",
- #define SecurityKeywordRoot 3
-     "root",
- #define SecurityKeywordAny 4
-     "any"
- };
- 
- #define NUMKEYWORDS (sizeof(SecurityKeywords) / sizeof(char *))
- 
- #undef PROPDEBUG
- /*#define PROPDEBUG  1*/
- 
  static void
- SecurityFreePropertyAccessList(void)
- {
-     while (PropertyAccessList)
-     {
- 	PropertyAccessPtr freeit = PropertyAccessList;
- 	PropertyAccessList = PropertyAccessList->next;
- 	xfree(freeit);
-     }
- } /* SecurityFreePropertyAccessList */
- 
- #define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') )
- 
- static char *
- SecuritySkipWhitespace(
-     char *p)
+ SecurityClient(CallbackListPtr *pcbl, pointer unused, pointer calldata)
  {
-     while (SecurityIsWhitespace(*p))
- 	p++;
-     return p;
- } /* SecuritySkipWhitespace */
- 
- 
- static char *
- SecurityParseString(
-     char **rest)
- {
-     char *startOfString;
-     char *s = *rest;
-     char endChar = 0;
- 
-     s = SecuritySkipWhitespace(s);
- 
-     if (*s == '"' || *s == '\'')
-     {
- 	endChar = *s++;
- 	startOfString = s;
- 	while (*s && (*s != endChar))
- 	    s++;
-     }
-     else
-     {
- 	startOfString = s;
- 	while (*s && !SecurityIsWhitespace(*s))
- 	    s++;
+     XaceClientAccessRec *rec = calldata;
+     SecurityStateRec *subj, *obj;
+     Mask requested = rec->access_mode;
+     Mask allowed = SecurityAllowedMask;
+ 
+     subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+     obj = dixLookupPrivate(&rec->target->devPrivates, stateKey);
+ 
+     if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ 	SecurityAudit("Security: denied client %d access to client %d on "
+ 		      "request %s\n", rec->client->index, rec->target->index,
+ 		      SecurityLookupRequestName(rec->client));
+ 	rec->status = BadAccess;
      }
-     if (*s)
-     {
- 	*s = '\0';
- 	*rest = s + 1;
- 	return startOfString;
-     }
-     else
-     {
- 	*rest = s;
- 	return (endChar) ? NULL : startOfString;
-     }
- } /* SecurityParseString */
- 
- 
- static int
- SecurityParseKeyword(
-     char **p)
- {
-     int i;
-     char *s = *p;
-     s = SecuritySkipWhitespace(s);
-     for (i = 0; i < NUMKEYWORDS; i++)
-     {
- 	int len = strlen(SecurityKeywords[i]);
- 	if (strncmp(s, SecurityKeywords[i], len) == 0)
- 	{
- 	    *p = s + len;
- 	    return (i);
- 	}
-     }
-     *p = s;
-     return -1;
- } /* SecurityParseKeyword */
- 
- 
- static Bool
- SecurityParsePropertyAccessRule(
-     char *p)
- {
-     char *propname;
-     char c;
-     char action = SecurityDefaultAction;
-     char readAction, writeAction, destroyAction;
-     PropertyAccessPtr pacl, prev, cur;
-     char *mustHaveProperty = NULL;
-     char *mustHaveValue = NULL;
-     Bool invalid;
-     char windowRestriction;
-     int size;
-     int keyword;
- 
-     /* get property name */
-     propname = SecurityParseString(&p);
-     if (!propname || (strlen(propname) == 0))
- 	return FALSE;
- 
-     /* get window on which property must reside for rule to apply */
- 
-     keyword = SecurityParseKeyword(&p);
-     if (keyword == SecurityKeywordRoot)
- 	windowRestriction = SecurityRootWindow;
-     else if (keyword == SecurityKeywordAny) 
- 	windowRestriction = SecurityAnyWindow;
-     else /* not root or any, must be a property name */
-     {
- 	mustHaveProperty = SecurityParseString(&p);
- 	if (!mustHaveProperty || (strlen(mustHaveProperty) == 0))
- 	    return FALSE;
- 	windowRestriction = SecurityWindowWithProperty;
- 	p = SecuritySkipWhitespace(p);
- 	if (*p == '=')
- 	{ /* property value is specified too */
- 	    p++; /* skip over '=' */
- 	    mustHaveValue = SecurityParseString(&p);
- 	    if (!mustHaveValue)
- 		return FALSE;
- 	}
-     }
- 
-     /* get operations and actions */
- 
-     invalid = FALSE;
-     readAction = writeAction = destroyAction = SecurityDefaultAction;
-     while ( (c = *p++) && !invalid)
-     {
- 	switch (c)
- 	{
- 	    case 'i': action = XaceIgnoreOperation; break;
- 	    case 'a': action = XaceAllowOperation;  break;
- 	    case 'e': action = XaceErrorOperation;  break;
- 
- 	    case 'r': readAction    = action; break;
- 	    case 'w': writeAction   = action; break;
- 	    case 'd': destroyAction = action; break;
- 
- 	    default :
- 		if (!SecurityIsWhitespace(c))
- 		    invalid = TRUE;
- 	    break;
- 	}
-     }
-     if (invalid)
- 	return FALSE;
- 
-     /* We've successfully collected all the information needed for this
-      * property access rule.  Now record it in a PropertyAccessRec.
-      */
-     size = sizeof(PropertyAccessRec);
- 
-     /* If there is a property value string, allocate space for it 
-      * right after the PropertyAccessRec.
-      */
-     if (mustHaveValue)
- 	size += strlen(mustHaveValue) + 1;
-     pacl = (PropertyAccessPtr)Xalloc(size);
-     if (!pacl)
- 	return FALSE;
- 
-     pacl->name = MakeAtom(propname, strlen(propname), TRUE);
-     if (pacl->name == BAD_RESOURCE)
-     {
- 	Xfree(pacl);
- 	return FALSE;
-     }
-     if (mustHaveProperty)
-     {
- 	pacl->mustHaveProperty = MakeAtom(mustHaveProperty,
- 					  strlen(mustHaveProperty), TRUE);
- 	if (pacl->mustHaveProperty == BAD_RESOURCE)
- 	{
- 	    Xfree(pacl);
- 	    return FALSE;
- 	}
-     }
-     else
- 	pacl->mustHaveProperty = 0;
- 
-     if (mustHaveValue)
-     {
- 	pacl->mustHaveValue = (char *)(pacl + 1);
- 	strcpy(pacl->mustHaveValue, mustHaveValue);
-     }
-     else
- 	pacl->mustHaveValue = NULL;
- 
-     SecurityMaxPropertyName = max(SecurityMaxPropertyName, pacl->name);
- 
-     pacl->windowRestriction = windowRestriction;
-     pacl->readAction  = readAction;
-     pacl->writeAction = writeAction;
-     pacl->destroyAction = destroyAction;
- 
-     /* link the new rule into the list of rules in order of increasing
-      * property name (atom) value to make searching easier
-      */
+ }
  
-     for (prev = NULL,  cur = PropertyAccessList;
- 	 cur && cur->name <= pacl->name;
- 	 prev = cur, cur = cur->next)
- 	;
-     if (!prev)
-     {
- 	pacl->next = cur;
- 	PropertyAccessList = pacl;
-     }
-     else
-     {
- 	prev->next = pacl;
- 	pacl->next = cur;
+ static void
+ SecurityProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata)
+ {    
+     XacePropertyAccessRec *rec = calldata;
+     SecurityStateRec *subj, *obj;
+     ATOM name = rec->pProp->propertyName;
+     Mask requested = rec->access_mode;
+     Mask allowed = SecurityAllowedMask | DixReadAccess;
+ 
+     subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+     obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
+ 
+     if (SecurityDoCheck(subj, obj, requested, allowed) != Success) {
+ 	SecurityAudit("Security: denied client %d access to property %s "
+ 		      "(atom 0x%x) window 0x%x of client %d on request %s\n",
+ 		      rec->client->index, NameForAtom(name), name,
+ 		      rec->pWin->drawable.id, wClient(rec->pWin)->index,
+ 		      SecurityLookupRequestName(rec->client));
+ 	rec->status = BadAccess;
      }
-     return TRUE;
- } /* SecurityParsePropertyAccessRule */
- 
- static char **SecurityPolicyStrings = NULL;
- static int nSecurityPolicyStrings = 0;
+ }
  
- static Bool
- SecurityParseSitePolicy(
-     char *p)
+ static void
+ SecuritySend(CallbackListPtr *pcbl, pointer unused, pointer calldata)
  {
-     char *policyStr = SecurityParseString(&p);
-     char *copyPolicyStr;
-     char **newStrings;
- 
-     if (!policyStr)
- 	return FALSE;
- 
-     copyPolicyStr = (char *)Xalloc(strlen(policyStr) + 1);
-     if (!copyPolicyStr)
- 	return TRUE;
-     strcpy(copyPolicyStr, policyStr);
-     newStrings = (char **)Xrealloc(SecurityPolicyStrings,
- 			  sizeof (char *) * (nSecurityPolicyStrings + 1));
-     if (!newStrings)
-     {
- 	Xfree(copyPolicyStr);
- 	return TRUE;
-     }
- 
-     SecurityPolicyStrings = newStrings;
-     SecurityPolicyStrings[nSecurityPolicyStrings++] = copyPolicyStr;
+     XaceSendAccessRec *rec = calldata;
+     SecurityStateRec *subj, *obj;
  
-     return TRUE;
+     if (rec->client) {
+ 	int i;
  
- } /* SecurityParseSitePolicy */
+ 	subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+ 	obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
  
+ 	if (SecurityDoCheck(subj, obj, DixSendAccess, 0) == Success)
+ 	    return;
  
- char **
- SecurityGetSitePolicyStrings(n)
-     int *n;
- {
-     *n = nSecurityPolicyStrings;
-     return SecurityPolicyStrings;
- } /* SecurityGetSitePolicyStrings */
- 
- static void
- SecurityFreeSitePolicyStrings(void)
- {
-     if (SecurityPolicyStrings)
-     {
- 	assert(nSecurityPolicyStrings);
- 	while (nSecurityPolicyStrings--)
- 	{
- 	    Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]);
- 	}
- 	Xfree(SecurityPolicyStrings);
- 	SecurityPolicyStrings = NULL;
- 	nSecurityPolicyStrings = 0;
+ 	for (i = 0; i < rec->count; i++)
+ 	    if (rec->events[i].u.u.type != UnmapNotify &&
+ 		rec->events[i].u.u.type != ConfigureRequest &&
+ 		rec->events[i].u.u.type != ClientMessage) {
+ 
+ 		SecurityAudit("Security: denied client %d from sending event "
+ 			      "of type %s to window 0x%x of client %d\n",
+ 			      rec->client->index, rec->pWin->drawable.id,
+ 			      wClient(rec->pWin)->index,
+ 			      LookupEventName(rec->events[i].u.u.type));
+ 		rec->status = BadAccess;
+ 		return;
+ 	    }
      }
- } /* SecurityFreeSitePolicyStrings */
- 
+ }
  
  static void
- SecurityLoadPropertyAccessList(void)
+ SecurityReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata)
  {
-     FILE *f;
-     int lineNumber = 0;
+     XaceReceiveAccessRec *rec = calldata;
+     SecurityStateRec *subj, *obj;
  
-     SecurityMaxPropertyName = 0;
+     subj = dixLookupPrivate(&rec->client->devPrivates, stateKey);
+     obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey);
  
-     if (!SecurityPolicyFile)
- 	return;
- 
-     f = fopen(SecurityPolicyFile, "r");
-     if (!f)
-     {
- 	ErrorF("error opening security policy file %s\n",
- 	       SecurityPolicyFile);
+     if (SecurityDoCheck(subj, obj, DixReceiveAccess, 0) == Success)
  	return;
-     }
- 
-     while (!feof(f))
-     {
- 	char buf[200];
- 	Bool validLine;
- 	char *p;
- 
- 	if (!(p = fgets(buf, sizeof(buf), f)))
- 	    break;
- 	lineNumber++;
- 
- 	/* if first line, check version number */
- 	if (lineNumber == 1)
- 	{
- 	    char *v = SecurityParseString(&p);
- 	    if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0)
- 	    {
- 		ErrorF("%s: invalid security policy file version, ignoring file\n",
- 		       SecurityPolicyFile);
- 		break;
- 	    }
- 	    validLine = TRUE;
- 	}
- 	else
- 	{
- 	    switch (SecurityParseKeyword(&p))
- 	    {
- 		case SecurityKeywordComment:
- 		    validLine = TRUE;
- 		break;
- 
- 		case SecurityKeywordProperty:
- 		    validLine = SecurityParsePropertyAccessRule(p);
- 		break;
  
- 		case SecurityKeywordSitePolicy:
- 		    validLine = SecurityParseSitePolicy(p);
- 		break;
- 
- 		default:
- 		    validLine = (*p == '\0'); /* blank lines OK, others not */
- 		break;
- 	    }
- 	}
- 
- 	if (!validLine)
- 	    ErrorF("Line %d of %s invalid, ignoring\n",
- 		   lineNumber, SecurityPolicyFile);
-     } /* end while more input */
- 
- #ifdef PROPDEBUG
-     {
- 	PropertyAccessPtr pacl;
- 	char *op = "aie";
- 	for (pacl = PropertyAccessList; pacl; pacl = pacl->next)
- 	{
- 	    ErrorF("property %s ", NameForAtom(pacl->name));
- 	    switch (pacl->windowRestriction)
- 	    {
- 		case SecurityAnyWindow: ErrorF("any "); break;
- 		case SecurityRootWindow: ErrorF("root "); break;
- 		case SecurityWindowWithProperty:
- 		{
- 		    ErrorF("%s ", NameForAtom(pacl->mustHaveProperty));
- 		    if (pacl->mustHaveValue)
- 			ErrorF(" = \"%s\" ", pacl->mustHaveValue);
- 
- 		}
- 		break;
- 	    }
- 	    ErrorF("%cr %cw %cd\n", op[pacl->readAction],
- 		   op[pacl->writeAction], op[pacl->destroyAction]);
- 	}
-     }
- #endif /* PROPDEBUG */
- 
-     fclose(f);
- } /* SecurityLoadPropertyAccessList */
+     SecurityAudit("Security: denied client %d from receiving an event "
+ 		  "sent to window 0x%x of client %d\n",
+ 		  rec->client->index, rec->pWin->drawable.id,
+ 		  wClient(rec->pWin)->index);
+     rec->status = BadAccess;
+ }
  
+ /* SecurityClientStateCallback
+  *
+  * Arguments:
+  *	pcbl is &ClientStateCallback.
+  *	nullata is NULL.
+  *	calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
+  *	which contains information about client state changes.
+  *
+  * Returns: nothing.
+  *
+  * Side Effects:
+  * 
+  * If a new client is connecting, its authorization ID is copied to
+  * client->authID.  If this is a generated authorization, its reference
+  * count is bumped, its timer is cancelled if it was running, and its
+  * trustlevel is copied to TRUSTLEVEL(client).
+  * 
+  * If a client is disconnecting and the client was using a generated
+  * authorization, the authorization's reference count is decremented, and
+  * if it is now zero, the timer for this authorization is started.
+  */
  
- static Bool
- SecurityMatchString(
-     char *ws,
-     char *cs)
+ static void
+ SecurityClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata)
  {
-     while (*ws && *cs)
-     {
- 	if (*ws == '*')
- 	{
- 	    Bool match = FALSE;
- 	    ws++;
- 	    while (!(match = SecurityMatchString(ws, cs)) && *cs)
- 	    {
- 		cs++;
- 	    }
- 	    return match;
- 	}
- 	else if (*ws == *cs)
- 	{
- 	    ws++;
- 	    cs++;
- 	}
- 	else break;
-     }
-     return ( ( (*ws == '\0') || ((*ws == '*') && *(ws+1) == '\0') )
- 	     && (*cs == '\0') );
- } /* SecurityMatchString */
- 
- #ifdef PROPDEBUG
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
+     NewClientInfoRec *pci = calldata;
+     SecurityStateRec *state;
+     SecurityAuthorizationPtr pAuth;
+     int rc;
  
+     state = dixLookupPrivate(&pci->client->devPrivates, stateKey);
  
- CALLBACK(SecurityCheckPropertyAccess)
- {    
-     XacePropertyAccessRec *rec = (XacePropertyAccessRec*)calldata;
-     ClientPtr client = rec->client;
-     WindowPtr pWin = rec->pWin;
-     ATOM propertyName = rec->propertyName;
-     Mask access_mode = rec->access_mode;
-     PropertyAccessPtr pacl;
-     char action = SecurityDefaultAction;
- 
-     /* if client trusted or window untrusted, allow operation */
- 
-     if ( (TRUSTLEVEL(client) == XSecurityClientTrusted) ||
- 	 (TRUSTLEVEL(wClient(pWin)) != XSecurityClientTrusted) )
- 	return;
+     switch (pci->client->clientState) {
+     case ClientStateInitial:
+ 	state->trustLevel = XSecurityClientTrusted;
+ 	state->authId = None;
+ 	state->haveState = TRUE;
+ 	break;
  
- #ifdef PROPDEBUG
-     /* For testing, it's more convenient if the property rules file gets
-      * reloaded whenever it changes, so we can rapidly try things without
-      * having to reset the server.
-      */
-     {
- 	struct stat buf;
- 	static time_t lastmod = 0;
- 	int ret = stat(SecurityPolicyFile , &buf);
- 	if ( (ret == 0) && (buf.st_mtime > lastmod) )
- 	{
- 	    ErrorF("reloading property rules\n");
- 	    SecurityFreePropertyAccessList();
- 	    SecurityLoadPropertyAccessList();
- 	    lastmod = buf.st_mtime;
+     case ClientStateRunning:
+ 	state->authId = AuthorizationIDOfClient(pci->client);
+ 	rc = dixLookupResource((pointer *)&pAuth, state->authId,
+ 			       SecurityAuthorizationResType, serverClient,
+ 			       DixGetAttrAccess);
+ 	if (rc == Success) {
+ 	    /* it is a generated authorization */
+ 	    pAuth->refcnt++;
+ 	    if (pAuth->refcnt == 1 && pAuth->timer)
+ 		TimerCancel(pAuth->timer);
+ 
+ 	    state->trustLevel = pAuth->trustLevel;
  	}
-     }
- #endif
- 
-     /* If the property atom is bigger than any atoms on the list, 
-      * we know we won't find it, so don't even bother looking.
-      */
-     if (propertyName <= SecurityMaxPropertyName)
-     {
- 	/* untrusted client operating on trusted window; see if it's allowed */
- 
- 	for (pacl = PropertyAccessList; pacl; pacl = pacl->next)
- 	{
- 	    if (pacl->name < propertyName)
- 		continue;
- 	    if (pacl->name > propertyName)
- 		break;
+ 	break;
  
- 	    /* pacl->name == propertyName, so see if it applies to this window */
+     case ClientStateGone:
+     case ClientStateRetained:
+ 	rc = dixLookupResource((pointer *)&pAuth, state->authId,
+ 			       SecurityAuthorizationResType, serverClient,
+ 			       DixGetAttrAccess);
+ 	if (rc == Success) {
+ 	    /* it is a generated authorization */
+ 	    pAuth->refcnt--;
+ 	    if (pAuth->refcnt == 0)
+ 		SecurityStartAuthorizationTimer(pAuth);
+ 	}
+ 	break;
  
- 	    switch (pacl->windowRestriction)
- 	    {
- 		case SecurityAnyWindow: /* always applies */
- 		    break;
- 
- 		case SecurityRootWindow:
- 		{
- 		    /* if not a root window, this rule doesn't apply */
- 		    if (pWin->parent)
- 			continue;
- 		}
- 		break;
- 
- 		case SecurityWindowWithProperty:
- 		{
- 		    PropertyPtr pProp = wUserProps (pWin);
- 		    Bool match = FALSE;
- 		    char *p;
- 		    char *pEndData;
- 
- 		    while (pProp)
- 		    {
- 			if (pProp->propertyName == pacl->mustHaveProperty)
- 			    break;
- 			pProp = pProp->next;
- 		    }
- 		    if (!pProp)
- 			continue;
- 		    if (!pacl->mustHaveValue)
- 			break;
- 		    if (pProp->type != XA_STRING || pProp->format != 8)
- 			continue;
- 
- 		    p = pProp->data;
- 		    pEndData = ((char *)pProp->data) + pProp->size;
- 		    while (!match && p < pEndData)
- 		    {
- 			 if (SecurityMatchString(pacl->mustHaveValue, p))
- 			     match = TRUE;
- 			 else
- 			 { /* skip to the next string */
- 			     while (*p++ && p < pEndData)
- 				 ;
- 			 }
- 		    }
- 		    if (!match)
- 			continue;
- 		}
- 		break; /* end case SecurityWindowWithProperty */
- 	    } /* end switch on windowRestriction */
- 
- 	    /* If we get here, the property access rule pacl applies.
- 	     * If pacl doesn't apply, something above should have
- 	     * executed a continue, which will skip the follwing code.
- 	     */
- 	    action = XaceAllowOperation;
- 	    if (access_mode & DixReadAccess)
- 		action = max(action, pacl->readAction);
- 	    if (access_mode & DixWriteAccess)
- 		action = max(action, pacl->writeAction);
- 	    if (access_mode & DixDestroyAccess)
- 		action = max(action, pacl->destroyAction);
- 	    break;
- 	} /* end for each pacl */
-     } /* end if propertyName <= SecurityMaxPropertyName */
- 
-     if (XaceAllowOperation != action)
-     { /* audit the access violation */
- 	int cid = CLIENT_ID(pWin->drawable.id);
- 	int reqtype = ((xReq *)client->requestBuffer)->reqType;
- 	char *actionstr = (XaceIgnoreOperation == action) ?
- 							"ignored" : "error";
- 	SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n",
- 		client->index, reqtype, pWin->drawable.id,
- 		      NameForAtom(propertyName), propertyName, cid, actionstr);
+     default:
 -	break; 
++	break;
      }
-     /* return codes increase with strictness */
-     if (action > rec->rval)
-         rec->rval = action;
- } /* SecurityCheckPropertyAccess */
- 
+ }
  
  /* SecurityResetProc
   *
diff --cc Xext/shape.c
index 2425eeb,2f1baf9..6857c28
--- a/Xext/shape.c
+++ b/Xext/shape.c
@@@ -996,10 -990,10 +990,10 @@@ ProcShapeInputSelected (client
      ShapeEventPtr	pShapeEvent, *pHead;
      int			enabled, rc;
      xShapeInputSelectedReply	rep;
 -    register int		n;
 +    int		n;
  
      REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
-     rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
      if (rc != Success)
  	return rc;
      pHead = (ShapeEventPtr *) SecurityLookupIDByType(client,
@@@ -1038,10 -1032,10 +1032,10 @@@ ProcShapeGetRectangles (client
      xRectangle			*rects;
      int				nrects, i, rc;
      RegionPtr			region;
 -    register int		n;
 +    int		n;
  
      REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
-     rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
      if (rc != Success)
  	return rc;
      switch (stuff->kind) {
diff --cc Xext/xtest.c
index 371be4e,db6d545..8d27e16
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@@ -139,23 -125,23 +125,24 @@@ ProcXTestCompareCursor(client
      xXTestCompareCursorReply rep;
      WindowPtr pWin;
      CursorPtr pCursor;
 -    register int n, rc;
 +    int n, rc;
-     DeviceIntPtr pointer = PickPointer(client);
++    DeviceIntPtr ptr = PickPointer(client);
  
      REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
-     rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
      if (rc != Success)
          return rc;
      if (stuff->cursor == None)
  	pCursor = NullCursor;
      else if (stuff->cursor == XTestCurrentCursor)
- 	pCursor = GetSpriteCursor(pointer);
 -	pCursor = GetSpriteCursor();
++	pCursor = GetSpriteCursor(ptr);
      else {
- 	pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
- 	if (!pCursor)
+ 	rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
+ 			       client, DixReadAccess);
 -	if (rc != Success) 
++	if (rc != Success)
  	{
  	    client->errorValue = stuff->cursor;
- 	    return (BadCursor);
+ 	    return (rc == BadValue) ? BadCursor : rc;
  	}
      }
      rep.type = X_Reply;
diff --cc Xi/chaccess.c
index 9baa871,0000000..872612e
mode 100644,000000..100644
--- a/Xi/chaccess.c
+++ b/Xi/chaccess.c
@@@ -1,177 -1,0 +1,174 @@@
 +/*
 +
 +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/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 "chaccess.h"
 +
 +/***********************************************************************
 + * This procedure allows a client to change window access control.
 + */
 +
 +int
 +SProcXChangeWindowAccess(ClientPtr client)
 +{
 +    char n;
 +    REQUEST(xChangeWindowAccessReq);
 +
 +    swaps(&stuff->length, n);
 +    swapl(&stuff->win, n);
 +    return ProcXChangeWindowAccess(client);
 +}
 +
 +int
 +ProcXChangeWindowAccess(ClientPtr client)
 +{
 +    int padding, err, i;
 +    XID* deviceids = NULL;
 +    WindowPtr win;
 +    DeviceIntPtr* perm_devices = NULL;
 +    DeviceIntPtr* deny_devices = NULL;
 +    REQUEST(xChangeWindowAccessReq);
 +    REQUEST_AT_LEAST_SIZE(xChangeWindowAccessReq);
 +
 +
 +    padding = (4 - (((stuff->npermit + stuff->ndeny) * sizeof(XID)) % 4)) % 4;
 +
 +    if (stuff->length != ((sizeof(xChangeWindowAccessReq)  +
 +            (((stuff->npermit + stuff->ndeny) * sizeof(XID)) + padding)) >> 2))
 +    {
 +        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
 +                0, BadLength);
 +        return Success;
 +    }
 +
 +
 +    err = dixLookupWindow(&win, stuff->win, client, DixWriteAccess);
 +    if (err != Success)
 +    {
 +        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
 +                          stuff->win, err);
 +        return Success;
 +    }
 +
 +    /* Are we clearing? if so, ignore the rest */
 +    if (stuff->clear)
 +    {
 +        err = ACClearWindowAccess(client, win, stuff->clear);
 +        if (err != Success)
 +            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, err);
 +        return Success;
 +    }
 +
 +    if (stuff->npermit || stuff->ndeny)
 +        deviceids = (XID*)&stuff[1];
 +
 +    if (stuff->npermit)
 +    {
 +        perm_devices =
 +            (DeviceIntPtr*)xalloc(stuff->npermit * sizeof(DeviceIntPtr));
 +        if (!perm_devices)
 +        {
 +            ErrorF("[Xi] ProcXChangeWindowAccess: alloc failure.\n");
 +            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0,
 +                    BadImplementation);
 +            return Success;
 +        }
 +
 +        /* if one of the devices cannot be accessed, we don't do anything.*/
 +        for (i = 0; i < stuff->npermit; i++)
 +        {
-             perm_devices[i] = LookupDeviceIntRec(deviceids[i]);
-             if (!perm_devices[i])
++            err = dixLookupDevice(&perm_devices[i], deviceids[i], client,
++                                  DixWriteAccess);
++            if (err != Success)
 +            {
 +                xfree(perm_devices);
-                 SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
-                         deviceids[i], BadDevice);
-                 return Success;
++                return err;
 +            }
 +        }
 +    }
 +
 +    if (stuff->ndeny)
 +    {
 +        deny_devices =
 +            (DeviceIntPtr*)xalloc(stuff->ndeny * sizeof(DeviceIntPtr));
 +        if (!deny_devices)
 +        {
 +            ErrorF("[Xi] ProcXChangeWindowAccecss: alloc failure.\n");
 +            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0,
 +                    BadImplementation);
 +
 +            xfree(perm_devices);
 +            return Success;
 +        }
 +
 +        for (i = 0; i < stuff->ndeny; i++)
 +        {
-             deny_devices[i] =
-                 LookupDeviceIntRec(deviceids[i+stuff->npermit]);
- 
-             if (!deny_devices[i])
++            err = dixLookupDevice(&deny_devices[i],
++                                  deviceids[i+stuff->npermit],
++                                  client,
++                                  DixWriteAccess);
++            if (err != Success)
 +            {
 +                xfree(perm_devices);
 +                xfree(deny_devices);
-                 SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
-                         deviceids[i + stuff->npermit], BadDevice);
-                 return Success;
++                return err;
 +            }
 +        }
 +    }
 +
 +    err = ACChangeWindowAccess(client, win, stuff->defaultRule,
 +                               perm_devices, stuff->npermit,
 +                               deny_devices, stuff->ndeny);
 +    if (err != Success)
 +    {
 +        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
 +                          stuff->win, err);
 +        return Success;
 +    }
 +
 +    xfree(perm_devices);
 +    xfree(deny_devices);
 +    return Success;
 +}
 +
diff --cc Xi/chdevcur.c
index dfa45ee,0000000..0baee58
mode 100644,000000..100644
--- a/Xi/chdevcur.c
+++ b/Xi/chdevcur.c
@@@ -1,123 -1,0 +1,116 @@@
 +/*
 +
 +Copyright 2006 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 change a given device pointer's cursor.
 + *
 + */
 +
 +#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 "input.h"
 +
 +#include "chdevcur.h"
 +
 +/***********************************************************************
 + *
 + * This procedure allows a client to set one pointer's cursor.
 + *
 + */
 +
 +int
 +SProcXChangeDeviceCursor(ClientPtr client)
 +{
 +    char n;
 +
 +    REQUEST(xChangeDeviceCursorReq);
 +    swaps(&stuff->length, n);
 +    REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
 +    return (ProcXChangeDeviceCursor(client));
 +}
 +
 +int ProcXChangeDeviceCursor(ClientPtr client)
 +{
 +    int err;
 +    WindowPtr pWin    = NULL;
 +    DeviceIntPtr pDev = NULL;
 +    CursorPtr pCursor = NULL;
 +
 +    REQUEST(xChangeDeviceCursorReq);
 +    REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
 +
-     pDev = LookupDeviceIntRec(stuff->deviceid);
-     if (pDev == NULL) {
-         SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 0,
-                 BadDevice);
-         return Success;
-     }
++    err = dixLookupDevice(&pDev, stuff->deviceid, client, DixSetAttrAccess);
++    if (err != Success)
++        return err;
 +
 +    if (stuff->win != None)
 +    {
-         err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
++        err = dixLookupWindow(&pWin, stuff->win, client, DixSetAttrAccess);
 +        if (err != Success)
-         {
-             SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor,
-                     stuff->win, err);
-             return Success;
-         }
++            return err;
 +    }
 +
 +    if (stuff->cursor == None)
 +    {
 +        if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
 +            pCursor = rootCursor;
 +        else
 +            pCursor = (CursorPtr)None;
 +    }
 +    else
 +    {
 +        pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
 +                                RT_CURSOR, DixReadAccess);
 +        if (!pCursor)
 +        {
 +            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor,
 +                    stuff->cursor, BadCursor);
 +            return Success;
 +        }
 +    }
 +
 +    ChangeWindowDeviceCursor(pWin, pDev, pCursor);
 +
 +    return Success;
 +}
 +
diff --cc Xi/chdevhier.c
index ac912f7,0000000..0b2e3f1
mode 100644,000000..100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@@ -1,241 -1,0 +1,278 @@@
 +/*
 +
 +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 change in the device hierarchy.
 + *
 + */
 +
 +
 +#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/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 "chdevhier.h"
 +
 +
 +/***********************************************************************
 + *
 + * This procedure allows a client to change the device hierarchy through
 + * adding new master devices, removing them, etc.
 + *
 + */
 +
 +int SProcXChangeDeviceHierarchy(ClientPtr client)
 +{
 +    char n;
 +
 +    REQUEST(xChangeDeviceHierarchyReq);
 +    swaps(&stuff->length, n);
 +    return (ProcXChangeDeviceHierarchy(client));
 +}
 +
 +#define SWAPIF(cmd) if (client->swapped) { cmd; }
 +
 +int
 +ProcXChangeDeviceHierarchy(ClientPtr client)
 +{
 +    DeviceIntPtr ptr, keybd;
 +    DeviceIntRec dummyDev;
 +    xAnyHierarchyChangeInfo *any;
 +    int required_len = sizeof(xChangeDeviceHierarchyReq);
 +    char n;
++    int rc;
 +    deviceHierarchyChangedEvent ev;
 +
 +    REQUEST(xChangeDeviceHierarchyReq);
 +    REQUEST_AT_LEAST_SIZE(xChangeDeviceHierarchyReq);
 +
 +    /* XXX: check if client is allowed to change hierarch */
 +
 +
 +    any = (xAnyHierarchyChangeInfo*)&stuff[1];
 +    while(stuff->num_changes--)
 +    {
 +        SWAPIF(swapl(&any->type, n));
 +        SWAPIF(swaps(&any->length, n));
 +
 +        required_len += any->length;
 +        if ((stuff->length * 4) < required_len)
 +            return BadLength;
 +
 +        switch(any->type)
 +        {
 +            case CH_CreateMasterDevice:
 +                {
 +                    xCreateMasterInfo* c = (xCreateMasterInfo*)any;
 +                    char* name;
 +                    int ret;
 +
 +                    SWAPIF(swaps(&c->namelen, n));
 +                    name = xcalloc(c->namelen + 1, sizeof(char));
 +                    strncpy(name, (char*)&c[1], c->namelen);
 +
 +                    ret = AllocMasterDevice(name, &ptr, &keybd);
 +                    if (ret != Success)
 +                    {
 +                        xfree(name);
 +                        return ret;
 +                    }
 +
 +                    if (!c->sendCore)
 +                        ptr->coreEvents = keybd->coreEvents =  FALSE;
 +
 +                    ActivateDevice(ptr);
 +                    ActivateDevice(keybd);
 +
 +                    if (c->enable)
 +                    {
 +                        EnableDevice(ptr);
 +                        EnableDevice(keybd);
 +                    }
 +                    xfree(name);
 +                }
 +                break;
 +            case CH_RemoveMasterDevice:
 +                {
 +                    xRemoveMasterInfo* r = (xRemoveMasterInfo*)any;
 +
 +                    if (r->returnMode != AttachToMaster &&
 +                            r->returnMode != Floating)
 +                        return BadValue;
 +
-                     ptr = LookupDeviceIntRec(r->deviceid);
-                     if (!ptr || !ptr->isMaster)
++                    rc = dixLookupDevice(&ptr, r->deviceid, client,
++                                         DixWriteAccess);
++                    if (rc != Success)
++                        return rc;
++
++                    if (!ptr->isMaster)
++                    {
++                        client->errorValue = r->deviceid;
 +                        return BadDevice;
++                    }
 +
 +                    /* XXX: For now, don't allow removal of VCP, VCK */
 +                    if (ptr == inputInfo.pointer ||
 +                            ptr == inputInfo.keyboard)
 +                        return BadDevice;
 +
 +                    /* disable keyboards first */
 +                    if (IsPointerDevice(ptr))
 +                        keybd = ptr->spriteInfo->paired;
 +                    else
 +                    {
 +                        keybd = ptr;
 +                        ptr = keybd->spriteInfo->paired;
 +                    }
 +
 +                    /* Disabling sends the devices floating, reattach them if
 +                     * desired. */
 +                    if (r->returnMode == AttachToMaster)
 +                    {
 +                        DeviceIntPtr attached,
 +                                     newptr,
 +                                     newkeybd;
 +
-                         newptr = LookupDeviceIntRec(r->returnPointer);
-                         newkeybd = LookupDeviceIntRec(r->returnKeyboard);
-                         if (!newptr || !newptr->isMaster ||
-                                 !newkeybd || !newkeybd->isMaster)
++                        rc = dixLookupDevice(&newptr, r->returnPointer,
++                                             client, DixWriteAccess);
++                        if (rc != Success)
++                            return rc;
++
++                        if (!newptr->isMaster)
++                        {
++                            client->errorValue = r->returnPointer;
++                            return BadDevice;
++                        }
++
++                        rc = dixLookupDevice(&newkeybd, r->returnKeyboard,
++                                             client, DixWriteAccess);
++                        if (rc != Success)
++                            return rc;
++
++                        if (!newkeybd->isMaster)
++                        {
++                            client->errorValue = r->returnKeyboard;
 +                            return BadDevice;
++                        }
 +
 +                        for (attached = inputInfo.devices;
 +                                attached;
 +                                attached = attached->next)
 +                        {
 +                            if (!attached->isMaster) {
 +                                if (attached->u.master == ptr)
 +                                    AttachDevice(client, attached, newptr);
 +                                if (attached->u.master == keybd)
 +                                    AttachDevice(client, attached, newkeybd);
 +                            }
 +                        }
 +                    }
 +
 +                    /* can't disable until we removed pairing */
 +                    keybd->spriteInfo->paired = NULL;
 +                    ptr->spriteInfo->paired = NULL;
 +                    DisableDevice(keybd);
 +                    DisableDevice(ptr);
 +
 +                    RemoveDevice(keybd);
 +                    RemoveDevice(ptr);
 +                }
 +                break;
 +            case CH_ChangeAttachment:
 +                {
 +                    xChangeAttachmentInfo* c = (xChangeAttachmentInfo*)any;
 +
-                     ptr = LookupDeviceIntRec(c->deviceid);
-                     if (!ptr || ptr->isMaster)
++                    rc = dixLookupDevice(&ptr, c->deviceid, client,
++                                          DixWriteAccess);
++                    if (rc != Success)
++                        return rc;
++
++                    if (ptr->isMaster)
++                    {
++                        client->errorValue = c->deviceid;
 +                        return BadDevice;
++                    }
 +
 +                    if (c->changeMode == Floating)
 +                        AttachDevice(client, ptr, NULL);
 +                    else
 +                    {
-                         DeviceIntPtr newmaster = LookupDeviceIntRec(c->newMaster);
-                         if (!newmaster || !newmaster->isMaster)
++                        DeviceIntPtr newmaster;
++                        rc = dixLookupDevice(&newmaster, c->newMaster,
++                                             client, DixWriteAccess);
++                        if (rc != Success)
++                            return rc;
++                        if (!newmaster->isMaster)
++                        {
++                            client->errorValue = c->newMaster;
 +                            return BadDevice;
++                        }
 +
 +                        if ((IsPointerDevice(newmaster) &&
 +                                    !IsPointerDevice(ptr)) ||
 +                                (IsKeyboardDevice(newmaster) &&
 +                                 !IsKeyboardDevice(ptr)))
 +                                return BadDevice;
 +                        AttachDevice(client, ptr, newmaster);
 +                    }
 +
 +                }
 +                break;
 +        }
 +
 +        any = (xAnyHierarchyChangeInfo*)((char*)any + any->length);
 +    }
 +
 +    ev.type = GenericEvent;
 +    ev.extension = IReqCode;
 +    ev.length = 0;
 +    ev.evtype = XI_DeviceHierarchyChangedNotify;
 +    ev.time = GetTimeInMillis();
 +
 +    SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask,
 +            (xEvent*)&ev, 1);
 +    return Success;
 +}
 +
diff --cc Xi/closedev.c
index f9a0f4f,b2b5f69..4c593ec
--- a/Xi/closedev.c
+++ b/Xi/closedev.c
@@@ -147,14 -146,14 +146,14 @@@ ProcXCloseDevice(ClientPtr client
      REQUEST(xCloseDeviceReq);
      REQUEST_SIZE_MATCH(xCloseDeviceReq);
  
-     d = LookupDeviceIntRec(stuff->deviceid);
-     if (d == NULL)
- 	return BadDevice;
+     rc = dixLookupDevice(&d, stuff->deviceid, client, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
  
 -    if (d->grab && SameClient(d->grab, client))
 -	(*d->DeactivateGrab) (d);	/* release active grab */
 +    if (d->deviceGrab.grab && SameClient(d->deviceGrab.grab, client))
 +	(*d->deviceGrab.DeactivateGrab) (d);	/* release active grab */
  
 -    /* Remove event selections from all windows for events from this device 
 +    /* Remove event selections from all windows for events from this device
       * and selected by this client.
       * Delete passive grabs from all windows for this device.      */
  
diff --cc Xi/exevents.c
index f0d288f,ac6b923..e577e3b
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@@ -73,12 -71,10 +72,13 @@@ SOFTWARE
  #include "dixevents.h"	/* DeliverFocusedEvent */
  #include "dixgrabs.h"	/* CreateGrab() */
  #include "scrnintstr.h"
 +#include "listdev.h" /* for CopySwapXXXClass */
+ #include "xace.h"
  
  #ifdef XKB
 +#include <X11/extensions/XKBproto.h>
  #include "xkbsrv.h"
 +extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
  #endif
  
  #define WID(w) ((w) ? ((w)->drawable.id) : 0)
@@@ -102,374 -103,58 +102,375 @@@ RegisterOtherDevice(DeviceIntPtr device
  {
      device->public.processInputProc = ProcessOtherEvent;
      device->public.realInputProc = ProcessOtherEvent;
 -    (device)->ActivateGrab = ActivateKeyboardGrab;
 -    (device)->DeactivateGrab = DeactivateKeyboardGrab;
  }
  
 - /*ARGSUSED*/ void
 -ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 +/**
 + * Copy the device->key into master->key and send a mapping notify to the
 + * clients if appropriate.
 + * master->key needs to be allocated by the caller.
 + *
 + * Device is the slave device. If it is attached to a master device, we may
 + * need to send a mapping notify to the client because it causes the MD
 + * to change state.
 + *
 + * Mapping notify needs to be sent in the following cases:
 + *      - different slave device on same master
 + *      - different master
 + *
 + * XXX: They way how the code is we also send a map notify if the slave device
 + * stays the same, but the master changes. This isn't really necessary though.
 + *
 + * XXX: this gives you funny behaviour with the ClientPointer. When a
 + * MappingNotify is sent to the client, the client usually responds with a
 + * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
 + * mapping, regardless of which keyboard sent the last mapping notify request.
 + * So depending on the CP setting, your keyboard may change layout in each
 + * app...
 + *
 + * This code is basically the old SwitchCoreKeyboard.
 + */
 +
 +static void
 +CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
  {
 -    BYTE *kptr;
 +    static DeviceIntPtr lastMapNotifyDevice = NULL;
 +    KeyClassPtr mk, dk; /* master, device */
 +    BOOL sendNotify = FALSE;
      int i;
 -    CARD16 modifiers;
 -    CARD16 mask;
 -    GrabPtr grab = other->grab;
 -    Bool deactivateDeviceGrab = FALSE;
 -    int key = 0, bit = 0, rootX, rootY;
 -    ButtonClassPtr b = other->button;
 -    KeyClassPtr k = other->key;
 -    ValuatorClassPtr v = other->valuator;
 -    deviceValuator *xV = (deviceValuator *) xE;
 -
 -    if (xE->u.u.type != DeviceValuator) {
 -	GetSpritePosition(&rootX, &rootY);
 -	xE->u.keyButtonPointer.rootX = rootX;
 -	xE->u.keyButtonPointer.rootY = rootY;
 -	key = xE->u.u.detail;
 -	NoticeEventTime(xE);
 -	xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state |
 -	    inputInfo.pointer->button->state;
 -	bit = 1 << (key & 7);
 +
 +    if (device == master)
 +        return;
 +
 +    dk = device->key;
 +    mk = master->key;
 +
-     if (master->devPrivates[CoreDevicePrivatesIndex].ptr != device) {
++    if (device != dixLookupPrivate(&master->devPrivates,
++                                   CoreDevicePrivateKey)) {
 +        memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH);
 +
 +        if (dk->maxKeysPerModifier)
 +        {
 +            mk->modifierKeyMap = xcalloc(8, dk->maxKeysPerModifier);
 +            if (!mk->modifierKeyMap)
 +                FatalError("[Xi] no memory for class shift.\n");
 +            memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
 +                    (8 * dk->maxKeysPerModifier));
 +        }
 +
 +        mk->maxKeysPerModifier = dk->maxKeysPerModifier;
 +        mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode;
 +        mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode;
 +        SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms);
 +
 +        /*
 +         * Copy state from the extended keyboard to core.  If you omit this,
 +         * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
 +         * cause your app to quit.  This feels wrong to me, hence the below
 +         * code.
 +         *
 +         * XXX: If you synthesise core modifier events, the state will get
 +         *      clobbered here.  You'll have to work out something sensible
 +         *      to fix that.  Good luck.
 +         */
 +
 +#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
 +        Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
 +        mk->state &= ~(KEYBOARD_MASK);
 +        mk->state |= (dk->state & KEYBOARD_MASK);
 +#undef KEYBOARD_MASK
 +        for (i = 0; i < 8; i++)
 +            mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
 +
 +#ifdef XKB
 +        if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) {
 +            if (!mk->xkbInfo || !mk->xkbInfo->desc)
 +                XkbInitDevice(master);
 +            if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True))
 +                FatalError("Couldn't pivot keymap from device to core!\n");
 +        }
 +#endif
 +
-         master->devPrivates[CoreDevicePrivatesIndex].ptr = device;
++        dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, device);
 +        sendNotify = TRUE;
 +    } else if (lastMapNotifyDevice != master)
 +        sendNotify = TRUE;
 +
 +    if (sendNotify)
 +    {
 +        SendMappingNotify(master, MappingKeyboard,
 +                           mk->curKeySyms.minKeyCode,
 +                          (mk->curKeySyms.maxKeyCode -
 +                           mk->curKeySyms.minKeyCode),
 +                          serverClient);
 +        lastMapNotifyDevice = master;
      }
 -    if (DeviceEventCallback) {
 -	DeviceEventInfoRec eventinfo;
 +}
  
 -	eventinfo.events = (xEventPtr) xE;
 -	eventinfo.count = count;
 -	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
 +/**
 + * Copies the feedback classes from device "from" into device "to". Classes
 + * are duplicated (not just flipping the pointers). All feedback classes are
 + * linked lists, the full list is duplicated.
 + *
 + * XXX: some XKB stuff is still missing.
 + */
 +static void
 +DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 +{
 +    if (from->kbdfeed)
 +    {
 +        KbdFeedbackPtr *k, it;
 +        k = &to->kbdfeed;
 +        for(it = from->kbdfeed; it; it = it->next)
 +        {
 +            *k = xcalloc(1, sizeof(KbdFeedbackClassRec));
 +            (*k)->BellProc = it->BellProc;
 +            (*k)->CtrlProc = it->CtrlProc;
 +            (*k)->ctrl     = it->ctrl;
 +            /* XXX: xkb_sli needs to be copied */
 +
 +            k = &(*k)->next;
 +        }
      }
 -    for (i = 1; i < count; i++)
 +
 +    if (from->ptrfeed)
 +    {
 +        PtrFeedbackPtr *p, it;
 +        p = &to->ptrfeed;
 +        for (it = from->ptrfeed; it; it = it->next)
 +        {
 +            *p = xcalloc(1, sizeof(PtrFeedbackClassRec));
 +            (*p)->CtrlProc = it->CtrlProc;
 +            (*p)->ctrl     = it->ctrl;
 +            /* XXX: xkb_sli needs to be copied */
 +
 +            p = &(*p)->next;
 +        }
 +    }
 +
 +    if (from->intfeed)
 +    {
 +        IntegerFeedbackPtr *i, it;
 +        i = &to->intfeed;
 +        for (it = from->intfeed; it; it = it->next)
 +        {
 +            *i = xcalloc(1, sizeof(IntegerFeedbackClassRec));
 +            (*i)->CtrlProc = it->CtrlProc;
 +            (*i)->ctrl     = it->ctrl;
 +
 +            i = &(*i)->next;
 +        }
 +    }
 +
 +    if (from->stringfeed)
 +    {
 +        StringFeedbackPtr *s, it;
 +        s = &to->stringfeed;
 +        for (it = from->stringfeed; it; it = it->next)
 +        {
 +            *s = xcalloc(1, sizeof(StringFeedbackClassRec));
 +            (*s)->CtrlProc = it->CtrlProc;
 +            (*s)->ctrl     = it->ctrl;
 +
 +            s = &(*s)->next;
 +        }
 +    }
 +
 +    if (from->bell)
 +    {
 +        BellFeedbackPtr *b, it;
 +        b = &to->bell;
 +        for (it = from->bell; it; it = it->next)
 +        {
 +            *b = xcalloc(1, sizeof(BellFeedbackClassRec));
 +            (*b)->BellProc = it->BellProc;
 +            (*b)->CtrlProc = it->CtrlProc;
 +            (*b)->ctrl     = it->ctrl;
 +
 +            b = &(*b)->next;
 +        }
 +    }
 +
 +    if (from->leds)
 +    {
 +        LedFeedbackPtr *l, it;
 +        l = &to->leds;
 +        for (it = from->leds; it; it = it->next)
 +        {
 +            *l = xcalloc(1, sizeof(LedFeedbackClassRec));
 +            (*l)->CtrlProc = it->CtrlProc;
 +            (*l)->ctrl     = it->ctrl;
 +            /* XXX: xkb_sli needs to be copied */
 +
 +            l = &(*l)->next;
 +        }
 +    }
 +}
 +
 +_X_EXPORT void
 +DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 +{
 +#define ALLOC_COPY_CLASS_IF(field, type) \
 +    if (from->field)\
 +    { \
 +        to->field = xcalloc(1, sizeof(type)); \
 +        if (!to->field) \
 +            FatalError("[Xi] no memory for class shift.\n"); \
 +        memcpy(to->field, from->field, sizeof(type)); \
 +    }
 +
 +    ALLOC_COPY_CLASS_IF(key, KeyClassRec);
 +    if (to->key)
 +    {
 +#ifdef XKB
 +        to->key->xkbInfo = NULL;
 +#endif
 +        to->key->curKeySyms.map = NULL;
 +        CopyKeyClass(from, to);
 +    }
 +
 +    if (from->valuator)
 +    {
 +        ValuatorClassPtr v;
 +        to->valuator = xalloc(sizeof(ValuatorClassRec) +
 +                from->valuator->numAxes * sizeof(AxisInfo) +
 +                from->valuator->numAxes * sizeof(unsigned int));
 +        v = to->valuator;
 +        if (!v)
 +            FatalError("[Xi] no memory for class shift.\n");
 +        memcpy(v, from->valuator, sizeof(ValuatorClassRec));
 +        v->motion = NULL;
 +        AllocateMotionHistory(to); /*XXX should be copied somehow */
 +
 +        v->axes = (AxisInfoPtr)&v[1];
 +        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
 +
 +        v->axisVal = (int*)(v->axes + from->valuator->numAxes);
 +    }
 +
 +    ALLOC_COPY_CLASS_IF(button, ButtonClassRec);
 +#ifdef XKB
 +    if (to->button)
 +    {
 +        to->button->xkb_acts = NULL;
 +        /* XXX: XkbAction needs to be copied */
 +    }
 +#endif
 +    ALLOC_COPY_CLASS_IF(focus, FocusClassRec);
 +    ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
 +    ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
 +
 +    ALLOC_COPY_CLASS_IF(kbdfeed, KbdFeedbackClassRec);
 +#ifdef XKB
 +    if (to->kbdfeed)
 +    {
 +        to->kbdfeed->xkb_sli = NULL;
 +        /* XXX: XkbSrvLedInfo needs to be copied*/
 +        to->kbdfeed->next = NULL;
 +    }
 +#endif
 +    ALLOC_COPY_CLASS_IF(ptrfeed, PtrFeedbackClassRec);
 +    if (to->ptrfeed)
 +    {
 +        to->ptrfeed->next = NULL;
 +    }
 +
 +
 +    DeepCopyFeedbackClasses(from, to);
 +}
 +
 +static void
 +ChangeMasterDeviceClasses(DeviceIntPtr device,
 +                          deviceClassesChangedEvent *dcce)
 +{
 +    DeviceIntPtr master = device->u.master;
 +    char* classbuff;
 +
 +    if (device->isMaster)
 +        return;
 +
 +    if (!master) /* if device was set floating between SIGIO and now */
 +        return;
 +
 +    dcce->deviceid     = master->id;
 +    dcce->num_classes  = 0;
 +
 +    master->public.devicePrivate = device->public.devicePrivate;
 +
 +    FreeAllDeviceClasses((ClassesPtr)&master->key);
 +    DeepCopyDeviceClasses(device, master);
 +
 +    /* event is already correct size, see comment in GetPointerEvents */
 +    classbuff = (char*)&dcce[1];
 +
 +    /* we don't actually swap if there's a NullClient, swapping is done
 +     * later when event is delivered. */
 +    CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff);
 +    SendEventToAllWindows(master, XI_DeviceClassesChangedMask,
 +                          (xEvent*)dcce, 1);
 +}
 +
 +/**
 + * Update the device state according to the data in the event.
 + *
 + * return values are
 + *   DEFAULT ... process as normal
 + *   DONT_PROCESS ... return immediately from caller
 + *   IS_REPEAT .. event is a repeat event.
 + */
 +#define DEFAULT 0
 +#define DONT_PROCESS 1
 +#define IS_REPEAT 2
 +static int
 +UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 +{
 +    int i;
 +    int key = 0,
 +        bit = 0;
 +
 +    KeyClassPtr k       = NULL;
 +    ButtonClassPtr b    = NULL;
 +    ValuatorClassPtr v  = NULL;
 +    deviceValuator *xV  = (deviceValuator *) xE;
 +    BYTE *kptr          = NULL;
 +    CARD16 modifiers    = 0,
 +           mask         = 0;
 +
 +    /* This event is always the first we get, before the actual events with
 +     * the data. However, the way how the DDX is set up, "device" will
 +     * actually be the slave device that caused the event.
 +     */
 +    if (GEIsType(xE, IReqCode, XI_DeviceClassesChangedNotify))
 +    {
 +        ChangeMasterDeviceClasses(device, (deviceClassesChangedEvent*)xE);
 +        return DONT_PROCESS; /* event has been sent already */
 +    }
 +
 +    /* currently no other generic event modifies the device */
 +    if (xE->u.u.type == GenericEvent)
 +        return DEFAULT;
 +
 +    k = device->key;
 +    v = device->valuator;
 +    b = device->button;
 +
 +
 +    if (xE->u.u.type != DeviceValuator)
 +    {
 +        key = xE->u.u.detail;
 +        bit = 1 << (key & 7);
 +    }
 +
 +    /* Update device axis */
 +    for (i = 1; i < count; i++) {
  	if ((++xV)->type == DeviceValuator) {
 -	    int first = xV->first_valuator;
  	    int *axisvals;
 +            int first = xV->first_valuator;
  
 -	    if (xV->num_valuators
 -		&& (!v
 -		    || (xV->num_valuators
 -			&& (first + xV->num_valuators > v->numAxes))))
 +	    if (xV->num_valuators &&
 +                (!v || (xV->num_valuators &&
 +                      (first + xV->num_valuators > v->numAxes))))
  		FatalError("Bad valuators reported for device %s\n",
 -			   other->name);
 -	    xV->device_state = 0;
 -	    if (k)
 -		xV->device_state |= k->state;
 -	    if (b)
 -		xV->device_state |= b->state;
 +			   device->name);
  	    if (v && v->axisVal) {
  		axisvals = v->axisVal;
  		switch (xV->num_valuators) {
@@@ -542,212 -240,55 +543,212 @@@
  
  	kptr = &b->down[key >> 3];
  	*kptr |= bit;
 -	if (other->valuator)
 -	    other->valuator->motionHintWindow = NullWindow;
 -	b->buttonsDown++;
 +	if (device->valuator)
 +	    device->valuator->motionHintWindow = NullWindow;
 +        b->buttonsDown++;
  	b->motionMask = DeviceButtonMotionMask;
 +        if (!b->map[key])
 +            return DONT_PROCESS;
 +        if (b->map[key] <= 5)
 +	    b->state |= (Button1Mask >> 1) << b->map[key];
 +	SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
 +    } else if (xE->u.u.type == DeviceButtonRelease) {
 +        if (!b)
 +            return DONT_PROCESS;
 +
 +	kptr = &b->down[key >> 3];
 +        if (!(*kptr & bit))
 +            return DONT_PROCESS;
 +	*kptr &= ~bit;
 +	if (device->valuator)
 +	    device->valuator->motionHintWindow = NullWindow;
 +        if (b->buttonsDown >= 1 && !--b->buttonsDown)
 +	    b->motionMask = 0;
 +        if (!b->map[key])
 +            return DONT_PROCESS;
 +	if (b->map[key] <= 5)
 +	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
 +	SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
 +    } else if (xE->u.u.type == ProximityIn)
 +	device->valuator->mode &= ~OutOfProximity;
 +    else if (xE->u.u.type == ProximityOut)
 +	device->valuator->mode |= OutOfProximity;
 +
 +    return DEFAULT;
 +}
 +
 +/**
 + * Main device event processing function.
 + * Called from when processing the events from the event queue.
 + * Generates core events for XI events as needed.
 + *
 + * Note that these core events are then delivered first. For passive grabs, XI
 + * events have preference over core.
 + */
 +void
 +ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 +{
 +    int i;
 +    CARD16 modifiers;
 +    GrabPtr grab = device->deviceGrab.grab;
 +    Bool deactivateDeviceGrab = FALSE;
 +    int key = 0, rootX, rootY;
 +    ButtonClassPtr b;
 +    KeyClassPtr k;
 +    ValuatorClassPtr v;
 +    deviceValuator *xV  = (deviceValuator *) xE;
 +    BOOL sendCore = FALSE;
 +    xEvent core;
 +    int coretype = 0;
 +    int ret = 0;
 +
 +    ret = UpdateDeviceState(device, xE, count);
 +    if (ret == DONT_PROCESS)
 +        return;
 +
 +    v = device->valuator;
 +    b = device->button;
 +    k = device->key;
 +
 +    coretype = XItoCoreType(xE->u.u.type);
 +    if (device->isMaster && device->coreEvents && coretype)
 +        sendCore = TRUE;
 +
 +    if (device->isMaster)
 +        CheckMotion(xE, device);
 +
 +    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;
 +	xE->u.keyButtonPointer.rootY = rootY;
 +	NoticeEventTime(xE);
 +
 +        /* If 'device' is a pointer device, we need to get the paired keyboard
 +         * for the state. If there is none, the kbd bits of state are 0.
 +         * If 'device' is a keyboard device, get the paired pointer and use the
 +         * pointer's state for the button bits.
 +         */
 +        if (IsPointerDevice(device))
 +        {
 +            kbd = GetPairedDevice(device);
 +            mouse = device;
 +        }
 +        else
 +        {
 +            mouse = GetPairedDevice(device);
 +            kbd = device;
 +        }
 +        xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0;
 +        xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0;
 +
 +        key = xE->u.u.detail;
 +    }
 +    if (DeviceEventCallback) {
 +	DeviceEventInfoRec eventinfo;
 +
 +	eventinfo.events = (xEventPtr) xE;
 +	eventinfo.count = count;
 +	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
 +    }
 +
 +    /* Valuator event handling */
 +    for (i = 1; i < count; i++) {
 +	if ((++xV)->type == DeviceValuator) {
 +	    int first = xV->first_valuator;
 +	    if (xV->num_valuators
 +		&& (!v
 +		    || (xV->num_valuators
 +			&& (first + xV->num_valuators > v->numAxes))))
 +		FatalError("Bad valuators reported for device %s\n",
 +			   device->name);
 +	    xV->device_state = 0;
 +	    if (k)
 +		xV->device_state |= k->state;
 +	    if (b)
 +		xV->device_state |= b->state;
 +	}
 +    }
 +
 +    if (xE->u.u.type == DeviceKeyPress) {
 +        if (ret == IS_REPEAT) {	/* allow ddx to generate multiple downs */
 +            modifiers = k->modifierMap[key];
 +	    if (!modifiers) {
 +		xE->u.u.type = DeviceKeyRelease;
 +		ProcessOtherEvent(xE, device, count);
 +		xE->u.u.type = DeviceKeyPress;
 +		/* release can have side effects, don't fall through */
 +		ProcessOtherEvent(xE, device, count);
 +	    }
 +	    return;
 +	}
 +        /* XI grabs have priority */
 +        core = *xE;
 +        core.u.u.type = coretype;
 +	if (!grab &&
 +              (CheckDeviceGrabs(device, xE, 0, count) ||
 +                 (sendCore && CheckDeviceGrabs(device, &core, 0, 1)))) {
 +	    device->deviceGrab.activatingKey = key;
 +	    return;
 +	}
 +    } else if (xE->u.u.type == DeviceKeyRelease) {
 +	if (device->deviceGrab.fromPassiveGrab &&
 +            (key == device->deviceGrab.activatingKey))
 +	    deactivateDeviceGrab = TRUE;
 +    } else if (xE->u.u.type == DeviceButtonPress) {
- 	xE->u.u.detail = b->map[key];
+ 	xE->u.u.detail = key;
  	if (xE->u.u.detail == 0)
  	    return;
 -	if (xE->u.u.detail <= 5)
 -	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
 -	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
 -	if (!grab)
 -	    if (CheckDeviceGrabs(other, xE, 0, count))
 +        if (!grab)
 +        {
 +            core = *xE;
 +            core.u.u.type = coretype;
 +            if (CheckDeviceGrabs(device, xE, 0, count) ||
 +                    (sendCore && CheckDeviceGrabs(device, &core, 0, 1)))
 +            {
                  /* if a passive grab was activated, the event has been sent
                   * already */
                  return;
 +            }
 +        }
  
      } else if (xE->u.u.type == DeviceButtonRelease) {
- 	xE->u.u.detail = b->map[key];
 -        if (!b)
 -            return;
 -
 -	kptr = &b->down[key >> 3];
 -	*kptr &= ~bit;
 -	if (other->valuator)
 -	    other->valuator->motionHintWindow = NullWindow;
 -        if (b->buttonsDown >= 1 && !--b->buttonsDown)
 -	    b->motionMask = 0;
+ 	xE->u.u.detail = key;
  	if (xE->u.u.detail == 0)
  	    return;
 -	if (xE->u.u.detail <= 5)
 -	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 -	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
 -	if (!b->state && other->fromPassiveGrab)
 -	    deactivateDeviceGrab = TRUE;
 -    } else if (xE->u.u.type == ProximityIn)
 -	other->valuator->mode &= ~OutOfProximity;
 -    else if (xE->u.u.type == ProximityOut)
 -	other->valuator->mode |= OutOfProximity;
 +        if (!b->state && device->deviceGrab.fromPassiveGrab)
 +            deactivateDeviceGrab = TRUE;
 +    }
 +
 +    if (sendCore)
 +    {
 +        core = *xE;
 +        core.u.u.type = coretype;
 +    }
  
      if (grab)
 -	DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count);
 -    else if (other->focus)
 -	DeliverFocusedEvent(other, xE, GetSpriteWindow(), count);
 +    {
 +        if (sendCore)                      /* never deactivate from core */
 +            DeliverGrabbedEvent(&core, device, FALSE , 1);
 +        DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
 +    }
 +    else if (device->focus)
 +    {
 +        if (sendCore)
 +            DeliverFocusedEvent(device, &core, GetSpriteWindow(device), 1);
 +	DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
 +    }
      else
 -	DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow,
 -			    other, count);
 +    {
 +        if (sendCore)
 +            DeliverDeviceEvents(GetSpriteWindow(device), &core, NullGrab,
 +                                NullWindow, device, 1);
 +	DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
 +			    device, count);
 +    }
  
      if (deactivateDeviceGrab == TRUE)
 -	(*other->DeactivateGrab) (other);
 +	(*device->deviceGrab.DeactivateGrab) (device);
  }
  
  _X_EXPORT int
@@@ -1296,8 -852,8 +1312,8 @@@ SendEvent(ClientPtr client, DeviceIntPt
  	    if (!mask)
  		break;
  	}
-     } else
+     } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
 -	(void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id));
 +	(void)(DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id));
      return Success;
  }
  
diff --cc Xi/extgrbdev.c
index 7cafdba,0000000..7738f15
mode 100644,000000..100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@@ -1,242 -1,0 +1,237 @@@
 +/*
 +
 +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 <X11/extensions/Xge.h>
 +#include "extnsionst.h"
- #include "extinit.h"	/* LookupDeviceIntRec */
 +#include "exevents.h"
 +#include "exglobals.h"
 +
 +#include "grabdev.h"    /* CreateMaskFromList */
 +
 +#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_count, n);
 +    swaps(&stuff->generic_event_count, n);
 +
 +    p = (long *)&stuff[1];
 +    for (i = 0; i < stuff->event_count; i++) {
 +	swapl(p, n);
 +	p++;
 +    }
 +
 +    for (i = 0; i < stuff->generic_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 = Success,
 +                             errval = 0,
 +                             i;
 +    WindowPtr                grab_window,
 +                             confineTo = 0;
 +    CursorPtr                cursor = NULL;
 +    struct tmask             tmp[EMASKSIZE];
 +    TimeStamp                time;
 +    XGenericEventMask*       xgeMask;
 +    GenericMaskPtr           gemasks = NULL;
 +
 +    REQUEST(xExtendedGrabDeviceReq);
 +    REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq);
 +
 +    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;
 +        goto cleanup;
 +    }
 +
-     dev = LookupDeviceIntRec(stuff->deviceid);
-     if (dev == NULL) {
-         errval = stuff->deviceid;
-         err = BadDevice;
++    err = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
++    if (err != Success) {
 +	goto cleanup;
 +    }
 +
 +
 +    if (stuff->ungrab)
 +    {
 +        ExtUngrabDevice(client, dev);
 +        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;
 +        }
 +    }
 +
 +    if (CreateMaskFromList(client,
 +                           (XEventClass*)&stuff[1],
 +                           stuff->event_count,
 +                           tmp,
 +                           dev,
 +                           X_GrabDevice) != Success)
 +        return Success;
 +
 +    time = ClientTimeToServerTime(stuff->time);
 +
 +    if (stuff->generic_event_count)
 +    {
 +        xgeMask =
 +            (XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
 +
 +        gemasks = xcalloc(1, sizeof(GenericMaskRec));
 +        gemasks->client = client;
 +        gemasks->next = NULL;
 +        gemasks->eventMask[xgeMask->extension & 0x7F] = xgeMask->evmask;
 +
 +        xgeMask++;
 +        for (i = 1; i < stuff->generic_event_count; i++, xgeMask++)
 +            gemasks->eventMask[xgeMask->extension & 0x7F]= xgeMask->evmask;
 +    }
 +
 +    ExtGrabDevice(client, dev, stuff->device_mode,
 +                  grab_window, confineTo, time, stuff->owner_events,
 +                  cursor, tmp[stuff->deviceid].mask,
 +                  gemasks);
 +
 +    if (err != Success) {
 +        errval = 0;
 +        goto cleanup;
 +    }
 +
 +cleanup:
 +
 +    if (gemasks)
 +        xfree(gemasks);
 +
 +    if (err == Success)
 +    {
 +        WriteReplyToClient(client, sizeof(xGrabDeviceReply), &rep);
 +    }
 +    else
 +    {
-         SendErrorToClient(client, IReqCode,
-                           X_ExtendedGrabDevice,
-                           errval, err);
++        return 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 --cc Xi/fakedevdata.c
index 2ebb7c3,0000000..7f2d3ec
mode 100644,000000..100644
--- a/Xi/fakedevdata.c
+++ b/Xi/fakedevdata.c
@@@ -1,128 -1,0 +1,126 @@@
 +/*
 +
 +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;
++    int rc;
 +
 +    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;
-     }
++    rc = dixLookupDevice(&dev, stuff->deviceid, client, DixWriteAccess);
++    if (rc != Success)
++        return rc;
 +
 +    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 --cc Xi/getpairp.c
index 1833a00,0000000..59ed189
mode 100644,000000..100644
--- a/Xi/getpairp.c
+++ b/Xi/getpairp.c
@@@ -1,103 -1,0 +1,104 @@@
 +/*
 +
 +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 <X11/X.h>	/* for inputstr.h    */
 +#include <X11/Xproto.h>	/* Request macro     */
 +#include "inputstr.h"	/* DeviceIntPtr      */
 +#include "windowstr.h"	/* window structure  */
 +#include <X11/extensions/XI.h>
 +#include <X11/extensions/XIproto.h>
 +#include "extnsionst.h"
- #include "extinit.h"	/* LookupDeviceIntRec */
 +#include "exevents.h"
 +#include "exglobals.h"
 +
 +#ifdef PANORAMIX
 +#include "panoramiXsrv.h"
 +#endif
 +
 +#include "getpairp.h"
 +
 +/***********************************************************************
 + *
 + * This procedure allows a client to query the paired pointer for a keyboard
 + * device.
 + *
 + */
 +
 +int
 +SProcXGetPairedPointer(ClientPtr client)
 +{
 +    char n;
 +    REQUEST(xGetPairedPointerReq);
 +    swaps(&stuff->length, n);
 +    return (ProcXGetPairedPointer(client));
 +}
 +
 +int 
 +ProcXGetPairedPointer(ClientPtr client)
 +{
 +    xGetPairedPointerReply rep;
 +    DeviceIntPtr kbd, ptr;
++    int rc;
 +
 +    REQUEST(xGetPairedPointerReq);
 +    REQUEST_SIZE_MATCH(xGetPairedPointerReq);
 +
-     kbd = LookupDeviceIntRec(stuff->deviceid);
-     if (!kbd || !kbd->key || !kbd->isMaster) {
-         SendErrorToClient(client, IReqCode, X_GetPairedPointer,
-                 stuff->deviceid, BadDevice);
-         return Success;
++    rc = dixLookupDevice(&kbd, stuff->deviceid, client, DixReadAccess);
++    if (rc != Success)
++        return rc;
++    else if (!kbd->key || !kbd->isMaster) {
++        client->errorValue = stuff->deviceid;
++        return BadDevice;
 +    }
 +
 +    ptr = GetPairedDevice(kbd);
 +
 +    rep.repType = X_Reply;
 +    rep.RepType = X_GetPairedPointer;
 +    rep.length = 0;
 +    rep.sequenceNumber = client->sequence;
 +    rep.paired = TRUE;
 +    rep.deviceid = ptr->id;
 +    WriteReplyToClient(client, sizeof(xGetPairedPointerReply), &rep);
 +    return Success;
 +}
 +
 +void
 +SRepXGetPairedPointer(ClientPtr client, int size,
 +        xGetPairedPointerReply* rep)
 +{
 +    char n;
 +
 +    swaps(&rep->sequenceNumber, n);
 +    swapl(&rep->length, n);
 +    WriteToClient(client, size, (char *)rep);
 +}
diff --cc Xi/grabdev.c
index a963aa4,110fc6b..fe58d56
--- a/Xi/grabdev.c
+++ b/Xi/grabdev.c
@@@ -182,11 -163,13 +181,13 @@@ CreateMaskFromList(ClientPtr client, XE
  
      for (i = 0; i < count; i++, list++) {
  	device = *list >> 8;
 -	if (device > 255)
 +	if (device > 255) /* FIXME: we only use 7 bit for devices? */
  	    return BadClass;
  
- 	tdev = LookupDeviceIntRec(device);
- 	if (tdev == NULL || (dev != NULL && tdev != dev))
+ 	rc = dixLookupDevice(&tdev, device, client, DixReadAccess);
+ 	if (rc != BadDevice && rc != Success)
+ 	    return rc;
+ 	if (rc == BadDevice || (dev != NULL && tdev != dev))
  	    return BadClass;
  
  	for (j = 0; j < ExtEventIndex; j++)
diff --cc Xi/grabdevb.c
index 7ef8ad7,c2661e8..a28a4ed
--- a/Xi/grabdevb.c
+++ b/Xi/grabdevb.c
@@@ -117,18 -117,23 +117,23 @@@ ProcXGrabDeviceButton(ClientPtr client
  	(sizeof(xGrabDeviceButtonReq) >> 2) + stuff->event_count)
  	return BadLength;
  
-     dev = LookupDeviceIntRec(stuff->grabbed_device);
-     if (dev == NULL)
- 	return BadDevice;
+     ret = dixLookupDevice(&dev, stuff->grabbed_device, client, DixGrabAccess);
+     if (ret != Success)
+ 	return ret;
  
      if (stuff->modifier_device != UseXKeyboard) {
- 	mdev = LookupDeviceIntRec(stuff->modifier_device);
- 	if (mdev == NULL)
- 	    return BadDevice;
+ 	ret = dixLookupDevice(&mdev, stuff->modifier_device, client,
+ 			      DixReadAccess);
+ 	if (ret != Success)
+ 	    return ret;
  	if (mdev->key == NULL)
  	    return BadMatch;
-     } else
+     } else {
 -	mdev = inputInfo.keyboard;
 +	mdev = PickKeyboard(client);
+ 	ret = XaceHook(XACE_DEVICE_ACCESS, client, mdev, DixReadAccess);
+ 	if (ret != Success)
+ 	    return ret;
+     }
  
      class = (XEventClass *) (&stuff[1]);	/* first word of values */
  
diff --cc Xi/grabdevk.c
index d38c053,43b1928..238718b
--- a/Xi/grabdevk.c
+++ b/Xi/grabdevk.c
@@@ -115,18 -115,23 +115,23 @@@ ProcXGrabDeviceKey(ClientPtr client
      if (stuff->length != (sizeof(xGrabDeviceKeyReq) >> 2) + stuff->event_count)
  	return BadLength;
  
-     dev = LookupDeviceIntRec(stuff->grabbed_device);
-     if (dev == NULL)
- 	return BadDevice;
+     ret = dixLookupDevice(&dev, stuff->grabbed_device, client, DixGrabAccess);
+     if (ret != Success)
+ 	return ret;
  
      if (stuff->modifier_device != UseXKeyboard) {
- 	mdev = LookupDeviceIntRec(stuff->modifier_device);
- 	if (mdev == NULL)
- 	    return BadDevice;
+ 	ret = dixLookupDevice(&mdev, stuff->modifier_device, client,
+ 			      DixReadAccess);
+ 	if (ret != Success)
+ 	    return ret;
  	if (mdev->key == NULL)
  	    return BadMatch;
-     } else
+     } else {
 -	mdev = inputInfo.keyboard;
 +	mdev = PickKeyboard(client);
+ 	ret = XaceHook(XACE_DEVICE_ACCESS, client, mdev, DixReadAccess);
+ 	if (ret != Success)
+ 	    return ret;
+     }
  
      class = (XEventClass *) (&stuff[1]);	/* first word of values */
  
diff --cc Xi/opendev.c
index f869df2,128b1bd..f4c0066
--- a/Xi/opendev.c
+++ b/Xi/opendev.c
@@@ -103,7 -102,12 +102,8 @@@ ProcXOpenDevice(ClientPtr client
      REQUEST(xOpenDeviceReq);
      REQUEST_SIZE_MATCH(xOpenDeviceReq);
  
-     if ((dev = LookupDeviceIntRec(stuff->deviceid)) == NULL) {	/* not open */
 -    if (stuff->deviceid == inputInfo.pointer->id ||
 -	stuff->deviceid == inputInfo.keyboard->id)
 -	return BadDevice;
 -
+     status = dixLookupDevice(&dev, stuff->deviceid, client, DixReadAccess);
+     if (status == BadDevice) {  /* not open */
  	for (dev = inputInfo.off_devices; dev; dev = dev->next)
  	    if (dev->id == stuff->deviceid)
  		break;
diff --cc Xi/querydp.c
index 85b4802,0000000..629d8ef
mode 100644,000000..100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@@ -1,167 -1,0 +1,169 @@@
 +/*
 +
 +Copyright 2006 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 query the pointer location of an extension input 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 <X11/extensions/XI.h>
 +#include <X11/extensions/XIproto.h>
 +#include "extnsionst.h"
- #include "extinit.h"	/* LookupDeviceIntRec */
 +#include "exevents.h"
 +#include "exglobals.h"
 +
 +#ifdef PANORAMIX
 +#include "panoramiXsrv.h"
 +#endif
 +
 +#include "querydp.h"
 +
 +/***********************************************************************
 + *
 + * This procedure allows a client to query the pointer of a device.
 + *
 + */
 +
 +int
 +SProcXQueryDevicePointer(ClientPtr client)
 +{
 +    char n;
 +
 +    REQUEST(xQueryDevicePointerReq);
 +    swaps(&stuff->length, n);
 +    return (ProcXQueryDevicePointer(client));
 +}
 +
 +int
 +ProcXQueryDevicePointer(ClientPtr client)
 +{
 +    int rc;
 +    xQueryDevicePointerReply rep;
 +    DeviceIntPtr pDev;
 +    WindowPtr pWin, t;
 +    SpritePtr pSprite;
 +
 +    REQUEST(xQueryDevicePointerReq);
 +    REQUEST_SIZE_MATCH(xQueryDevicePointerReq);
 +
-     pDev = LookupDeviceIntRec(stuff->deviceid);
-     if (pDev == NULL || pDev->valuator == NULL) {
-         SendErrorToClient(client, IReqCode, X_QueryDevicePointer,
-                 stuff->deviceid, BadDevice);
-         return Success;
++    rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess);
++    if (rc != Success)
++        return rc;
++
++    if (pDev->valuator == NULL)
++    {
++        client->errorValue = stuff->deviceid;
++        return BadDevice;
 +    }
 +
 +    rc = dixLookupWindow(&pWin, stuff->win, client, DixReadAccess);
 +    if (rc != Success)
 +    {
 +        SendErrorToClient(client, IReqCode, X_QueryDevicePointer,
 +                stuff->win, rc);
 +        return Success;
 +    }
 +
 +    if (pDev->valuator->motionHintWindow)
 +        MaybeStopHint(pDev, client);
 +
 +    pSprite = pDev->spriteInfo->sprite;
 +    rep.repType = X_Reply;
 +    rep.RepType = X_QueryDevicePointer;
 +    rep.length = 0;
 +    rep.sequenceNumber = client->sequence;
 +    rep.mask = pDev->button->state | inputInfo.keyboard->key->state;
 +    rep.root = (GetCurrentRootWindow(pDev))->drawable.id;
 +    rep.rootX = pSprite->hot.x;
 +    rep.rootY = pSprite->hot.y;
 +    rep.child = None;
 +    rep.shared = (pDev->spriteInfo->spriteOwner) ? xFalse : xTrue;
 +
 +    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
 +    {
 +        rep.sameScreen = xTrue;
 +        rep.winX = pSprite->hot.x - pWin->drawable.x;
 +        rep.winY = pSprite->hot.y - pWin->drawable.y;
 +        for (t = pSprite->win; t; t = t->parent)
 +            if (t->parent == pWin)
 +            {
 +                rep.child = t->drawable.id;
 +                break;
 +            }
 +    } else
 +    {
 +        rep.sameScreen = xFalse;
 +        rep.winX = 0;
 +        rep.winY = 0;
 +    }
 +
 +#ifdef PANORAMIX
 +    if(!noPanoramiXExtension) {
 +        rep.rootX += panoramiXdataPtr[0].x;
 +        rep.rootY += panoramiXdataPtr[0].y;
 +        if (stuff->win == rep.root)
 +        {
 +            rep.winX += panoramiXdataPtr[0].x;
 +            rep.winY += panoramiXdataPtr[0].y;
 +        }
 +    }
 +#endif
 +
 +    WriteReplyToClient(client, sizeof(xQueryDevicePointerReply), &rep);
 +    return Success;
 +}
 +
 +/***********************************************************************
 + *
 + * This procedure writes the reply for the XQueryDevicePointer function,
 + * if the client and server have a different byte ordering.
 + *
 + */
 +
 +void
 +SRepXQueryDevicePointer(ClientPtr client, int size,
 +        xQueryDevicePointerReply * rep)
 +{
 +    char n;
 +
 +    swaps(&rep->sequenceNumber, n);
 +    swapl(&rep->length, n);
 +    WriteToClient(client, size, (char *)rep);
 +}
 +
diff --cc Xi/setcptr.c
index a3bd9c2,0000000..8dd7181
mode 100644,000000..100644
--- a/Xi/setcptr.c
+++ b/Xi/setcptr.c
@@@ -1,113 -1,0 +1,116 @@@
 +/*
 +
 +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 set the client pointer for the owner of the given window.
 + * All subsequent calls that are ambiguous will choose the client pointer as
 + * default value.
 + */
 +
 +
 +#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 "setcptr.h"
 +
 +int
 +SProcXSetClientPointer(ClientPtr client)
 +{
 +    char n;
 +
 +    REQUEST(xSetClientPointerReq);
 +    swaps(&stuff->length, n);
 +    REQUEST_SIZE_MATCH(xSetClientPointerReq);
 +    return (ProcXSetClientPointer(client));
 +}
 +
 +int
 +ProcXSetClientPointer(ClientPtr client)
 +{
 +    DeviceIntPtr pDev;
 +    WindowPtr pWin;
 +    ClientPtr targetClient;
 +    int err;
 +
 +    REQUEST(xSetClientPointerReq);
 +    REQUEST_SIZE_MATCH(xSetClientPointerReq);
 +
 +
-     pDev = LookupDeviceIntRec(stuff->deviceid);
-     if (pDev == NULL || !IsPointerDevice(pDev) || !pDev->isMaster)
++    err = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
++    if (err != Success)
++        return err;
++
++    if (!IsPointerDevice(pDev) || !pDev->isMaster)
 +    {
 +        client->errorValue = stuff->deviceid;
 +        return BadDevice;
 +    }
 +
 +    if (stuff->win != None)
 +    {
-         err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
++        err = dixLookupWindow(&pWin, stuff->win, client, DixWriteAccess);
 +        if (err != Success)
 +        {
 +            /* window could not be found. maybe the window ID given was a pure
 +               client id? */
++            /* XXX: Needs to be fixed for XACE */
 +            err = dixLookupClient(&targetClient, stuff->win,
-                                   client, DixReadWriteAccess);
++                                  client, DixWriteAccess);
 +            if (err != Success)
 +            {
 +                client->errorValue = stuff->win;
 +                return err;
 +            }
 +        } else
 +            targetClient= wClient(pWin);
 +    } else
 +        targetClient = client;
 +
 +    if (!SetClientPointer(targetClient, client, pDev))
 +    {
 +        client->errorValue = stuff->win;
 +        return BadAccess;
 +    }
 +
 +    return Success;
 +}
diff --cc Xi/setmode.c
index d8a5695,8b6003a..2badb51
--- a/Xi/setmode.c
+++ b/Xi/setmode.c
@@@ -101,12 -101,12 +101,12 @@@ ProcXSetDeviceMode(ClientPtr client
      rep.length = 0;
      rep.sequenceNumber = client->sequence;
  
-     dev = LookupDeviceIntRec(stuff->deviceid);
-     if (dev == NULL)
- 	return BadDevice;
+     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetAttrAccess);
+     if (rc != Success)
+ 	return rc;
      if (dev->valuator == NULL)
  	return BadMatch;
 -    if ((dev->grab) && !SameClient(dev->grab, client))
 +    if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client))
  	rep.status = AlreadyGrabbed;
      else
  	rep.status = SetDeviceMode(client, dev, stuff->mode);
diff --cc Xi/ungrdev.c
index 3b6b252,7abb1d0..f6525a2
--- a/Xi/ungrdev.c
+++ b/Xi/ungrdev.c
@@@ -98,10 -98,10 +98,10 @@@ ProcXUngrabDevice(ClientPtr client
      REQUEST(xUngrabDeviceReq);
      REQUEST_SIZE_MATCH(xUngrabDeviceReq);
  
-     dev = LookupDeviceIntRec(stuff->deviceid);
-     if (dev == NULL)
- 	return BadDevice;
+     rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
 -    grab = dev->grab;
 +    grab = dev->deviceGrab.grab;
  
      time = ClientTimeToServerTime(stuff->time);
      if ((CompareTimeStamps(time, currentTime) != LATER) &&
diff --cc Xi/ungrdevb.c
index 46d3250,590699f..d1aef5f
--- a/Xi/ungrdevb.c
+++ b/Xi/ungrdevb.c
@@@ -120,9 -120,9 +120,9 @@@ ProcXUngrabDeviceButton(ClientPtr clien
  	if (mdev->key == NULL)
  	    return BadMatch;
      } else
 -	mdev = inputInfo.keyboard;
 +	mdev = PickKeyboard(client);
  
-     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixUnknownAccess);
+     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
      if (rc != Success)
  	return rc;
  
diff --cc Xi/ungrdevk.c
index 7df4095,521765e..bc3ada9
--- a/Xi/ungrdevk.c
+++ b/Xi/ungrdevk.c
@@@ -120,9 -120,9 +120,9 @@@ ProcXUngrabDeviceKey(ClientPtr client
  	if (mdev->key == NULL)
  	    return BadMatch;
      } else
 -	mdev = inputInfo.keyboard;
 +	mdev = PickKeyboard(client);
  
-     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixUnknownAccess);
+     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
      if (rc != Success)
  	return rc;
  
diff --cc Xi/warpdevp.c
index 85fa7a9,0000000..24661d0
mode 100644,000000..100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@@ -1,187 -1,0 +1,183 @@@
 +/*
 +
 +Copyright 2006 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 Warp the pointer location of an extension input 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 "warpdevp.h"
 +/***********************************************************************
 + *
 + * This procedure allows a client to warp the pointer of a device.
 + *
 + */
 +
 +int
 +SProcXWarpDevicePointer(ClientPtr client)
 +{
 +    char n;
 +
 +    REQUEST(xWarpDevicePointerReq);
 +    swaps(&stuff->length, n);
 +    return (ProcXWarpDevicePointer(client));
 +}
 +
 +int
 +ProcXWarpDevicePointer(ClientPtr client)
 +{
 +    int err;
 +    int x, y;
 +    WindowPtr dest = NULL;
 +    DeviceIntPtr pDev;
 +    SpritePtr pSprite;
 +    ScreenPtr newScreen;
 +
 +    REQUEST(xWarpDevicePointerReq);
 +    REQUEST_SIZE_MATCH(xWarpDevicePointerReq);
 +
 +    /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */
 +
-     pDev = LookupDeviceIntRec(stuff->deviceid);
-     if (pDev == NULL) {
-         SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
-                 stuff->deviceid,
-                 BadDevice);
-         return Success;
-     }
++    err = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess);
++
++    if (err != Success)
++        return err;
 +
 +    if (stuff->dst_win != None)
 +    {
 +        err = dixLookupWindow(&dest, stuff->dst_win, client, DixReadAccess);
 +        if (err != Success)
 +        {
 +            SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
 +                    stuff->dst_win, err);
 +            return Success;
 +        }
 +    }
 +
 +    pSprite = pDev->spriteInfo->sprite;
 +    x = pSprite->hotPhys.x;
 +    y = pSprite->hotPhys.y;
 +
 +    if (stuff->src_win != None)
 +    {
 +        int winX, winY;
 +        WindowPtr src;
 +
 +        err = dixLookupWindow(&src, stuff->src_win, client, DixReadAccess);
 +        if (err != Success)
 +        {
 +            SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
 +                    stuff->src_win, err);
 +            return Success;
 +        }
 +
 +        winX = src->drawable.x;
 +        winY = src->drawable.y;
 +        if (src->drawable.pScreen != pSprite->hotPhys.pScreen ||
 +                x < winX + stuff->src_x ||
 +                y < winY + stuff->src_y ||
 +                (stuff->src_width != 0 &&
 +                 winX + stuff->src_x + (int)stuff->src_width < 0) ||
 +                (stuff->src_height != 0 &&
 +                 winY + stuff->src_y + (int)stuff->src_height < y) ||
 +                !PointInWindowIsVisible(src, x, y))
 +            return Success;
 +    }
 +
 +    if (dest)
 +    {
 +        x = dest->drawable.x;
 +        y = dest->drawable.y;
 +        newScreen = dest->drawable.pScreen;
 +    } else
 +        newScreen = pSprite->hotPhys.pScreen;
 +
 +    x += stuff->dst_x;
 +    y += stuff->dst_y;
 +
 +    if (x < 0)
 +        x = 0;
 +    else if (x > newScreen->width)
 +        x = newScreen->width - 1;
 +
 +    if (y < 0)
 +        y = 0;
 +    else if (y > newScreen->height)
 +        y = newScreen->height - 1;
 +
 +    if (newScreen == pSprite->hotPhys.pScreen)
 +    {
 +        if (x < pSprite->physLimits.x1)
 +            x = pSprite->physLimits.x1;
 +        else if (x >= pSprite->physLimits.x2)
 +            x = pSprite->physLimits.x2 - 1;
 +
 +        if (y < pSprite->physLimits.y1)
 +            y = pSprite->physLimits.y1;
 +        else if (y >= pSprite->physLimits.y2)
 +            y = pSprite->physLimits.y2 - 1;
 +
 +#if defined(SHAPE)
 +        if (pSprite->hotShape)
 +            ConfineToShape(pDev, pSprite->hotShape, &x, &y);
 +#endif
 +        (*newScreen->SetCursorPosition)(pDev, newScreen, x, y, TRUE);
 +    } else if (!PointerConfinedToScreen(pDev))
 +    {
 +        NewCurrentScreen(pDev, newScreen, x, y);
 +    }
 +
 +    /* if we don't update the device, we get a jump next time it moves */
 +    pDev->lastx = x;
 +    pDev->lasty = x;
 +    miPointerUpdateSprite(pDev);
 +
 +    /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
 +       here though. */
 +    return Success;
 +}
 +
diff --cc Xi/xiselev.c
index 8740487,0000000..59f75b5
mode 100644,000000..100644
--- a/Xi/xiselev.c
+++ b/Xi/xiselev.c
@@@ -1,78 -1,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);
++    ret = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
 +    if (ret != Success)
 +    {
 +        SendErrorToClient(client, IReqCode, X_XiSelectEvent, 0, ret);
 +        return Success;
 +    }
 +
 +    GEWindowSetMask(client, pWin, IReqCode, stuff->mask);
 +
 +    return Success;
 +}
 +
diff --cc dix/cursor.c
index 5f48c83,0ddf9d7..81540fd
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@@ -59,7 -59,7 +59,8 @@@ SOFTWARE
  #include "cursorstr.h"
  #include "dixfontstr.h"
  #include "opaque.h"
 +#include "inputstr.h"
+ #include "xace.h"
  
  typedef struct _GlyphShare {
      FontPtr font;
@@@ -123,8 -123,9 +125,9 @@@ FreeCursor(pointer value, XID cid
      for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
      {
  	pscr = screenInfo.screens[nscr];
 -	(void)( *pscr->UnrealizeCursor)( pscr, pCurs);
 +        (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
      }
+     dixFreePrivates(pCurs->devPrivates);
      FreeCursorBits(pCurs->bits);
      xfree( pCurs);
      return(Success);
@@@ -171,11 -173,11 +175,12 @@@ AllocARGBCursor(unsigned char *psrcbits
  {
      CursorBitsPtr  bits;
      CursorPtr 	pCurs;
-     int		nscr;
+     int		rc, nscr;
      ScreenPtr 	pscr;
 +    DeviceIntPtr pDev; 
  
+     *ppCurs = NULL;
 -    pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
 +    pCurs = (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1);
      if (!pCurs)
      {
  	xfree(psrcbits);
@@@ -192,10 -194,11 +197,11 @@@
      bits->height = cm->height;
      bits->xhot = cm->xhot;
      bits->yhot = cm->yhot;
 +    pCurs->refcnt = 1;		
+     bits->devPrivates = NULL;
+     bits->refcnt = -1;
      CheckForEmptyMask(bits);
- 
      pCurs->bits = bits;
 -    pCurs->refcnt = 1;		
  #ifdef XFIXES
      pCurs->serialNumber = ++cursorSerial;
      pCurs->name = None;
@@@ -209,70 -212,40 +215,69 @@@
      pCurs->backGreen = backGreen;
      pCurs->backBlue = backBlue;
  
+     pCurs->id = cid;
+     pCurs->devPrivates = NULL;
+ 
+     /* security creation/labeling check */
+     rc = XaceHook(XACE_RESOURCE_ACCESS, client, cid, RT_CURSOR,
+ 		  pCurs, RT_NONE, NULL, DixCreateAccess);
+     if (rc != Success) {
+ 	dixFreePrivates(pCurs->devPrivates);
+ 	FreeCursorBits(bits);
+ 	xfree(pCurs);
+ 	return rc;
+     }
+ 	
      /*
       * realize the cursor for every screen
 +     * Do not change the refcnt, this will be changed when ChangeToCursor
 +     * actually changes the sprite.
       */
      for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
      {
 -	pscr = screenInfo.screens[nscr];
 -        if (!( *pscr->RealizeCursor)( pscr, pCurs))
 -	{
 -	    while (--nscr >= 0)
 -	    {
 -		pscr = screenInfo.screens[nscr];
 -		( *pscr->UnrealizeCursor)( pscr, pCurs);
 -	    }
 -	    dixFreePrivates(pCurs->devPrivates);
 -	    FreeCursorBits(bits);
 -	    xfree(pCurs);
 -	    return BadAlloc;
 -	}
 +        pscr = screenInfo.screens[nscr];
 +        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
 +        {
 +            if (DevHasCursor(pDev))
 +            {
 +                if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
 +                {
 +                    /* Realize failed for device pDev on screen pscr.
 +                     * We have to assume that for all devices before, realize
 +                     * worked. We need to rollback all devices so far on the
 +                     * current screen and then all devices on previous
 +                     * screens.
 +                     */
 +                    DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
 +                    while(pDevIt && pDevIt != pDev)
 +                    {
 +                        if (DevHasCursor(pDevIt))
 +                            ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
 +                        pDevIt = pDevIt->next;
 +                    }
 +                    while (--nscr >= 0)
 +                    {
 +                        pscr = screenInfo.screens[nscr];
 +                        /* now unrealize all devices on previous screens */
 +                        pDevIt = inputInfo.devices;
 +                        while (pDevIt)
 +                        {
 +                            if (DevHasCursor(pDevIt))
 +                                ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
 +                            pDevIt = pDevIt->next;
 +                        }
 +                        ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
 +                    }
++                    dixFreePrivates(pCurs->devPrivates);
 +                    FreeCursorBits(bits);
 +                    xfree(pCurs);
-                     return (CursorPtr)NULL;
++                    return BadAlloc;
 +                }
 +            }
 +        }
      }
-     return pCurs;
- }
- 
- /**
-  *
-  * \param psrcbits   server-defined padding
-  * \param pmaskbits  server-defined padding
-  */
- CursorPtr 
- AllocCursor(unsigned char *psrcbits, unsigned char *pmaskbits, 
-             CursorMetricPtr cm,
-             unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
-             unsigned backRed, unsigned backGreen, unsigned backBlue)
- {
-     return AllocCursorARGB (psrcbits, pmaskbits, (CARD32 *) 0, cm,
- 			    foreRed, foreGreen, foreBlue,
- 			    backRed, backGreen, backBlue);
+     *ppCurs = pCurs;
+     return rc;
  }
  
  int
@@@ -291,22 -264,20 +296,21 @@@ AllocGlyphCursor(Font source, unsigned 
      int		nscr;
      ScreenPtr 	pscr;
      GlyphSharePtr pShare;
 +    DeviceIntPtr pDev;
  
-     sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT,
- 						  DixReadAccess);
-     maskfont = (FontPtr) SecurityLookupIDByType(client, mask, RT_FONT,
- 						DixReadAccess);
- 
-     if (!sourcefont)
+     rc = dixLookupResource((pointer *)&sourcefont, source, RT_FONT, client,
+ 			   DixUseAccess);
+     if (rc != Success)
      {
  	client->errorValue = source;
- 	return(BadFont);
+ 	return (rc == BadValue) ? BadFont : rc;
      }
-     if (!maskfont && (mask != None))
+     rc = dixLookupResource((pointer *)&maskfont, mask, RT_FONT, client,
+ 			   DixUseAccess);
+     if (rc != Success && mask != None)
      {
  	client->errorValue = mask;
- 	return(BadFont);
+ 	return (rc == BadValue) ? BadFont : rc;
      }
      if (sourcefont != maskfont)
  	pShare = (GlyphSharePtr)NULL;
@@@ -437,51 -420,19 +455,52 @@@
       */
      for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
      {
 -	pscr = screenInfo.screens[nscr];
 -        if (!( *pscr->RealizeCursor)( pscr, pCurs))
 -	{
 -	    while (--nscr >= 0)
 -	    {
 -		pscr = screenInfo.screens[nscr];
 -		( *pscr->UnrealizeCursor)( pscr, pCurs);
 -	    }
 -	    dixFreePrivates(pCurs->devPrivates);
 -	    FreeCursorBits(pCurs->bits);
 -	    xfree(pCurs);
 -	    return BadAlloc;
 -	}
 +        pscr = screenInfo.screens[nscr];
 +
 +        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
 +        {
 +            if (DevHasCursor(pDev))
 +            {
 +                if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
 +                {
 +                    /* Realize failed for device pDev on screen pscr.
 +                     * We have to assume that for all devices before, realize
 +                     * worked. We need to rollback all devices so far on the
 +                     * current screen and then all devices on previous
 +                     * screens.
 +                     */
 +                    DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
 +                    while(pDevIt && pDevIt != pDev)
 +                    {
 +                        if (DevHasCursor(pDevIt))
 +                            ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
 +                        pDevIt = pDevIt->next;
 +                    }
 +
 +                    (*pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs);
 +
 +                    while (--nscr >= 0)
 +                    {
 +                        pscr = screenInfo.screens[nscr];
 +                        /* now unrealize all devices on previous screens */
 +                        ( *pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs);
 +
 +                        pDevIt = inputInfo.devices;
 +                        while (pDevIt)
 +                        {
 +                            if (DevHasCursor(pDevIt))
 +                                ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
 +                            pDevIt = pDevIt->next;
 +                        }
 +                        ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
 +                    }
++                    dixFreePrivates(pCurs->devPrivates);
 +                    FreeCursorBits(bits);
 +                    xfree(pCurs);
 +                    return BadAlloc;
 +                }
 +            }
 +        }
      }
      *ppCurs = pCurs;
      return Success;
diff --cc dix/devices.c
index 59db509,adf2fba..ed69cb8
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -85,13 -85,8 +86,12 @@@ SOFTWARE
   * This file handles input device-related stuff.
   */
  
- int CoreDevicePrivatesIndex = 0;
- static int CoreDevicePrivatesGeneration = -1;
- int MasterDevClassesPrivIdx = -1;
- 
 +/* The client that is allowed to change pointer-keyboard pairings. */
 +static ClientPtr pairingClient = NULL;
 +
++DevPrivateKey MasterDevClassesPrivateKey = &MasterDevClassesPrivateKey;
+ DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey;
+ 
  /**
   * Create a new input device and init it to sane values. The device is added
   * to the server's off_devices list.
@@@ -166,11 -155,15 +164,20 @@@ AddInputDevice(DeviceProc deviceProc, B
      dev->inited = FALSE;
      dev->enabled = FALSE;
  
 +    /* sprite defaults */
 +    dev->spriteInfo = (SpriteInfoPtr)&dev[1];
 +    dev->spriteInfo->sprite = NULL;
 +    dev->spriteInfo->spriteOwner = FALSE;
 +
+     /*  security creation/labeling check
+      */
+     if (XaceHook(XACE_DEVICE_ACCESS, serverClient, dev, DixCreateAccess)) {
+ 	xfree(dev);
+ 	return NULL;
+     }
+ 
+     inputInfo.numDevices++;
+ 
      for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next)
          ;
      *prev = dev;
@@@ -204,35 -193,9 +211,36 @@@ EnableDevice(DeviceIntPtr dev
  	 *prev && (*prev != dev);
  	 prev = &(*prev)->next)
  	;
 +
 +    if (!dev->spriteInfo->sprite)
 +    {
 +        if (dev->isMaster)
 +        {
 +            /* Sprites appear on first root window, so we can hardcode it */
 +            if (dev->spriteInfo->spriteOwner)
 +            {
 +                InitializeSprite(dev, WindowTable[0]);
-                 ((FocusSemaphoresPtr)(WindowTable[0])->devPrivates[FocusPrivatesIndex].ptr)->enterleave++;
++                ((FocusSemaphoresPtr)dixLookupPrivate(&(WindowTable[0])->devPrivates,
++                    FocusPrivatesKey))->enterleave++;
 +            }
 +            else if ((other = NextFreePointerDevice()) == NULL)
 +            {
 +                ErrorF("[dix] cannot find pointer to pair with. "
 +                       "This is a bug.\n");
 +                return FALSE;
 +            } else
 +                PairDevices(NULL, other, dev);
 +        } else
 +        {
 +            other = (IsPointerDevice(dev)) ? inputInfo.pointer :
 +                inputInfo.keyboard;
 +            AttachDevice(NULL, dev, other);
 +        }
 +    }
 +
      if ((*prev != dev) || !dev->inited ||
  	((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
 -        ErrorF("couldn't enable device %d\n", dev->id);
 +        ErrorF("[dix] couldn't enable device %d\n", dev->id);
  	return FALSE;
      }
      dev->enabled = TRUE;
@@@ -390,14 -318,6 +398,14 @@@ CoreKeyboardProc(DeviceIntPtr pDev, in
  
      switch (what) {
      case DEVICE_INIT:
-         if (MasterDevClassesPrivIdx == -1)
-             MasterDevClassesPrivIdx = AllocateDevicePrivateIndex();
- 
-         if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) ||
-                 !(classes = xcalloc(1, sizeof(ClassesRec))))
++        if (!(classes = xcalloc(1, sizeof(ClassesRec))))
++        {
++            ErrorF("[dix] Could not allocate device classes.\n");
++            return BadAlloc;
++        }
 +
-         pDev->devPrivates[MasterDevClassesPrivIdx].ptr = NULL;
++        dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, NULL);
 +
          keySyms.minKeyCode = 8;
          keySyms.maxKeyCode = 255;
          keySyms.mapWidth = 4;
@@@ -435,32 -355,6 +443,33 @@@
          xfree(keySyms.map);
          xfree(modMap);
  
 +        classes->key = pDev->key;
 +        classes->valuator = pDev->valuator;
 +        classes->button = pDev->button;
 +        classes->focus = pDev->focus;
 +        classes->proximity = pDev->proximity;
 +        classes->absolute = pDev->absolute;
 +        classes->kbdfeed = pDev->kbdfeed;
 +        classes->ptrfeed = pDev->ptrfeed;
 +        classes->intfeed = pDev->intfeed;
 +        classes->stringfeed = pDev->stringfeed;
 +        classes->bell = pDev->bell;
 +        classes->leds = pDev->leds;
 +
 +        /* Each time we switch classes we free the MD's classes and copy the
 +         * SD's classes into the MD. We mustn't lose the first set of classes
 +         * though as we need it to restore them when the last SD disconnects.
 +         *
 +         * So we create a fake device, seem to copy from the fake to the real
 +         * one, thus ending up with a copy of the original ones in our MD.
 +         *
 +         * If we don't do that, we're in SIGABRT territory (double-frees, etc)
 +         */
 +        memcpy(&dummy, pDev, sizeof(DeviceIntRec));
 +        DeepCopyDeviceClasses(&dummy, pDev);
 +
-         pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes;
++        dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey,
++                      classes);
          break;
  
      case DEVICE_CLOSE:
@@@ -490,43 -378,15 +499,39 @@@ CorePointerProc(DeviceIntPtr pDev, int 
  
      switch (what) {
      case DEVICE_INIT:
-         if (MasterDevClassesPrivIdx == -1)
-             MasterDevClassesPrivIdx = AllocateDevicePrivateIndex();
- 
-         if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) ||
-                 !(classes = xcalloc(1, sizeof(ClassesRec))))
++        if (!(classes = xcalloc(1, sizeof(ClassesRec))))
 +            return BadAlloc;
 +
-         pDev->devPrivates[MasterDevClassesPrivIdx].ptr = NULL;
++        dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, NULL);
 +
          for (i = 1; i <= 32; i++)
              map[i] = i;
          InitPointerDeviceStruct((DevicePtr)pDev, map, 32,
                                  GetMotionHistory, (PtrCtrlProcPtr)NoopDDA,
                                  GetMotionHistorySize(), 2);
          pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
 -        pDev->valuator->lastx = pDev->valuator->axisVal[0];
 +        pDev->lastx = pDev->valuator->axisVal[0];
          pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
 -        pDev->valuator->lasty = pDev->valuator->axisVal[1];
 +        pDev->lasty = pDev->valuator->axisVal[1];
 +
 +        classes->key = pDev->key;
 +        classes->valuator = pDev->valuator;
 +        classes->button = pDev->button;
 +        classes->focus = pDev->focus;
 +        classes->proximity = pDev->proximity;
 +        classes->absolute = pDev->absolute;
 +        classes->kbdfeed = pDev->kbdfeed;
 +        classes->ptrfeed = pDev->ptrfeed;
 +        classes->intfeed = pDev->intfeed;
 +        classes->stringfeed = pDev->stringfeed;
 +        classes->bell = pDev->bell;
 +        classes->leds = pDev->leds;
 +
 +        /* See comment in CoreKeyboardProc. */
 +        memcpy(&dummy, pDev, sizeof(DeviceIntRec));
 +        DeepCopyDeviceClasses(&dummy, pDev);
 +
-         pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes;
++        dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, classes);
          break;
  
      case DEVICE_CLOSE:
@@@ -555,23 -409,49 +560,10 @@@
  void
  InitCoreDevices(void)
  {
-     if (CoreDevicePrivatesGeneration != serverGeneration) {
-         CoreDevicePrivatesIndex = AllocateDevicePrivateIndex();
-         CoreDevicePrivatesGeneration = serverGeneration;
-     }
- 
 -    DeviceIntPtr dev;
 -
 -    if (!inputInfo.keyboard) {
 -        dev = AddInputDevice(CoreKeyboardProc, TRUE);
 -        if (!dev)
 -            FatalError("Failed to allocate core keyboard");
 -        dev->name = strdup("Virtual core keyboard");
 -#ifdef XKB
 -        dev->public.processInputProc = CoreProcessKeyboardEvent;
 -        dev->public.realInputProc = CoreProcessKeyboardEvent;
 -        if (!noXkbExtension)
 -           XkbSetExtension(dev, ProcessKeyboardEvent);
 -#else
 -        dev->public.processInputProc = ProcessKeyboardEvent;
 -        dev->public.realInputProc = ProcessKeyboardEvent;
 -#endif
 -        dev->ActivateGrab = ActivateKeyboardGrab;
 -        dev->DeactivateGrab = DeactivateKeyboardGrab;
 -        dev->coreEvents = FALSE;
 -        (void)ActivateDevice(dev);
 -        inputInfo.keyboard = dev;
 -    }
 -
 -    if (!inputInfo.pointer) {
 -        dev = AddInputDevice(CorePointerProc, TRUE);
 -        if (!dev)
 -            FatalError("Failed to allocate core pointer");
 -        dev->name = strdup("Virtual core pointer");
 -#ifdef XKB
 -        dev->public.processInputProc = CoreProcessPointerEvent;
 -        dev->public.realInputProc = CoreProcessPointerEvent;
 -        if (!noXkbExtension)
 -           XkbSetExtension(dev, ProcessPointerEvent);
 -#else
 -        dev->public.processInputProc = ProcessPointerEvent;
 -        dev->public.realInputProc = ProcessPointerEvent;
 -#endif
 -        dev->ActivateGrab = ActivatePointerGrab;
 -        dev->DeactivateGrab = DeactivatePointerGrab;
 -        dev->coreEvents = FALSE;
 -        (void)ActivateDevice(dev);
 -        inputInfo.pointer = dev;
 -    }
 +    if (AllocMasterDevice("Virtual core",
 +                          &inputInfo.pointer,
 +                          &inputInfo.keyboard) == BadAlloc)
 +        FatalError("Failed to allocate core devices");
- 
-     if (!AllocateDevicePrivate(inputInfo.keyboard, CoreDevicePrivatesIndex))
-         FatalError("Couldn't allocate keyboard devPrivates\n");
-     inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
- 
-     if (!AllocateDevicePrivate(inputInfo.pointer, CoreDevicePrivatesIndex))
-         FatalError("Couldn't allocate pointer devPrivates\n");
-     inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
  }
  
  /**
@@@ -623,233 -497,110 +615,237 @@@ InitAndStartDevices(WindowPtr root
      return Success;
  }
  
 -/**
 - * Close down a device and free all resources. 
 - * Once closed down, the driver will probably not expect you that you'll ever
 - * enable it again and free associated structs. If you want the device to just
 - * be disabled, DisableDevice().
 - * Don't call this function directly, use RemoveDevice() instead.
 - */
 -static void
 -CloseDevice(DeviceIntPtr dev)
 +_X_EXPORT void
 +FreeAllDeviceClasses(ClassesPtr classes)
  {
 -    KbdFeedbackPtr k, knext;
 -    PtrFeedbackPtr p, pnext;
 -    IntegerFeedbackPtr i, inext;
 -    StringFeedbackPtr s, snext;
 -    BellFeedbackPtr b, bnext;
 -    LedFeedbackPtr l, lnext;
 +    if (!classes)
 +        return;
 +
 +    FreeDeviceClass(KeyClass, (pointer)&classes->key);
 +    FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
 +    FreeDeviceClass(ButtonClass, (pointer)&classes->button);
 +    FreeDeviceClass(FocusClass, (pointer)&classes->focus);
 +    FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
 +
 +    FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed);
 +    FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed);
 +    FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed);
 +    FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed);
 +    FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell);
 +    FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds);
  
 -    if (dev->inited)
 -	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
 +}
  
 -    xfree(dev->name);
 +/**
 + * Free the given device class and reset the pointer to NULL.
 + */
 +_X_EXPORT void
 +FreeDeviceClass(int type, pointer *class)
 +{
 +    if (!(*class))
 +        return;
  
 -    if (dev->key) {
 +    switch(type)
 +    {
 +        case KeyClass:
 +            {
 +                KeyClassPtr* k = (KeyClassPtr*)class;
  #ifdef XKB
 -	if (dev->key->xkbInfo)
 -	    XkbFreeInfo(dev->key->xkbInfo);
 +                if ((*k)->xkbInfo)
++                {
 +                    XkbFreeInfo((*k)->xkbInfo);
++                    (*k)->xkbInfo = NULL;
++                }
  #endif
- 
 -        dev->key->xkbInfo = NULL;
 -	xfree(dev->key->curKeySyms.map);
 -	xfree(dev->key->modifierKeyMap);
 -	xfree(dev->key);
 -    }
 -
 -    if (dev->valuator) {
 -        /* Counterpart to 'biggest hack ever' in init. */
 -        if (dev->valuator->motion &&
 -            dev->valuator->GetMotionProc == GetMotionHistory)
 -            xfree(dev->valuator->motion);
 -        xfree(dev->valuator);
 -    }
 -
 -    if (dev->button) {
 +                xfree((*k)->curKeySyms.map);
 +                xfree((*k)->modifierKeyMap);
 +                xfree((*k));
 +                break;
 +            }
 +        case ButtonClass:
 +            {
 +                ButtonClassPtr *b = (ButtonClassPtr*)class;
  #ifdef XKB
 -        if (dev->button->xkb_acts)
 -            xfree(dev->button->xkb_acts);
 +                if ((*b)->xkb_acts)
 +                    xfree((*b)->xkb_acts);
  #endif
 -        xfree(dev->button);
 -    }
 +                xfree((*b));
 +                break;
 +            }
 +        case ValuatorClass:
 +            {
 +                ValuatorClassPtr *v = (ValuatorClassPtr*)class;
 +
 +                /* Counterpart to 'biggest hack ever' in init. */
 +                if ((*v)->motion && (*v)->GetMotionProc == GetMotionHistory)
 +                    xfree((*v)->motion);
 +                xfree((*v));
 +                break;
 +            }
 +        case FocusClass:
 +            {
 +                FocusClassPtr *f = (FocusClassPtr*)class;
 +                xfree((*f)->trace);
 +                xfree((*f));
 +                break;
 +            }
 +        case ProximityClass:
 +            {
 +                ProximityClassPtr *p = (ProximityClassPtr*)class;
 +                xfree((*p));
 +                break;
 +            }
  
 -    if (dev->focus) {
 -	xfree(dev->focus->trace);
 -	xfree(dev->focus);
      }
 +    *class = NULL;
 +}
 +_X_EXPORT void
 +FreeFeedbackClass(int type, pointer *class)
 +{
 +    if (!(*class))
 +        return;
  
 -    if (dev->proximity)
 -        xfree(dev->proximity);
 +    switch(type)
 +    {
 +        case KbdFeedbackClass:
 +            {
 +                KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class;
 +                KbdFeedbackPtr k, knext;
 +                for (k = (*kbdfeed); k; k = knext) {
 +                    knext = k->next;
 +#ifdef XKB
 +                    if (k->xkb_sli)
 +                        XkbFreeSrvLedInfo(k->xkb_sli);
 +#endif
 +                    xfree(k);
 +                }
 +                break;
 +            }
 +        case PtrFeedbackClass:
 +            {
 +                PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class;
 +                PtrFeedbackPtr p, pnext;
 +
 +                for (p = (*ptrfeed); p; p = pnext) {
 +                    pnext = p->next;
 +                    xfree(p);
 +                }
 +                break;
 +            }
 +        case IntegerFeedbackClass:
 +            {
 +                IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class;
 +                IntegerFeedbackPtr i, inext;
 +
 +                for (i = (*intfeed); i; i = inext) {
 +                    inext = i->next;
 +                    xfree(i);
 +                }
 +                break;
 +            }
 +        case StringFeedbackClass:
 +            {
 +                StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class;
 +                StringFeedbackPtr s, snext;
 +
 +                for (s = (*stringfeed); s; s = snext) {
 +                    snext = s->next;
 +                    xfree(s->ctrl.symbols_supported);
 +                    xfree(s->ctrl.symbols_displayed);
 +                    xfree(s);
 +                }
 +                break;
 +            }
 +        case BellFeedbackClass:
 +            {
 +                BellFeedbackPtr *bell = (BellFeedbackPtr*)class;
 +                BellFeedbackPtr b, bnext;
 +
 +                for (b = (*bell); b; b = bnext) {
 +                    bnext = b->next;
 +                    xfree(b);
 +                }
 +                break;
 +            }
 +        case LedFeedbackClass:
 +            {
 +                LedFeedbackPtr *leds = (LedFeedbackPtr*)class;
 +                LedFeedbackPtr l, lnext;
  
 -    for (k = dev->kbdfeed; k; k = knext) {
 -	knext = k->next;
 +                for (l = (*leds); l; l = lnext) {
 +                    lnext = l->next;
  #ifdef XKB
 -	if (k->xkb_sli)
 -	    XkbFreeSrvLedInfo(k->xkb_sli);
 +                    if (l->xkb_sli)
 +                        XkbFreeSrvLedInfo(l->xkb_sli);
  #endif
 -	xfree(k);
 +                    xfree(l);
 +                }
 +                break;
 +            }
      }
 +    *class = NULL;
 +}
 +/**
 + * Close down a device and free all resources.
 + * Once closed down, the driver will probably not expect you that you'll ever
 + * enable it again and free associated structs. If you want the device to just
 + * be disabled, DisableDevice().
 + * Don't call this function directly, use RemoveDevice() instead.
 + */
 +static void
 +CloseDevice(DeviceIntPtr dev)
 +{
 +    ScreenPtr screen = screenInfo.screens[0];
 +    ClassesPtr classes;
 +    int j;
  
 -    for (p = dev->ptrfeed; p; p = pnext) {
 -	pnext = p->next;
 -	xfree(p);
 -    }
 -    
 -    for (i = dev->intfeed; i; i = inext) {
 -	inext = i->next;
 -	xfree(i);
 -    }
 +    if (!dev)
 +        return;
  
 -    for (s = dev->stringfeed; s; s = snext) {
 -	snext = s->next;
 -	xfree(s->ctrl.symbols_supported);
 -	xfree(s->ctrl.symbols_displayed);
 -	xfree(s);
 -    }
 +    if (dev->inited)
 +	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
  
 -    for (b = dev->bell; b; b = bnext) {
 -	bnext = b->next;
 -	xfree(b);
 -    }
 +    /* free sprite memory */
 +    if (dev->isMaster && dev->spriteInfo->sprite)
 +        screen->DeviceCursorCleanup(dev, screen);
  
 -    for (l = dev->leds; l; l = lnext) {
 -	lnext = l->next;
 -#ifdef XKB
 -	if (l->xkb_sli)
 -	    XkbFreeSrvLedInfo(l->xkb_sli);
 -#endif
 -	xfree(l);
 +    xfree(dev->name);
 +
 +    if (dev->isMaster)
 +    {
-         classes = (ClassesPtr)dev->devPrivates[MasterDevClassesPrivIdx].ptr;
++        classes = (ClassesPtr)dixLookupPrivate(&dev->devPrivates,
++                MasterDevClassesPrivateKey);
 +        FreeAllDeviceClasses(classes);
      }
  
 +    classes = (ClassesPtr)&dev->key;
 +    FreeAllDeviceClasses(classes);
 +
  #ifdef XKB
      while (dev->xkb_interest)
  	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
  #endif
  
 -    xfree(dev->sync.event);
 +    if (DevHasCursor(dev)) {
 +        xfree(dev->spriteInfo->sprite->spriteTrace);
 +        xfree(dev->spriteInfo->sprite);
 +    }
 +
 +    /* a client may have the device set as client pointer */
 +    for (j = 0; j < currentMaxClients; j++)
 +    {
 +        if (clients[j] && clients[j]->clientPtr == dev)
 +        {
 +            clients[j]->clientPtr = NULL;
 +            clients[j]->clientPtr = PickPointer(clients[j]);
 +        }
 +    }
 +
 +    if (dev->devPrivates)
 +	xfree(dev->devPrivates);
 +
 +    xfree(dev->deviceGrab.sync.event);
+     dixFreePrivates(dev->devPrivates);
      xfree(dev);
  }
  
@@@ -1654,9 -1365,12 +1649,11 @@@ ProcSetModifierMapping(ClientPtr client
      rep.length = 0;
      rep.sequenceNumber = client->sequence;
  
-     rep.success = DoSetModifierMapping(client, (KeyCode *)&stuff[1],
-                                        stuff->numKeyPerModifier);
+     rc = DoSetModifierMapping(client, (KeyCode *)&stuff[1],
+ 			      stuff->numKeyPerModifier, &rep);
+     if (rc != Success)
+ 	return rc;
  
 -    SendMappingNotify(MappingModifier, 0, 0, client);
      for (dev = inputInfo.devices; dev; dev = dev->next)
          if (dev->key && dev->coreEvents)
              SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev);
@@@ -1668,9 -1382,15 +1665,15 @@@ in
  ProcGetModifierMapping(ClientPtr client)
  {
      xGetModifierMappingReply rep;
-     KeyClassPtr keyc = PickKeyboard(client)->key;
- 
 -    KeyClassPtr keyc = inputInfo.keyboard->key;
++    DeviceIntPtr dev = PickKeyboard(client);
++    KeyClassPtr keyc = dev->key;
+     int rc;
      REQUEST_SIZE_MATCH(xReq);
+ 
 -    rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
 -		  DixGetAttrAccess);
++    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
+ 
      rep.type = X_Reply;
      rep.numKeyPerModifier = keyc->maxKeysPerModifier;
      rep.sequenceNumber = client->sequence;
@@@ -1691,11 -1411,12 +1694,12 @@@ ProcChangeKeyboardMapping(ClientPtr cli
      REQUEST(xChangeKeyboardMappingReq);
      unsigned len;
      KeySymsRec keysyms;
 -    KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
 +    KeySymsPtr curKeySyms = &PickKeyboard(client)->key->curKeySyms;
      DeviceIntPtr pDev = NULL;
+     int rc;
      REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
  
 -    len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2);  
 +    len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2);
      if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
              return BadLength;
  
@@@ -1769,13 -1501,12 +1782,13 @@@ DoSetPointerMapping(ClientPtr client, D
  int
  ProcSetPointerMapping(ClientPtr client)
  {
-     REQUEST(xSetPointerMappingReq);
      BYTE *map;
      int ret;
 +    DeviceIntPtr ptr = PickPointer(client);
      xSetPointerMappingReply rep;
- 
+     REQUEST(xSetPointerMappingReq);
      REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
+ 
      if (client->req_len != (sizeof(xSetPointerMappingReq)+stuff->nElts+3) >> 2)
  	return BadLength;
      rep.type = X_Reply;
@@@ -1797,7 -1524,7 +1810,7 @@@
      if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue))
  	return BadValue;
  
-     ret = DoSetPointerMapping(ptr, map, stuff->nElts);
 -    ret = DoSetPointerMapping(client, inputInfo.pointer, map, stuff->nElts);
++    ret = DoSetPointerMapping(client, ptr, map, stuff->nElts);
      if (ret != Success) {
          rep.success = ret;
          WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
@@@ -1814,12 -1541,16 +1827,16 @@@ in
  ProcGetKeyboardMapping(ClientPtr client)
  {
      xGetKeyboardMappingReply rep;
-     REQUEST(xGetKeyboardMappingReq);
 -    KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
 +    DeviceIntPtr kbd = PickKeyboard(client);
 +    KeySymsPtr curKeySyms = &kbd->key->curKeySyms;
- 
+     int rc;
+     REQUEST(xGetKeyboardMappingReq);
      REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
  
 -    rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
 -		  DixGetAttrAccess);
++    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
+ 
      if ((stuff->firstKeyCode < curKeySyms->minKeyCode) ||
          (stuff->firstKeyCode > curKeySyms->maxKeyCode)) {
  	client->errorValue = stuff->firstKeyCode;
@@@ -1851,11 -1582,15 +1868,17 @@@ in
  ProcGetPointerMapping(ClientPtr client)
  {
      xGetPointerMappingReply rep;
 -    ButtonClassPtr butc = inputInfo.pointer->button;
 +    /* Apps may get different values each time they call GetPointerMapping as
 +     * the ClientPointer could change. */
-     ButtonClassPtr butc = PickPointer(client)->button;
- 
++    DeviceIntPtr ptr = PickPointer(client);
++    ButtonClassPtr butc = ptr->button;
+     int rc;
      REQUEST_SIZE_MATCH(xReq);
+ 
 -    rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer,
 -		  DixGetAttrAccess);
++    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
+ 
      rep.type = X_Reply;
      rep.sequenceNumber = client->sequence;
      rep.nElts = butc->numButtons;
@@@ -2094,11 -1830,16 +2118,16 @@@ ProcChangeKeyboardControl (ClientPtr cl
  int
  ProcGetKeyboardControl (ClientPtr client)
  {
-     int i;
-     KeybdCtrl *ctrl = &PickKeyboard(client)->kbdfeed->ctrl;
+     int rc, i;
 -    KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl;
++    DeviceIntPtr kbd = PickKeyboard(client);
++    KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl;
      xGetKeyboardControlReply rep;
- 
      REQUEST_SIZE_MATCH(xReq);
+ 
 -    rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
 -		  DixGetAttrAccess);
++    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
+ 
      rep.type = X_Reply;
      rep.length = 5;
      rep.sequenceNumber = client->sequence;
@@@ -2117,9 -1858,10 +2146,10 @@@
  int
  ProcBell(ClientPtr client)
  {
 -    DeviceIntPtr keybd = inputInfo.keyboard;
 +    DeviceIntPtr keybd = PickKeyboard(client);
      int base = keybd->kbdfeed->ctrl.bell;
      int newpercent;
+     int rc;
      REQUEST(xBellReq);
      REQUEST_SIZE_MATCH(xBellReq);
  
@@@ -2162,15 -1903,15 +2196,15 @@@
  int
  ProcChangePointerControl(ClientPtr client)
  {
 -    DeviceIntPtr mouse = inputInfo.pointer;
 +    DeviceIntPtr mouse = PickPointer(client);
      PtrCtrl ctrl;		/* might get BadValue part way through */
+     int rc;
      REQUEST(xChangePointerControlReq);
- 
      REQUEST_SIZE_MATCH(xChangePointerControlReq);
 -    
 +
      if (!mouse->ptrfeed->CtrlProc)
          return BadDevice;
 -    
 +
      ctrl = mouse->ptrfeed->ctrl;
      if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
  	client->errorValue = stuff->doAccel;
@@@ -2216,9 -1957,17 +2250,17 @@@
          }
      }
  
+     for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
+         if ((mouse->coreEvents || mouse == inputInfo.pointer) &&
+             mouse->ptrfeed && mouse->ptrfeed->CtrlProc) {
+ 	    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixSetAttrAccess);
+ 	    if (rc != Success)
+ 		return rc;
+ 	}
+     }
  
      for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
 -        if ((mouse->coreEvents || mouse == inputInfo.pointer) &&
 +        if ((mouse->coreEvents || mouse == PickPointer(client)) &&
              mouse->ptrfeed && mouse->ptrfeed->CtrlProc) {
              mouse->ptrfeed->ctrl = ctrl;
              (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl);
@@@ -2231,11 -1980,16 +2273,16 @@@
  int
  ProcGetPointerControl(ClientPtr client)
  {
 -    PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl;
 +    DeviceIntPtr ptr = PickPointer(client);
 +    PtrCtrl *ctrl = &ptr->ptrfeed->ctrl;
      xGetPointerControlReply rep;
- 
+     int rc;
      REQUEST_SIZE_MATCH(xReq);
+ 
 -    rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer,
 -		  DixGetAttrAccess);
++    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
+ 
      rep.type = X_Reply;
      rep.length = 0;
      rep.sequenceNumber = client->sequence;
@@@ -2270,14 -2024,18 +2317,18 @@@ ProcGetMotionEvents(ClientPtr client
      xGetMotionEventsReply rep;
      int i, count, xmin, xmax, ymin, ymax, rc;
      unsigned long nEvents;
 -    DeviceIntPtr mouse = inputInfo.pointer;
 +    DeviceIntPtr mouse = PickPointer(client);
      TimeStamp start, stop;
      REQUEST(xGetMotionEventsReq);
- 
      REQUEST_SIZE_MATCH(xGetMotionEventsReq);
-     rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
+ 
+     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
+     rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
      if (rc != Success)
  	return rc;
+ 
      if (mouse->valuator->motionHintWindow)
  	MaybeStopHint(mouse, client);
      rep.type = X_Reply;
@@@ -2333,274 -2091,22 +2384,277 @@@ in
  ProcQueryKeymap(ClientPtr client)
  {
      xQueryKeymapReply rep;
-     int i;
-     CARD8 *down = PickKeyboard(client)->key->down;
+     int rc, i;
 -    CARD8 *down = inputInfo.keyboard->key->down;
++    DeviceIntPtr keybd = PickKeyboard(client);
++    CARD8 *down = keybd->key->down;
  
      REQUEST_SIZE_MATCH(xReq);
      rep.type = X_Reply;
      rep.sequenceNumber = client->sequence;
      rep.length = 2;
  
-     if (XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
- 	for (i = 0; i<32; i++)
- 	    rep.map[i] = down[i];
-     else
- 	bzero((char *)&rep.map[0], 32);
 -    rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
 -		  DixReadAccess);
++    rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
+     if (rc != Success)
+ 	return rc;
+ 
+     for (i = 0; i<32; i++)
+ 	rep.map[i] = down[i];
  
      WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
 +
 +   return Success;
 +}
 +
 +/* Pair the keyboard to the pointer device. Keyboard events will follow the
 + * pointer sprite. Only applicable for master devices.
 + * If the client is set, the request to pair comes from some client. In this
 + * case, we need to check for access. If the client is NULL, it's from an
 + * internal automatic pairing, we must always permit this.
 + */
 +int
 +PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
 +{
 +    if (!ptr)
 +        return BadDevice;
 +
 +    /* Don't allow pairing for slave devices */
 +    if (!ptr->isMaster || !kbd->isMaster)
 +        return BadDevice;
 +
 +    if (ptr->spriteInfo->paired)
 +        return BadDevice;
 +
 +    if (kbd->spriteInfo->spriteOwner)
 +    {
 +        xfree(kbd->spriteInfo->sprite);
 +        kbd->spriteInfo->sprite = NULL;
 +        kbd->spriteInfo->spriteOwner = FALSE;
 +    }
 +
 +    kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
 +    kbd->spriteInfo->paired = ptr;
 +    ptr->spriteInfo->paired = kbd;
 +    return Success;
 +}
 +
 +/**
 + * Attach device 'dev' to device 'master'.
 + * Client is set to the client that issued the request, or NULL if it comes
 + * from some internal automatic pairing.
 + *
 + * Master may be NULL to set the device floating.
 + *
 + * We don't allow multi-layer hierarchies right now. You can't attach a slave
 + * to another slave.
 + */
 +int
 +AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 +{
 +    DeviceIntPtr oldmaster;
 +    if (!dev || dev->isMaster)
 +        return BadDevice;
 +
 +    if (master && !master->isMaster) /* can't attach to slaves */
 +        return BadDevice;
 +
 +    /* set from floating to floating? */
 +    if (!dev->u.master && !master)
 +        return Success;
 +
 +    /* free the existing sprite. */
 +    if (!dev->u.master && dev->spriteInfo->sprite)
 +        xfree(dev->spriteInfo->sprite);
 +
 +    oldmaster = dev->u.master;
 +    dev->u.master = master;
 +
 +    /* If device is set to floating, we need to create a sprite for it,
 +     * otherwise things go bad. However, we don't want to render the cursor,
 +     * so we reset spriteOwner.
 +     */
 +    if (!master)
 +    {
 +                              /* current root window */
 +        InitializeSprite(dev, dev->spriteInfo->sprite->spriteTrace[0]);
 +        dev->spriteInfo->spriteOwner = FALSE;
 +
 +    } else
 +        dev->spriteInfo->sprite = master->spriteInfo->sprite;
 +
 +    /* If we were connected to master device before, this MD may need to
 +     * change back to it's original classes.
 +     */
 +    if (oldmaster)
 +    {
 +        DeviceIntPtr it;
 +        for (it = inputInfo.devices; it; it = it->next)
 +            if (!it->isMaster && it->u.master == oldmaster)
 +                break;
 +
 +        if (!it)  /* no dev is paired with old master */
 +        {
 +            ClassesPtr classes;
 +            EventList event = { NULL, 0};
 +            char* classbuf;
 +            DeviceIntRec dummy;
 +
 +            FreeAllDeviceClasses((ClassesPtr)&oldmaster->key);
-             classes = oldmaster->devPrivates[MasterDevClassesPrivIdx].ptr;
++            classes = (ClassesPtr)dixLookupPrivate(&oldmaster->devPrivates,
++                                        MasterDevClassesPrivateKey);
 +            memcpy(&dummy.key, classes, sizeof(ClassesRec));
 +            DeepCopyDeviceClasses(&dummy, oldmaster);
 +
 +            /* Send event to clients */
 +            CreateClassesChangedEvent(&event, oldmaster, oldmaster);
 +            deviceClassesChangedEvent *dcce =
 +                (deviceClassesChangedEvent*)event.event;
 +            dcce->deviceid = oldmaster->id;
 +            dcce->num_classes = 0;
 +            classbuf = (char*)&event.event[1];
 +            CopySwapClasses(NullClient, oldmaster,
 +                    &dcce->num_classes, &classbuf);
 +            SendEventToAllWindows(oldmaster, XI_DeviceClassesChangedMask,
 +                    event.event, 1);
 +            xfree(event.event);
 +        }
 +    }
 +
 +    return Success;
 +}
 +
 +/**
 + * Return the device paired with the given device or NULL.
 + * Returns the device paired with the parent master if the given device is a
 + * slave device.
 + */
 +_X_EXPORT DeviceIntPtr
 +GetPairedDevice(DeviceIntPtr dev)
 +{
 +    if (!dev->isMaster && dev->u.master)
 +        dev = dev->u.master;
 +
 +    if (!dev->spriteInfo->paired)
 +        return NULL;
 +
 +    return dev->spriteInfo->paired;
 +}
 +
 +/* Guess a pointer that could be a good one for pairing. Any pointer that is
 + * not yet paired with keyboard is considered a good one.
 + * If no pointer is found, the last real pointer is chosen. If that doesn't
 + * work either, we take the core pointer.
 + */
 +DeviceIntPtr
 +GuessFreePointerDevice()
 +{
 +    DeviceIntPtr it, it2;
 +    DeviceIntPtr lastRealPtr = NULL;
 +
 +    it = inputInfo.devices;
 +
 +    while(it)
 +    {
 +        /* found device with a sprite? */
 +        if (it->spriteInfo->spriteOwner)
 +        {
 +            lastRealPtr = it;
 +
 +            it2 = inputInfo.devices;
 +            while(it2)
 +            {
 +                /* something paired with it? */
 +                if (it != it2 &&
 +                        it2->spriteInfo->sprite == it->spriteInfo->sprite)
 +                    break;
 +
 +                it2 = it2->next;
 +            }
 +
 +            /* woohoo! no pairing set up for 'it' yet */
 +            if (!it2)
 +                return it;
 +        }
 +        it = it->next;
 +    }
 +
 +    return (lastRealPtr) ? lastRealPtr : inputInfo.pointer;
 +}
 +
 +DeviceIntPtr
 +NextFreePointerDevice()
 +{
 +    DeviceIntPtr dev;
 +    for (dev = inputInfo.devices; dev; dev = dev->next)
 +        if (dev->isMaster &&
 +                dev->spriteInfo->spriteOwner &&
 +                !dev->spriteInfo->paired)
 +            return dev;
 +    return NULL;
 +}
 +/**
 + * Create a new master device (== one pointer, one keyboard device).
 + * Only allocates the devices, you will need to call ActivateDevice() and
 + * EnableDevice() manually.
 + */
 +int
 +AllocMasterDevice(char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
 +{
 +    DeviceIntPtr pointer;
 +    DeviceIntPtr keyboard;
 +    *ptr = *keybd = NULL;
 +
 +    pointer = AddInputDevice(CorePointerProc, TRUE);
 +    if (!pointer)
 +        return BadAlloc;
 +
 +    pointer->name = xcalloc(strlen(name) + strlen(" pointer") + 1, sizeof(char));
 +    strcpy(pointer->name, name);
 +    strcat(pointer->name, " pointer");
 +
 +#ifdef XKB
 +    pointer->public.processInputProc = ProcessOtherEvent;
 +    pointer->public.realInputProc = ProcessOtherEvent;
 +    if (!noXkbExtension)
 +        XkbSetExtension(pointer, ProcessPointerEvent);
 +#else
 +    pointer->public.processInputProc = ProcessPointerEvent;
 +    pointer->public.realInputProc = ProcessPointerEvent;
 +#endif
 +    pointer->deviceGrab.ActivateGrab = ActivatePointerGrab;
 +    pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
 +    pointer->coreEvents = TRUE;
 +    pointer->spriteInfo->spriteOwner = TRUE;
 +
 +    pointer->u.lastSlave = NULL;
 +    pointer->isMaster = TRUE;
 +
 +    keyboard = AddInputDevice(CoreKeyboardProc, TRUE);
 +    if (!keyboard)
 +        return BadAlloc;
 +
 +    keyboard->name = xcalloc(strlen(name) + strlen(" keyboard") + 1, sizeof(char));
 +    strcpy(keyboard->name, name);
 +    strcat(keyboard->name, " keyboard");
 +
 +#ifdef XKB
 +    keyboard->public.processInputProc = ProcessOtherEvent;
 +    keyboard->public.realInputProc = ProcessOtherEvent;
 +    if (!noXkbExtension)
 +        XkbSetExtension(keyboard, ProcessKeyboardEvent);
 +#else
 +    keyboard->public.processInputProc = ProcessKeyboardEvent;
 +    keyboard->public.realInputProc = ProcessKeyboardEvent;
 +#endif
 +    keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
 +    keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
 +    keyboard->coreEvents = TRUE;
 +    keyboard->spriteInfo->spriteOwner = FALSE;
 +
 +    keyboard->u.lastSlave = NULL;
 +    keyboard->isMaster = TRUE;
 +
 +    *ptr = pointer;
 +    *keybd = keyboard;
 +
      return Success;
  }
diff --cc dix/dispatch.c
index 34b0de1,577e17c..51be6de
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@@ -3710,58 -3751,8 +3752,10 @@@ void InitClient(ClientPtr client, int i
      client->smart_stop_tick = SmartScheduleTime;
      client->smart_check_tick = SmartScheduleTime;
  #endif
 +
 +    client->clientPtr = NULL;
  }
  
- int
- InitClientPrivates(ClientPtr client)
- {
-     char *ptr;
-     DevUnion *ppriv;
-     unsigned *sizes;
-     unsigned size;
-     int i;
- 
-     if (totalClientSize == sizeof(ClientRec))
- 	ppriv = (DevUnion *)NULL;
-     else if (client->index)
- 	ppriv = (DevUnion *)(client + 1);
-     else
-     {
- 	ppriv = (DevUnion *)xalloc(totalClientSize - sizeof(ClientRec));
- 	if (!ppriv)
- 	    return 0;
-     }
-     client->devPrivates = ppriv;
-     sizes = clientPrivateSizes;
-     ptr = (char *)(ppriv + clientPrivateLen);
-     if (ppriv)
- 	bzero(ppriv, totalClientSize - sizeof(ClientRec));
-     for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++)
-     {
- 	if ( (size = *sizes) )
- 	{
- 	    ppriv->ptr = (pointer)ptr;
- 	    ptr += size;
- 	}
- 	else
- 	    ppriv->ptr = (pointer)NULL;
-     }
- 
-     /* Allow registrants to initialize the serverClient devPrivates */
-     if (!client->index && ClientStateCallback)
-     {
- 	NewClientInfoRec clientinfo;
- 
- 	clientinfo.client = client; 
- 	clientinfo.prefix = (xConnSetupPrefix *)NULL;  
- 	clientinfo.setup = (xConnSetup *) NULL;
- 	CallCallbacks((&ClientStateCallback), (pointer)&clientinfo);
-     } 
-     return 1;
- }
- 
  /************************
   * int NextAvailableClient(ospriv)
   *
diff --cc dix/events.c
index bb42259,15aa16e..d2309eb
--- a/dix/events.c
+++ b/dix/events.c
@@@ -1352,15 -1184,7 +1352,15 @@@ FreezeThaw(DeviceIntPtr dev, Bool froze
  	dev->public.processInputProc = dev->public.realInputProc;
  }
  
 +/**
 + * Unfreeze devices and replay all events to the respective clients.
 + *
 + * ComputeFreezes takes the first event in the device's frozen event queue. It
 + * runs up the sprite tree (spriteTrace) and searches for the window to replay
 + * the events from. If it is found, it checks for passive grabs one down from
 + * the window or delivers the events.
 + */
- void
+ static void
  ComputeFreezes(void)
  {
      DeviceIntPtr replayDev = syncEvents.replayDev;
@@@ -1499,10 -1265,13 +1499,10 @@@ ScreenRestructured (ScreenPtr pScreen
 -    else
 -	ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
 -			      TRUE, FALSE);
  }
  #endif
  
- void
+ static void
  CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
  {
 -    GrabPtr grab = thisDev->grab;
 +    GrabPtr grab = thisDev->deviceGrab.grab;
      DeviceIntPtr dev;
  
      if (thisMode == GrabModeSync)
@@@ -1537,64 -1302,14 +1537,60 @@@
      ComputeFreezes();
  }
  
 +/* Only ever used if a grab is called on an attached slave device. */
- static int GrabPrivateIndex = -1;
++static DevPrivateKey GrabPrivateKey = -1;
 +typedef struct _GrabMemoryRec {
 +    DeviceIntPtr oldmaster;
 +} GrabMemoryRec, *GrabMemoryPtr;
 +
 +/**
 + * Save the device's master device in the devPrivates. This needs to be done
 + * if a client directly grabs a slave device that is attached to a master. For
 + * the duration of the grab, the device is detached, ungrabbing re-attaches it
 + * though.
 + */
 +static void
 +SaveOldMaster(DeviceIntPtr dev)
 +{
 +    GrabMemoryPtr gm;
 +
-     if (GrabPrivateIndex == -1)
-         GrabPrivateIndex = AllocateDevicePrivateIndex();
- 
-     if (!AllocateDevicePrivate(dev, GrabPrivateIndex) ||
-             !(gm = xalloc(sizeof(GrabMemoryRec))))
++    if (!(gm = xalloc(sizeof(GrabMemoryRec))))
 +    {
 +        ErrorF("[dix] Cannot allocate grab private. Grab not "
 +                "possible on device.\n");
 +        return;
 +    }
 +    gm->oldmaster = dev->u.master;
-     dev->devPrivates[GrabPrivateIndex].ptr = gm;
++    dixSetPrivate(&dev->devPrivates, GrabPrivateKey, gm);
 +}
 +
 +static void
 +RestoreOldMaster(DeviceIntPtr dev)
 +{
 +    GrabMemoryPtr gm;
 +
-     if (dev->isMaster || GrabPrivateIndex == -1)
++    if (dev->isMaster)
 +        return;
 +
-     gm = ((GrabMemoryPtr)dev->devPrivates[GrabPrivateIndex].ptr);
++    gm = (GrabMemoryPtr)dixLookupPrivate(&dev->devPrivates, GrabPrivateKey);
 +    if (gm)
 +    {
 +        dev->u.master = gm->oldmaster;
 +        xfree(gm);
-         dev->devPrivates[GrabPrivateIndex].ptr = NULL;
++        dixSetPrivate(&dev->devPrivates, GrabPrivateKey, NULL);
 +    }
 +}
 +
  /**
   * Activate a pointer grab on the given device. A pointer grab will cause all
 - * core pointer events to be delivered to the grabbing client only. Can cause
 - * the cursor to change if a grab cursor is set.
 - * 
 - * As a pointer grab can only be issued on the core devices, mouse is always
 - * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
 - * 
 + * core pointer events of this device to be delivered to the grabbing client only.
 + * No other device will send core events to the grab client while the grab is
 + * on, but core events will be sent to other clients.
 + * Can cause the cursor to change if a grab cursor is set.
 + *
 + * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
 + * is an implicit grab caused by a ButtonPress event.
 + *
   * @param mouse The device to grab.
   * @param grab The grab structure, needs to be setup.
   * @param autoGrab True if the grab was caused by a button down event and not
@@@ -2131,13 -1754,10 +2127,15 @@@ DeliverEventsToWindow(DeviceIntPtr pDev
  	if (filter != CantBeFiltered &&
  	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
  	    return 0;
 +
 +        if (!(type & EXTENSION_EVENT_BASE) &&
 +            IsInterferingGrab(wClient(pWin), pDev, pEvents))
 +                return 0;
 +
- 	if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
+ 	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
+ 	    /* do nothing */;
 -	else if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
 -					     pWin->eventMask, filter, grab)) )
++        else if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
 +				      pWin->eventMask, filter, grab)) )
  	{
  	    if (attempt > 0)
  	    {
@@@ -2150,84 -1770,41 +2148,90 @@@
      }
      if (filter != CantBeFiltered)
      {
 -	if (type & EXTENSION_EVENT_BASE)
 -	{
 -	    OtherInputMasks *inputMasks;
 +        /* Handle generic events */
 +        if (type == GenericEvent)
 +        {
 +            GenericMaskPtr pClient;
 +            /* We don't do more than one GenericEvent at a time. */
 +            if (count > 1)
 +            {
 +                ErrorF("[dix] 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)
 -	{
 -	    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
 -			 count))
 -		/* do nothing */;
 -	    else 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 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;
 +
 +            /* 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,
++                    if (XaceHook(XACE_RECEIVE_ACCESS, pClient->client, pWin,
++                                pEvents, count))
++                        /* do nothing */;
++                    else 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), pDev, pEvents))
 +                    continue;
 +
-                 if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
++                if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
++                             pEvents, count))
++                    /* do nothing */;
++                else 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))
 +    /*
 +     * Note that since core events are delivered first, an implicit grab may
 +     * be activated on a core grab, stopping the XI events.
 +     */
 +    if ((type == DeviceButtonPress || type == ButtonPress)
 +            && deliveries
 +            && (!grab))
      {
  	GrabRec tempGrab;
 +        OtherInputMasks *inputMasks;
  
 -	tempGrab.device = inputInfo.pointer;
 +        tempGrab.next = NULL;
 +	tempGrab.device = pDev;
  	tempGrab.resource = client->clientAsMask;
  	tempGrab.window = pWin;
  	tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
@@@ -2443,9 -1994,12 +2452,12 @@@ DeliverDeviceEvents(WindowPtr pWin, xEv
  {
      Window child = None;
      int type = xE->u.u.type;
 -    Mask filter = filters[type];
 +    Mask filter = filters[dev->id][type];
      int deliveries = 0;
  
+     if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count))
+ 	return 0;
+ 
      if (type & EXTENSION_EVENT_BASE)
      {
  	OtherInputMasks *inputMasks;
@@@ -3232,12 -2592,17 +3244,20 @@@ ProcWarpPointer(ClientPtr client
      WindowPtr	dest = NULL;
      int		x, y, rc;
      ScreenPtr	newScreen;
-     SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
 -    DeviceIntPtr dev;
++    DeviceIntPtr dev = PickPointer(client);
++    SpritePtr   pSprite = dev->spriteInfo->sprite;
 +
      REQUEST(xWarpPointerReq);
- 
      REQUEST_SIZE_MATCH(xWarpPointerReq);
  
++    /* XXX XACE ??*/
+     for (dev = inputInfo.devices; dev; dev = dev->next) {
+         if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) {
+ 	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
+ 	    if (rc != Success)
+ 		return rc;
+ 	}
+     }
  #ifdef PANORAMIX
      if(!noPanoramiXExtension)
  	return XineramaWarpPointer(client);
@@@ -3254,10 -2619,10 +3274,10 @@@
      if (stuff->srcWid != None)
      {
  	int     winX, winY;
 - 	XID 	winID = stuff->srcWid;
 +	XID	winID = stuff->srcWid;
          WindowPtr source;
 -	
 +
- 	rc = dixLookupWindow(&source, winID, client, DixReadAccess);
+ 	rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
  	if (rc != Success)
  	    return rc;
  
@@@ -3400,20 -2755,15 +3420,18 @@@ CheckPassiveGrabsOnWindow
  	else
  	    tempGrab.modifiersDetail.exact =
  #ifdef XKB
 -		(noXkbExtension ? gdev->key->state : xkbi->state.grab_mods);
 +                (noXkbExtension) ?
 +                        ((gdev) ? gdev->key->state : 0) :
 +                        ((xkbi) ? xkbi->state.grab_mods : 0);
  #else
 -		grab->modifierDevice->key->state;
 +                (gdev) ? gdev->key->state : 0;
  #endif
 -	if (GrabMatchesSecond(&tempGrab, grab) &&
 +            /* ignore the device for core events when comparing grabs */
 +	if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) &&
  	    (!grab->confineTo ||
 -	     (grab->confineTo->realized && 
 -				BorderSizeNotEmpty(grab->confineTo))))
 +	     (grab->confineTo->realized &&
 +				BorderSizeNotEmpty(device, grab->confineTo))))
  	{
- 	    if (!XaceHook(XACE_DEVICE_ACCESS, wClient(pWin), device, FALSE))
- 		return FALSE;
  #ifdef XKB
  	    if (!noXkbExtension) {
  		XE_KBPTR.state &= 0x1f00;
@@@ -3590,13 -2897,13 +3608,15 @@@ DeliverFocusedEvent(DeviceIntPtr keybd
  	if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
  	    return;
      }
 +    pointer = GetPairedDevice(keybd);
+     if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count))
+ 	return;
      /* just deliver it to the focus window */
 -    FixUpEventFromWindow(xE, focus, None, FALSE);
 +    FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
      if (xE->u.u.type & EXTENSION_EVENT_BASE)
  	mskidx = keybd->id;
 -    (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
 +    (void)DeliverEventsToWindow(keybd, focus, xE, count,
 +                                filters[keybd->id][xE->u.u.type],
  				NullGrab, mskidx);
  }
  
@@@ -3646,49 -2947,28 +3666,54 @@@ DeliverGrabbedEvent(xEvent *xE, DeviceI
      }
      if (!deliveries)
      {
 -	FixUpEventFromWindow(xE, grab->window, None, TRUE);
 -	if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xE, count) ||
 -	    XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), grab->window, xE,
 -		     count))
 -	    deliveries = 1; /* don't send, but pretend we did */
 -	else
 -	    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
 -#endif
 -			   ))
 -	    thisDev->valuator->motionHintWindow = grab->window;
 +        if (ACDeviceAllowed(grab->window, thisDev, xE))
 +        {
 +            if (xE->u.u.type == GenericEvent)
 +            {
 +                /* find evmask for event's extension */
 +                xGenericEvent* ge = ((xGenericEvent*)xE);
 +                GenericMaskPtr    gemask = grab->genericMasks;
 +
 +                if (!gemask || !gemask->eventMask[GEEXTIDX(ge)])
 +                    return;
 +
 +                if (GEEventFill(xE))
 +                    GEEventFill(xE)(ge, thisDev, grab->window, grab);
 +                deliveries = TryClientEvents(rClient(grab), xE, count,
 +                        gemask->eventMask[GEEXTIDX(ge)],
 +                        generic_filters[GEEXTIDX(ge)][ge->evtype],
 +                        grab);
 +            } else
 +            {
 +                Mask mask = grab->eventMask;
 +                if (grabinfo->fromPassiveGrab  &&
 +                        grabinfo->implicitGrab &&
 +                        (xE->u.u.type & EXTENSION_EVENT_BASE))
 +                    mask = grab->deviceMask;
 +
 +                FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
 +
-                 if (!(!(xE->u.u.type & EXTENSION_EVENT_BASE) &&
++                if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xE,
++                            count) ||
++                    XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), grab->window,
++                             xE, count))
++                    deliveries = 1; /* don't send, but pretend we did */
++                else if (!(!(xE->u.u.type & EXTENSION_EVENT_BASE) &&
 +                        IsInterferingGrab(rClient(grab), thisDev, xE)))
 +                {
 +                    deliveries = TryClientEvents(rClient(grab), xE, count,
 +                            mask, filters[thisDev->id][xE->u.u.type], grab);
 +                }
 +            }
 +            if (deliveries && (xE->u.u.type == MotionNotify
 +                        || xE->u.u.type == DeviceMotionNotify))
 +                thisDev->valuator->motionHintWindow = grab->window;
 +        }
      }
 -    if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
 -#ifdef XINPUT
 -					  && xE->u.u.type != DeviceMotionNotify
 -#endif
 -					  ))
 -	switch (thisDev->sync.state)
 +    if (deliveries && !deactivateGrab &&
 +       (xE->u.u.type != MotionNotify && xE->u.u.type != DeviceMotionNotify))
 +    {
 +	switch (grabinfo->sync.state)
  	{
  	case FREEZE_BOTH_NEXT_EVENT:
  	    for (dev = inputInfo.devices; dev; dev = dev->next)
@@@ -4288,109 -3594,40 +4323,109 @@@ EnterLeaveEvent
      {
  	mask = pWin->eventMask | wOtherEventMasks(pWin);
      }
 -    if (mask & filters[type])
 -    {
 -	event.u.u.type = type;
 -	event.u.u.detail = detail;
 -	event.u.enterLeave.time = currentTime.milliseconds;
 -	event.u.enterLeave.rootX = sprite.hot.x;
 -	event.u.enterLeave.rootY = sprite.hot.y;
 -	/* Counts on the same initial structure of crossing & button events! */
 -	FixUpEventFromWindow(&event, pWin, None, FALSE);
 -	/* Enter/Leave events always set child */
 -	event.u.enterLeave.child = child;
 -	event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
 -					    ELFlagSameScreen : 0;
 +
 +    event.u.u.type = type;
 +    event.u.u.detail = detail;
 +    event.u.enterLeave.time = currentTime.milliseconds;
 +    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
 +    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
 +    /* Counts on the same initial structure of crossing & button events! */
 +    FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
 +    /* Enter/Leave events always set child */
 +    event.u.enterLeave.child = child;
 +    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
 +        ELFlagSameScreen : 0;
  #ifdef XKB
 -	if (!noXkbExtension) {
 -	    event.u.enterLeave.state = mouse->button->state & 0x1f00;
 -	    event.u.enterLeave.state |= 
 -			XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
 -	} else
 +    if (!noXkbExtension) {
 +        event.u.enterLeave.state = mouse->button->state & 0x1f00;
 +        if (keybd)
 +            event.u.enterLeave.state |=
 +                XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
 +    } else
  #endif
 -	event.u.enterLeave.state = keybd->key->state | mouse->button->state;
 -	event.u.enterLeave.mode = mode;
 -	focus = keybd->focus->win;
 -	if ((focus != NoneWin) &&
 -	    ((pWin == focus) || (focus == PointerRootWin) ||
 -	     IsParent(focus, pWin)))
 -	    event.u.enterLeave.flags |= ELFlagFocus;
 -	if (grab)
 -	    (void)TryClientEvents(rClient(grab), &event, 1, mask,
 -				  filters[type], grab);
 +    {
 +        event.u.enterLeave.state = (keybd) ? keybd->key->state : 0;
 +        event.u.enterLeave.state |= mouse->button->state;
 +    }
 +    event.u.enterLeave.mode = mode;
 +    focus = (keybd) ? keybd->focus->win : None;
 +    if ((focus != NoneWin) &&
 +            ((pWin == focus) || (focus == PointerRootWin) ||
 +             IsParent(focus, pWin)))
 +        event.u.enterLeave.flags |= ELFlagFocus;
 +
-     inWindow = &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave;
++    inWindow = &((FocusSemaphoresPtr)dixLookupPrivate(&pWin->devPrivates, FocusPrivatesKey))->enterleave;
 +
 +    /*
 +     * Sending multiple core enter/leave events to the same window confuse the
 +     * client.
 +     * We can send multiple events that have detail NotifyVirtual or
 +     * NotifyNonlinearVirtual however. For most clients anyway.
 +     *
 +     * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
 +     * we only send an enter event for the first pointer to enter. A leave
 +     * event is sent for the last pointer to leave.
 +     *
 +     * For events with Virtual detail, we send them only to a window that does
 +     * not have a pointer inside.
 +     *
 +     * For a window tree in the form of
 +     *
 +     * A -> Bp -> C -> D
 +     *  \               (where B and E have pointers)
 +     *    -> Ep
 +     *
 +     * If the pointer moves from E into D, a LeaveNotify is sent to E, an
 +     * EnterNotify is sent to D, an EnterNotify with detail
 +     * NotifyNonlinearVirtual to C and nothing to B.
 +     */
 +
 +    if (event.u.u.detail != NotifyVirtual &&
 +            event.u.u.detail != NotifyNonlinearVirtual)
 +    {
 +        if (((*inWindow) == (LeaveNotify - type)))
 +            sendevent = TRUE;
 +    } else
 +    {
 +        if (!(*inWindow))
 +            sendevent = TRUE;
 +    }
 +
 +    if ((mask & filters[mouse->id][type]) && sendevent)
 +    {
 +        if (grab)
 +            (void)TryClientEvents(rClient(grab), &event, 1, mask,
 +                                  filters[mouse->id][type], grab);
 +        else
 +            (void)DeliverEventsToWindow(mouse, pWin, &event, 1,
 +                                  filters[mouse->id][type], 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);
 +    if (inputMasks &&
 +       (filters[mouse->id][devEnterLeave->type] &
 +            inputMasks->deliverableEvents[mskidx]))
 +    {
 +        if (devgrab)
 +            (void)TryClientEvents(rClient(devgrab), (xEvent*)devEnterLeave, 1,
 +                                mask, filters[mouse->id][devEnterLeave->type],
 +                                devgrab);
  	else
 -	    (void)DeliverEventsToWindow(pWin, &event, 1, filters[type],
 -					NullGrab, 0);
 +	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave,
 +                                   1, filters[mouse->id][devEnterLeave->type],
 +                                   NullGrab, mouse->id);
      }
 +
      if ((type == EnterNotify) && (mask & KeymapStateMask))
      {
  	xKeymapEvent ke;
@@@ -4454,27 -3682,6 +4489,27 @@@ LeaveNotifies(DeviceIntPtr pDev
      }
  }
  
 +/* welcome to insanity */
 +#define FOCUS_SEMAPHORE_MODIFY(win, field, mode, val) \
 +{ \
 +    FocusSemaphoresPtr sem;\
-     sem = (FocusSemaphoresPtr)win->devPrivates[FocusPrivatesIndex].ptr; \
++    sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \
 +    if (mode != NotifyGrab && mode != NotifyUngrab) { \
 +        sem->field += val; \
 +    } else if (mode == NotifyUngrab) { \
 +        if (sem->field == 0 && val > 0) \
 +            sem->field += val; \
 +        else if (sem->field == 1 && val < 0) \
 +            sem->field += val; \
 +    } \
 +}
 +#define ENTER_LEAVE_SEMAPHORE_UP(win, mode)  \
 +        FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode, 1);
 +
 +#define ENTER_LEAVE_SEMAPHORE_DOWN(win, mode) \
 +        FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode,  -1);
 +
 +
  /**
   * Figure out if enter/leave events are necessary and send them to the
   * appropriate windows.
@@@ -4528,81 -3721,33 +4563,82 @@@ static voi
  FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
  {
      xEvent event;
 +    int* numFoci; /* no of foci the window has already */
 +    Bool sendevent = FALSE;
  
 -#ifdef XINPUT
      if (dev != inputInfo.keyboard)
 -    {
  	DeviceFocusEvent(dev, type, mode, detail, pWin);
 -	return;
 -    }
 -#endif
 -    event.u.focus.mode = mode;
 -    event.u.u.type = type;
 -    event.u.u.detail = detail;
 -    event.u.focus.window = pWin->drawable.id;
 -    (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab,
 -				0);
 -    if ((type == FocusIn) &&
 -	((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
 +
 +    /*
 +     * Same procedure as for Enter/Leave events.
 +     *
 +     * Sending multiple core FocusIn/Out events to the same window may confuse
 +     * the client.
 +     * We can send multiple events that have detail NotifyVirtual,
 +     * NotifyNonlinearVirtual, NotifyPointerRoot, NotifyDetailNone or
 +     * NotifyPointer however.
 +     *
 +     * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
 +     * we only send an FocusIn event for the first kbd to set the focus. A
 +     * FocusOut event is sent for the last kbd to set the focus away from the
 +     * window.
 +     *
 +     * For events with Virtual detail, we send them only to a window that does
 +     * not have a focus from another keyboard.
 +     *
 +     * For a window tree in the form of
 +     *
 +     * A -> Bf -> C -> D
 +     *  \               (where B and E have focus)
 +     *    -> Ef
 +     *
 +     * If the focus changes from E into D, a FocusOut is sent to E, a
 +     * FocusIn is sent to D, a FocusIn with detail
 +     * NotifyNonlinearVirtual to C and nothing to B.
 +     */
 +
 +    numFoci =
-         &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout;
++        &((FocusSemaphoresPtr)dixLookupPrivate(&pWin->devPrivates,
++                    FocusPrivatesKey))->focusinout;
 +    if (mode == NotifyGrab || mode == NotifyUngrab)
 +        sendevent = TRUE;
 +    else if (detail != NotifyVirtual &&
 +            detail != NotifyNonlinearVirtual &&
 +            detail != NotifyPointer &&
 +            detail != NotifyPointerRoot &&
 +            detail != NotifyDetailNone)
 +    {
 +        (type == FocusIn) ? (*numFoci)++ : (*numFoci)--;
 +        if (((*numFoci) == (FocusOut - type)))
 +            sendevent = TRUE;
 +    } else
      {
 -	xKeymapEvent ke;
 -	ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
 -	if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess))
 -	    bzero((char *)&ke.map[0], 31);
 -	else
 -	    memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
 +        if (!(*numFoci))
 +            sendevent = TRUE;
 +    }
  
 -	ke.type = KeymapNotify;
 -	(void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
 -				    KeymapStateMask, NullGrab, 0);
 +    if (sendevent)
 +    {
 +        event.u.focus.mode = mode;
 +        event.u.u.type = type;
 +        event.u.u.detail = detail;
 +        event.u.focus.window = pWin->drawable.id;
 +        (void)DeliverEventsToWindow(dev, pWin, &event, 1,
 +                                    filters[dev->id][type], NullGrab, 0);
 +        if ((type == FocusIn) &&
 +                ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
 +        {
 +            xKeymapEvent ke;
 +            ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
 +            if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
 +                memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
 +            else
 +                bzero((char *)&ke.map[0], 31);
 +
 +            ke.type = KeymapNotify;
 +            (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
 +                                        KeymapStateMask, NullGrab, 0);
 +        }
      }
  }
  
@@@ -4830,14 -3966,12 +4866,14 @@@ SetInputFocus
      if ((focusID == None) || (focusID == PointerRoot))
  	focusWin = (WindowPtr)(long)focusID;
      else if ((focusID == FollowKeyboard) && followOK)
 -	focusWin = inputInfo.keyboard->focus->win;
 +    {
 +	focusWin = keybd->focus->win;
 +    }
      else {
- 	rc = dixLookupWindow(&focusWin, focusID, client, DixReadAccess);
+ 	rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
  	if (rc != Success)
  	    return rc;
 - 	/* It is a match error to try to set the input focus to an 
 +	/* It is a match error to try to set the input focus to an
  	unviewable window. */
  	if(!focusWin->realized)
  	    return(BadMatch);
@@@ -4895,10 -4032,7 +4935,7 @@@ ProcSetInputFocus(client
  
      REQUEST_SIZE_MATCH(xSetInputFocusReq);
  
-     if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
- 	return Success;
- 
 -    return SetInputFocus(client, inputInfo.keyboard, stuff->focus,
 +    return SetInputFocus(client, kbd, stuff->focus,
  			 stuff->revertTo, stuff->time, FALSE);
  }
  
@@@ -4911,12 -4045,17 +4948,17 @@@
  int
  ProcGetInputFocus(ClientPtr client)
  {
 +    DeviceIntPtr kbd = PickKeyboard(client);
      xGetInputFocusReply rep;
-     /* REQUEST(xReq); */
 -    FocusClassPtr focus = inputInfo.keyboard->focus;
 +    FocusClassPtr focus = kbd->focus;
- 
+     int rc;
+     /* REQUEST(xReq); */
      REQUEST_SIZE_MATCH(xReq);
+ 
 -    rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
 -		  DixGetFocusAccess);
++    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
+     if (rc != Success)
+ 	return rc;
+ 
      rep.type = X_Reply;
      rep.length = 0;
      rep.sequenceNumber = client->sequence;
@@@ -4952,8 -4085,8 +4994,9 @@@ ProcGrabPointer(ClientPtr client
      CursorPtr cursor, oldCursor;
      REQUEST(xGrabPointerReq);
      TimeStamp time;
+     Mask access_mode = DixGrabAccess;
      int rc;
 +    DeviceIntPtr grabbed = NULL;
  
      REQUEST_SIZE_MATCH(xGrabPointerReq);
      UpdateCurrentTime();
@@@ -4984,10 -4117,10 +5027,10 @@@
  	return rc;
      if (stuff->confineTo == None)
  	confineTo = NullWindow;
 -    else 
 +    else
      {
  	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
- 			     DixReadAccess);
+ 			     DixSetAttrAccess);
  	if (rc != Success)
  	    return rc;
      }
@@@ -5108,43 -4218,14 +5159,43 @@@ ProcChangeActivePointerGrab(ClientPtr c
  	newCursor = NullCursor;
      else
      {
- 	newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
- 						RT_CURSOR, DixReadAccess);
- 	if (!newCursor)
+ 	int rc = dixLookupResource((pointer *)&newCursor, stuff->cursor,
+ 				   RT_CURSOR, client, DixUseAccess);
+ 	if (rc != Success)
  	{
  	    client->errorValue = stuff->cursor;
- 	    return BadCursor;
+ 	    return (rc == BadValue) ? BadCursor : rc;
  	}
      }
 +
 +    device = PickPointer(client);
 +    grab = device->deviceGrab.grab;
 +
 +    if (!grab || !SameClient(grab, client))
 +    {
 +        /* no grab on ClientPointer, or some other client has a grab on our
 +         * ClientPointer, let's check if we have a pointer grab on some other
 +         * device. */
 +        for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
 +        {
 +            if (IsPointerDevice(grabbed))
 +            {
 +                grab = grabbed->deviceGrab.grab;
 +                if (grab && grab->coreGrab && SameClient(grab, client))
 +                {
 +                    device = grabbed;
 +                    break;
 +                }
 +            }
 +        }
 +        /* nope. no grab on any actual device */
 +        if (!grabbed)
 +        {
 +            device = inputInfo.pointer;
 +            grab = inputInfo.pointer->deviceGrab.grab;
 +        }
 +    }
 +
      if (!grab)
  	return Success;
      if (!SameClient(grab, client))
@@@ -5245,8 -4295,8 +5296,9 @@@ GrabDevice(ClientPtr client, DeviceIntP
      WindowPtr pWin;
      GrabPtr grab;
      TimeStamp time;
+     Mask access_mode = DixGrabAccess;
      int rc;
 +    GrabInfoPtr grabInfo = &dev->deviceGrab;
  
      UpdateCurrentTime();
      if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
@@@ -5264,11 -4314,18 +5316,18 @@@
  	client->errorValue = ownerEvents;
          return BadValue;
      }
-     rc = dixLookupWindow(&pWin, grabWindow, client, DixReadAccess);
+ 
+     rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
+     if (rc != Success)
+ 	return rc;
+     if (this_mode == GrabModeSync || other_mode == GrabModeSync)
+ 	access_mode |= DixFreezeAccess;
+     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
      if (rc != Success)
  	return rc;
+ 
      time = ClientTimeToServerTime(ctime);
 -    grab = dev->grab;
 +    grab = grabInfo->grab;
      if (grab && !SameClient(grab, client))
  	*status = AlreadyGrabbed;
      else if (!pWin->realized)
@@@ -5371,32 -4367,10 +5430,25 @@@ ProcGrabKeyboard(ClientPtr client
  
      REQUEST_SIZE_MATCH(xGrabKeyboardReq);
  
 -    result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode,
 -			stuff->pointerMode, stuff->grabWindow,
 -			stuff->ownerEvents, stuff->time,
 -			KeyPressMask | KeyReleaseMask, &rep.status);
 +    for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
 +    {
 +	if (IsKeyboardDevice(grabbed))
 +	{
 +	    grab = grabbed->deviceGrab.grab;
 +	    if (grab && grab->coreGrab && SameClient(grab, client))
 +	    {
 +		keyboard = grabbed;
 +		break;
 +	    }
 +	}
 +    }
++    result = GrabDevice(client, keyboard, stuff->keyboardMode,
++            stuff->pointerMode, stuff->grabWindow,
++            stuff->ownerEvents, stuff->time,
++            KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
 +
-     if (XaceHook(XACE_DEVICE_ACCESS, client, keyboard, TRUE))
-     {
- 	result = GrabDevice(client, keyboard, stuff->keyboardMode,
- 			    stuff->pointerMode, stuff->grabWindow,
- 			    stuff->ownerEvents, stuff->time,
- 			    KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
-         /* ensure only one core keyboard grab by this client */
-         RemoveOtherCoreGrabs(client, keyboard);
-     }
-     else {
- 	result = Success;
- 	rep.status = AlreadyGrabbed;
-     }
++    /* ensure only one core keyboard grab by this client */
++    RemoveOtherCoreGrabs(client, keyboard);
  
      if (result != Success)
  	return result;
@@@ -5466,16 -4415,18 +5518,19 @@@ ProcQueryPointer(ClientPtr client
  {
      xQueryPointerReply rep;
      WindowPtr pWin, t;
 -    DeviceIntPtr mouse = inputInfo.pointer;
 +    DeviceIntPtr mouse = PickPointer(client);
 +    SpritePtr pSprite = mouse->spriteInfo->sprite;
      int rc;
- 
      REQUEST(xResourceReq);
- 
      REQUEST_SIZE_MATCH(xResourceReq);
-     rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
+ 
+     rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
+     rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
      if (rc != Success)
  	return rc;
+ 
      if (mouse->valuator->motionHintWindow)
  	MaybeStopHint(mouse, client);
      rep.type = X_Reply;
@@@ -5655,8 -4613,11 +5710,11 @@@ ProcSendEvent(ClientPtr client
      {
  	for (;pWin; pWin = pWin->parent)
  	{
+ 	    if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
+ 			 &stuff->event, 1))
+ 		return Success;
 -	    if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
 -				      NullGrab, 0))
 +            if (DeliverEventsToWindow(PickPointer(client), pWin,
 +                        &stuff->event, 1, stuff->eventMask, NullGrab, 0))
  		return Success;
  	    if (pWin == effectiveFocus)
  		return Success;
@@@ -5665,9 -4626,9 +5723,9 @@@
  		break;
  	}
      }
-     else
+     else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
 -	(void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
 -				    NullGrab, 0);
 +        (void)DeliverEventsToWindow(PickPointer(client), pWin, &stuff->event,
 +                                    1, stuff->eventMask, NullGrab, 0);
      return Success;
  }
  
@@@ -5794,7 -4754,7 +5852,8 @@@ ProcGrabButton(ClientPtr client
      REQUEST(xGrabButtonReq);
      CursorPtr cursor;
      GrabPtr grab;
-     DeviceIntPtr pointer, modifierDevice;
++    DeviceIntPtr ptr, modifierDevice;
+     Mask access_mode = DixGrabAccess;
      int rc;
  
      REQUEST_SIZE_MATCH(xGrabButtonReq);
@@@ -5846,17 -4807,21 +5906,24 @@@
  	if (!cursor)
  	{
  	    client->errorValue = stuff->cursor;
- 	    return BadCursor;
+ 	    return (rc == BadValue) ? BadCursor : rc;
  	}
+ 	access_mode |= DixForceAccess;
      }
 +
-     pointer = PickPointer(client);
-     modifierDevice = GetPairedDevice(pointer);
++    ptr = PickPointer(client);
++    modifierDevice = GetPairedDevice(ptr);
+     if (stuff->pointerMode == GrabModeSync ||
+ 	stuff->keyboardMode == GrabModeSync)
+ 	access_mode |= DixFreezeAccess;
 -    rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, access_mode);
++    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
+     if (rc != Success)
+ 	return rc;
  
-     grab = CreateGrab(client->index, pointer, pWin,
 -    grab = CreateGrab(client->index, inputInfo.pointer, pWin, 
++    grab = CreateGrab(client->index, ptr, pWin,
          (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
          (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode,
 -        inputInfo.keyboard, stuff->modifiers, ButtonPress,
 +        modifierDevice, stuff->modifiers, ButtonPress,
          stuff->button, confineTo, cursor);
      if (!grab)
  	return BadAlloc;
@@@ -6076,10 -5011,9 +6143,10 @@@ in
  ProcRecolorCursor(ClientPtr client)
  {
      CursorPtr pCursor;
-     int		nscr;
+     int		rc, nscr;
      ScreenPtr	pscr;
 -    Bool 	displayed;
 +    Bool	displayed;
 +    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
      REQUEST(xRecolorCursorReq);
  
      REQUEST_SIZE_MATCH(xRecolorCursorReq);
diff --cc dix/getevents.c
index f21bb1b,40fc7f2..b704371
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -256,9 -212,8 +258,8 @@@ updateMotionHistory(DeviceIntPtr pDev, 
   */
  _X_EXPORT int
  GetMaximumEventsNum(void) {
 -    /* Two base events -- core and device, plus valuator events.  Multiply
 -     * by two if we're doing non-XKB key repeats. */
 +    /* Three base events -- raw event and device, plus valuator events.
-      * Multiply by two if we're doing key repeats.
-      */
++     *  Multiply by two if we're doing non-XKB key repeats. */
      int ret = 2 + MAX_VALUATOR_EVENTS;
  
  #ifdef XKB
@@@ -815,11 -704,11 +816,11 @@@ GetPointerEvents(EventList *events, Dev
   * 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;
+     int num_events = 1;
 -    deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events;
 +    deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events->event;
  
      /* Sanity checks. */
      if (type != ProximityIn && type != ProximityOut)
diff --cc dix/main.c
index 0bb823d,9114f00..63e3273
--- a/dix/main.c
+++ b/dix/main.c
@@@ -395,14 -387,18 +389,14 @@@ 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();
- 	if (loadableFonts) {
- 	    SetFontPath(0, 0, (unsigned char *)defaultFontPath, &error);
- 	}
+ 	if (loadableFonts)
+ 	    SetFontPath(serverClient, 0, (unsigned char *)defaultFontPath,
+ 			&error);
          else {
  	    if (SetDefaultFontPath(defaultFontPath) != Success)
 -		ErrorF("failed to set default font path '%s'",
 +		ErrorF("[dix] failed to set default font path '%s'",
  			defaultFontPath);
  	}
  	if (!SetDefaultFont(defaultTextFont)) {
@@@ -432,13 -428,7 +426,13 @@@
  	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);
+ 	dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
  
  #ifdef PANORAMIX
  	if (!noPanoramiXExtension) {
@@@ -457,11 -447,9 +451,11 @@@
  
  	Dispatch();
  
 +        UndisplayDevices();
 +
  	/* Now free up whatever must be freed */
  	if (screenIsSaved == SCREEN_SAVER_ON)
- 	    SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
+ 	    dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
  	FreeScreenSaverTimer();
  	CloseDownExtensions();
  
@@@ -484,9 -472,11 +478,10 @@@
  	    FreeGCperDepth(i);
  	    FreeDefaultStipple(i);
  	    (* screenInfo.screens[i]->CloseScreen)(i, screenInfo.screens[i]);
- 	    FreeScreen(screenInfo.screens[i]);
+ 	    dixFreePrivates(screenInfo.screens[i]->devPrivates);
+ 	    xfree(screenInfo.screens[i]);
  	    screenInfo.numScreens = i;
  	}
 -  	CloseDownEvents();
  	xfree(WindowTable);
  	WindowTable = NULL;
  	FreeFonts();
diff --cc dix/resource.c
index 4234beb,6c1b04d..dfc7bea
--- a/dix/resource.c
+++ b/dix/resource.c
@@@ -582,14 -568,9 +568,9 @@@ FreeResource(XID id, RESTYPE skipDelete
  	    else
  		prev = &res->next;
          }
- 	if(clients[cid] && (id == clients[cid]->lastDrawableID))
- 	{
- 	    clients[cid]->lastDrawable = (DrawablePtr)WindowTable[0];
- 	    clients[cid]->lastDrawableID = WindowTable[0]->drawable.id;
- 	}
      }
      if (!gotOne)
 -	ErrorF("Freeing resource id=%lX which isn't there.\n",
 +	ErrorF("[dix] Freeing resource id=%lX which isn't there.\n",
  		   (unsigned long)id);
  }
  
diff --cc dix/window.c
index 76e5dec,33cf76b..d937ca8
--- a/dix/window.c
+++ b/dix/window.c
@@@ -155,15 -146,6 +156,8 @@@ _X_EXPORT int screenIsSaved = SCREEN_SA
  
  _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
  
- _X_EXPORT int FocusPrivatesIndex = -1;
- 
- #if 0
- extern void DeleteWindowFromAnyEvents();
- extern Mask EventMaskForClient();
- extern void WindowHasNewCursor();
- extern void RecalculateDeliverableEvents();
- #endif
++_X_EXPORT DevPrivateKey FocusPrivatesKey = &FocusPrivatesKey;
 +
  static Bool TileScreenSaver(int i, int kind);
  
  
@@@ -283,6 -264,6 +277,8 @@@ Bool	disableSaveUnders = FALSE
  static void
  SetWindowToDefaults(WindowPtr pWin)
  {
++    FocusSemaphoresPtr sem;
++
      pWin->prevSib = NullWindow;
      pWin->firstChild = NullWindow;
      pWin->lastChild = NullWindow;
@@@ -312,12 -293,6 +308,9 @@@
  #ifdef COMPOSITE
      pWin->redirectDraw = RedirectDrawNone;
  #endif
 +
-     ((FocusSemaphoresPtr)
-      pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave = 0;
-     ((FocusSemaphoresPtr)
-      pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout = 0;
- 
++    sem = xcalloc(1, sizeof(FocusSemaphoresRec));
++    dixSetPrivate(&pWin->devPrivates, FocusPrivatesKey, sem);
  }
  
  static void
@@@ -3786,233 -3686,6 +3769,229 @@@ MakeWindowOptional (WindowPtr pWin
      return TRUE;
  }
  
 +/*
 + * Changes the cursor struct for the given device and the given window.
 + * A cursor that does not have a device cursor set will use whatever the
 + * standard cursor is for the window. If all devices have a cursor set,
 + * changing the window cursor (e.g. using XDefineCursor()) will not have any
 + * visible effect. Only when one of the device cursors is set to None again,
 + * this device's cursor will display the changed standard cursor.
 + * 
 + * CursorIsNone of the window struct is NOT modified if you set a device
 + * cursor. 
 + *
 + * Assumption: If there is a node for a device in the list, the device has a
 + * cursor. If the cursor is set to None, it is inherited by the parent.
 + */
 +_X_EXPORT int
 +ChangeWindowDeviceCursor(WindowPtr pWin, 
 +                         DeviceIntPtr pDev, 
 +                         CursorPtr pCursor) 
 +{
 +    DevCursNodePtr pNode, pPrev;
 +    CursorPtr pOldCursor = NULL;
 +    ScreenPtr pScreen;
 +    WindowPtr pChild;
 +
 +    if (!pWin->optional && !MakeWindowOptional(pWin))
 +        return BadAlloc;
 +
 +    /* 1) Check if window has device cursor set
 +     *  Yes: 1.1) swap cursor with given cursor if parent does not have same
 +     *            cursor, free old cursor
 +     *       1.2) free old cursor, use parent cursor
 +     *  No: 1.1) add node to beginning of list.
 +     *      1.2) add cursor to node if parent does not have same cursor
 +     *      1.3) use parent cursor if parent does not have same cursor
 +     *  2) Patch up children if child has a devcursor
 +     *  2.1) if child has cursor None, it inherited from parent, set to old
 +     *  cursor
 +     *  2.2) if child has same cursor as new cursor, remove and set to None
 +     */
 +
 +    pScreen = pWin->drawable.pScreen;
 +
 +    if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev))
 +    {
 +        /* has device cursor */
 +
 +        if (pNode->cursor == pCursor)
 +            return Success;
 +
 +        pOldCursor = pNode->cursor;
 +
 +        if (!pCursor) /* remove from list */
 +        {
 +            pPrev->next = pNode->next;
 +            xfree(pNode);
 +        }
 +
 +    } else
 +    {
 +        /* no device cursor yet */
 +        DevCursNodePtr pNewNode;
 +
 +        if (!pCursor)
 +            return Success;
 +
 +        pNewNode = (DevCursNodePtr)xalloc(sizeof(DevCursNodeRec));
 +        pNewNode->dev = pDev;
 +        pNewNode->next = pWin->optional->deviceCursors;
 +        pWin->optional->deviceCursors = pNewNode;
 +        pNode = pNewNode;
 +
 +    }
 +
 +    if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
 +        pNode->cursor = None;
 +    else
 +    {
 +        pNode->cursor = pCursor;
 +        pCursor->refcnt++;
 +    }
 +
 +    pNode = pPrev = NULL;
 +    /* fix up children */
 +    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
 +    {
 +        if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev))
 +        {
 +            if (pNode->cursor == None) /* inherited from parent */
 +            {
 +                pNode->cursor = pOldCursor;
 +                pOldCursor->refcnt++;
 +            } else if (pNode->cursor == pCursor)
 +            {
 +                pNode->cursor = None;
 +                FreeCursor(pCursor, (Cursor)0); /* fix up refcnt */
 +            }
 +        }
 +    }
 +
 +    if (pWin->realized)
 +        WindowHasNewCursor(pWin);
 +
 +    if (pOldCursor)
 +        FreeCursor(pOldCursor, (Cursor)0);
 +
 +    /* FIXME: We SHOULD check for an error value here XXX  
 +       (comment taken from ChangeWindowAttributes) */
 +    (*pScreen->ChangeWindowAttributes)(pWin, CWCursor);
 +
 +    return Success;
 +}
 +
 +/* Get device cursor for given device or None if none is set */
 +_X_EXPORT CursorPtr 
 +WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
 +{
 +    DevCursorList pList;
 +
 +    if (!pWin->optional || !pWin->optional->deviceCursors)
 +        return NULL;
 +
 +    pList = pWin->optional->deviceCursors;
 +
 +    while(pList)
 +    {
 +        if (pList->dev == pDev)
 +        {
 +            if (pList->cursor == None) /* inherited from parent */
 +                return WindowGetDeviceCursor(pWin->parent, pDev);
 +            else
 +                return pList->cursor;
 +        }
 +        pList = pList->next;
 +    }
 +    return NULL;
 +}
 +
 +/* Searches for a DevCursorNode for the given window and device. If one is
 + * found, return True and set pNode and pPrev to the node and to the node
 + * before the node respectively. Otherwise return False.
 + * If the device is the first in list, pPrev is set to NULL.
 + */
 +static Bool 
 +WindowSeekDeviceCursor(WindowPtr pWin, 
 +                       DeviceIntPtr pDev, 
 +                       DevCursNodePtr* pNode, 
 +                       DevCursNodePtr* pPrev)
 +{
 +    DevCursorList pList;
 +
 +    if (!pWin->optional)
 +        return FALSE;
 +
 +    pList = pWin->optional->deviceCursors;
 +
 +    if (pList && pList->dev == pDev)
 +    {
 +        *pNode = pList;
 +        *pPrev = NULL;
 +        return TRUE;
 +    }
 +
 +    while(pList)
 +    {
 +        if (pList->next)
 +        {
 +            if (pList->next->dev == pDev)
 +            {
 +                *pNode = pList->next;
 +                *pPrev = pList;
 +                return TRUE;
 +            }
 +        }
 +        pList = pList->next;
 +    }
 +    return FALSE;
 +}
 +
 +/* Return True if a parent has the same device cursor set or False if
 + * otherwise 
 + */ 
 +static Bool 
 +WindowParentHasDeviceCursor(WindowPtr pWin, 
 +                            DeviceIntPtr pDev, 
 +                            CursorPtr pCursor)
 +{
 +    WindowPtr pParent;
 +    DevCursNodePtr pParentNode, pParentPrev;
 +
 +    pParent = pWin->parent;
 +    while(pParent)
 +    {
 +        if (WindowSeekDeviceCursor(pParent, pDev, 
 +                    &pParentNode, &pParentPrev))
 +        {
 +            /* if there is a node in the list, the win has a dev cursor */
 +            if (!pParentNode->cursor) /* inherited. loop needs to cont. */
 +            {
 +            } else if (pParentNode->cursor == pCursor) /* inherit */
 +                return TRUE;
 +            else  /* different cursor */
 +                return FALSE;
 +        } 
 +        else 
 +            /* parent does not have a device cursor for our device */
 +            return FALSE;
 +    }
 +    return FALSE;
 +}
 +
 +/**
 + * Initialize some mandatory devPrivates for windows. 
 + *
 + * At the moment, this includes only the enter/leave semaphore.
 + *
 + * Returns TRUE on success.
 + */
 +_X_EXPORT Bool
 +InitWindowPrivates(ScreenPtr screen)
 +{
-     if (FocusPrivatesIndex == -1)
-         FocusPrivatesIndex = AllocateWindowPrivateIndex();
- 
-     return AllocateWindowPrivate(screen, FocusPrivatesIndex, 
-             sizeof(FocusSemaphoresRec));
++    /* obsolete with devPrivates rework */
 +}
 +
  #ifndef NOLOGOHACK
  static void
  DrawLogo(WindowPtr pWin)
diff --cc hw/xfree86/ramdac/xf86Cursor.c
index c968f18,5b1ce5e..5c909c7
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@@ -8,18 -8,7 +8,17 @@@
  #include "colormapst.h"
  #include "cursorstr.h"
  
 +/* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for
 + * MPX.
 + * inputInfo is needed to pass the core pointer as the default argument into
 + * the cursor functions.
-  * 
++ *
 + * Externing inputInfo is not the nice way to do it but it works.
 + */
 +#include "inputstr.h"
 +extern InputInfo inputInfo;
 +
- int xf86CursorScreenIndex = -1;
- static unsigned long xf86CursorGeneration = 0;
+ DevPrivateKey xf86CursorScreenKey = &xf86CursorScreenKey;
  
  /* sprite functions */
  
@@@ -205,17 -187,14 +198,17 @@@ xf86CursorEnableDisableFBAccess
      int index,
      Bool enable)
  {
 +    DeviceIntPtr pDev = inputInfo.pointer;
 +
      ScreenPtr pScreen = screenInfo.screens[index];
-     xf86CursorScreenPtr ScreenPriv =
- 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
+     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+ 	&pScreen->devPrivates, xf86CursorScreenKey);
  
      if (!enable && ScreenPriv->CurrentCursor != NullCursor) {
 -	CursorPtr   currentCursor = ScreenPriv->CurrentCursor;
 -	xf86CursorSetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
 -	ScreenPriv->isUp = FALSE;
 +        CursorPtr currentCursor = ScreenPriv->CurrentCursor;
 +        xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x,
 +                ScreenPriv->y); 
 +        ScreenPriv->isUp = FALSE;
  	ScreenPriv->SWCursor = TRUE;
  	ScreenPriv->SavedCursor = currentCursor;
      }
@@@ -266,38 -245,36 +259,38 @@@ xf86CursorSwitchMode(int index, Display
  /****** miPointerSpriteFunctions *******/
  
  static Bool
 -xf86CursorRealizeCursor(ScreenPtr pScreen, CursorPtr pCurs)
 +xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
  {
-     xf86CursorScreenPtr ScreenPriv =
- 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
+     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+ 	&pScreen->devPrivates, xf86CursorScreenKey);
  
      if (pCurs->refcnt <= 1)
- 	pCurs->devPriv[pScreen->myNum] = NULL;
+ 	dixSetPrivate(&pCurs->devPrivates, pScreen, NULL);
  
 -    return (*ScreenPriv->spriteFuncs->RealizeCursor)(pScreen, pCurs);
 +    return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs);
  }
  
  static Bool
 -xf86CursorUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCurs)
 +xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                          CursorPtr pCurs)
  {
-     xf86CursorScreenPtr ScreenPriv =
- 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
+     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+ 	&pScreen->devPrivates, xf86CursorScreenKey);
  
      if (pCurs->refcnt <= 1) {
- 	xfree(pCurs->devPriv[pScreen->myNum]);
- 	pCurs->devPriv[pScreen->myNum] = NULL;
+ 	xfree(dixLookupPrivate(&pCurs->devPrivates, pScreen));
+ 	dixSetPrivate(&pCurs->devPrivates, pScreen, NULL);
      }
  
 -    return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pScreen, pCurs);
 +    return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs);
  }
  
  static void
 -xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
 +xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, 
 +                    int x, int y)
  {
-     xf86CursorScreenPtr ScreenPriv =
- 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
+     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+ 	&pScreen->devPrivates, xf86CursorScreenKey);
      xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
      miPointerScreenPtr PointPriv;
  
@@@ -367,10 -342,10 +360,10 @@@
  }
  
  static void
 -xf86CursorMoveCursor(ScreenPtr pScreen, int x, int y)
 +xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
  {
-     xf86CursorScreenPtr ScreenPriv =
- 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
+     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+ 	&pScreen->devPrivates, xf86CursorScreenKey);
  
      ScreenPriv->x = x;
      ScreenPriv->y = y;
@@@ -387,10 -362,8 +380,9 @@@
  void
  xf86ForceHWCursor (ScreenPtr pScreen, Bool on)
  {
 +    DeviceIntPtr pDev = inputInfo.pointer;
- 
-     xf86CursorScreenPtr ScreenPriv =
- 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
+     xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate(
+ 	&pScreen->devPrivates, xf86CursorScreenKey);
  
      if (on)
      {
diff --cc include/dix.h
index 6da3ee8,8cfbbc4..fc862df
--- a/include/dix.h
+++ b/include/dix.h
@@@ -694,28 -599,36 +650,54 @@@ typedef struct 
  extern int xstrcasecmp(char *s1, char *s2);
  #endif
  
 +extern int XItoCoreType(int xi_type);
 +extern Bool DevHasCursor(DeviceIntPtr pDev);
- 
 +extern Bool IsPointerDevice( DeviceIntPtr dev);
 +extern Bool IsKeyboardDevice(DeviceIntPtr dev);
 +
+ /*
+  * These are deprecated compatibility functions and will be removed soon!
+  * Please use the noted replacements instead.
+  */
 -
+ /* replaced by dixLookupWindow */
+ extern WindowPtr SecurityLookupWindow(
+     XID id,
+     ClientPtr client,
+     Mask access_mode);
 -
+ /* replaced by dixLookupWindow */
+ extern WindowPtr LookupWindow(
+     XID id,
+     ClientPtr client);
+ 
+ /* replaced by dixLookupDrawable */
+ extern pointer SecurityLookupDrawable(
+     XID id,
+     ClientPtr client,
+     Mask access_mode);
+ 
+ /* replaced by dixLookupDrawable */
+ extern pointer LookupDrawable(
+     XID id,
+     ClientPtr client);
+ 
+ /* replaced by dixLookupClient */
+ extern ClientPtr LookupClient(
+     XID id,
+     ClientPtr client);
  
 +/* GE stuff */
 +extern void SetGenericFilter(int extension, Mask* filters);
- 
 +extern int ExtGrabDevice(ClientPtr client,
 +                         DeviceIntPtr dev,
 +                         int device_mode,
 +                         WindowPtr grabWindow,
 +                         WindowPtr confineTo,
 +                         TimeStamp ctime,
 +                         Bool ownerEvents,
 +                         CursorPtr cursor, 
 +                         Mask xi_mask,
 +                         GenericMaskPtr ge_masks);
- 
 +extern int ExtUngrabDevice(ClientPtr client,
 +                         DeviceIntPtr dev);
 +
  #endif /* DIX_H */
diff --cc include/dixgrabs.h
index b237ab3,f93e999..29aa828
--- a/include/dixgrabs.h
+++ b/include/dixgrabs.h
@@@ -47,10 -47,10 +47,11 @@@ extern int DeletePassiveGrab
  
  extern Bool GrabMatchesSecond(
  	GrabPtr /* pFirstGrab */,
 -	GrabPtr /* pSecondGrab */);
 +	GrabPtr /* pSecondGrab */,
 +	Bool /*ignoreDevice*/);
  
  extern int AddPassiveGrabToList(
+ 	ClientPtr /* client */,
  	GrabPtr /* pGrab */);
  
  extern Bool DeletePassiveGrabFromList(
diff --cc include/input.h
index c436943,ca67cfa..6384716
--- a/include/input.h
+++ b/include/input.h
@@@ -459,59 -432,9 +454,56 @@@ extern int GetMotionHistory
      unsigned long stop,
      ScreenPtr pScreen);
  
 -extern void SwitchCoreKeyboard(DeviceIntPtr pDev);
  extern void SwitchCorePointer(DeviceIntPtr pDev);
  
- extern DeviceIntPtr LookupDeviceIntRec(
-     CARD8 deviceid);
- 
 +/* Pairing input devices */
 +extern int PairDevices(ClientPtr client, 
 +                       DeviceIntPtr pointer, 
 +                       DeviceIntPtr keyboard);
 +extern int AttachDevice(ClientPtr client,
 +                        DeviceIntPtr slave,
 +                        DeviceIntPtr master);
 +
 +extern DeviceIntPtr GetPairedDevice(DeviceIntPtr kbd);
 +
 +extern Bool RegisterPairingClient(ClientPtr client);
 +
 +extern DeviceIntPtr GuessFreePointerDevice(void);
 +extern DeviceIntPtr NextFreePointerDevice(void);
 +
 +extern int AllocMasterDevice(char* name,
 +                             DeviceIntPtr* ptr,
 +                             DeviceIntPtr* keybd);
 +extern void DeepCopyDeviceClasses(DeviceIntPtr from,
 +                                  DeviceIntPtr to);
 +extern void FreeDeviceClass(int type, pointer* class);
 +extern void FreeFeedbackClass(int type, pointer* class);
 +extern void FreeAllDeviceClasses(ClassesPtr classes);
 +
 +/* Window/device based access control */
 +extern Bool ACRegisterClient(ClientPtr client);
 +extern Bool ACUnregisterClient(ClientPtr client);
 +extern int ACClearWindowAccess(ClientPtr client,
 +                        WindowPtr win,
 +                        int what);
 +extern int ACChangeWindowAccess(ClientPtr client, 
 +                                WindowPtr win, 
 +                                int defaultRule,
 +                                DeviceIntPtr* perm_devices,
 +                                int npermit,
 +                                DeviceIntPtr* deny_devices,
 +                                int ndeny);
 +extern void ACQueryWindowAccess(WindowPtr win, 
 +                                int* defaultRule,
 +                                DeviceIntPtr** perm,
 +                                int* nperm,
 +                                DeviceIntPtr** deny,
 +                                int* ndeny);
 +
 +extern Bool ACDeviceAllowed(WindowPtr win, 
 +                            DeviceIntPtr dev,
 +                            xEvent* xE);
 +
  /* Implemented by the DDX. */
  extern int NewInputDeviceRequest(
      InputOption *options,
diff --cc include/inputstr.h
index bcb8079,6a1d5c9..9011ba2
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@@ -52,8 -52,7 +52,9 @@@ SOFTWARE
  #include "input.h"
  #include "window.h"
  #include "dixstruct.h"
 +#include "cursorstr.h"
 +#include "geext.h"
+ #include "privates.h"
  
  #define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7)))
  
@@@ -411,16 -329,9 +412,16 @@@ typedef struct _DeviceIntRec 
      void                *pad0;
  #endif
      char                *config_info; /* used by the hotplug layer */
-     DevUnion		*devPrivates;
+     PrivateRec		*devPrivates;
      int			nPrivates;
      DeviceUnwrapProc    unwrapProc;
 +    SpriteInfoPtr       spriteInfo;
 +    union {
 +    DeviceIntPtr        master;       /* master device */
 +    DeviceIntPtr        lastSlave;    /* last slave device used */
 +    } u;
 +    int                 lastx, lasty; /* last event recorded, not posted to
 +                                       * client; see dix/devices.c */
  } DeviceIntRec;
  
  typedef struct {
diff --cc include/window.h
index 4913758,52b3982..8dbef22
--- a/include/window.h
+++ b/include/window.h
@@@ -138,18 -131,9 +135,18 @@@ extern int ChangeWindowAttributes
      XID* /*vlist*/,
      ClientPtr /*client*/);
  
 +extern int ChangeWindowDeviceCursor(
 +    WindowPtr /*pWin*/,
 +    struct _DeviceIntRec* /*pDev*/,
 +    struct _Cursor* /*pCursor*/);
 +
 +extern struct _Cursor* WindowGetDeviceCursor(
 +    WindowPtr /*pWin*/,
 +    struct _DeviceIntRec* /*pDev*/);
 +
  /* Quartz support on Mac OS X uses the HIToolbox
     framework whose GetWindowAttributes function conflicts here. */
- #ifdef __DARWIN__
+ #ifdef __APPLE__
  #define GetWindowAttributes(w,c,x) Darwin_X_GetWindowAttributes(w,c,x)
  extern void Darwin_X_GetWindowAttributes(
  #else
diff --cc include/windowstr.h
index 8e6d451,4359481..01952e2
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@@ -254,15 -227,6 +255,15 @@@ typedef struct _ScreenSaverStuff 
  
  extern int screenIsSaved;
  extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
- extern int FocusPrivatesIndex;
++extern DevPrivateKey FocusPrivatesKey;
 +
 +/* Used to maintain semantics of core protocol for Enter/LeaveNotifies and
 + * FocusIn/Out events for multiple pointers/keyboards. 
 + */ 
 +typedef struct _FocusSemaphores {
 +    int                 enterleave;
 +    int                 focusinout;
 +} FocusSemaphoresRec, *FocusSemaphoresPtr;
  
  /*
   * this is the configuration parameter "NO_BACK_SAVE"
diff --cc mi/midispcur.c
index 203809d,45e0e9a..7d1aed9
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@@ -58,18 -52,12 +58,17 @@@ in this Software without prior written 
  # include   "picturestr.h"
  #endif
  
 +# include "inputstr.h" /* for MAX_DEVICES */
 +
  /* per-screen private data */
  
- static int	miDCScreenIndex;
- static unsigned long miDCGeneration = 0;
+ static DevPrivateKey miDCScreenKey = &miDCScreenKey;
  
  static Bool	miDCCloseScreen(int index, ScreenPtr pScreen);
  
 +/* per device private data */
- static int      miDCSpriteIndex;
++static DevPrivateKey miDCSpriteKey = &miDCSpriteKey;
 +
  typedef struct {
      GCPtr	    pSourceGC, pMaskGC;
      GCPtr	    pSaveGC, pRestoreGC;
@@@ -80,19 -69,6 +79,19 @@@
      PicturePtr	    pRootPicture;
      PicturePtr	    pTempPicture;
  #endif
 +} miDCBufferRec, *miDCBufferPtr;
 +
 +#define MIDCBUFFER(dev) \
 + ((DevHasCursor(dev)) ? \
-   (miDCBufferPtr)dev->devPrivates[miDCSpriteIndex].ptr :\
-   (miDCBufferPtr)dev->u.master->devPrivates[miDCSpriteIndex].ptr)
++  (miDCBufferPtr)dixLookupPrivate(&dev->devPrivates, miDCSpriteKey) : \
++  (miDCBufferPtr)dixLookupPrivate(&dev->u.master->devPrivates, miDCSpriteKey))
 +
 +/* 
 + * The core pointer buffer will point to the index of the virtual core pointer
 + * in the pCursorBuffers array. 
 + */
 +typedef struct {
 +    CloseScreenProcPtr CloseScreen;
  } miDCScreenRec, *miDCScreenPtr;
  
  /* per-cursor per-screen private data */
@@@ -160,13 -120,28 +152,11 @@@ miDCInitialize (pScreen, screenFuncs
      if (!pScreenPriv)
  	return FALSE;
  
 -    /*
 -     * initialize the entire private structure to zeros
 -     */
 -
 -    pScreenPriv->pSourceGC =
 -	pScreenPriv->pMaskGC =
 -	pScreenPriv->pSaveGC =
 - 	pScreenPriv->pRestoreGC =
 - 	pScreenPriv->pMoveGC =
 - 	pScreenPriv->pPixSourceGC =
 -	pScreenPriv->pPixMaskGC = NULL;
 -#ifdef ARGB_CURSOR
 -    pScreenPriv->pRootPicture = NULL;
 -    pScreenPriv->pTempPicture = NULL;
 -#endif
 -    
 -    pScreenPriv->pSave = pScreenPriv->pTemp = NULL;
  
-     miDCSpriteIndex = AllocateDevicePrivateIndex();
- 
      pScreenPriv->CloseScreen = pScreen->CloseScreen;
      pScreen->CloseScreen = miDCCloseScreen;
--    
-     pScreen->devPrivates[miDCScreenIndex].ptr = (pointer) pScreenPriv;
++
+     dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
  
      if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
      {
@@@ -187,9 -162,21 +177,9 @@@ miDCCloseScreen (index, pScreen
  {
      miDCScreenPtr   pScreenPriv;
  
-     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
+     pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						  miDCScreenKey);
      pScreen->CloseScreen = pScreenPriv->CloseScreen;
- 
 -    tossGC (pScreenPriv->pSourceGC);
 -    tossGC (pScreenPriv->pMaskGC);
 -    tossGC (pScreenPriv->pSaveGC);
 -    tossGC (pScreenPriv->pRestoreGC);
 -    tossGC (pScreenPriv->pMoveGC);
 -    tossGC (pScreenPriv->pPixSourceGC);
 -    tossGC (pScreenPriv->pPixMaskGC);
 -    tossPix (pScreenPriv->pSave);
 -    tossPix (pScreenPriv->pTemp);
 -#ifdef ARGB_CURSOR
 -    tossPict (pScreenPriv->pTempPicture);
 -#endif
      xfree ((pointer) pScreenPriv);
      return (*pScreen->CloseScreen) (index, pScreen);
  }
@@@ -470,20 -458,19 +462,22 @@@ miDCPutUpCursor (pDev, pScreen, pCursor
  {
      miDCScreenPtr   pScreenPriv;
      miDCCursorPtr   pPriv;
 +    miDCBufferPtr   pBuffer;
      WindowPtr	    pWin;
  
-     pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
+     pPriv = (miDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates,
+ 					    pScreen);
      if (!pPriv)
      {
  	pPriv = miDCRealize(pScreen, pCursor);
  	if (!pPriv)
  	    return FALSE;
      }
-     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
+     pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						  miDCScreenKey);
      pWin = WindowTable[pScreen->myNum];
 +    pBuffer = MIDCBUFFER(pDev);
 +
  #ifdef ARGB_CURSOR
      if (pPriv->pPicture)
      {
@@@ -557,10 -514,9 +551,11 @@@ miDCSaveUnderCursor (pDev, pScreen, x, 
      WindowPtr	    pWin;
      GCPtr	    pGC;
  
-     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
+     pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						  miDCScreenKey);
 -    pSave = pScreenPriv->pSave;
 +    pBuffer = MIDCBUFFER(pDev);
 +
 +    pSave = pBuffer->pSave;
      pWin = WindowTable[pScreen->myNum];
      if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
      {
@@@ -599,10 -547,9 +594,11 @@@ miDCRestoreUnderCursor (pDev, pScreen, 
      WindowPtr	    pWin;
      GCPtr	    pGC;
  
-     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
+     pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						  miDCScreenKey);
 -    pSave = pScreenPriv->pSave;
 +    pBuffer = MIDCBUFFER(pDev);
- 
 +    pSave = pBuffer->pSave;
++
      pWin = WindowTable[pScreen->myNum];
      if (!pSave)
  	return FALSE;
@@@ -635,10 -574,9 +631,11 @@@ miDCChangeSave (pDev, pScreen, x, y, w
      GCPtr	    pGC;
      int		    sourcex, sourcey, destx, desty, copyw, copyh;
  
-     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
+     pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						  miDCScreenKey);
 -    pSave = pScreenPriv->pSave;
 +    pBuffer = MIDCBUFFER(pDev);
 +
 +    pSave = pBuffer->pSave;
      pWin = WindowTable[pScreen->myNum];
      /*
       * restore the bits which are about to get trashed
@@@ -794,14 -719,13 +792,15 @@@ miDCMoveCursor (pDev, pScreen, pCursor
  	if (!pPriv)
  	    return FALSE;
      }
-     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
+     pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						  miDCScreenKey);
      pWin = WindowTable[pScreen->myNum];
 -    pTemp = pScreenPriv->pTemp;
 +    pBuffer = MIDCBUFFER(pDev);
 +
 +    pTemp = pBuffer->pTemp;
      if (!pTemp ||
 -	pTemp->drawable.width != pScreenPriv->pSave->drawable.width ||
 -	pTemp->drawable.height != pScreenPriv->pSave->drawable.height)
 +	pTemp->drawable.width != pBuffer->pSave->drawable.width ||
 +	pTemp->drawable.height != pBuffer->pSave->drawable.height)
      {
  	if (pTemp)
  	    (*pScreen->DestroyPixmap) (pTemp);
@@@ -817,11 -741,11 +816,11 @@@
  	if (!pTemp)
  	    return FALSE;
      }
 -    if (!pScreenPriv->pMoveGC)
 +    if (!pBuffer->pMoveGC)
      {
 -	pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp,
 +	pBuffer->pMoveGC = CreateGC ((DrawablePtr)pTemp,
- 	    GCGraphicsExposures, &gcval, &status);
+ 	    GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
 -	if (!pScreenPriv->pMoveGC)
 +	if (!pBuffer->pMoveGC)
  	    return FALSE;
      }
      /*
@@@ -862,18 -777,18 +861,18 @@@
      else
  #endif
      {
 -	if (!pScreenPriv->pPixSourceGC)
 +	if (!pBuffer->pPixSourceGC)
  	{
 -	    pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
 +	    pBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
- 		GCGraphicsExposures, &gcval, &status);
+ 		GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
 -	    if (!pScreenPriv->pPixSourceGC)
 +	    if (!pBuffer->pPixSourceGC)
  		return FALSE;
  	}
 -	if (!pScreenPriv->pPixMaskGC)
 +	if (!pBuffer->pPixMaskGC)
  	{
 -	    pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
 +	    pBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
- 		GCGraphicsExposures, &gcval, &status);
+ 		GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
 -	    if (!pScreenPriv->pPixMaskGC)
 +	    if (!pBuffer->pPixMaskGC)
  		return FALSE;
  	}
  	miDCPutBits ((DrawablePtr)pTemp, pPriv,
@@@ -903,62 -812,3 +902,59 @@@
  			    0, 0, w, h, x, y);
      return TRUE;
  }
 +
 +static Bool
 +miDCDeviceInitialize(pDev, pScreen)
 +    DeviceIntPtr pDev;
 +    ScreenPtr pScreen;
 +{
 +    miDCBufferPtr pBuffer;
 +
-     if (!AllocateDevicePrivate(pDev, miDCSpriteIndex))
-         return FALSE;
- 
-     pBuffer = 
-        pDev->devPrivates[miDCSpriteIndex].ptr = xalloc(sizeof(miDCBufferRec));
++    pBuffer = xalloc(sizeof(miDCBufferRec));
++    dixSetPrivate(&pDev->devPrivates, miDCSpriteKey, pBuffer);
 +
 +    pBuffer->pSourceGC =
 +        pBuffer->pMaskGC =
 +        pBuffer->pSaveGC =
 +        pBuffer->pRestoreGC =
 +        pBuffer->pMoveGC =
 +        pBuffer->pPixSourceGC =
 +        pBuffer->pPixMaskGC = NULL;
 +#ifdef ARGB_CURSOR
 +    pBuffer->pRootPicture = NULL;
 +    pBuffer->pTempPicture = NULL;
 +#endif
 +    pBuffer->pSave = pBuffer->pTemp = NULL;
 +
 +    return TRUE;
 +}
 +
 +static void
 +miDCDeviceCleanup(pDev, pScreen)
 +    DeviceIntPtr pDev;
 +    ScreenPtr pScreen;
 +{
 +    miDCBufferPtr   pBuffer;
 +
 +    if (DevHasCursor(pDev))
 +    {
 +        pBuffer = MIDCBUFFER(pDev);
 +        tossGC (pBuffer->pSourceGC);
 +        tossGC (pBuffer->pMaskGC);
 +        tossGC (pBuffer->pSaveGC);
 +        tossGC (pBuffer->pRestoreGC);
 +        tossGC (pBuffer->pMoveGC);
 +        tossGC (pBuffer->pPixSourceGC);
 +        tossGC (pBuffer->pPixMaskGC);
 +        tossPix (pBuffer->pSave);
 +        tossPix (pBuffer->pTemp);
 +#ifdef ARGB_CURSOR
 +#if 0				/* This has been free()d before */
 +        tossPict (pScreenPriv->pRootPicture);
 +#endif 
 +        tossPict (pBuffer->pTempPicture);
 +#endif
-         xfree(pDev->devPrivates[miDCSpriteIndex].ptr);
-         pDev->devPrivates[miDCSpriteIndex].ptr = NULL;
++        xfree(pBuffer);
++        dixSetPrivate(&pDev->devPrivates, miDCSpriteKey, NULL);
 +    }
 +}
diff --cc mi/mieq.c
index 31f838c,c2f687a..a1a434a
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@@ -148,14 -128,15 +148,16 @@@ mieqEnqueue(DeviceIntPtr pDev, xEvent *
          if (oldtail == miEventQueue.head ||
              !(lastkbp->type == DeviceMotionNotify ||
                lastkbp->type == DeviceButtonPress ||
-               lastkbp->type == DeviceButtonRelease) ||
+               lastkbp->type == DeviceButtonRelease ||
+               lastkbp->type == ProximityIn ||
+               lastkbp->type == ProximityOut) ||
              ((lastkbp->deviceid & DEVICE_BITS) !=
               (v->deviceid & DEVICE_BITS))) {
 -            ErrorF("mieqEnequeue: out-of-order valuator event; dropping.\n");
 +            ErrorF("[mi] 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;
      }
  
diff --cc mi/miinitext.c
index 45a14af,319d2ce..4024100
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@@ -533,11 -534,6 +537,8 @@@ InitExtensions(argc, argv
      int		argc;
      char	*argv[];
  {
 +    if (!noGEExtension) GEExtensionInit();
 +
- #ifdef XCSECURITY
-     SecurityExtensionSetup();
- #endif
  #ifdef PANORAMIX
  # if !defined(PRINT_ONLY_SERVER) && !defined(NO_PANORAMIX)
    if (!noPanoramiXExtension) PanoramiXExtensionInit();
diff --cc mi/mipointer.c
index ff58823,2c3c689..5706ef4
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@@ -48,45 -41,31 +48,45 @@@ in this Software without prior written 
  # include   "dixstruct.h"
  # include   "inputstr.h"
  
- _X_EXPORT int miPointerScreenIndex;
- static unsigned long miPointerGeneration = 0;
+ _X_EXPORT DevPrivateKey miPointerScreenKey = &miPointerScreenKey;
  
- #define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr))
+ #define GetScreenPrivate(s) ((miPointerScreenPtr) \
+     dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
  #define SetupScreen(s)	miPointerScreenPtr  pScreenPriv = GetScreenPrivate(s)
  
- static int miPointerPrivatesIndex = 0;
 -/*
 - * until more than one pointer device exists.
 - */
 -
 -static miPointerRec miPointer;
 -
 -static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 -static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 -static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
 -static void miPointerConstrainCursor(ScreenPtr pScreen, BoxPtr pBox);
 -static void miPointerPointerNonInterestBox(ScreenPtr pScreen, BoxPtr pBox);
 -static void miPointerCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
 -				  BoxPtr pHotBox, BoxPtr pTopLeftBox);
 -static Bool miPointerSetCursorPosition(ScreenPtr pScreen, int x, int y,
++static DevPrivateKey miPointerPrivKey = &miPointerPrivKey;
 +
 +#define MIPOINTER(dev) \
 +    ((DevHasCursor((dev))) ? \
-         (miPointerPtr) dev->devPrivates[miPointerPrivatesIndex].ptr : \
-         (miPointerPtr) dev->u.master->devPrivates[miPointerPrivatesIndex].ptr)
++        (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
++        (miPointerPtr)dixLookupPrivate(&(dev)->u.master->devPrivates, miPointerPrivKey))
 +
 +static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                                   CursorPtr pCursor);
 +static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                                     CursorPtr pCursor);
 +static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                                   CursorPtr pCursor);
 +static void miPointerUndisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
 +static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
 +                                     BoxPtr pBox); 
 +static void miPointerPointerNonInterestBox(DeviceIntPtr pDev, 
 +                                           ScreenPtr pScreen, BoxPtr pBox);
 +static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
 +                                  CursorPtr pCursor, BoxPtr pHotBox, 
 +                                  BoxPtr pTopLeftBox);
 +static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                                       int x, int y,
  				       Bool generateEvent);
  static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
 -static void miPointerMove(ScreenPtr pScreen, int x, int y, unsigned long time);
 +static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                          int x, int y,
 +                          unsigned long time);
 +static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
 +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)
@@@ -134,12 -104,23 +127,10 @@@
      pScreen->SetCursorPosition = miPointerSetCursorPosition;
      pScreen->RecolorCursor = miRecolorCursor;
      pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
 -    /*
 -     * set up the pointer object
 -     */
 -    miPointer.pScreen = NULL;
 -    miPointer.pSpriteScreen = NULL;
 -    miPointer.pCursor = NULL;
 -    miPointer.pSpriteCursor = NULL;
 -    miPointer.limits.x1 = 0;
 -    miPointer.limits.x2 = 32767;
 -    miPointer.limits.y1 = 0;
 -    miPointer.limits.y2 = 32767;
 -    miPointer.confined = FALSE;
 -    miPointer.x = 0;
 -    miPointer.y = 0;
 +    pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
 +    pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
  
-     miPointerPrivatesIndex = AllocateDevicePrivateIndex();
- 
      events = NULL;
 -
      return TRUE;
  }
  
@@@ -285,71 -218,12 +276,68 @@@ miPointerSetCursorPosition(pDev, pScree
  
      GenerateEvent = generateEvent;
      /* device dependent - must pend signal and call miPointerWarpCursor */
 -    (*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y);
 +    (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
      if (!generateEvent)
 -	miPointerUpdateSprite(inputInfo.pointer);
 +	miPointerUpdateSprite(pDev);
 +    return TRUE;
 +}
 +
 +/* Set up sprite information for the device. 
 +   This function will be called once for each device after it is initialized
 +   in the DIX.
 + */ 
 +static Bool
 +miPointerDeviceInitialize(pDev, pScreen)
 +    DeviceIntPtr pDev;
 +    ScreenPtr pScreen;
 +{
 +    miPointerPtr pPointer;
 +    SetupScreen (pScreen);
 +
-     if (!AllocateDevicePrivate(pDev, miPointerPrivatesIndex))
-         return FALSE;
- 
 +    pPointer = xalloc(sizeof(miPointerRec));
 +    if (!pPointer)
 +        return FALSE;
 +
 +    pPointer->pScreen = NULL;
 +    pPointer->pSpriteScreen = NULL;
 +    pPointer->pCursor = NULL;
 +    pPointer->pSpriteCursor = NULL;
 +    pPointer->limits.x1 = 0;
 +    pPointer->limits.x2 = 32767;
 +    pPointer->limits.y1 = 0;
 +    pPointer->limits.y2 = 32767;
 +    pPointer->confined = FALSE;
 +    pPointer->x = 0;
 +    pPointer->y = 0;
 +
 +    if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
 +    {
 +        xfree(pPointer);
 +        return FALSE;
 +    }
 +
-     pDev->devPrivates[miPointerPrivatesIndex].ptr = pPointer;
++    dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
      return TRUE;
  }
  
 +/* Clean up after device. 
 +   This function will be called once before the device is freed in the DIX
 + */
 +static void
 +miPointerDeviceCleanup(pDev, pScreen)
 +    DeviceIntPtr pDev;
 +    ScreenPtr pScreen;
 +{
 +    if (DevHasCursor(pDev))
 +    {
 +        SetupScreen(pScreen);
 +        (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
-         xfree(pDev->devPrivates[miPointerPrivatesIndex].ptr);
-         pDev->devPrivates[miPointerPrivatesIndex].ptr = NULL;
++        xfree(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
++        dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
 +    }
 +}
 +
 +
  /* Once signals are ignored, the WarpCursor function can call this */
  
  _X_EXPORT void
diff --cc mi/misprite.c
index 8c99abb,0af3368..2be814f
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@@ -72,20 -63,11 +72,19 @@@ in this Software without prior written 
  #define SPRITE_DEBUG(x)
  #endif
  
 +
- static int miSpriteDevPrivatesIndex;
 +#define MISPRITE(dev) \
 +    ((DevHasCursor(dev)) ? \
-        (miCursorInfoPtr) dev->devPrivates[miSpriteDevPrivatesIndex].ptr : \
-        (miCursorInfoPtr) dev->u.master->devPrivates[miSpriteDevPrivatesIndex].ptr)
++       (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
++       (miCursorInfoPtr)dixLookupPrivate(&dev->u.master->devPrivates, miSpriteDevPrivatesKey))
 +
 +
  /*
   * screen wrappers
   */
  
- static int  miSpriteScreenIndex;
- static unsigned long miSpriteGeneration = 0;
+ static DevPrivateKey miSpriteScreenKey = &miSpriteScreenKey;
++static DevPrivateKey miSpriteDevPrivatesKey = &miSpriteDevPrivatesKey;
  
  static Bool	    miSpriteCloseScreen(int i, ScreenPtr pScreen);
  static void	    miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
@@@ -106,18 -88,11 +105,17 @@@ static void	    miSpriteInstallColormap
  static void	    miSpriteStoreColors(ColormapPtr pMap, int ndef,
  					xColorItem *pdef);
  
 -static void	    miSpriteComputeSaved(ScreenPtr pScreen);
 +static void	    miSpriteComputeSaved(DeviceIntPtr pDev, 
 +                                         ScreenPtr pScreen);
 +
 +static Bool         miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, 
 +                                                   ScreenPtr pScreen);
 +static void         miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, 
 +                                                ScreenPtr pScreen);
  
- #define SCREEN_PROLOGUE(pScreen, field)\
-   ((pScreen)->field = \
-    ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
- 
+ #define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
+    ((miSpriteScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \
+ 					miSpriteScreenKey))->field)
  #define SCREEN_EPILOGUE(pScreen, field)\
      ((pScreen)->field = miSprite##field)
  
@@@ -161,26 -125,14 +159,27 @@@ miSpriteReportDamage (DamagePtr pDamage
  {
      ScreenPtr		    pScreen = closure;
      miSpriteScreenPtr	    pScreenPriv;
 +    miCursorInfoPtr         pCursorInfo;
 +    DeviceIntPtr            pDev;
      
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    if (pScreenPriv->isUp &&
 -	RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
 +
 +    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
      {
 -	SPRITE_DEBUG(("Damage remove\n"));
 -	miSpriteRemoveCursor (pScreen);
 +        if (DevHasCursor(pDev))
 +        {
 +            pCursorInfo = MISPRITE(pDev);
 +
 +            if (pCursorInfo->isUp &&
 +                pCursorInfo->pScreen == pScreen && 
 +                RECT_IN_REGION (pScreen, pRegion, &pCursorInfo->saved) 
 +                         != rgnOUT) 
 +            {
 +                SPRITE_DEBUG(("Damage remove\n"));
 +                miSpriteRemoveCursor (pDev, pScreen);
 +            }
 +        }
      }
  }
  
@@@ -267,10 -217,7 +258,9 @@@ miSpriteInitialize (pScreen, cursorFunc
      pScreen->StoreColors = miSpriteStoreColors;
  
      pScreen->BlockHandler = miSpriteBlockHandler;
 -    
 +
 +    damageRegister = 0;
-     miSpriteDevPrivatesIndex = AllocateDevicePrivateIndex();
 +
      return TRUE;
  }
  
@@@ -289,10 -236,9 +279,10 @@@ miSpriteCloseScreen (i, pScreen
      ScreenPtr	pScreen;
  {
      miSpriteScreenPtr   pScreenPriv;
 +    DeviceIntPtr        pDev;
  
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
- 
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
      pScreen->CloseScreen = pScreenPriv->CloseScreen;
      pScreen->GetImage = pScreenPriv->GetImage;
      pScreen->GetSpans = pScreenPriv->GetSpans;
@@@ -323,23 -268,14 +313,23 @@@ miSpriteGetImage (pDrawable, sx, sy, w
      
      SCREEN_PROLOGUE (pScreen, GetImage);
  
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
- 
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    if (pDrawable->type == DRAWABLE_WINDOW &&
 -        pScreenPriv->isUp &&
 -	ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
 +    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
      {
 -	SPRITE_DEBUG (("GetImage remove\n"));
 -	miSpriteRemoveCursor (pScreen);
 +        if (DevHasCursor(pDev))
 +        {
 +             pCursorInfo = MISPRITE(pDev);
 +             if (pDrawable->type == DRAWABLE_WINDOW &&
 +                     pCursorInfo->isUp &&
 +                     pCursorInfo->pScreen == pScreen &&
 +                     ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, 
 +                         sx, sy, w, h)) 
 +             {
 +                 SPRITE_DEBUG (("GetImage remove\n"));
 +                 miSpriteRemoveCursor (pDev, pScreen);
 +             }
 +        }
      }
  
      (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
@@@ -364,41 -298,31 +354,42 @@@ miSpriteGetSpans (pDrawable, wMax, ppt
      
      SCREEN_PROLOGUE (pScreen, GetSpans);
  
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
 +
 +    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
      {
 -	DDXPointPtr    	pts;
 -	int    		*widths;
 -	int    		nPts;
 -	int    		xorg,
 -			yorg;
 -
 -	xorg = pDrawable->x;
 -	yorg = pDrawable->y;
 -
 -	for (pts = ppt, widths = pwidth, nPts = nspans;
 -	     nPts--;
 -	     pts++, widths++)
 - 	{
 -	    if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
 -			     pts->x+xorg,*widths))
 -	    {
 -		SPRITE_DEBUG (("GetSpans remove\n"));
 -		miSpriteRemoveCursor (pScreen);
 -		break;
 -	    }
 -	}
 +        if (DevHasCursor(pDev))
 +        {
 +            pCursorInfo = MISPRITE(pDev);
 +
 +            if (pDrawable->type == DRAWABLE_WINDOW && 
 +                    pCursorInfo->isUp && 
 +                    pCursorInfo->pScreen == pScreen)
 +            {
 +                DDXPointPtr    pts;
 +                int    	       *widths;
 +                int    	       nPts;
 +                int    	       xorg,
 +                               yorg;
 +
 +                xorg = pDrawable->x;
 +                yorg = pDrawable->y;
 +
 +                for (pts = ppt, widths = pwidth, nPts = nspans;
 +                        nPts--;
 +                        pts++, widths++)
 +                {
 +                    if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
 +                                pts->x+xorg,*widths))
 +                    {
 +                        SPRITE_DEBUG (("GetSpans remove\n"));
 +                        miSpriteRemoveCursor (pDev, pScreen);
 +                        break;
 +                    }
 +                }
 +            }
 +        }
      }
  
      (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
@@@ -418,22 -340,14 +409,23 @@@ miSpriteSourceValidate (pDrawable, x, y
      
      SCREEN_PROLOGUE (pScreen, SourceValidate);
  
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
 -	ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
 -		    x, y, width, height))
 +
 +    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
      {
 -	SPRITE_DEBUG (("SourceValidate remove\n"));
 -	miSpriteRemoveCursor (pScreen);
 +        if (DevHasCursor(pDev))
 +        {
 +            pCursorInfo = MISPRITE(pDev);
 +            if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp &&
 +                    pCursorInfo->pScreen == pScreen && 
 +                    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
 +                        x, y, width, height))
 +            {
 +                SPRITE_DEBUG (("SourceValidate remove\n"));
 +                miSpriteRemoveCursor (pDev, pScreen);
 +            }
 +        }
      }
  
      if (pScreen->SourceValidate)
@@@ -452,23 -364,16 +444,24 @@@ miSpriteCopyWindow (WindowPtr pWindow, 
      
      SCREEN_PROLOGUE (pScreen, CopyWindow);
  
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    /*
 -     * Damage will take care of destination check
 -     */
 -    if (pScreenPriv->isUp &&
 -	RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->saved) != rgnOUT)
 +
 +    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
      {
 -	SPRITE_DEBUG (("CopyWindow remove\n"));
 -	miSpriteRemoveCursor (pScreen);
 +        if (DevHasCursor(pDev))
 +        {
 +            pCursorInfo = MISPRITE(pDev);
 +            /*
 +             * Damage will take care of destination check
 +             */
 +            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
 +                    RECT_IN_REGION (pScreen, prgnSrc, &pCursorInfo->saved) != rgnOUT)
 +            {
 +                SPRITE_DEBUG (("CopyWindow remove\n"));
 +                miSpriteRemoveCursor (pDev, pScreen);
 +            }
 +        }
      }
  
      (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
@@@ -484,11 -389,9 +477,11 @@@ miSpriteBlockHandler (i, blockData, pTi
  {
      ScreenPtr		pScreen = screenInfo.screens[i];
      miSpriteScreenPtr	pPriv;
 +    DeviceIntPtr            pDev = inputInfo.pointer;
 +    miCursorInfoPtr         pCursorInfo;
  
-     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
- 
+     pPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						miSpriteScreenKey);
      SCREEN_PROLOGUE(pScreen, BlockHandler);
      
      (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
@@@ -571,11 -440,9 +564,11 @@@ miSpriteStoreColors (pMap, ndef, pdef
      int			i;
      int			updated;
      VisualPtr		pVisual;
 +    DeviceIntPtr        pDev = inputInfo.pointer;
 +    miCursorInfoPtr     pCursorInfo;
  
-     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
- 
+     pPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						miSpriteScreenKey);
      SCREEN_PROLOGUE(pScreen, StoreColors);
      
      (*pScreen->StoreColors) (pMap, ndef, pdef);
@@@ -648,10 -506,10 +641,10 @@@
  }
  
  static void
 -miSpriteFindColors (ScreenPtr pScreen)
 +miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
  {
 -    miSpriteScreenPtr	pScreenPriv = (miSpriteScreenPtr)
 +    miSpriteScreenPtr   pScreenPriv = (miSpriteScreenPtr)
-                                pScreen->devPrivates[miSpriteScreenIndex].ptr;
+ 	dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
      CursorPtr		pCursor;
      xColorItem		*sourceColor, *maskColor;
  
@@@ -697,20 -552,11 +690,20 @@@ miSpriteRealizeCursor (pDev, pScreen, p
      CursorPtr	pCursor;
  {
      miSpriteScreenPtr	pScreenPriv;
 +    miCursorInfoPtr pCursorInfo;
  
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
- 
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    if (pCursor == pScreenPriv->pCursor)
 -	pScreenPriv->checkPixels = TRUE;
 +    if (!pDev->isMaster && !pDev->u.master)
 +    {
 +        ErrorF("[mi] miSpriteRealizeCursor called for floating device.\n");
 +        return FALSE;
 +    }
 +    pCursorInfo = MISPRITE(pDev);
 +
 +    if (pCursor == pCursorInfo->pCursor)
 +	pCursorInfo->checkPixels = TRUE;
 +
      return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
  }
  
@@@ -736,29 -581,21 +730,30 @@@ miSpriteSetCursor (pDev, pScreen, pCurs
  {
      miSpriteScreenPtr	pScreenPriv;
  
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 +    miCursorInfoPtr pPointer;
 +    
 +    if (!pDev->isMaster && !pDev->u.master)
 +    {
 +        ErrorF("[mi] miSpriteSetCursor called for floating device.\n");
 +        return;
 +    }
 +    pPointer = MISPRITE(pDev);
 +
      if (!pCursor)
      {
 -    	pScreenPriv->shouldBeUp = FALSE;
 -    	if (pScreenPriv->isUp)
 -	    miSpriteRemoveCursor (pScreen);
 -	pScreenPriv->pCursor = 0;
 +    	pPointer->shouldBeUp = FALSE;
 +    	if (pPointer->isUp)
 +	    miSpriteRemoveCursor (pDev, pScreen);
 +	pPointer->pCursor = 0;
  	return;
      }
 -    pScreenPriv->shouldBeUp = TRUE;
 -    if (pScreenPriv->x == x &&
 -	pScreenPriv->y == y &&
 -	pScreenPriv->pCursor == pCursor &&
 -	!pScreenPriv->checkPixels)
 +    pPointer->shouldBeUp = TRUE;
 +    if (pPointer->x == x &&
 +	pPointer->y == y &&
 +	pPointer->pCursor == pCursor &&
 +	!pPointer->checkPixels)
      {
  	return;
      }
@@@ -856,88 -681,10 +851,84 @@@ miSpriteMoveCursor (pDev, pScreen, x, y
      int		x, y;
  {
      miSpriteScreenPtr	pScreenPriv;
 +    CursorPtr pCursor;
 +
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
++    pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
++						      miSpriteScreenKey);
 +    if (!pDev->isMaster && !pDev->u.master)
 +    {
 +        ErrorF("[mi] miSpriteMoveCursor called for floating device.\n");
 +        return;
 +    }
 +    pCursor = MISPRITE(pDev)->pCursor;
 +
 +    miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
 +}
 +
 +
 +static Bool
 +miSpriteDeviceCursorInitialize(pDev, pScreen)
 +    DeviceIntPtr pDev;
 +    ScreenPtr pScreen;
 +{
 +    miSpriteScreenPtr pScreenPriv;
 +    miCursorInfoPtr pCursorInfo;
 +    int ret = FALSE;
  
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
 +
-     if (!AllocateDevicePrivate(pDev, miSpriteDevPrivatesIndex))
-         return FALSE;
- 
-     pCursorInfo = 
-         pDev->devPrivates[miSpriteDevPrivatesIndex].ptr = 
-             xalloc(sizeof(miCursorInfoRec));
++    pCursorInfo = xalloc(sizeof(miCursorInfoRec));
 +    if (!pCursorInfo)
 +        return FALSE;
 +
 +    pCursorInfo->pCursor = NULL;
 +    pCursorInfo->x = 0;
 +    pCursorInfo->y = 0;
 +    pCursorInfo->isUp = FALSE;
 +    pCursorInfo->shouldBeUp = FALSE;
 +    pCursorInfo->pCacheWin = NullWindow;
 +    pCursorInfo->isInCacheWin = FALSE;
 +    pCursorInfo->checkPixels = TRUE;
 +    pCursorInfo->pScreen = FALSE;
 +
 +    ret = (*pScreenPriv->funcs->DeviceCursorInitialize)(pDev, pScreen);
 +    if (!ret)
 +    {
 +        xfree(pCursorInfo);
-         pDev->devPrivates[miSpriteDevPrivatesIndex].ptr = NULL;
-     } 
++        pCursorInfo = NULL;
++    }
++    dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo);
 +    return ret;
 +}
 +
 +static void
 +miSpriteDeviceCursorCleanup(pDev, pScreen)
 +    DeviceIntPtr pDev;
 +    ScreenPtr    pScreen;
 +{
 +    if (DevHasCursor(pDev))
 +    {
 +        miSpriteScreenPtr pScreenPriv;
-         pScreenPriv = 
-             (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
++        pScreenPriv = (miSpriteScreenPtr)
++                dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
 +
 +        (*pScreenPriv->funcs->DeviceCursorCleanup)(pDev, pScreen);
-         pDev->devPrivates[miSpriteDevPrivatesIndex].ptr = NULL;
-         xfree(MISPRITE(pDev));
 +    }
 +}
 +
 +static void
 +miSpriteUndisplayCursor(pDev, pScreen)
 +    DeviceIntPtr pDev;
 +    ScreenPtr    pScreen;
 +{
 +    if (!pDev->isMaster && !pDev->u.master)
 +    {
 +        ErrorF("[mi] miSpriteUndisplayCursor called for floating device.\n");
 +        return;
 +    }
 +    if (MISPRITE(pDev)->isUp)
 +        miSpriteRemoveCursor(pDev, pScreen);
  }
  
  /*
@@@ -950,77 -696,20 +941,79 @@@ miSpriteRemoveCursor (pDev, pScreen
      ScreenPtr	pScreen;
  {
      miSpriteScreenPtr   pScreenPriv;
 +    miCursorInfoPtr     pCursorInfo;
 +
  
 +    if (!pDev->isMaster && !pDev->u.master)
 +    {
 +        ErrorF("[mi] miSpriteRemoveCursor called for floating device.\n");
 +        return;
 +    }
      DamageDrawInternal (pScreen, TRUE);
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    miSpriteIsUpFALSE (pScreen, pScreenPriv);
 -    pScreenPriv->pCacheWin = NullWindow;
 -    if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
 -					 pScreenPriv->saved.x1,
 -					 pScreenPriv->saved.y1,
 -					 pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
 -					 pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
 +    pCursorInfo = MISPRITE(pDev);
 +
 +    miSpriteIsUpFALSE (pCursorInfo, pScreen, pScreenPriv);
 +    pCursorInfo->pCacheWin = NullWindow;
 +    miSpriteDisableDamage(pScreen, pScreenPriv);
 +    if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDev,
 +                                         pScreen,
 +					 pCursorInfo->saved.x1,
 +                                         pCursorInfo->saved.y1,
 +                                         pCursorInfo->saved.x2 -
 +                                         pCursorInfo->saved.x1,
 +                                         pCursorInfo->saved.y2 -
 +                                         pCursorInfo->saved.y1))
 +    {
 +	miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
 +    }
 +    miSpriteEnableDamage(pScreen, pScreenPriv);
 +    DamageDrawInternal (pScreen, FALSE);
 +}
 +
 +/*
 + * Called from the block handler, saves area under cursor
 + * before waiting for something to do.
 + */
 +
 +static void 
 +miSpriteSaveUnderCursor(pDev, pScreen)
 +    DeviceIntPtr pDev;
 +    ScreenPtr	pScreen;
 +{
 +    miSpriteScreenPtr   pScreenPriv;
 +    int			x, y;
 +    CursorPtr		pCursor;
 +    miCursorInfoPtr     pCursorInfo;
 +
 +    if (!pDev->isMaster && !pDev->u.master)
      {
 -	miSpriteIsUpTRUE (pScreen, pScreenPriv);
 +        ErrorF("[mi] miSpriteSaveUnderCursor called for floating device.\n");
 +        return;
      }
 +    DamageDrawInternal (pScreen, TRUE);
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
++    pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
++						      miSpriteScreenKey);
 +    pCursorInfo = MISPRITE(pDev);
 +
 +    miSpriteComputeSaved (pDev, pScreen);
 +    pCursor = pCursorInfo->pCursor;
 +
 +    x = pCursorInfo->x - (int)pCursor->bits->xhot;
 +    y = pCursorInfo->y - (int)pCursor->bits->yhot;
 +    miSpriteDisableDamage(pScreen, pScreenPriv);
 +
 +    (*pScreenPriv->funcs->SaveUnderCursor) (pDev,
 +                                      pScreen,
 +				      pCursorInfo->saved.x1,
 +				      pCursorInfo->saved.y1,
 +                                      pCursorInfo->saved.x2 -
 +                                      pCursorInfo->saved.x1,
 +                                      pCursorInfo->saved.y2 -
 +                                      pCursorInfo->saved.y1);
 +    SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
 +    miSpriteEnableDamage(pScreen, pScreenPriv);
      DamageDrawInternal (pScreen, FALSE);
  }
  
@@@ -1038,36 -725,29 +1031,37 @@@ miSpriteRestoreCursor (pDev, pScreen
      miSpriteScreenPtr   pScreenPriv;
      int			x, y;
      CursorPtr		pCursor;
 +    miCursorInfoPtr     pCursorInfo;
 +    
 +    if (!pDev->isMaster && !pDev->u.master)
 +    {
 +        ErrorF("[mi] miSpriteRestoreCursor called for floating device.\n");
 +        return;
 +    }
  
      DamageDrawInternal (pScreen, TRUE);
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 -    miSpriteComputeSaved (pScreen);
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    pCursor = pScreenPriv->pCursor;
 -    x = pScreenPriv->x - (int)pCursor->bits->xhot;
 -    y = pScreenPriv->y - (int)pCursor->bits->yhot;
 -    if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
 -				      pScreenPriv->saved.x1,
 -				      pScreenPriv->saved.y1,
 -				      pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
 -				      pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
 +    pCursorInfo = MISPRITE(pDev);
 +
 +    miSpriteComputeSaved (pDev, pScreen);
 +    pCursor = pCursorInfo->pCursor;
 +
 +    x = pCursorInfo->x - (int)pCursor->bits->xhot;
 +    y = pCursorInfo->y - (int)pCursor->bits->yhot;
 +    miSpriteDisableDamage(pScreen, pScreenPriv);
 +    SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
 +    if (pCursorInfo->checkPixels)
 +        miSpriteFindColors (pCursorInfo, pScreen);
 +    if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen, 
 +                pCursor, x, y,
 +                pScreenPriv->colors[SOURCE_COLOR].pixel,
 +                pScreenPriv->colors[MASK_COLOR].pixel))
      {
 -	if (pScreenPriv->checkPixels)
 -	    miSpriteFindColors (pScreen);
 -	if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
 -				  pScreenPriv->colors[SOURCE_COLOR].pixel,
 -				  pScreenPriv->colors[MASK_COLOR].pixel))
 -	{
 -	    miSpriteIsUpTRUE (pScreen, pScreenPriv);
 -	}
 +        miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
 +        pCursorInfo->pScreen = pScreen;
      }
 +    miSpriteEnableDamage(pScreen, pScreenPriv);
      DamageDrawInternal (pScreen, FALSE);
  }
  
@@@ -1084,19 -763,12 +1078,20 @@@ miSpriteComputeSaved (pDev, pScreen
      int		    x, y, w, h;
      int		    wpad, hpad;
      CursorPtr	    pCursor;
 +    miCursorInfoPtr pCursorInfo;
  
 +    if (!pDev->isMaster && !pDev->u.master)
 +    {
 +        ErrorF("[mi] miSpriteComputeSaved called for floating device.\n");
 +        return;
 +    }
-     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+     pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ 						      miSpriteScreenKey);
 -    pCursor = pScreenPriv->pCursor;
 -    x = pScreenPriv->x - (int)pCursor->bits->xhot;
 -    y = pScreenPriv->y - (int)pCursor->bits->yhot;
 +    pCursorInfo = MISPRITE(pDev);
 +
 +    pCursor = pCursorInfo->pCursor;
 +    x = pCursorInfo->x - (int)pCursor->bits->xhot;
 +    y = pCursorInfo->y - (int)pCursor->bits->yhot;
      w = pCursor->bits->width;
      h = pCursor->bits->height;
      wpad = SPRITE_PAD;
diff --cc render/animcur.c
index 1172877,1259289..a87718d
--- a/render/animcur.c
+++ b/render/animcur.c
@@@ -44,7 -44,7 +44,8 @@@
  #include "dixfontstr.h"
  #include "opaque.h"
  #include "picturestr.h"
 +#include "inputstr.h"
+ #include "xace.h"
  
  typedef struct _AnimCurElt {
      CursorPtr	pCursor;    /* cursor to show */
@@@ -351,17 -323,11 +350,14 @@@ AnimCurInit (ScreenPtr pScreen
  
      if (AnimCurGeneration != serverGeneration)
      {
 +        int i;
- 	AnimCurScreenPrivateIndex = AllocateScreenPrivateIndex ();
- 	if (AnimCurScreenPrivateIndex < 0)
- 	    return FALSE;
  	AnimCurGeneration = serverGeneration;
 -	animCurState.pCursor = 0;
 -	animCurState.pScreen = 0;
 -	animCurState.elt = 0;
 -	animCurState.time = 0;
 +        for (i = 0; i < MAX_DEVICES; i++) {
 +            animCurState[i].pCursor = 0;
 +            animCurState[i].pScreen = 0;
 +            animCurState[i].elt = 0;
 +            animCurState[i].time = 0;
 +        }
      }
      as = (AnimCurScreenPtr) xalloc (sizeof (AnimCurScreenRec));
      if (!as)
diff --cc xfixes/cursor.c
index 0c2b0d2,1d122fa..a804a89
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@@ -355,7 -350,11 +351,11 @@@ ProcXFixesGetCursorImage (ClientPtr cli
      pCursor = CursorCurrent;
      if (!pCursor)
  	return BadCursor;
+     rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
+ 		  pCursor, RT_NONE, NULL, DixReadAccess);
+     if (rc != Success)
+ 	return rc;
 -    GetSpritePosition (&x, &y);
 +    GetSpritePosition (inputInfo.pointer, &x, &y);
      width = pCursor->bits->width;
      height = pCursor->bits->height;
      npixels = width * height;
@@@ -503,7 -502,11 +503,11 @@@ ProcXFixesGetCursorImageAndName (Client
      pCursor = CursorCurrent;
      if (!pCursor)
  	return BadCursor;
+     rc = XaceHook(XACE_RESOURCE_ACCESS, client, pCursor->id, RT_CURSOR,
+ 		  pCursor, RT_NONE, NULL, DixReadAccess|DixGetAttrAccess);
+     if (rc != Success)
+ 	return rc;
 -    GetSpritePosition (&x, &y);
 +    GetSpritePosition (inputInfo.pointer, &x, &y);
      width = pCursor->bits->width;
      height = pCursor->bits->height;
      npixels = width * height;
diff --cc xkb/ddxFakeBtn.c
index 3dbb533,2dad54f..f9dcbf7
--- a/xkb/ddxFakeBtn.c
+++ b/xkb/ddxFakeBtn.c
@@@ -46,9 -46,9 +46,9 @@@ xEvent	ev
  int	x,y;
  DevicePtr ptr;
  
-     if ((ptr = LookupPointerDevice())==NULL)
+     if ((ptr = (DevicePtr)inputInfo.pointer)==NULL)
  	return;
 -    GetSpritePosition(&x,&y);
 +    GetSpritePosition(inputInfo.pointer, &x,&y);
      ev.u.u.type = event;
      ev.u.u.detail = button;
      ev.u.keyButtonPointer.time = GetTimeInMillis();
commit eace88989c3b65d5c20e9f37ea9b23c7c8e19335
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Dec 19 16:20:36 2007 +1030

    include: never overwrite realInputProc with enqueueInputProc. Bug #13511
    
    In some cases (triggered by a key repeat during a sync grab) XKB unwrapping
    can overwrite the device's realInputProc with the enqueueInputProc. When the
    grab is released and the events are replayed, we end up in an infinite loop.
    Each event is replayed and in replaying pushed to the end of the queue again.
    
    This fix is a hack only. It ensures that the realInputProc is never
    overwritten with the enqueueInputProc.
    
    This fixes Bug #13511 (https://bugs.freedesktop.org/show_bug.cgi?id=13511)

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 4395c87..b9d7084 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -258,7 +258,8 @@ typedef struct
 	    device->public.processInputProc = proc; \
 	oldprocs->processInputProc = \
 	oldprocs->realInputProc = device->public.realInputProc; \
-	device->public.realInputProc = proc; \
+	if (proc != device->public.enqueueInputProc) \
+		device->public.realInputProc = proc; \
 	oldprocs->unwrapProc = device->unwrapProc; \
 	device->unwrapProc = unwrapproc;
 
commit 9f6ae61ad12cc2813d04405458e1ca5aed8a539e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 18 13:57:07 2007 +1030

    dix: set the correct number of valuators in valuator events.
    
    (first_valuator + num_valuators) must never be larger than the number of axes,
    otherwise DIX freaks out. And from looking at libXI, anything larger than 6 is
    wrong too.

diff --git a/dix/getevents.c b/dix/getevents.c
index 9f955cf..f21bb1b 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -392,7 +392,7 @@ getValuatorEvents(EventList *events, DeviceIntPtr pDev, int first_valuator,
         xv = (deviceValuator*)events->event;
         xv->type = DeviceValuator;
         xv->first_valuator = i;
-        xv->num_valuators = num_valuators;
+        xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i);
         xv->deviceid = pDev->id;
         switch (final_valuator - i) {
         case 6:
commit d86e7f2ecc0a0129a722ffaca93dfc7c0c60e842
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Dec 7 20:40:21 2007 +1030

    dix: when getting a bogus event, at least print out the type.

diff --git a/dix/events.c b/dix/events.c
index 340e2bc..bb42259 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4008,7 +4008,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 		deactivateGrab = TRUE;
 	    break;
 	default:
-	    FatalError("bogus pointer event from ddx");
+	    FatalError("bogus pointer event from ddx. Type %d\n", xE->u.u.type);
 	}
     }
 
commit 3a058456e0ce531b21ae2b37be8868b8e0d56e56
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Dec 7 20:23:36 2007 +1030

    mi: unify ErrorFs, prepend [mi]

diff --git a/mi/miinitext.c b/mi/miinitext.c
index 6eb0352..45a14af 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -518,11 +518,11 @@ void EnableDisableExtensionError(char *name, Bool enable)
 {
     ExtensionToggle *ext = &ExtensionToggleList[0];
 
-    ErrorF("Extension \"%s\" is not recognized\n", name);
-    ErrorF("Only the following extensions can be run-time %s:\n",
+    ErrorF("[mi] Extension \"%s\" is not recognized\n", name);
+    ErrorF("[mi] Only the following extensions can be run-time %s:\n",
 	   enable ? "enabled" : "disabled");
     for (ext = &ExtensionToggleList[0]; ext->name != NULL; ext++)
-	ErrorF("    %s\n", ext->name);
+	ErrorF("[mi]    %s\n", ext->name);
 }
 
 #ifndef XFree86LOADER
diff --git a/mi/miregion.c b/mi/miregion.c
index 45768a3..6316561 100644
--- a/mi/miregion.c
+++ b/mi/miregion.c
@@ -267,13 +267,13 @@ miPrintRegion(rgn)
     num = REGION_NUM_RECTS(rgn);
     size = REGION_SIZE(rgn);
     rects = REGION_RECTS(rgn);
-    ErrorF("num: %d size: %d\n", num, size);
-    ErrorF("extents: %d %d %d %d\n",
+    ErrorF("[mi] num: %d size: %d\n", num, size);
+    ErrorF("[mi] extents: %d %d %d %d\n",
 	   rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
     for (i = 0; i < num; i++)
-      ErrorF("%d %d %d %d \n",
+      ErrorF("[mi] %d %d %d %d \n",
 	     rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
-    ErrorF("\n");
+    ErrorF("[mi] \n");
 }
 
 _X_EXPORT Bool
commit c5acf401dad6fbca47f2bb870185c1d08ac947a5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Dec 7 20:19:43 2007 +1030

    mi: unify last two ErrorF's in mieq.c

diff --git a/mi/mieq.c b/mi/mieq.c
index 1515512..31f838c 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -187,7 +187,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
         evt->event = xrealloc(evt->event, evt->evlen);
         if (!evt->event)
         {
-            ErrorF("Running out of memory. Tossing event.\n");
+            ErrorF("[mi] Running out of memory. Tossing event.\n");
             return;
         }
     }
@@ -221,7 +221,7 @@ void
 mieqSetHandler(int event, mieqHandler handler)
 {
     if (handler && miEventQueue.handlers[event])
-        ErrorF("mieq: warning: overriding existing handler %p with %p for "
+        ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for "
                "event %d\n", miEventQueue.handlers[event], handler, event);
 
     miEventQueue.handlers[event] = handler;
commit 117458d2db49efd3f04432ff45871b44c7d4ad57
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Dec 7 20:18:49 2007 +1030

    mi: change infamous "Tossed event ..." error for something more explanatory.
    
    Few whitespace errors fixed.
    Two ErrorF's prefixed with [mi].

diff --git a/mi/mieq.c b/mi/mieq.c
index 5dcc404..1515512 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -142,7 +142,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
         lastkbp = (deviceKeyButtonPointer *) laste->events->event;
 
         if (laste->nevents > 6) {
-            ErrorF("mieqEnqueue: more than six valuator events; dropping.\n");
+            ErrorF("[mi] mieqEnqueue: more than six valuator events; dropping.\n");
             return;
         }
         if (oldtail == miEventQueue.head ||
@@ -151,7 +151,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
               lastkbp->type == DeviceButtonRelease) ||
             ((lastkbp->deviceid & DEVICE_BITS) !=
              (v->deviceid & DEVICE_BITS))) {
-            ErrorF("mieqEnequeue: out-of-order valuator event; dropping.\n");
+            ErrorF("[mi] mieqEnequeue: out-of-order valuator event; dropping.\n");
             return;
         }
 
@@ -164,12 +164,13 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 	oldtail = (oldtail - 1) % QUEUE_SIZE;
     }
     else {
-    	newtail = (oldtail + 1) % QUEUE_SIZE;
-    	/* Toss events which come in late.  Usually this means your server's
+	newtail = (oldtail + 1) % QUEUE_SIZE;
+	/* Toss events which come in late.  Usually this means your server's
          * stuck in an infinite loop somewhere, but SIGIO is still getting
          * handled. */
-    	if (newtail == miEventQueue.head) {
-            ErrorF("tossed event which came in late\n");
+	if (newtail == miEventQueue.head) {
+            ErrorF("[mi] EQ overflowing. The server is probably stuck "
+                   "in an infinite loop.\n");
 	    return;
         }
 	miEventQueue.tail = newtail;
commit 447cd5d411875b62eb1a501bf00e604225b74d26
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 4 19:09:37 2007 +1030

    dix: update comments about inputInfo.pointer.

diff --git a/dix/events.c b/dix/events.c
index 046e4cd..340e2bc 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -237,24 +237,21 @@ static int DontPropagateRefCnts[DNPMCOUNT];
  *     inputInfo.pointer
  *     is the core pointer. Referred to as "virtual core pointer", "VCP",
  *     "core pointer" or inputInfo.pointer. There is exactly one core pointer,
- *     but multiple devices may send core events. The VCP is only used if no
- *     physical device is connected and does not have a visible cursor.
- *     Before the integration of MPX, any core request would operate on the
- *     VCP/VCK. Core events would always come from one of those two. Now both
- *     are only fallback devices if no physical devices are available.
+ *     but multiple devices may send core events. The VCP is the first master
+ *     pointer device and cannot be deleted.
  *
  *     inputInfo.keyboard
  *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
  *     See inputInfo.pointer.
  *
  *     inputInfo.devices
- *     linked list containing all devices BUT NOT INCLUDING VCK and VCP.
+ *     linked list containing all devices including VCP and VCK.
  *
  *     inputInfo.off_devices
  *     Devices that have not been initialized and are thus turned off.
  *
  *     inputInfo.numDevices
- *     Total number of devices (not counting VCP and VCK).
+ *     Total number of devices.
  */
 _X_EXPORT InputInfo inputInfo;
 
commit f44d7dcb5fefca3ddfd45e75d0bd0b47ec785e48
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 4 19:07:46 2007 +1030

    dix: change the filters to be per-device.
    
    If we have one global filter, one pointer may change the filter value and
    affect another pointer.
    
    Reproduceable effect:
    blackbox and xterm, start dragging xterm then click anywhere with the other
    pointer (attached to different masterd device!).  The button release resets
    the filter[Motion_Filter(button)] value, thus stopping dragging and no event
    is sent to the client anymore.
    Having the filters set per device gets around this.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 8c8cdfd..f0d288f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -550,7 +550,7 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
             return DONT_PROCESS;
         if (b->map[key] <= 5)
 	    b->state |= (Button1Mask >> 1) << b->map[key];
-	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
+	SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
     } else if (xE->u.u.type == DeviceButtonRelease) {
         if (!b)
             return DONT_PROCESS;
@@ -567,7 +567,7 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
             return DONT_PROCESS;
 	if (b->map[key] <= 5)
 	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
-	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
+	SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
     } else if (xE->u.u.type == ProximityIn)
 	device->valuator->mode &= ~OutOfProximity;
     else if (xE->u.u.type == ProximityOut)
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 2d077b2..cc75d23 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -827,13 +827,16 @@ SetExclusiveAccess(Mask mask)
 static void
 SetMaskForExtEvent(Mask mask, int event)
 {
+    int i;
 
     EventInfo[ExtEventIndex].mask = mask;
     EventInfo[ExtEventIndex++].type = event;
 
     if ((event < LASTEvent) || (event >= 128))
 	FatalError("MaskForExtensionEvent: bogus event number");
-    SetMaskForEvent(mask, event);
+
+    for (i = 0; i < MAX_DEVICES; i++)
+        SetMaskForEvent(i, mask, event);
 }
 
 /************************************************************************
@@ -974,13 +977,16 @@ FixExtensionEvents(ExtensionEntry * extEntry)
 static void
 RestoreExtensionEvents(void)
 {
-    int i;
+    int i, j;
 
     IReqCode = 0;
 
     for (i = 0; i < ExtEventIndex - 1; i++) {
 	if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
-	    SetMaskForEvent(0, EventInfo[i].type);
+        {
+            for (j = 0; j < MAX_DEVICES; j++)
+                SetMaskForEvent(j, 0, EventInfo[i].type);
+        }
 	EventInfo[i].mask = 0;
 	EventInfo[i].type = 0;
     }
diff --git a/dix/events.c b/dix/events.c
index 21b0eee..046e4cd 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -367,8 +367,12 @@ static Mask lastEventMask;
 
 extern int DeviceMotionNotify;
 
+/**
+ * Event filters. One set of filters for each device, but only the first layer
+ * is initialized. The rest is memcpy'd in InitEvents.
+ */
 #define CantBeFiltered NoEventMask
-static Mask filters[128] =
+static Mask filters[MAX_DEVICES][128] = {
 {
 	NoSuchEvent,		       /* 0 */
 	NoSuchEvent,		       /* 1 */
@@ -405,7 +409,7 @@ static Mask filters[128] =
 	ColormapChangeMask,	       /* ColormapNotify */
 	CantBeFiltered,		       /* ClientMessage */
 	CantBeFiltered		       /* MappingNotify */
-};
+}};
 
 
 /**
@@ -787,17 +791,19 @@ XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 #endif  /* PANORAMIX */
 
 void
-SetMaskForEvent(Mask mask, int event)
+SetMaskForEvent(int deviceid, Mask mask, int event)
 {
     int coretype;
+    if (deviceid < 0 || deviceid > MAX_DEVICES)
+        FatalError("SetMaskForEvent: bogus device id");
     if ((event < LASTEvent) || (event >= 128))
 	FatalError("SetMaskForEvent: bogus event number");
-    filters[event] = mask;
+    filters[deviceid][event] = mask;
 
     /* Need to change the mask for the core events too */
     coretype = XItoCoreType(event);
     if (coretype)
-        filters[coretype] = mask;
+        filters[deviceid][coretype] = mask;
 }
 
 _X_EXPORT void
@@ -2440,7 +2446,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
 {
     Window child = None;
     int type = xE->u.u.type;
-    Mask filter = filters[type];
+    Mask filter = filters[dev->id][type];
     int deliveries = 0;
 
     if (type & EXTENSION_EVENT_BASE)
@@ -2555,7 +2561,9 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
 
     if (!count)
 	return 0;
-    filter = filters[xE->u.u.type];
+    /* We don't know a device here. However, this should only ever be called
+       for a non-device event so we are safe to use 0*/
+    filter = filters[0][xE->u.u.type];
     if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
 	xE->u.destroyNotify.event = pWin->drawable.id;
     if (filter != StructureAndSubMask)
@@ -3466,8 +3474,8 @@ CheckPassiveGrabsOnWindow(
 	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
 
 	    (void) TryClientEvents(rClient(grab), xE, count,
-				   filters[xE->u.u.type],
-				   filters[xE->u.u.type],  grab);
+				   filters[device->id][xE->u.u.type],
+				   filters[device->id][xE->u.u.type],  grab);
 
 	    if (grabinfo->sync.state == FROZEN_NO_EVENT)
 	    {
@@ -3590,7 +3598,8 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
     FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
     if (xE->u.u.type & EXTENSION_EVENT_BASE)
 	mskidx = keybd->id;
-    (void)DeliverEventsToWindow(keybd, focus, xE, count, filters[xE->u.u.type],
+    (void)DeliverEventsToWindow(keybd, focus, xE, count,
+                                filters[keybd->id][xE->u.u.type],
 				NullGrab, mskidx);
 }
 
@@ -3671,7 +3680,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                         IsInterferingGrab(rClient(grab), thisDev, xE)))
                 {
                     deliveries = TryClientEvents(rClient(grab), xE, count,
-                            mask, filters[xE->u.u.type], grab);
+                            mask, filters[thisDev->id][xE->u.u.type], grab);
                 }
             }
             if (deliveries && (xE->u.u.type == MotionNotify
@@ -3989,7 +3998,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
              */
 	    if (xE->u.u.detail == 0)
 		return;
-	    filters[MotionNotify] = Motion_Filter(butc);
+            filters[mouse->id][Motion_Filter(butc)] = MotionNotify;
 	    if (!grab)
 		if (CheckDeviceGrabs(mouse, xE, 0, count))
 		    return;
@@ -3997,7 +4006,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 	case ButtonRelease:
 	    if (xE->u.u.detail == 0)
 		return;
-	    filters[MotionNotify] = Motion_Filter(butc);
+            filters[mouse->id][Motion_Filter(butc)] = MotionNotify;
 	    if (!butc->state && mouse->deviceGrab.fromPassiveGrab)
 		deactivateGrab = TRUE;
 	    break;
@@ -4350,14 +4359,14 @@ EnterLeaveEvent(
             sendevent = TRUE;
     }
 
-    if ((mask & filters[type]) && sendevent)
+    if ((mask & filters[mouse->id][type]) && sendevent)
     {
         if (grab)
             (void)TryClientEvents(rClient(grab), &event, 1, mask,
-                                  filters[type], grab);
+                                  filters[mouse->id][type], grab);
         else
-            (void)DeliverEventsToWindow(mouse, pWin, &event, 1, filters[type],
-                                        NullGrab, 0);
+            (void)DeliverEventsToWindow(mouse, pWin, &event, 1,
+                                  filters[mouse->id][type], NullGrab, 0);
     }
 
     /* we don't have enough bytes, so we squash flags and mode into
@@ -4372,15 +4381,17 @@ EnterLeaveEvent(
     mskidx = mouse->id;
     inputMasks = wOtherInputMasks(pWin);
     if (inputMasks &&
-       (filters[devEnterLeave->type] & inputMasks->deliverableEvents[mskidx]))
+       (filters[mouse->id][devEnterLeave->type] &
+            inputMasks->deliverableEvents[mskidx]))
     {
         if (devgrab)
             (void)TryClientEvents(rClient(devgrab), (xEvent*)devEnterLeave, 1,
-                                mask, filters[devEnterLeave->type], devgrab);
+                                mask, filters[mouse->id][devEnterLeave->type],
+                                devgrab);
 	else
 	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave,
-                                        1, filters[devEnterLeave->type],
-                                        NullGrab, mouse->id);
+                                   1, filters[mouse->id][devEnterLeave->type],
+                                   NullGrab, mouse->id);
     }
 
     if ((type == EnterNotify) && (mask & KeymapStateMask))
@@ -4579,8 +4590,8 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
         event.u.u.type = type;
         event.u.u.detail = detail;
         event.u.focus.window = pWin->drawable.id;
-        (void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab,
-                                    0);
+        (void)DeliverEventsToWindow(dev, pWin, &event, 1,
+                                    filters[dev->id][type], NullGrab, 0);
         if ((type == FocusIn) &&
                 ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
         {
@@ -5528,7 +5539,12 @@ InitEvents(void)
     inputInfo.keyboard = (DeviceIntPtr)NULL;
     inputInfo.pointer = (DeviceIntPtr)NULL;
     lastEventMask = OwnerGrabButtonMask;
-    filters[MotionNotify] = PointerMotionMask;
+    filters[0][PointerMotionMask] = MotionNotify;
+    for (i = 1; i < MAX_DEVICES; i++)
+    {
+        memcpy(&filters[i], filters[0], sizeof(filters[0]));
+    }
+
 #ifdef XEVIE
     xeviewin = NULL;
 #endif
diff --git a/include/dix.h b/include/dix.h
index db90579..6da3ee8 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -345,6 +345,7 @@ extern void SetVendorString(char *string);
 /* events.c */
 
 extern void SetMaskForEvent(
+    int /* deviceid */,
     Mask /* mask */,
     int /* event */);
 
commit 0931f40bf1bd6e00b8d95968d761a495b2c9a46c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 4 17:08:56 2007 +1030

    dix: comments, whitespaces, copyright fixes.
    
    Removing my copyright message for now, should eventually be in line with the
    rest of the messages.

diff --git a/dix/events.c b/dix/events.c
index 5242f43..21b0eee 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -107,12 +107,6 @@ of the copyright holder.
 
 ******************************************************************/
 
-/*
- * MPX additions
- * Copyright 2006 by Peter Hutterer
- * Author: Peter Hutterer <peter at cs.unisa.edu.au>
- */
-
 /** @file
  * This file handles event delivery and a big part of the server-side protocol
  * handling (the parts for input devices).
@@ -5022,6 +5016,12 @@ ProcGrabPointer(ClientPtr client)
     }
 
     grab = device->deviceGrab.grab;
+    /* check for
+       1. other client has a grab on the device already.
+       2. window is viewable
+       3. other client has this device as frozen "other" device
+       4. times are screwed.
+     */
     if ((grab) && !SameClient(grab, client))
 	rep.status = AlreadyGrabbed;
     else if ((!pWin->realized) ||
diff --git a/dix/getevents.c b/dix/getevents.c
index 6791bd8..9f955cf 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -23,12 +23,6 @@
  *
  * Author: Daniel Stone <daniel at fooishbar.org>
  */
- /*
-  * MPX additions:
-  * Copyright © 2006 Peter Hutterer
-  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
-  *
-  */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -112,18 +106,18 @@ key_autorepeats(DeviceIntPtr pDev, int key_code)
 }
 
 void
-CreateClassesChangedEvent(EventList* event, 
-                          DeviceIntPtr master, 
+CreateClassesChangedEvent(EventList* event,
+                          DeviceIntPtr master,
                           DeviceIntPtr slave)
 {
-    deviceClassesChangedEvent *dcce; 
+    deviceClassesChangedEvent *dcce;
     int len = sizeof(xEvent);
     CARD32 ms = GetTimeInMillis();
 
     /* XXX: ok, this is a bit weird. We need to alloc enough size for the
      * event so it can be filled in in POE lateron. Reason being that if
      * we realloc the event in POE we can get SIGABRT when we try to free
-     * or realloc the original pointer. 
+     * or realloc the original pointer.
      * We can only do it here as we don't have the EventList in the event
      * processing any more.
      *
commit 09c0c1a3cc4807813774a3c0e28a7ba9a87bb5c7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 4 16:51:52 2007 +1030

    dix: remove #ifdef XINPUT.
    
    No escaping XINPUT anymore.

diff --git a/dix/events.c b/dix/events.c
index 418079d..5242f43 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -371,9 +371,7 @@ extern int lastEvent;
 
 static Mask lastEventMask;
 
-#ifdef XINPUT
 extern int DeviceMotionNotify;
-#endif
 
 #define CantBeFiltered NoEventMask
 static Mask filters[128] =
@@ -2049,7 +2047,6 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
 		pEvents->u.u.detail = NotifyNormal;
 	    }
 	}
-#ifdef XINPUT
 	else
 	{
 	    if ((type == DeviceMotionNotify) &&
@@ -2057,7 +2054,6 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
 			((deviceKeyButtonPointer*)pEvents, mask) != 0)
 		return 1;
 	}
-#endif
 	type &= 0177;
 	if (type != KeymapNotify)
 	{
@@ -2271,7 +2267,6 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
     }
     else if ((type == MotionNotify) && deliveries)
 	pDev->valuator->motionHintWindow = pWin;
-#ifdef XINPUT
     else
     {
 	if (((type == DeviceMotionNotify)
@@ -2283,7 +2278,6 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 					  (deviceKeyButtonPointer*) pEvents,
 					  grab, client, deliveryMask);
     }
-#endif
     if (deliveries)
 	return deliveries;
     return nondeliveries;
@@ -3395,11 +3389,7 @@ CheckPassiveGrabsOnWindow(
 #endif
 	tempGrab.modifierDevice = grab->modifierDevice;
 	if ((device == grab->modifierDevice) &&
-	    ((xE->u.u.type == KeyPress)
-#if defined(XINPUT) && defined(XKB)
-	     || (xE->u.u.type == DeviceKeyPress)
-#endif
-	     ))
+	    ((xE->u.u.type == KeyPress) || (xE->u.u.type == DeviceKeyPress)))
 	    tempGrab.modifiersDetail.exact =
 #ifdef XKB
                 (noXkbExtension) ?
@@ -3537,11 +3527,8 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
     WindowPtr pWin = NULL;
     FocusClassPtr focus = device->focus;
 
-    if (((xE->u.u.type == ButtonPress)
-#if defined(XINPUT) && defined(XKB)
-	 || (xE->u.u.type == DeviceButtonPress)
-#endif
-	 ) && (device->button->buttonsDown != 1))
+    if (((xE->u.u.type == ButtonPress) || (xE->u.u.type == DeviceButtonPress))
+            && (device->button->buttonsDown != 1))
 	return FALSE;
 
     i = checkFirst;
@@ -3694,18 +3681,13 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                 }
             }
             if (deliveries && (xE->u.u.type == MotionNotify
-#ifdef XINPUT
-                        || xE->u.u.type == DeviceMotionNotify
-#endif
-                        ))
+                        || xE->u.u.type == DeviceMotionNotify))
                 thisDev->valuator->motionHintWindow = grab->window;
         }
     }
-    if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
-#ifdef XINPUT
-					  && xE->u.u.type != DeviceMotionNotify
-#endif
-					  ))
+    if (deliveries && !deactivateGrab &&
+       (xE->u.u.type != MotionNotify && xE->u.u.type != DeviceMotionNotify))
+    {
 	switch (grabinfo->sync.state)
 	{
 	case FREEZE_BOTH_NEXT_EVENT:
@@ -3737,6 +3719,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
 		*dxE = *xE;
 	    break;
 	}
+    }
 }
 
 /**
@@ -6022,9 +6005,8 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
 	while ( (passive = wPassiveGrabs(pWin)) )
 	    FreeResource(passive->resource, RT_NONE);
      }
-#ifdef XINPUT
+
     DeleteWindowFromAnyExtEvents(pWin, freeResources);
-#endif
 }
 
 /**
diff --git a/dix/window.c b/dix/window.c
index 51891a8..76e5dec 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -452,7 +452,6 @@ CreateRootWindow(ScreenPtr pScreen)
     pWin->optional->clipShape = NULL;
     pWin->optional->inputShape = NULL;
 #endif
-#ifdef XINPUT
     pWin->optional->inputMasks = NULL;
     pWin->optional->deviceCursors = NULL;
     pWin->optional->geMasks = (GenericClientMasksPtr)xcalloc(1, sizeof(GenericClientMasksRec));
@@ -461,7 +460,6 @@ CreateRootWindow(ScreenPtr pScreen)
         xfree(pWin->optional);
         return FALSE;
     }
-#endif
 
     pWin->optional->access.perm = NULL;
     pWin->optional->access.deny = NULL;
@@ -3690,10 +3688,8 @@ CheckWindowOptionalNeed (WindowPtr w)
     if (optional->inputShape != NULL)
 	return;
 #endif
-#ifdef XINPUT
     if (optional->inputMasks != NULL)
 	return;
-#endif
     if (optional->deviceCursors != NULL)
     {
         DevCursNodePtr pNode = optional->deviceCursors;
@@ -3753,9 +3749,7 @@ MakeWindowOptional (WindowPtr pWin)
     optional->clipShape = NULL;
     optional->inputShape = NULL;
 #endif
-#ifdef XINPUT
     optional->inputMasks = NULL;
-#endif
     optional->deviceCursors = NULL;
 
     optional->geMasks = 
commit 28b93d74a11a1064d68a214fcaa7b0aede864a38
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Dec 3 14:32:53 2007 +1030

    ephyr: miPointerWarpCursor needs the device parameter.
    
    Thanks to Mitchell Quille for spotting it.

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 52f5dcf..efcca5a 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -829,7 +829,7 @@ ephyrWarpCursor (ScreenPtr pScreen, int x, int y)
 {
     ephyrBlockSigio ();
     ephyrCurScreen = pScreen->myNum;
-    miPointerWarpCursor (pScreen, x, y);
+    miPointerWarpCursor (inputInfo.pointer, pScreen, x, y);
     ephyrUnblockSigio ();
 }
 
commit 004876355b43fb4d3c2bc5653a7dc1bfd3f985ee
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 30 13:56:04 2007 +1030

    dix: Remove RegisterPairingClient and UnregisterPairingClient.

diff --git a/dix/devices.c b/dix/devices.c
index 4c9c4fb..59db509 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2371,11 +2371,6 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
     if (ptr->spriteInfo->paired)
         return BadDevice;
 
-    if (!pairingClient)
-        RegisterPairingClient(client);
-    else if (client && pairingClient != client)
-        return BadAccess;
-
     if (kbd->spriteInfo->spriteOwner)
     {
         xfree(kbd->spriteInfo->sprite);
@@ -2409,11 +2404,6 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
     if (master && !master->isMaster) /* can't attach to slaves */
         return BadDevice;
 
-    if (!pairingClient)
-        RegisterPairingClient(client);
-    else if (client && pairingClient != client)
-        return BadAccess;
-
     /* set from floating to floating? */
     if (!dev->u.master && !master)
         return Success;
@@ -2495,39 +2485,6 @@ GetPairedDevice(DeviceIntPtr dev)
     return dev->spriteInfo->paired;
 }
 
-/*
- * Register a client to be able to pair devices.
- */
-Bool
-RegisterPairingClient(ClientPtr client)
-{
-    if (!pairingClient)
-    {
-        pairingClient = client;
-    } else if (pairingClient != client)
-    {
-        return False;
-    }
-    return True;
-}
-
-/*
- * Unregister pairing client;
- */
-Bool
-UnregisterPairingClient(ClientPtr client)
-{
-    if (pairingClient)
-    {
-        if ( pairingClient == client)
-        {
-            pairingClient = NULL;
-        } else
-            return False;
-    }
-    return True;
-}
-
 /* Guess a pointer that could be a good one for pairing. Any pointer that is
  * not yet paired with keyboard is considered a good one.
  * If no pointer is found, the last real pointer is chosen. If that doesn't
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 5e43902..34b0de1 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3572,7 +3572,6 @@ CloseDownClient(ClientPtr client)
 	ReleaseActiveGrabs(client);
 	DeleteClientFontStuff(client);
         ACUnregisterClient(client);
-        UnregisterPairingClient(client); /* other clients can pair devices */
 	if (!really_close_down)
 	{
 	    /*  This frees resources that should never be retained
diff --git a/include/input.h b/include/input.h
index 9e73dc2..c436943 100644
--- a/include/input.h
+++ b/include/input.h
@@ -475,7 +475,6 @@ extern int AttachDevice(ClientPtr client,
 extern DeviceIntPtr GetPairedDevice(DeviceIntPtr kbd);
 
 extern Bool RegisterPairingClient(ClientPtr client);
-extern Bool UnregisterPairingClient(ClientPtr client);
 
 extern DeviceIntPtr GuessFreePointerDevice(void);
 extern DeviceIntPtr NextFreePointerDevice(void);
commit 6216abe0c1a94efa4b2f0d14e88278f128304cd2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 30 11:34:24 2007 +1030

    dix: avoid activating the VCP/VCK twice.
    
    This may set dev->key-xkbinfo to NULL, causing a segfault in xkb code lateron.
    Spotted by David Huggins-Daines.

diff --git a/dix/devices.c b/dix/devices.c
index 98cd290..4c9c4fb 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -572,9 +572,6 @@ InitCoreDevices(void)
     if (!AllocateDevicePrivate(inputInfo.pointer, CoreDevicePrivatesIndex))
         FatalError("Couldn't allocate pointer devPrivates\n");
     inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
-
-    ActivateDevice(inputInfo.keyboard);
-    ActivateDevice(inputInfo.pointer);
 }
 
 /**
commit 9eb8ea9e615ebd8b568711eeca36aa84aa781ad3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 30 11:32:59 2007 +1030

    dix: only freeze the paired MD on a grab, not all other devices.

diff --git a/dix/events.c b/dix/events.c
index 43f4e37..418079d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1520,23 +1520,24 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
 	     CLIENT_BITS(grab->resource)))
 	    thisDev->deviceGrab.sync.other = NullGrab;
     }
-    /* XXX: other should only work on the paired keyboard, not on all other
-       devices
+
+    /*
+        XXX: Direct slave grab won't freeze the paired master device.
+        The correct thing to do would be to freeze all SDs attached to the
+        paired master device.
      */
-    for (dev = inputInfo.devices; dev; dev = dev->next)
+    if (thisDev->isMaster)
     {
-	if (dev != thisDev)
-	{
-	    if (otherMode == GrabModeSync)
-		dev->deviceGrab.sync.other = grab;
-	    else
-	    {	/* free both if same client owns both */
-		if (dev->deviceGrab.sync.other &&
-		    (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
-		     CLIENT_BITS(grab->resource)))
-		    dev->deviceGrab.sync.other = NullGrab;
-	    }
-	}
+        dev = GetPairedDevice(thisDev);
+        if (otherMode == GrabModeSync)
+            dev->deviceGrab.sync.other = grab;
+        else
+        {	/* free both if same client owns both */
+            if (dev->deviceGrab.sync.other &&
+                    (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
+                     CLIENT_BITS(grab->resource)))
+                dev->deviceGrab.sync.other = NullGrab;
+        }
     }
     ComputeFreezes();
 }
commit e4fe0a3cb789b8757f1c80f606dfe32bccada582
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 29 09:55:24 2007 +1030

    xkb: swap a LookupKeyboardDevice over in favour of GetPairedDevice
    
    The former always returns the VCK, which is obviously wrong if we have
    multiple devices.

diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index 063c844..b26c918 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -691,7 +691,7 @@ ProcessPointerEvent(	register xEvent  *	xE,
 			register DeviceIntPtr	mouse, 
 			int		        count)
 {
-DeviceIntPtr	dev = (DeviceIntPtr)LookupKeyboardDevice();
+DeviceIntPtr	dev = GetPairedDevice(mouse);
 XkbSrvInfoPtr	xkbi = dev->key->xkbInfo;
 unsigned 	changed = 0;
 ProcessInputProc backupproc;
commit 0f2398d06ce591724e388b3270800c5e22b3de2d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 27 10:22:44 2007 +1030

    Xi: set DeviceXXXState's length fields to the correct size of the struct.
    
    Setting it to the size of a pointer is an interesting but equally wrong
    approach. Luckily Xlib never used this field anyway so nobody got hurt so far.
    
    Spotted by Simon Thum.

diff --git a/Xi/getdctl.c b/Xi/getdctl.c
index 8a84e91..7175dc2 100644
--- a/Xi/getdctl.c
+++ b/Xi/getdctl.c
@@ -128,7 +128,7 @@ static void CopySwapDeviceAbsCalib (ClientPtr client, AbsoluteClassPtr dts,
     xDeviceAbsCalibState *calib = (xDeviceAbsCalibState *) buf;
 
     calib->control = DEVICE_ABS_CALIB;
-    calib->length = sizeof(calib);
+    calib->length = sizeof(xDeviceAbsCalibState);
     calib->min_x = dts->min_x;
     calib->max_x = dts->max_x;
     calib->min_y = dts->min_y;
@@ -159,7 +159,7 @@ static void CopySwapDeviceAbsArea (ClientPtr client, AbsoluteClassPtr dts,
     xDeviceAbsAreaState *area = (xDeviceAbsAreaState *) buf;
 
     area->control = DEVICE_ABS_AREA;
-    area->length = sizeof(area);
+    area->length = sizeof(xDeviceAbsAreaState);
     area->offset_x = dts->offset_x;
     area->offset_y = dts->offset_y;
     area->width = dts->width;
@@ -185,7 +185,7 @@ static void CopySwapDeviceCore (ClientPtr client, DeviceIntPtr dev, char *buf)
     xDeviceCoreState *c = (xDeviceCoreState *) buf;
 
     c->control = DEVICE_CORE;
-    c->length = sizeof(c);
+    c->length = sizeof(xDeviceCoreState);
     c->status = dev->coreEvents;
     c->iscore = (dev == inputInfo.keyboard || dev == inputInfo.pointer);
 
@@ -202,7 +202,7 @@ static void CopySwapDeviceEnable (ClientPtr client, DeviceIntPtr dev, char *buf)
     xDeviceEnableState *e = (xDeviceEnableState *) buf;
 
     e->control = DEVICE_ENABLE;
-    e->length = sizeof(e);
+    e->length = sizeof(xDeviceEnableState);
     e->enable = dev->enabled;
 
     if (client->swapped) {
commit a4edfbef022f9635c2c9b9eb229cb622834dc68c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Nov 24 16:16:48 2007 +1030

    mi: only call UpdateSpriteForScreen if the screen actually changed.
    
    If we call it unconditionally, we flip the dev->spriteInfo->sprite permanently
    when using XTestFakeInput (once in CheckMotion as called from the
    processInputProc, another time in UpdateSpriteForScreen when we actually warp
    the cursor). USFS also updates to the screen's root window unconditionally,
    which is not really what we want if we haven't changed screen at all.

diff --git a/mi/mipointer.c b/mi/mipointer.c
index b2f31c1..ff58823 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -359,6 +359,7 @@ miPointerWarpCursor (pDev, pScreen, x, y)
     int	   	 x, y;
 {
     miPointerPtr pPointer;
+    BOOL changedScreen = FALSE;
     
     if (!pDev->isMaster && !pDev->u.master)
         return;
@@ -366,7 +367,10 @@ miPointerWarpCursor (pDev, pScreen, x, y)
     SetupScreen (pScreen);
 
     if (pPointer->pScreen != pScreen)
+    {
 	(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
+        changedScreen = TRUE;
+    }
 
     if (GenerateEvent)
     {
@@ -387,7 +391,8 @@ miPointerWarpCursor (pDev, pScreen, x, y)
 	pPointer->y = y;
 	pPointer->pScreen = pScreen;
     }
-    UpdateSpriteForScreen (pDev, pScreen) ;
+    if (changedScreen)
+        UpdateSpriteForScreen (pDev, pScreen) ;
 }
 
 /*
commit bf3198c8c56289244c58d36c6869442479fd3481
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Nov 24 15:00:57 2007 +1030

    dix: fix typo

diff --git a/dix/events.c b/dix/events.c
index 123f21f..43f4e37 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4326,7 +4326,7 @@ EnterLeaveEvent(
 #endif
     {
         event.u.enterLeave.state = (keybd) ? keybd->key->state : 0;
-        event.u.enterLeave.state |+ mouse->button->state;
+        event.u.enterLeave.state |= mouse->button->state;
     }
     event.u.enterLeave.mode = mode;
     focus = (keybd) ? keybd->focus->win : None;
commit 5dabe448bda68a483bf444a4adfed2b25b30f600
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Nov 24 15:00:43 2007 +1030

    dix: Add special treatment of NotifyUngrab for enter/leave events.
    
    In some cases (e.g. using x2x) the previous model broke, with a window ending
    not counting down to 0 anymore. Special treatment for NotifyUngrab seems to
    help here.
    
    Current solution: If a NotifyGrab is to be sent ignore it. If a NotifyUngrab
    enter is sent, only adjust the semaphore if it is on 0. Likewise, do the same
    for a NotifyUngrab leave if the semaphore is on 1. This seems to work alright
    so far.

diff --git a/dix/events.c b/dix/events.c
index 88ce501..123f21f 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4468,15 +4468,20 @@ LeaveNotifies(DeviceIntPtr pDev,
     }
 }
 
+/* welcome to insanity */
 #define FOCUS_SEMAPHORE_MODIFY(win, field, mode, val) \
-    { \
-        if (mode != NotifyGrab && mode != NotifyUngrab) \
-        { \
-            FocusSemaphoresPtr sem;\
-            sem = (FocusSemaphoresPtr)win->devPrivates[FocusPrivatesIndex].ptr; \
+{ \
+    FocusSemaphoresPtr sem;\
+    sem = (FocusSemaphoresPtr)win->devPrivates[FocusPrivatesIndex].ptr; \
+    if (mode != NotifyGrab && mode != NotifyUngrab) { \
+        sem->field += val; \
+    } else if (mode == NotifyUngrab) { \
+        if (sem->field == 0 && val > 0) \
             sem->field += val; \
-        } \
-    }
+        else if (sem->field == 1 && val < 0) \
+            sem->field += val; \
+    } \
+}
 #define ENTER_LEAVE_SEMAPHORE_UP(win, mode)  \
         FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode, 1);
 
commit 691da031319dc59b9496101358c267f317abfd1e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 22 17:44:39 2007 +1030

    Xi: allocate motion history for master device.
    
    We're still missing out on the actual content of the history but at least this
    way we don't segfault.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index d72f00a..8c8cdfd 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -338,6 +338,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
             FatalError("[Xi] no memory for class shift.\n");
         memcpy(v, from->valuator, sizeof(ValuatorClassRec));
         v->motion = NULL;
+        AllocateMotionHistory(to); /*XXX should be copied somehow */
 
         v->axes = (AxisInfoPtr)&v[1];
         memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
commit f9269bebae27bbc9d0e03e02943166b83946623d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 22 17:30:14 2007 +1030

    DeviceIntRec: move lastx/lasty from valuator into DeviceIntRec.
    
    We free the ValuatorClassRec quite regularly. If a SIGIO is handled while
    we're swapping device classes, we can bring the server down when we try to
    access lastx/lasty of the master device.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index bd203b1..371be4e 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -444,8 +444,8 @@ ProcXTestFakeInput(client)
 	    (dev, root->drawable.pScreen,
 	     ev->u.keyButtonPointer.rootX,
 	     ev->u.keyButtonPointer.rootY, FALSE);
-        dev->valuator->lastx = ev->u.keyButtonPointer.rootX;
-        dev->valuator->lasty = ev->u.keyButtonPointer.rootY;
+        dev->lastx = ev->u.keyButtonPointer.rootX;
+        dev->lasty = ev->u.keyButtonPointer.rootY;
 	break;
     case ButtonPress:
     case ButtonRelease:
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index a675bdc..85fa7a9 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -176,8 +176,8 @@ ProcXWarpDevicePointer(ClientPtr client)
     }
 
     /* if we don't update the device, we get a jump next time it moves */
-    pDev->valuator->lastx = x;
-    pDev->valuator->lasty = x;
+    pDev->lastx = x;
+    pDev->lasty = x;
     miPointerUpdateSprite(pDev);
 
     /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
diff --git a/dix/devices.c b/dix/devices.c
index 7d889a2..98cd290 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -505,9 +505,9 @@ CorePointerProc(DeviceIntPtr pDev, int what)
                                 GetMotionHistory, (PtrCtrlProcPtr)NoopDDA,
                                 GetMotionHistorySize(), 2);
         pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
-        pDev->valuator->lastx = pDev->valuator->axisVal[0];
+        pDev->lastx = pDev->valuator->axisVal[0];
         pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
-        pDev->valuator->lasty = pDev->valuator->axisVal[1];
+        pDev->lasty = pDev->valuator->axisVal[1];
 
         classes->key = pDev->key;
         classes->valuator = pDev->valuator;
@@ -1226,8 +1226,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
     valc->mode = mode;
     valc->axes = (AxisInfoPtr)(valc + 1);
     valc->axisVal = (int *)(valc->axes + numAxes);
-    valc->lastx = 0;
-    valc->lasty = 0;
     valc->dxremaind = 0;
     valc->dyremaind = 0;
     dev->valuator = valc;
diff --git a/dix/getevents.c b/dix/getevents.c
index 585fddd..6791bd8 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -487,8 +487,8 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
 
         if (master->valuator && pDev->valuator)
         {
-            pDev->valuator->lastx = master->valuator->lastx;
-            pDev->valuator->lasty = master->valuator->lasty;
+            pDev->lastx = master->lastx;
+            pDev->lasty = master->lasty;
         }
         master->u.lastSlave = pDev;
         numEvents++;
@@ -671,8 +671,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     {
         CreateClassesChangedEvent(events, master, pDev);
 
-        pDev->valuator->lastx = master->valuator->lastx;
-        pDev->valuator->lasty = master->valuator->lasty;
+        pDev->lastx = master->lastx;
+        pDev->lasty = master->lasty;
         master->u.lastSlave = pDev;
 
         num_events++;
@@ -728,14 +728,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
             x = valuators[0];
         }
         else {
-            x = pDev->valuator->lastx;
+            x = pDev->lastx;
         }
 
         if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
             y = valuators[1 - first_valuator];
         }
         else {
-            y = pDev->valuator->lasty;
+            y = pDev->lasty;
         }
     }
     else {
@@ -744,14 +744,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
                               valuators);
 
         if (first_valuator == 0 && num_valuators >= 1)
-            x = pDev->valuator->lastx + valuators[0];
+            x = pDev->lastx + valuators[0];
         else
-            x = pDev->valuator->lastx;
+            x = pDev->lastx;
 
         if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-            y = pDev->valuator->lasty + valuators[1 - first_valuator];
+            y = pDev->lasty + valuators[1 - first_valuator];
         else
-            y = pDev->valuator->lasty;
+            y = pDev->lasty;
     }
 
     /* Clip both x and y to the defined limits (usually co-ord space limit). */
@@ -772,12 +772,12 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
-    pDev->valuator->lastx = x;
-    pDev->valuator->lasty = y;
+    pDev->lastx = x;
+    pDev->lasty = y;
     if (master)
     {
-        master->valuator->lastx = x;
-        master->valuator->lasty = y;
+        master->lastx = x;
+        master->lasty = y;
     }
 
     if (!coreOnly)
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 810f45b..7223f1d 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -554,14 +554,14 @@ xf86PostMotionEventP(DeviceIntPtr	device,
             {
                 dx = valuators[0];
                 if (is_absolute)
-                    dx -= device->valuator->lastx;
+                    dx -= device->lastx;
             }
 
             if (first_valuator == 1 || num_valuators >= 2)
             {
                 dy = valuators[1 - first_valuator];
                 if (is_absolute)
-                    dy -= device->valuator->lasty;
+                    dy -= device->lasty;
             }
 
             if (DGAStealMotionEvent(device, index, dx, dy))
@@ -825,11 +825,11 @@ xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum)
 {
     if (axnum == 0) {
 	dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
-        dev->valuator->lastx = dev->valuator->axisVal[0];
+        dev->lastx = dev->valuator->axisVal[0];
     }
     else if (axnum == 1) {
 	dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
-        dev->valuator->lasty = dev->valuator->axisVal[1];
+        dev->lasty = dev->valuator->axisVal[1];
     }
 }
 
diff --git a/include/inputstr.h b/include/inputstr.h
index 0589097..bcb8079 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -174,8 +174,6 @@ typedef struct _ValuatorClassRec {
     AxisInfoPtr 	  axes;
     unsigned short	  numAxes;
     int			  *axisVal;
-    int                   lastx, lasty; /* last event recorded, not posted to
-                                         * client; see dix/devices.c */
     int                   dxremaind, dyremaind; /* for acceleration */
     CARD8	 	  mode;
 } ValuatorClassRec, *ValuatorClassPtr;
@@ -421,6 +419,8 @@ typedef struct _DeviceIntRec {
     DeviceIntPtr        master;       /* master device */
     DeviceIntPtr        lastSlave;    /* last slave device used */
     } u;
+    int                 lastx, lasty; /* last event recorded, not posted to
+                                       * client; see dix/devices.c */
 } DeviceIntRec;
 
 typedef struct {
commit 9ed43eff48201520797f89a12bb3b2f5819bd99f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 21 17:16:27 2007 +1030

    Xi: allow clients to specify pure client id in SetClientPointer.
    
    If no window was found with the given ID, try if there's a client with the ID.
    Allows us to set the CP for apps that don't open windows (e.g. x2x).

diff --git a/Xi/setcptr.c b/Xi/setcptr.c
index ad8f571..a3bd9c2 100644
--- a/Xi/setcptr.c
+++ b/Xi/setcptr.c
@@ -89,10 +89,17 @@ ProcXSetClientPointer(ClientPtr client)
         err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
         if (err != Success)
         {
-            client->errorValue = stuff->win;
-            return err;
-        }
-        targetClient= wClient(pWin);
+            /* window could not be found. maybe the window ID given was a pure
+               client id? */
+            err = dixLookupClient(&targetClient, stuff->win,
+                                  client, DixReadWriteAccess);
+            if (err != Success)
+            {
+                client->errorValue = stuff->win;
+                return err;
+            }
+        } else
+            targetClient= wClient(pWin);
     } else
         targetClient = client;
 
commit 33f15689922ad9f1193f803bc1636c82c23ab99e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 21 16:06:44 2007 +1030

    xtest: switch an inputInfo.pointer over to PickPointer.
    
    Couple of whitespace fixes too.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index 711b57c..bd203b1 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -124,7 +124,7 @@ ProcXTestGetVersion(client)
     rep.majorVersion = XTestMajorVersion;
     rep.minorVersion = XTestMinorVersion;
     if (client->swapped) {
-    	swaps(&rep.sequenceNumber, n);
+	swaps(&rep.sequenceNumber, n);
 	swaps(&rep.minorVersion, n);
     }
     WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep);
@@ -139,7 +139,8 @@ ProcXTestCompareCursor(client)
     xXTestCompareCursorReply rep;
     WindowPtr pWin;
     CursorPtr pCursor;
-     int n, rc;
+    int n, rc;
+    DeviceIntPtr pointer = PickPointer(client);
 
     REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
     rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
@@ -148,10 +149,10 @@ ProcXTestCompareCursor(client)
     if (stuff->cursor == None)
 	pCursor = NullCursor;
     else if (stuff->cursor == XTestCurrentCursor)
-	pCursor = GetSpriteCursor(inputInfo.pointer);
+	pCursor = GetSpriteCursor(pointer);
     else {
 	pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
-	if (!pCursor) 
+	if (!pCursor)
 	{
 	    client->errorValue = stuff->cursor;
 	    return (BadCursor);
@@ -162,7 +163,7 @@ ProcXTestCompareCursor(client)
     rep.sequenceNumber = client->sequence;
     rep.same = (wCursor(pWin) == pCursor);
     if (client->swapped) {
-    	swaps(&rep.sequenceNumber, n);
+	swaps(&rep.sequenceNumber, n);
     }
     WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep);
     return(client->noClientException);
@@ -276,7 +277,7 @@ ProcXTestFakeInput(client)
 	/* swap the request back so we can simply re-execute it */
 	if (client->swapped)
 	{
-    	    (void) XTestSwapFakeInput(client, (xReq *)stuff);
+	    (void) XTestSwapFakeInput(client, (xReq *)stuff);
 	    swaps(&stuff->length, n);
 	}
 	ResetCurrentRequest (client);
@@ -426,7 +427,7 @@ ProcXTestFakeInput(client)
 
 #ifdef PANORAMIX
 	if ((!noPanoramiXExtension
-	     && root->drawable.pScreen->myNum 
+	     && root->drawable.pScreen->myNum
                 != XineramaGetCursorScreen(dev))
 	    || (noPanoramiXExtension && root != GetCurrentRootWindow(dev)))
 
@@ -545,14 +546,14 @@ XTestSwapFakeInput(client, req)
     nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
     for (ev = (xEvent *)&req[1]; --nev >= 0; ev++)
     {
-    	/* Swap event */
-    	proc = EventSwapVector[ev->u.u.type & 0177];
+	/* Swap event */
+	proc = EventSwapVector[ev->u.u.type & 0177];
 	/* no swapping proc; invalid event type? */
-    	if (!proc ||  proc ==  NotImplemented) {
+	if (!proc ||  proc ==  NotImplemented) {
 	    client->errorValue = ev->u.u.type;
 	    return BadValue;
 	}
-    	(*proc)(ev, &sev);
+	(*proc)(ev, &sev);
 	*ev = sev;
     }
     return Success;
commit e5dd7a95791748c57cab75c0d8ba9d37f72edccf
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 21 15:59:31 2007 +1030

    Xext: Scruffy the janitor don't like no "register" keywords.

diff --git a/Xext/EVI.c b/Xext/EVI.c
index 8fe3481..edf8d66 100644
--- a/Xext/EVI.c
+++ b/Xext/EVI.c
@@ -45,7 +45,7 @@ ProcEVIQueryVersion(ClientPtr client)
 {
     /* REQUEST(xEVIQueryVersionReq); */
     xEVIQueryVersionReply rep;
-    register int n;
+    int n;
     REQUEST_SIZE_MATCH (xEVIQueryVersionReq);
     rep.type = X_Reply;
     rep.length = 0;
@@ -144,7 +144,7 @@ SProcEVIQueryVersion(ClientPtr client)
 static int
 SProcEVIGetVisualInfo(ClientPtr client)
 {
-    register int n;
+    int n;
     REQUEST(xEVIGetVisualInfoReq);
     swaps(&stuff->length, n);
     return ProcEVIGetVisualInfo(client);
diff --git a/Xext/appgroup.c b/Xext/appgroup.c
index 7bd2055..d721afc 100644
--- a/Xext/appgroup.c
+++ b/Xext/appgroup.c
@@ -183,11 +183,11 @@ void XagResetProc(
 
 static 
 int ProcXagQueryVersion(
-    register ClientPtr client)
+     ClientPtr client)
 {
     /* REQUEST (xXagQueryVersionReq); */
     xXagQueryVersionReply rep;
-    register int n;
+     int n;
 
     REQUEST_SIZE_MATCH (xXagQueryVersionReq);
     rep.type = X_Reply;
@@ -378,7 +378,7 @@ int AttrValidate(
 }
 
 static int ProcXagCreate (
-    register ClientPtr client)
+     ClientPtr client)
 {
     REQUEST (xXagCreateReq);
     AppGroupPtr pAppGrp;
@@ -409,7 +409,7 @@ static int ProcXagCreate (
 }
 
 static int ProcXagDestroy(
-    register ClientPtr client)
+     ClientPtr client)
 {
     AppGroupPtr pAppGrp;
     REQUEST (xXagDestroyReq);
@@ -426,7 +426,7 @@ static int ProcXagDestroy(
 
 static 
 int ProcXagGetAttr(
-    register ClientPtr client)
+     ClientPtr client)
 {
     AppGroupPtr pAppGrp;
     REQUEST (xXagGetAttrReq);
@@ -462,7 +462,7 @@ int ProcXagGetAttr(
 
 static 
 int ProcXagQuery(
-    register ClientPtr client)
+     ClientPtr client)
 {
     ClientPtr pClient;
     AppGroupPtr pAppGrp;
@@ -497,7 +497,7 @@ int ProcXagQuery(
 
 static 
 int ProcXagCreateAssoc(
-    register ClientPtr client)
+     ClientPtr client)
 {
     REQUEST (xXagCreateAssocReq);
 
@@ -520,7 +520,7 @@ int ProcXagCreateAssoc(
 
 static 
 int ProcXagDestroyAssoc(
-    register ClientPtr client)
+     ClientPtr client)
 {
     /* REQUEST (xXagDestroyAssocReq); */
 
@@ -531,7 +531,7 @@ int ProcXagDestroyAssoc(
 
 static 
 int ProcXagDispatch (
-    register ClientPtr client)
+     ClientPtr client)
 {
     REQUEST (xReq);
     switch (stuff->data)
@@ -557,9 +557,9 @@ int ProcXagDispatch (
 
 static 
 int SProcXagQueryVersion(
-    register ClientPtr client)
+     ClientPtr client)
 {
-    register int n;
+     int n;
     REQUEST(xXagQueryVersionReq);
     swaps(&stuff->length, n);
     return ProcXagQueryVersion(client);
@@ -569,7 +569,7 @@ static
 int SProcXagCreate(
     ClientPtr client)
 {
-    register int n;
+     int n;
     REQUEST (xXagCreateReq);
     swaps (&stuff->length, n);
     REQUEST_AT_LEAST_SIZE (xXagCreateReq);
@@ -583,7 +583,7 @@ static
 int SProcXagDestroy(
     ClientPtr client)
 {
-    register int n;
+     int n;
     REQUEST (xXagDestroyReq);
     swaps (&stuff->length, n);
     REQUEST_SIZE_MATCH (xXagDestroyReq);
@@ -595,7 +595,7 @@ static
 int SProcXagGetAttr(
     ClientPtr client)
 {
-    register int n;
+     int n;
     REQUEST (xXagGetAttrReq);
     swaps (&stuff->length, n);
     REQUEST_SIZE_MATCH (xXagGetAttrReq);
@@ -607,7 +607,7 @@ static
 int SProcXagQuery(
     ClientPtr client)
 {
-    register int n;
+     int n;
     REQUEST (xXagQueryReq);
     swaps (&stuff->length, n);
     REQUEST_SIZE_MATCH (xXagQueryReq);
@@ -619,7 +619,7 @@ static
 int SProcXagCreateAssoc(
     ClientPtr client)
 {
-    register int n;
+     int n;
     REQUEST (xXagCreateAssocReq);
     swaps (&stuff->length, n);
     REQUEST_SIZE_MATCH (xXagCreateAssocReq);
@@ -633,7 +633,7 @@ static
 int SProcXagDestroyAssoc(
     ClientPtr client)
 {
-    register int n;
+     int n;
     REQUEST (xXagDestroyAssocReq);
     swaps (&stuff->length, n);
     REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
@@ -643,7 +643,7 @@ int SProcXagDestroyAssoc(
 
 static 
 int SProcXagDispatch(
-    register ClientPtr client)
+     ClientPtr client)
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/bigreq.c b/Xext/bigreq.c
index fcd848a..f1f85f9 100644
--- a/Xext/bigreq.c
+++ b/Xext/bigreq.c
@@ -79,11 +79,11 @@ BigReqResetProc (extEntry)
 
 static int
 ProcBigReqDispatch (client)
-    register ClientPtr	client;
+     ClientPtr	client;
 {
     REQUEST(xBigReqEnableReq);
     xBigReqEnableReply rep;
-    register int n;
+     int n;
 
     if (client->swapped) {
 	swaps(&stuff->length, n);
diff --git a/Xext/cup.c b/Xext/cup.c
index 6bfa278..d146959 100644
--- a/Xext/cup.c
+++ b/Xext/cup.c
@@ -163,11 +163,11 @@ void ResetProc(
 
 static 
 int ProcQueryVersion(
-    register ClientPtr client)
+    ClientPtr client)
 {
     /* REQUEST (xXcupQueryVersionReq); */
     xXcupQueryVersionReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH (xXcupQueryVersionReq);
     rep.type = X_Reply;
@@ -187,12 +187,12 @@ int ProcQueryVersion(
 
 static
 int ProcGetReservedColormapEntries(
-    register ClientPtr client)
+    ClientPtr client)
 {
     REQUEST (xXcupGetReservedColormapEntriesReq);
     xXcupGetReservedColormapEntriesReply rep;
     xColorItem* cptr;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH (xXcupGetReservedColormapEntriesReq);
 
@@ -220,7 +220,7 @@ int ProcGetReservedColormapEntries(
 
 static
 int ProcStoreColors(
-    register ClientPtr client)
+    ClientPtr client)
 {
     REQUEST (xXcupStoreColorsReq);
     ColormapPtr pcmp;
@@ -279,7 +279,7 @@ int ProcStoreColors(
 
 static 
 int ProcDispatch(
-    register ClientPtr client)
+    ClientPtr client)
 {
     REQUEST (xReq);
     switch (stuff->data)
@@ -297,9 +297,9 @@ int ProcDispatch(
 
 static 
 int SProcQueryVersion(
-    register ClientPtr client)
+    ClientPtr client)
 {
-    register int n;
+    int n;
 
     REQUEST(xXcupQueryVersionReq);
     swaps(&stuff->length, n);
@@ -310,7 +310,7 @@ static
 int SProcGetReservedColormapEntries(
     ClientPtr client)
 {
-    register int n;
+    int n;
 
     REQUEST (xXcupGetReservedColormapEntriesReq);
     swaps (&stuff->length, n);
@@ -323,7 +323,7 @@ static
 int SProcXcupStoreColors(
     ClientPtr client)
 {
-    register int n;
+    int n;
     int count;
     xColorItem* pItem;
 
@@ -339,7 +339,7 @@ int SProcXcupStoreColors(
 
 static 
 int SProcDispatch(
-    register ClientPtr client)
+    ClientPtr client)
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/dpms.c b/Xext/dpms.c
index aced406..edd9ff7 100644
--- a/Xext/dpms.c
+++ b/Xext/dpms.c
@@ -99,11 +99,11 @@ DPMSResetProc (extEntry)
 
 static int
 ProcDPMSGetVersion(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     /* REQUEST(xDPMSGetVersionReq); */
     xDPMSGetVersionReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xDPMSGetVersionReq);
 
@@ -122,11 +122,11 @@ ProcDPMSGetVersion(client)
 }
 
 static int
-ProcDPMSCapable(register ClientPtr client)
+ProcDPMSCapable(ClientPtr client)
 {
     /* REQUEST(xDPMSCapableReq); */
     xDPMSCapableReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xDPMSCapableReq);
 
@@ -144,11 +144,11 @@ ProcDPMSCapable(register ClientPtr client)
 
 static int
 ProcDPMSGetTimeouts(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     /* REQUEST(xDPMSGetTimeoutsReq); */
     xDPMSGetTimeoutsReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
 
@@ -171,7 +171,7 @@ ProcDPMSGetTimeouts(client)
 
 static int
 ProcDPMSSetTimeouts(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xDPMSSetTimeoutsReq);
 
@@ -198,7 +198,7 @@ ProcDPMSSetTimeouts(client)
 
 static int
 ProcDPMSEnable(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     /* REQUEST(xDPMSEnableReq); */
 
@@ -212,7 +212,7 @@ ProcDPMSEnable(client)
 
 static int
 ProcDPMSDisable(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     /* REQUEST(xDPMSDisableReq); */
 
@@ -227,7 +227,7 @@ ProcDPMSDisable(client)
 
 static int
 ProcDPMSForceLevel(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xDPMSForceLevelReq);
 
@@ -259,11 +259,11 @@ ProcDPMSForceLevel(client)
 }
 
 static int
-ProcDPMSInfo(register ClientPtr client)
+ProcDPMSInfo(ClientPtr client)
 {
     /* REQUEST(xDPMSInfoReq); */
     xDPMSInfoReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xDPMSInfoReq);
 
@@ -283,7 +283,7 @@ ProcDPMSInfo(register ClientPtr client)
 
 static int
 ProcDPMSDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
 
@@ -312,9 +312,9 @@ ProcDPMSDispatch (client)
 
 static int
 SProcDPMSGetVersion(client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int n;
+    int n;
     REQUEST(xDPMSGetVersionReq);
 
     swaps(&stuff->length, n);
@@ -325,10 +325,10 @@ SProcDPMSGetVersion(client)
 }
 
 static int
-SProcDPMSCapable(register ClientPtr client)
+SProcDPMSCapable(ClientPtr client)
 {
     REQUEST(xDPMSCapableReq);
-    register int n;
+    int n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xDPMSCapableReq);
@@ -338,10 +338,10 @@ SProcDPMSCapable(register ClientPtr client)
 
 static int
 SProcDPMSGetTimeouts(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xDPMSGetTimeoutsReq);
-    register int n;
+    int n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
@@ -351,10 +351,10 @@ SProcDPMSGetTimeouts(client)
 
 static int
 SProcDPMSSetTimeouts(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xDPMSSetTimeoutsReq);
-    register int n;
+    int n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq);
@@ -367,10 +367,10 @@ SProcDPMSSetTimeouts(client)
 
 static int
 SProcDPMSEnable(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xDPMSEnableReq);
-    register int n;
+    int n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xDPMSEnableReq);
@@ -380,10 +380,10 @@ SProcDPMSEnable(client)
 
 static int
 SProcDPMSDisable(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xDPMSDisableReq);
-    register int n;
+    int n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xDPMSDisableReq);
@@ -393,10 +393,10 @@ SProcDPMSDisable(client)
 
 static int
 SProcDPMSForceLevel(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xDPMSForceLevelReq);
-    register int n;
+    int n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
@@ -408,10 +408,10 @@ SProcDPMSForceLevel(client)
 
 static int
 SProcDPMSInfo(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xDPMSInfoReq);
-    register int n;
+    int n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xDPMSInfoReq);
@@ -421,7 +421,7 @@ SProcDPMSInfo(client)
 
 static int
 SProcDPMSDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/fontcache.c b/Xext/fontcache.c
index c54340b..1b1ca41 100644
--- a/Xext/fontcache.c
+++ b/Xext/fontcache.c
@@ -100,10 +100,10 @@ FontCacheResetProc (extEntry)
 
 static int
 ProcFontCacheQueryVersion(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     xFontCacheQueryVersionReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xFontCacheQueryVersionReq);
     rep.type = X_Reply;
@@ -123,11 +123,11 @@ ProcFontCacheQueryVersion(client)
 
 static int
 ProcFontCacheGetCacheSettings(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     xFontCacheGetCacheSettingsReply rep;
     FontCacheSettings cinfo;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xFontCacheGetCacheSettingsReq);
     rep.type = X_Reply;
@@ -161,11 +161,11 @@ ProcFontCacheGetCacheSettings(client)
 
 static int
 ProcFontCacheGetCacheStatistics(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     xFontCacheGetCacheStatisticsReply rep;
     FontCacheStatistics cstats;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xFontCacheGetCacheStatisticsReq);
     rep.type = X_Reply;
@@ -214,7 +214,7 @@ ProcFontCacheGetCacheStatistics(client)
 
 static int
 ProcFontCacheChangeCacheSettings(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     FontCacheSettings cs;
 
@@ -243,7 +243,7 @@ ProcFontCacheChangeCacheSettings(client)
 
 static int
 ProcFontCacheDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
@@ -263,9 +263,9 @@ ProcFontCacheDispatch (client)
 
 static int
 SProcFontCacheQueryVersion(client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int n;
+    int n;
     REQUEST(xFontCacheQueryVersionReq);
     swaps(&stuff->length, n);
     return ProcFontCacheQueryVersion(client);
@@ -275,7 +275,7 @@ static int
 SProcFontCacheGetCacheSettings(client)
     ClientPtr client;
 {
-    register int n;
+    int n;
     REQUEST(xFontCacheGetCacheSettingsReq);
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xFontCacheGetCacheSettingsReq);
@@ -286,7 +286,7 @@ static int
 SProcFontCacheGetCacheStatistics(client)
     ClientPtr client;
 {
-    register int n;
+    int n;
     REQUEST(xFontCacheGetCacheStatisticsReq);
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xFontCacheGetCacheStatisticsReq);
@@ -297,7 +297,7 @@ static int
 SProcFontCacheChangeCacheSettings(client)
     ClientPtr client;
 {
-    register int n;
+    int n;
     REQUEST(xFontCacheChangeCacheSettingsReq);
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xFontCacheChangeCacheSettingsReq);
@@ -311,7 +311,7 @@ SProcFontCacheChangeCacheSettings(client)
 
 static int
 SProcFontCacheDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/mbuf.c b/Xext/mbuf.c
index 7296560..348a18d 100644
--- a/Xext/mbuf.c
+++ b/Xext/mbuf.c
@@ -282,10 +282,10 @@ ExtensionEntry	*extEntry;
 
 static int
 ProcGetBufferVersion (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     xMbufGetBufferVersionReply	rep;
-    register int		n;
+    int		n;
 
     REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq);
     rep.type = X_Reply;
@@ -441,11 +441,11 @@ CreateImageBuffers (pWin, nbuf, ids, action, hint)
 
 static int
 ProcCreateImageBuffers (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xMbufCreateImageBuffersReq);
     xMbufCreateImageBuffersReply	rep;
-    register int		n;
+    int		n;
     WindowPtr			pWin;
     XID				*ids;
     int				len, nbuf, i, err, rc;
@@ -506,7 +506,7 @@ ProcCreateImageBuffers (client)
 
 static int
 ProcDisplayImageBuffers (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xMbufDisplayImageBuffersReq);
     MultibufferPtr	    *pMultibuffer;
@@ -579,7 +579,7 @@ MultibufferResType);
 
 static int
 ProcDestroyImageBuffers (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST (xMbufDestroyImageBuffersReq);
     WindowPtr	pWin;
@@ -595,7 +595,7 @@ ProcDestroyImageBuffers (client)
 
 static int
 ProcSetMBufferAttributes (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST (xMbufSetMBufferAttributesReq);
     WindowPtr	pWin;
@@ -694,7 +694,7 @@ ProcGetMBufferAttributes (client)
 
 static int
 ProcSetBufferAttributes (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xMbufSetBufferAttributesReq);
     MultibufferPtr	pMultibuffer;
@@ -736,7 +736,7 @@ ProcSetBufferAttributes (client)
 
 int
 ProcGetBufferAttributes (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xMbufGetBufferAttributesReq);
     MultibufferPtr	pMultibuffer;
@@ -780,7 +780,7 @@ ProcGetBufferAttributes (client)
 
 static int
 ProcGetBufferInfo (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST (xMbufGetBufferInfoReq);
     DrawablePtr		    pDrawable;
@@ -845,7 +845,7 @@ ProcGetBufferInfo (client)
 
 static int
 ProcClearImageBufferArea (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST (xMbufClearImageBufferAreaReq);
     MultibufferPtr	pMultibuffer;
@@ -907,7 +907,7 @@ ProcClearImageBufferArea (client)
 
 static int
 ProcMultibufferDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data) {
@@ -938,9 +938,9 @@ ProcMultibufferDispatch (client)
 
 static int
 SProcGetBufferVersion (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufGetBufferVersionReq);
 
     swaps (&stuff->length, n);
@@ -949,9 +949,9 @@ SProcGetBufferVersion (client)
 
 static int
 SProcCreateImageBuffers (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufCreateImageBuffersReq);
 
     swaps (&stuff->length, n);
@@ -963,9 +963,9 @@ SProcCreateImageBuffers (client)
 
 static int
 SProcDisplayImageBuffers (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufDisplayImageBuffersReq);
     
     swaps (&stuff->length, n);
@@ -978,9 +978,9 @@ SProcDisplayImageBuffers (client)
 
 static int
 SProcDestroyImageBuffers (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufDestroyImageBuffersReq);
     
     swaps (&stuff->length, n);
@@ -991,9 +991,9 @@ SProcDestroyImageBuffers (client)
 
 static int
 SProcSetMBufferAttributes (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufSetMBufferAttributesReq);
 
     swaps (&stuff->length, n);
@@ -1006,9 +1006,9 @@ SProcSetMBufferAttributes (client)
 
 static int
 SProcGetMBufferAttributes (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufGetMBufferAttributesReq);
 
     swaps (&stuff->length, n);
@@ -1019,9 +1019,9 @@ SProcGetMBufferAttributes (client)
 
 static int
 SProcSetBufferAttributes (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufSetBufferAttributesReq);
 
     swaps (&stuff->length, n);
@@ -1034,9 +1034,9 @@ SProcSetBufferAttributes (client)
 
 static int
 SProcGetBufferAttributes (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufGetBufferAttributesReq);
 
     swaps (&stuff->length, n);
@@ -1047,9 +1047,9 @@ SProcGetBufferAttributes (client)
 
 static int
 SProcGetBufferInfo (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xMbufGetBufferInfoReq);
 
     swaps (&stuff->length, n);
@@ -1060,9 +1060,9 @@ SProcGetBufferInfo (client)
 
 static int
 SProcClearImageBufferArea(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
-    register char n;
+    char n;
     REQUEST(xMbufClearImageBufferAreaReq);
 
     swaps(&stuff->length, n);
@@ -1077,7 +1077,7 @@ SProcClearImageBufferArea(client)
 
 static int
 SProcMultibufferDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data) {
@@ -1297,7 +1297,7 @@ QueueDisplayRequest (client, activateTime)
     /* swap the request back so we can simply re-execute it */
     if (client->swapped)
     {
-    	register int    n;
+    	int    n;
     	REQUEST (xMbufDisplayImageBuffersReq);
     	
     	SwapRestL(stuff);
@@ -1370,9 +1370,9 @@ MultibufferExpose (pMultibuffer, pRegion)
     {
 	xEvent *pEvent;
 	PixmapPtr   pPixmap;
-	register xEvent *pe;
-	register BoxPtr pBox;
-	register int i;
+	xEvent *pe;
+	BoxPtr pBox;
+	int i;
 	int numRects;
 
 	pPixmap = pMultibuffer->pPixmap;
@@ -1682,7 +1682,7 @@ OtherClientDelete (value, id)
     XID		id;
 {
     MultibufferPtr	pMultibuffer = (MultibufferPtr)value;
-    register OtherClientsPtr	other, prev;
+    OtherClientsPtr	other, prev;
 
     prev = 0;
     for (other = pMultibuffer->otherClients; other; other = other->next)
diff --git a/Xext/mbufbf.c b/Xext/mbufbf.c
index a3b3de7..afa6177 100644
--- a/Xext/mbufbf.c
+++ b/Xext/mbufbf.c
@@ -600,9 +600,9 @@ bufDrawSelectPlane(pScreen, selectPlane, prgn, bufferNum)
 {
     DrawablePtr pDrawable;
     GCPtr pGC;
-    register int i;
-    register BoxPtr pbox;
-    register xRectangle *prect;
+    int i;
+    BoxPtr pbox;
+    xRectangle *prect;
     int numRects;
     XID	value;
 
@@ -882,7 +882,7 @@ bufChangeWindowAttributes(pWin, mask)
 static void 
 bufWindowExposures(pWin, prgn, other_exposed)
     WindowPtr pWin;
-    register RegionPtr prgn, other_exposed;
+    RegionPtr prgn, other_exposed;
 {
     ScreenPtr pScreen = pWin->drawable.pScreen;
     mbufWindowPtr pMBWindow = MB_WINDOW_PRIV(pWin);
diff --git a/Xext/mitmisc.c b/Xext/mitmisc.c
index 924b880..365c7e6 100644
--- a/Xext/mitmisc.c
+++ b/Xext/mitmisc.c
@@ -83,7 +83,7 @@ ExtensionEntry	*extEntry;
 
 static int
 ProcMITSetBugMode(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xMITSetBugModeReq);
 
@@ -95,10 +95,10 @@ ProcMITSetBugMode(client)
 
 static int
 ProcMITGetBugMode(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     xMITGetBugModeReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xMITGetBugModeReq);
     rep.type = X_Reply;
@@ -115,7 +115,7 @@ ProcMITGetBugMode(client)
 
 static int
 ProcMITDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
@@ -131,9 +131,9 @@ ProcMITDispatch (client)
 
 static int
 SProcMITSetBugMode(client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int n;
+    int n;
     REQUEST(xMITSetBugModeReq);
 
     swaps(&stuff->length, n);
@@ -142,9 +142,9 @@ SProcMITSetBugMode(client)
 
 static int
 SProcMITGetBugMode(client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int n;
+    int n;
     REQUEST(xMITGetBugModeReq);
 
     swaps(&stuff->length, n);
@@ -153,7 +153,7 @@ SProcMITGetBugMode(client)
 
 static int
 SProcMITDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c
index 95df043..93c6fb4 100644
--- a/Xext/panoramiX.c
+++ b/Xext/panoramiX.c
@@ -916,7 +916,7 @@ ProcPanoramiXGetState(ClientPtr client)
 	REQUEST(xPanoramiXGetStateReq);
     	WindowPtr			pWin;
 	xPanoramiXGetStateReply		rep;
-	register int			n, rc;
+	int			n, rc;
 	
 	REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
 	rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
@@ -943,7 +943,7 @@ ProcPanoramiXGetScreenCount(ClientPtr client)
 	REQUEST(xPanoramiXGetScreenCountReq);
     	WindowPtr			pWin;
 	xPanoramiXGetScreenCountReply	rep;
-	register int			n, rc;
+	int			n, rc;
 
 	REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
 	rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
@@ -969,7 +969,7 @@ ProcPanoramiXGetScreenSize(ClientPtr client)
 	REQUEST(xPanoramiXGetScreenSizeReq);
     	WindowPtr			pWin;
 	xPanoramiXGetScreenSizeReply	rep;
-	register int			n, rc;
+	int			n, rc;
 	
 	REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
 	rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
@@ -1014,7 +1014,7 @@ ProcXineramaIsActive(ClientPtr client)
     rep.state = !noPanoramiXExtension;
 #endif
     if (client->swapped) {
-	register int n;
+	int n;
 	swaps (&rep.sequenceNumber, n);
 	swapl (&rep.length, n);
 	swapl (&rep.state, n);
@@ -1037,7 +1037,7 @@ ProcXineramaQueryScreens(ClientPtr client)
     rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens;
     rep.length = rep.number * sz_XineramaScreenInfo >> 2;
     if (client->swapped) {
-	register int n;
+	int n;
 	swaps (&rep.sequenceNumber, n);
 	swapl (&rep.length, n);
 	swapl (&rep.number, n);
@@ -1055,7 +1055,7 @@ ProcXineramaQueryScreens(ClientPtr client)
 	    scratch.height = panoramiXdataPtr[i].height;
 	
 	    if(client->swapped) {
-		register int n;
+		int n;
 		swaps (&scratch.x_org, n);
 		swaps (&scratch.y_org, n);
 		swaps (&scratch.width, n);
diff --git a/Xext/panoramiXSwap.c b/Xext/panoramiXSwap.c
index da445ff..dabab1f 100644
--- a/Xext/panoramiXSwap.c
+++ b/Xext/panoramiXSwap.c
@@ -55,7 +55,7 @@ static int
 SProcPanoramiXQueryVersion (ClientPtr client)
 {
 	REQUEST(xPanoramiXQueryVersionReq);
-	register int n;
+	int n;
 
 	swaps(&stuff->length,n);
 	REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
@@ -66,7 +66,7 @@ static int
 SProcPanoramiXGetState(ClientPtr client)
 {
 	REQUEST(xPanoramiXGetStateReq);
-	register int n;
+	int n;
 
  	swaps (&stuff->length, n);	
 	REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
@@ -77,7 +77,7 @@ static int
 SProcPanoramiXGetScreenCount(ClientPtr client)
 {
 	REQUEST(xPanoramiXGetScreenCountReq);
-	register int n;
+	int n;
 
 	swaps (&stuff->length, n);
 	REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
@@ -88,7 +88,7 @@ static int
 SProcPanoramiXGetScreenSize(ClientPtr client)
 {
 	REQUEST(xPanoramiXGetScreenSizeReq);
-	register int n;
+	int n;
 
 	swaps (&stuff->length, n);
 	REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
@@ -100,7 +100,7 @@ static int
 SProcXineramaIsActive(ClientPtr client)
 {
 	REQUEST(xXineramaIsActiveReq);
-	register int n;
+	int n;
 
 	swaps (&stuff->length, n);
 	REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
@@ -112,7 +112,7 @@ static int
 SProcXineramaQueryScreens(ClientPtr client)
 {
 	REQUEST(xXineramaQueryScreensReq);
-	register int n;
+	int n;
 
 	swaps (&stuff->length, n);
 	REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
diff --git a/Xext/sampleEVI.c b/Xext/sampleEVI.c
index 7508aa7..5dd6e45 100644
--- a/Xext/sampleEVI.c
+++ b/Xext/sampleEVI.c
@@ -46,7 +46,7 @@ static int sampleGetVisualInfo(
     VisualID32 *temp_conflict;
     xExtendedVisualInfo *evi;
     int max_visuals = 0, max_sz_conflict, sz_conflict = 0;
-    register int visualI, scrI, sz_evi = 0, conflictI, n_conflict;
+    int visualI, scrI, sz_evi = 0, conflictI, n_conflict;
     *evi_rn = evi = (xExtendedVisualInfo *)xalloc(max_sz_evi);
     if (!*evi_rn)
          return BadAlloc;
diff --git a/Xext/saver.c b/Xext/saver.c
index a590583..99b87aa 100644
--- a/Xext/saver.c
+++ b/Xext/saver.c
@@ -755,10 +755,10 @@ ScreenSaverHandle (pScreen, xstate, force)
 
 static int
 ProcScreenSaverQueryVersion (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     xScreenSaverQueryVersionReply	rep;
-    register int		n;
+    int		n;
 
     REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq);
     rep.type = X_Reply;
@@ -776,11 +776,11 @@ ProcScreenSaverQueryVersion (client)
 
 static int
 ProcScreenSaverQueryInfo (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xScreenSaverQueryInfoReq);
     xScreenSaverQueryInfoReply	rep;
-    register int		n, rc;
+    int		n, rc;
     ScreenSaverStuffPtr		pSaver;
     DrawablePtr			pDraw;
     CARD32			lastInput;
@@ -849,7 +849,7 @@ ProcScreenSaverQueryInfo (client)
 
 static int
 ProcScreenSaverSelectInput (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xScreenSaverSelectInputReq);
     DrawablePtr			pDraw;
diff --git a/Xext/security.c b/Xext/security.c
index a8b4690..231ea51 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -336,7 +336,7 @@ ProcSecurityQueryVersion(
     rep.minorVersion  	= SECURITY_MINOR_VERSION;
     if(client->swapped)
     {
-	register char n;
+	char n;
     	swaps(&rep.sequenceNumber, n);
 	swaps(&rep.majorVersion, n);
 	swaps(&rep.minorVersion, n);
@@ -554,7 +554,7 @@ ProcSecurityGenerateAuthorization(
 
     if (client->swapped)
     {
-	register char n;
+	char n;
     	swapl(&rep.length, n);
     	swaps(&rep.sequenceNumber, n);
     	swapl(&rep.authId, n);
@@ -633,7 +633,7 @@ SProcSecurityQueryVersion(
     ClientPtr client)
 {
     REQUEST(xSecurityQueryVersionReq);
-    register char 	n;
+    char 	n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
@@ -648,7 +648,7 @@ SProcSecurityGenerateAuthorization(
     ClientPtr client)
 {
     REQUEST(xSecurityGenerateAuthorizationReq);
-    register char 	n;
+    char 	n;
     CARD32 *values;
     unsigned long nvalues;
 
@@ -671,7 +671,7 @@ SProcSecurityRevokeAuthorization(
     ClientPtr client)
 {
     REQUEST(xSecurityRevokeAuthorizationReq);
-    register char 	n;
+    char 	n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
diff --git a/Xext/shape.c b/Xext/shape.c
index 6515a10..2425eeb 100644
--- a/Xext/shape.c
+++ b/Xext/shape.c
@@ -282,10 +282,10 @@ CreateClipShape (pWin)
 
 static int
 ProcShapeQueryVersion (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     xShapeQueryVersionReply	rep;
-    register int		n;
+    int		n;
 
     REQUEST_SIZE_MATCH (xShapeQueryVersionReq);
     rep.type = X_Reply;
@@ -310,7 +310,7 @@ ProcShapeQueryVersion (client)
 
 static int
 ProcShapeRectangles (client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     WindowPtr		pWin;
     ScreenPtr		pScreen;
@@ -381,7 +381,7 @@ ProcShapeRectangles (client)
 #ifdef PANORAMIX
 static int
 ProcPanoramiXShapeRectangles(
-    register ClientPtr client)
+    ClientPtr client)
 {
     REQUEST(xShapeRectanglesReq);
     PanoramiXRes	*win;
@@ -410,7 +410,7 @@ ProcPanoramiXShapeRectangles(
 
 static int
 ProcShapeMask (client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     WindowPtr		pWin;
     ScreenPtr		pScreen;
@@ -480,7 +480,7 @@ ProcShapeMask (client)
 #ifdef PANORAMIX
 static int
 ProcPanoramiXShapeMask(
-    register ClientPtr client)
+    ClientPtr client)
 {
     REQUEST(xShapeMaskReq);
     PanoramiXRes	*win, *pmap;
@@ -517,7 +517,7 @@ ProcPanoramiXShapeMask(
 
 static int
 ProcShapeCombine (client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     WindowPtr		pSrcWin, pDestWin;
     ScreenPtr		pScreen;
@@ -609,7 +609,7 @@ ProcShapeCombine (client)
 #ifdef PANORAMIX
 static int
 ProcPanoramiXShapeCombine(
-    register ClientPtr client)
+    ClientPtr client)
 {
     REQUEST(xShapeCombineReq);
     PanoramiXRes	*win, *win2;
@@ -641,7 +641,7 @@ ProcPanoramiXShapeCombine(
 
 static int
 ProcShapeOffset (client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     WindowPtr		pWin;
     ScreenPtr		pScreen;
@@ -682,7 +682,7 @@ ProcShapeOffset (client)
 #ifdef PANORAMIX
 static int
 ProcPanoramiXShapeOffset(
-    register ClientPtr client)
+    ClientPtr client)
 {
     REQUEST(xShapeOffsetReq);
     PanoramiXRes *win;
@@ -706,13 +706,13 @@ ProcPanoramiXShapeOffset(
 
 static int
 ProcShapeQueryExtents (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xShapeQueryExtentsReq);
     WindowPtr		pWin;
     xShapeQueryExtentsReply	rep;
     BoxRec		extents, *pExtents;
-    register int	n, rc;
+    int	n, rc;
     RegionPtr		region;
 
     REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
@@ -817,7 +817,7 @@ ShapeFreeEvents (data, id)
 
 static int
 ProcShapeSelectInput (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xShapeSelectInputReq);
     WindowPtr		pWin;
@@ -989,14 +989,14 @@ SendShapeNotify (pWin, which)
 
 static int
 ProcShapeInputSelected (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xShapeInputSelectedReq);
     WindowPtr		pWin;
     ShapeEventPtr	pShapeEvent, *pHead;
     int			enabled, rc;
     xShapeInputSelectedReply	rep;
-    register int		n;
+    int		n;
 
     REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
     rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
@@ -1030,7 +1030,7 @@ ProcShapeInputSelected (client)
 
 static int
 ProcShapeGetRectangles (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xShapeGetRectanglesReq);
     WindowPtr			pWin;
@@ -1038,7 +1038,7 @@ ProcShapeGetRectangles (client)
     xRectangle			*rects;
     int				nrects, i, rc;
     RegionPtr			region;
-    register int		n;
+    int		n;
 
     REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
     rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
@@ -1116,7 +1116,7 @@ ProcShapeGetRectangles (client)
 
 static int
 ProcShapeDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data) {
@@ -1181,9 +1181,9 @@ SShapeNotifyEvent(from, to)
 
 static int
 SProcShapeQueryVersion (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xShapeQueryVersionReq);
 
     swaps (&stuff->length, n);
@@ -1192,9 +1192,9 @@ SProcShapeQueryVersion (client)
 
 static int
 SProcShapeRectangles (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register char   n;
+    char   n;
     REQUEST (xShapeRectanglesReq);
 
     swaps (&stuff->length, n);
@@ -1208,9 +1208,9 @@ SProcShapeRectangles (client)
 
 static int
 SProcShapeMask (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register char   n;
+    char   n;
     REQUEST (xShapeMaskReq);
 
     swaps (&stuff->length, n);
@@ -1224,9 +1224,9 @@ SProcShapeMask (client)
 
 static int
 SProcShapeCombine (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register char   n;
+    char   n;
     REQUEST (xShapeCombineReq);
 
     swaps (&stuff->length, n);
@@ -1240,9 +1240,9 @@ SProcShapeCombine (client)
 
 static int
 SProcShapeOffset (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register char   n;
+    char   n;
     REQUEST (xShapeOffsetReq);
 
     swaps (&stuff->length, n);
@@ -1255,9 +1255,9 @@ SProcShapeOffset (client)
 
 static int
 SProcShapeQueryExtents (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register char   n;
+    char   n;
     REQUEST (xShapeQueryExtentsReq);
 
     swaps (&stuff->length, n);
@@ -1268,9 +1268,9 @@ SProcShapeQueryExtents (client)
 
 static int
 SProcShapeSelectInput (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register char   n;
+    char   n;
     REQUEST (xShapeSelectInputReq);
 
     swaps (&stuff->length, n);
@@ -1281,9 +1281,9 @@ SProcShapeSelectInput (client)
 
 static int
 SProcShapeInputSelected (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int    n;
+    int    n;
     REQUEST (xShapeInputSelectedReq);
 
     swaps (&stuff->length, n);
@@ -1294,10 +1294,10 @@ SProcShapeInputSelected (client)
 
 static int
 SProcShapeGetRectangles (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xShapeGetRectanglesReq);
-    register char   n;
+    char   n;
 
     swaps (&stuff->length, n);
     REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
@@ -1307,7 +1307,7 @@ SProcShapeGetRectangles (client)
 
 static int
 SProcShapeDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data) {
diff --git a/Xext/shm.c b/Xext/shm.c
index 5937a03..97a48cd 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -343,10 +343,10 @@ ShmRegisterFbFuncs(pScreen)
 
 static int
 ProcShmQueryVersion(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     xShmQueryVersionReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xShmQueryVersionReq);
     rep.type = X_Reply;
@@ -438,7 +438,7 @@ shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly)
 
 static int
 ProcShmAttach(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     SHMSTAT_TYPE buf;
     ShmDescPtr shmdesc;
@@ -518,7 +518,7 @@ ShmDetachSegment(value, shmseg)
 
 static int
 ProcShmDetach(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     ShmDescPtr shmdesc;
     REQUEST(xShmDetachReq);
@@ -595,7 +595,7 @@ fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data)
 
 #ifdef PANORAMIX
 static int 
-ProcPanoramiXShmPutImage(register ClientPtr client)
+ProcPanoramiXShmPutImage(ClientPtr client)
 {
     int			 j, result = 0, orig_x, orig_y;
     PanoramiXRes	*draw, *gc;
@@ -742,7 +742,7 @@ ProcPanoramiXShmGetImage(ClientPtr client)
     }
     
     if (client->swapped) {
-	register int n;
+	int n;
     	swaps(&xgi.sequenceNumber, n);
     	swapl(&xgi.length, n);
 	swapl(&xgi.visual, n);
@@ -755,7 +755,7 @@ ProcPanoramiXShmGetImage(ClientPtr client)
 
 static int
 ProcPanoramiXShmCreatePixmap(
-    register ClientPtr client)
+    ClientPtr client)
 {
     ScreenPtr pScreen = NULL;
     PixmapPtr pMap = NULL;
@@ -846,7 +846,7 @@ CreatePmap:
 
 static int
 ProcShmPutImage(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     GCPtr pGC;
     DrawablePtr pDraw;
@@ -950,7 +950,7 @@ ProcShmPutImage(client)
 
 static int
 ProcShmGetImage(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     DrawablePtr		pDraw;
     long		lenPer = 0, length;
@@ -1069,7 +1069,7 @@ fbShmCreatePixmap (pScreen, width, height, depth, addr)
     int		depth;
     char	*addr;
 {
-    register PixmapPtr pPixmap;
+    PixmapPtr pPixmap;
 
     pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0);
     if (!pPixmap)
@@ -1085,12 +1085,12 @@ fbShmCreatePixmap (pScreen, width, height, depth, addr)
 
 static int
 ProcShmCreatePixmap(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     PixmapPtr pMap;
     DrawablePtr pDraw;
     DepthPtr pDepth;
-    register int i, rc;
+    int i, rc;
     ShmDescPtr shmdesc;
     REQUEST(xShmCreatePixmapReq);
 
@@ -1143,7 +1143,7 @@ CreatePmap:
 
 static int
 ProcShmDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
@@ -1192,9 +1192,9 @@ SShmCompletionEvent(from, to)
 
 static int
 SProcShmQueryVersion(client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int n;
+    int n;
     REQUEST(xShmQueryVersionReq);
 
     swaps(&stuff->length, n);
@@ -1205,7 +1205,7 @@ static int
 SProcShmAttach(client)
     ClientPtr client;
 {
-    register int n;
+    int n;
     REQUEST(xShmAttachReq);
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xShmAttachReq);
@@ -1218,7 +1218,7 @@ static int
 SProcShmDetach(client)
     ClientPtr client;
 {
-    register int n;
+    int n;
     REQUEST(xShmDetachReq);
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xShmDetachReq);
@@ -1230,7 +1230,7 @@ static int
 SProcShmPutImage(client)
     ClientPtr client;
 {
-    register int n;
+    int n;
     REQUEST(xShmPutImageReq);
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xShmPutImageReq);
@@ -1253,7 +1253,7 @@ static int
 SProcShmGetImage(client)
     ClientPtr client;
 {
-    register int n;
+    int n;
     REQUEST(xShmGetImageReq);
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xShmGetImageReq);
@@ -1272,7 +1272,7 @@ static int
 SProcShmCreatePixmap(client)
     ClientPtr client;
 {
-    register int n;
+    int n;
     REQUEST(xShmCreatePixmapReq);
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
@@ -1287,7 +1287,7 @@ SProcShmCreatePixmap(client)
 
 static int
 SProcShmDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/sync.c b/Xext/sync.c
index e87e0bd..cea8f0a 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -1405,7 +1405,7 @@ ProcSyncListSystemCounters(client)
 
     if (client->swapped)
     {
-	register char n;
+	char n;
 	swaps(&rep.sequenceNumber, n);
 	swapl(&rep.length, n);
 	swapl(&rep.nCounters, n);
@@ -1425,7 +1425,7 @@ ProcSyncListSystemCounters(client)
 
 	if (client->swapped)
 	{
-	    register char n;
+	    char n;
 	    swapl(&walklist->counter, n);
 	    swapl(&walklist->resolution_hi, n);
 	    swapl(&walklist->resolution_lo, n);
@@ -1514,7 +1514,7 @@ ProcSyncGetPriority(client)
 
     if (client->swapped)
     {
-	register char n;
+	char n;
 	swaps(&rep.sequenceNumber, n);
 	swapl(&rep.priority, n);
     }
@@ -1799,7 +1799,7 @@ ProcSyncQueryCounter(client)
     rep.value_lo = XSyncValueLow32(pCounter->value);
     if (client->swapped)
     {
-	register char n;
+	char n;
 	swaps(&rep.sequenceNumber, n);
 	swapl(&rep.length, n);
 	swapl(&rep.value_hi, n);
@@ -1981,7 +1981,7 @@ ProcSyncQueryAlarm(client)
 
     if (client->swapped)
     {
-	register char n;
+	char n;
 	swaps(&rep.sequenceNumber, n);
 	swapl(&rep.length, n);
 	swapl(&rep.counter, n);
@@ -2070,7 +2070,7 @@ SProcSyncInitialize(client)
     ClientPtr       client;
 {
     REQUEST(xSyncInitializeReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncInitializeReq);
@@ -2083,7 +2083,7 @@ SProcSyncListSystemCounters(client)
     ClientPtr       client;
 {
     REQUEST(xSyncListSystemCountersReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
@@ -2096,7 +2096,7 @@ SProcSyncCreateCounter(client)
     ClientPtr       client;
 {
     REQUEST(xSyncCreateCounterReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
@@ -2112,7 +2112,7 @@ SProcSyncSetCounter(client)
     ClientPtr       client;
 {
     REQUEST(xSyncSetCounterReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncSetCounterReq);
@@ -2128,7 +2128,7 @@ SProcSyncChangeCounter(client)
     ClientPtr       client;
 {
     REQUEST(xSyncChangeCounterReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
@@ -2144,7 +2144,7 @@ SProcSyncQueryCounter(client)
     ClientPtr       client;
 {
     REQUEST(xSyncQueryCounterReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
@@ -2158,7 +2158,7 @@ SProcSyncDestroyCounter(client)
     ClientPtr       client;
 {
     REQUEST(xSyncDestroyCounterReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
@@ -2172,7 +2172,7 @@ SProcSyncAwait(client)
     ClientPtr       client;
 {
     REQUEST(xSyncAwaitReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
@@ -2187,7 +2187,7 @@ SProcSyncCreateAlarm(client)
     ClientPtr       client;
 {
     REQUEST(xSyncCreateAlarmReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
@@ -2203,7 +2203,7 @@ SProcSyncChangeAlarm(client)
     ClientPtr       client;
 {
     REQUEST(xSyncChangeAlarmReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
@@ -2218,7 +2218,7 @@ SProcSyncQueryAlarm(client)
     ClientPtr       client;
 {
     REQUEST(xSyncQueryAlarmReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
@@ -2232,7 +2232,7 @@ SProcSyncDestroyAlarm(client)
     ClientPtr       client;
 {
     REQUEST(xSyncDestroyAlarmReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
@@ -2246,7 +2246,7 @@ SProcSyncSetPriority(client)
     ClientPtr       client;
 {
     REQUEST(xSyncSetPriorityReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
@@ -2261,7 +2261,7 @@ SProcSyncGetPriority(client)
     ClientPtr       client;
 {
     REQUEST(xSyncGetPriorityReq);
-    register char   n;
+    char   n;
 
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
diff --git a/Xext/xcmisc.c b/Xext/xcmisc.c
index 8c7a86e..45450ef 100644
--- a/Xext/xcmisc.c
+++ b/Xext/xcmisc.c
@@ -93,10 +93,10 @@ XCMiscResetProc (extEntry)
 
 static int
 ProcXCMiscGetVersion(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     xXCMiscGetVersionReply rep;
-    register int n;
+    int n;
 
     REQUEST_SIZE_MATCH(xXCMiscGetVersionReq);
     rep.type = X_Reply;
@@ -115,10 +115,10 @@ ProcXCMiscGetVersion(client)
 
 static int
 ProcXCMiscGetXIDRange(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     xXCMiscGetXIDRangeReply rep;
-    register int n;
+    int n;
     XID min_id, max_id;
 
     REQUEST_SIZE_MATCH(xXCMiscGetXIDRangeReq);
@@ -139,11 +139,11 @@ ProcXCMiscGetXIDRange(client)
 
 static int
 ProcXCMiscGetXIDList(client)
-    register ClientPtr client;
+    ClientPtr client;
 {
     REQUEST(xXCMiscGetXIDListReq);
     xXCMiscGetXIDListReply rep;
-    register int n;
+    int n;
     XID *pids;
     unsigned int count;
 
@@ -179,7 +179,7 @@ ProcXCMiscGetXIDList(client)
 
 static int
 ProcXCMiscDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
@@ -197,9 +197,9 @@ ProcXCMiscDispatch (client)
 
 static int
 SProcXCMiscGetVersion(client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int n;
+    int n;
     REQUEST(xXCMiscGetVersionReq);
 
     swaps(&stuff->length, n);
@@ -211,9 +211,9 @@ SProcXCMiscGetVersion(client)
 
 static int
 SProcXCMiscGetXIDRange(client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int n;
+    int n;
     REQUEST(xReq);
 
     swaps(&stuff->length, n);
@@ -222,9 +222,9 @@ SProcXCMiscGetXIDRange(client)
 
 static int
 SProcXCMiscGetXIDList(client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
-    register int n;
+    int n;
     REQUEST(xXCMiscGetXIDListReq);
 
     swaps(&stuff->length, n);
@@ -234,7 +234,7 @@ SProcXCMiscGetXIDList(client)
 
 static int
 SProcXCMiscDispatch (client)
-    register ClientPtr	client;
+    ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/xevie.c b/Xext/xevie.c
index 0feb4d7..5016255 100644
--- a/Xext/xevie.c
+++ b/Xext/xevie.c
@@ -63,7 +63,7 @@ extern Bool noXkbExtension;
 #endif
 extern int    xeviegrabState;
 
-static int		ProcDispatch (register ClientPtr client), SProcDispatch (register ClientPtr client);
+static int		ProcDispatch (ClientPtr client), SProcDispatch (ClientPtr client);
 static void		ResetProc (ExtensionEntry *extEntry);
 
 static unsigned char	ReqCode = 0;
@@ -164,7 +164,7 @@ void ResetProc (ExtensionEntry *extEntry)
 }
 
 static 
-int ProcQueryVersion (register ClientPtr client)
+int ProcQueryVersion (ClientPtr client)
 {
     xXevieQueryVersionReply rep;
 
@@ -179,7 +179,7 @@ int ProcQueryVersion (register ClientPtr client)
 }
 
 static
-int ProcStart (register ClientPtr client)
+int ProcStart (ClientPtr client)
 {
     xXevieStartReply rep;
 
@@ -220,7 +220,7 @@ int ProcStart (register ClientPtr client)
 }
 
 static
-int ProcEnd (register ClientPtr client)
+int ProcEnd (ClientPtr client)
 {
     xXevieEndReply rep;
 
@@ -239,7 +239,7 @@ int ProcEnd (register ClientPtr client)
 }
 
 static
-int ProcSend (register ClientPtr client)
+int ProcSend (ClientPtr client)
 {
     REQUEST (xXevieSendReq);
     xXevieSendReply rep;
@@ -285,7 +285,7 @@ int ProcSend (register ClientPtr client)
 }
 
 static
-int ProcSelectInput (register ClientPtr client)
+int ProcSelectInput (ClientPtr client)
 {
     REQUEST (xXevieSelectInputReq);
     xXevieSelectInputReply rep;
@@ -301,7 +301,7 @@ int ProcSelectInput (register ClientPtr client)
 }
 
 static 
-int ProcDispatch (register ClientPtr client)
+int ProcDispatch (ClientPtr client)
 {
     REQUEST (xReq);
     switch (stuff->data)
@@ -322,9 +322,9 @@ int ProcDispatch (register ClientPtr client)
 }
 
 static 
-int SProcQueryVersion (register ClientPtr client)
+int SProcQueryVersion (ClientPtr client)
 {
-    register int n;
+    int n;
 
     REQUEST(xXevieQueryVersionReq);
     swaps(&stuff->length, n);
@@ -334,7 +334,7 @@ int SProcQueryVersion (register ClientPtr client)
 static 
 int SProcStart (ClientPtr client)
 {
-    register int n;
+    int n;
 
     REQUEST (xXevieStartReq);
     swaps (&stuff->length, n);
@@ -346,7 +346,7 @@ int SProcStart (ClientPtr client)
 static 
 int SProcEnd (ClientPtr client)
 {
-    register int n;
+    int n;
 
     REQUEST (xXevieEndReq);
     swaps (&stuff->length, n);
@@ -358,7 +358,7 @@ int SProcEnd (ClientPtr client)
 static
 int SProcSend (ClientPtr client)
 {
-    register int n;
+    int n;
 
     REQUEST (xXevieSendReq);
     swaps (&stuff->length, n);
@@ -370,7 +370,7 @@ int SProcSend (ClientPtr client)
 static
 int SProcSelectInput (ClientPtr client)
 {
-    register int n;
+    int n;
 
     REQUEST (xXevieSelectInputReq);
     swaps (&stuff->length, n);
@@ -381,7 +381,7 @@ int SProcSelectInput (ClientPtr client)
 
 
 static 
-int SProcDispatch (register ClientPtr client)
+int SProcDispatch (ClientPtr client)
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/xprint.c b/Xext/xprint.c
index 4ac13e6..df189a1 100644
--- a/Xext/xprint.c
+++ b/Xext/xprint.c
@@ -570,7 +570,7 @@ ProcXpQueryVersion(ClientPtr client)
 {
     /* REQUEST(xPrintQueryVersionReq); */
     xPrintQueryVersionReply rep;
-    register int n;
+    int n;
     long l;
 
     REQUEST_SIZE_MATCH(xPrintQueryVersionReq);
@@ -1101,8 +1101,8 @@ ProcXpGetContext(ClientPtr client)
     xPrintGetContextReply rep;
 
     XpContextPtr pContext;
-    register int n;
-    register long l;
+    int n;
+    long l;
 
     REQUEST_SIZE_MATCH(xPrintGetContextReq);
 
@@ -1383,11 +1383,11 @@ XpFreePage(pointer data, XID id)
 static void
 InitContextPrivates(XpContextPtr context)
 {
-    register char *ptr;
+    char *ptr;
     DevUnion *ppriv;
-    register unsigned *sizes;
-    register unsigned size;
-    register int i;
+    unsigned *sizes;
+    unsigned size;
+    int i;
 
     if (totalContextSize == sizeof(XpContextRec))
         ppriv = (DevUnion *)NULL;
@@ -2330,7 +2330,7 @@ ProcXpInputSelected(ClientPtr client)
 {
     REQUEST(xPrintInputSelectedReq);
     xPrintInputSelectedReply rep;
-    register int n;
+    int n;
     long l;
     XpClientPtr pXpClient;
     XpContextPtr pContext;
diff --git a/Xext/xres.c b/Xext/xres.c
index 32cc903..9bbf0a4 100644
--- a/Xext/xres.c
+++ b/Xext/xres.c
@@ -93,7 +93,7 @@ ProcXResQueryClients (ClientPtr client)
             scratch.resource_mask = RESOURCE_ID_MASK;
         
             if(client->swapped) {
-                register int n;
+                int n;
                 swapl (&scratch.resource_base, n);
                 swapl (&scratch.resource_mask, n);
             }
@@ -175,7 +175,7 @@ ProcXResQueryClientResources (ClientPtr client)
             scratch.count = counts[i];
 
             if(client->swapped) {
-                register int n;
+                int n;
                 swapl (&scratch.resource_type, n);
                 swapl (&scratch.count, n);
             }
diff --git a/Xext/xtest.c b/Xext/xtest.c
index 963029c..711b57c 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -112,10 +112,10 @@ ExtensionEntry	*extEntry;
 
 static int
 ProcXTestGetVersion(client)
-    register ClientPtr client;
+     ClientPtr client;
 {
     xXTestGetVersionReply rep;
-    register int n;
+     int n;
 
     REQUEST_SIZE_MATCH(xXTestGetVersionReq);
     rep.type = X_Reply;
@@ -133,13 +133,13 @@ ProcXTestGetVersion(client)
 
 static int
 ProcXTestCompareCursor(client)
-    register ClientPtr client;
+     ClientPtr client;
 {
     REQUEST(xXTestCompareCursorReq);
     xXTestCompareCursorReply rep;
     WindowPtr pWin;
     CursorPtr pCursor;
-    register int n, rc;
+     int n, rc;
 
     REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
     rc = dixLookupWindow(&pWin, stuff->window, client, DixUnknownAccess);
@@ -170,7 +170,7 @@ ProcXTestCompareCursor(client)
 
 static int
 ProcXTestFakeInput(client)
-    register ClientPtr client;
+     ClientPtr client;
 {
     REQUEST(xXTestFakeInputReq);
     int nev, n, type, rc;
@@ -468,7 +468,7 @@ ProcXTestFakeInput(client)
 
 static int
 ProcXTestGrabControl(client)
-    register ClientPtr client;
+     ClientPtr client;
 {
     REQUEST(xXTestGrabControlReq);
 
@@ -487,7 +487,7 @@ ProcXTestGrabControl(client)
 
 static int
 ProcXTestDispatch (client)
-    register ClientPtr	client;
+     ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
@@ -507,9 +507,9 @@ ProcXTestDispatch (client)
 
 static int
 SProcXTestGetVersion(client)
-    register ClientPtr	client;
+     ClientPtr	client;
 {
-    register int n;
+     int n;
     REQUEST(xXTestGetVersionReq);
 
     swaps(&stuff->length, n);
@@ -520,9 +520,9 @@ SProcXTestGetVersion(client)
 
 static int
 SProcXTestCompareCursor(client)
-    register ClientPtr	client;
+     ClientPtr	client;
 {
-    register int n;
+     int n;
     REQUEST(xXTestCompareCursorReq);
 
     swaps(&stuff->length, n);
@@ -534,11 +534,11 @@ SProcXTestCompareCursor(client)
 
 static int
 XTestSwapFakeInput(client, req)
-    register ClientPtr	client;
+     ClientPtr	client;
     xReq *req;
 {
-    register int nev;
-    register xEvent *ev;
+     int nev;
+     xEvent *ev;
     xEvent sev;
     EventSwapPtr proc;
 
@@ -560,9 +560,9 @@ XTestSwapFakeInput(client, req)
 
 static int
 SProcXTestFakeInput(client)
-    register ClientPtr	client;
+     ClientPtr	client;
 {
-    register int n;
+     int n;
     REQUEST(xReq);
 
     swaps(&stuff->length, n);
@@ -574,9 +574,9 @@ SProcXTestFakeInput(client)
 
 static int
 SProcXTestGrabControl(client)
-    register ClientPtr	client;
+     ClientPtr	client;
 {
-    register int n;
+     int n;
     REQUEST(xXTestGrabControlReq);
 
     swaps(&stuff->length, n);
@@ -586,7 +586,7 @@ SProcXTestGrabControl(client)
 
 static int
 SProcXTestDispatch (client)
-    register ClientPtr	client;
+     ClientPtr	client;
 {
     REQUEST(xReq);
     switch (stuff->data)
diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c
index 21d00aa..5465e25 100644
--- a/Xext/xvdisp.c
+++ b/Xext/xvdisp.c
@@ -1334,7 +1334,7 @@ ProcXvListImageFormats(ClientPtr client)
 static int
 SProcXvQueryExtension(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvQueryExtensionReq);
   swaps(&stuff->length, n);
   return ProcXvQueryExtension(client);
@@ -1343,7 +1343,7 @@ SProcXvQueryExtension(ClientPtr client)
 static int
 SProcXvQueryAdaptors(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvQueryAdaptorsReq);
   swaps(&stuff->length, n);
   swapl(&stuff->window, n);
@@ -1353,7 +1353,7 @@ SProcXvQueryAdaptors(ClientPtr client)
 static int
 SProcXvQueryEncodings(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvQueryEncodingsReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1363,7 +1363,7 @@ SProcXvQueryEncodings(ClientPtr client)
 static int
 SProcXvGrabPort(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvGrabPortReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1374,7 +1374,7 @@ SProcXvGrabPort(ClientPtr client)
 static int
 SProcXvUngrabPort(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvUngrabPortReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1385,7 +1385,7 @@ SProcXvUngrabPort(ClientPtr client)
 static int
 SProcXvPutVideo(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvPutVideoReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1405,7 +1405,7 @@ SProcXvPutVideo(ClientPtr client)
 static int
 SProcXvPutStill(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvPutStillReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1425,7 +1425,7 @@ SProcXvPutStill(ClientPtr client)
 static int
 SProcXvGetVideo(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvGetVideoReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1445,7 +1445,7 @@ SProcXvGetVideo(ClientPtr client)
 static int
 SProcXvGetStill(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvGetStillReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1465,7 +1465,7 @@ SProcXvGetStill(ClientPtr client)
 static int
 SProcXvPutImage(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvPutImageReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1489,7 +1489,7 @@ SProcXvPutImage(ClientPtr client)
 static int
 SProcXvShmPutImage(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvShmPutImageReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1516,7 +1516,7 @@ SProcXvShmPutImage(ClientPtr client)
 static int
 SProcXvSelectVideoNotify(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvSelectVideoNotifyReq);
   swaps(&stuff->length, n);
   swapl(&stuff->drawable, n);
@@ -1526,7 +1526,7 @@ SProcXvSelectVideoNotify(ClientPtr client)
 static int
 SProcXvSelectPortNotify(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvSelectPortNotifyReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1536,7 +1536,7 @@ SProcXvSelectPortNotify(ClientPtr client)
 static int
 SProcXvStopVideo(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvStopVideoReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1547,7 +1547,7 @@ SProcXvStopVideo(ClientPtr client)
 static int
 SProcXvSetPortAttribute(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvSetPortAttributeReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1558,7 +1558,7 @@ SProcXvSetPortAttribute(ClientPtr client)
 static int
 SProcXvGetPortAttribute(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvGetPortAttributeReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1569,7 +1569,7 @@ SProcXvGetPortAttribute(ClientPtr client)
 static int
 SProcXvQueryBestSize(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvQueryBestSizeReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1583,7 +1583,7 @@ SProcXvQueryBestSize(ClientPtr client)
 static int
 SProcXvQueryPortAttributes(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvQueryPortAttributesReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1593,7 +1593,7 @@ SProcXvQueryPortAttributes(ClientPtr client)
 static int
 SProcXvQueryImageAttributes(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvQueryImageAttributesReq);
   swaps(&stuff->length, n);
   swapl(&stuff->id, n);
@@ -1605,7 +1605,7 @@ SProcXvQueryImageAttributes(ClientPtr client)
 static int
 SProcXvListImageFormats(ClientPtr client)
 {
-  register char n;
+  char n;
   REQUEST(xvListImageFormatsReq);
   swaps(&stuff->length, n);
   swapl(&stuff->port, n);
@@ -1618,7 +1618,7 @@ SWriteQueryExtensionReply(
    ClientPtr client,
    xvQueryExtensionReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
@@ -1635,7 +1635,7 @@ SWriteQueryAdaptorsReply(
    ClientPtr client,
    xvQueryAdaptorsReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
@@ -1651,7 +1651,7 @@ SWriteQueryEncodingsReply(
    ClientPtr client,
    xvQueryEncodingsReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
@@ -1667,7 +1667,7 @@ SWriteAdaptorInfo(
    ClientPtr client,
    xvAdaptorInfo *pAdaptor
 ){
-  register char n;
+  char n;
 
   swapl(&pAdaptor->base_id, n);
   swaps(&pAdaptor->name_size, n);
@@ -1684,7 +1684,7 @@ SWriteEncodingInfo(
    ClientPtr client,
    xvEncodingInfo *pEncoding
 ){
-  register char n;
+  char n;
   
   swapl(&pEncoding->encoding, n);
   swaps(&pEncoding->name_size, n);
@@ -1702,7 +1702,7 @@ SWriteFormat(
    ClientPtr client,
    xvFormat *pFormat
 ){
-  register char n;
+  char n;
 
   swapl(&pFormat->visual, n);
   (void)WriteToClient(client, sz_xvFormat, (char *)pFormat);
@@ -1715,7 +1715,7 @@ SWriteAttributeInfo(
    ClientPtr client,
    xvAttributeInfo *pAtt
 ){
-  register char n;
+  char n;
 
   swapl(&pAtt->flags, n);
   swapl(&pAtt->size, n);
@@ -1731,7 +1731,7 @@ SWriteImageFormatInfo(
    ClientPtr client,
    xvImageFormatInfo *pImage
 ){
-  register char n;
+  char n;
 
   swapl(&pImage->id, n);
   swapl(&pImage->red_mask, n);
@@ -1759,7 +1759,7 @@ SWriteGrabPortReply(
    ClientPtr client,
    xvGrabPortReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
@@ -1774,7 +1774,7 @@ SWriteGetPortAttributeReply(
    ClientPtr client,
    xvGetPortAttributeReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
@@ -1790,7 +1790,7 @@ SWriteQueryBestSizeReply(
    ClientPtr client,
    xvQueryBestSizeReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
@@ -1807,7 +1807,7 @@ SWriteQueryPortAttributesReply(
    ClientPtr client,
    xvQueryPortAttributesReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
@@ -1824,7 +1824,7 @@ SWriteQueryImageAttributesReply(
    ClientPtr client,
    xvQueryImageAttributesReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
@@ -1844,7 +1844,7 @@ SWriteListImageFormatsReply(
    ClientPtr client,
    xvListImageFormatsReply *rep
 ){
-  register char n;
+  char n;
 
   swaps(&rep->sequenceNumber, n);
   swapl(&rep->length, n);
diff --git a/Xext/xvmc.c b/Xext/xvmc.c
index ae35893..97a02c1 100644
--- a/Xext/xvmc.c
+++ b/Xext/xvmc.c
@@ -613,8 +613,8 @@ ProcXvMCGetDRInfo(ClientPtr client)
 #ifdef HAS_XVMCSHM
     patternP = (CARD32 *)shmat( stuff->shmKey, NULL, SHM_RDONLY );
     if ( -1 != (long) patternP) {
-        register volatile CARD32 *patternC = patternP;
-	register int i;
+        volatile CARD32 *patternC = patternP;
+	int i;
 	CARD32 magic = stuff->magic;
 	
 	rep.isLocal = 1;
commit bad96e5a864e40fbd47265d7fb6eaa67c55fac11
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Nov 18 15:02:24 2007 +1030

    dix: getevents.c remove trailing whitespaces.

diff --git a/dix/getevents.c b/dix/getevents.c
index 20beff3..585fddd 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -23,7 +23,7 @@
  *
  * Author: Daniel Stone <daniel at fooishbar.org>
  */
- /* 
+ /*
   * MPX additions:
   * Copyright © 2006 Peter Hutterer
   * Author: Peter Hutterer <peter at cs.unisa.edu.au>
@@ -263,7 +263,7 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
 _X_EXPORT int
 GetMaximumEventsNum(void) {
     /* Three base events -- raw event and device, plus valuator events.
-     * Multiply by two if we're doing key repeats. 
+     * Multiply by two if we're doing key repeats.
      */
     int ret = 2 + MAX_VALUATOR_EVENTS;
 
@@ -567,7 +567,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
 }
 
 /**
- * Initialize an event list and fill with 32 byte sized events. 
+ * Initialize an event list and fill with 32 byte sized events.
  * This event list is to be passed into GetPointerEvents() and
  * GetKeyboardEvents().
  *
@@ -653,7 +653,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
         return 0;
-    
+
     /* FIXME: I guess it should, in theory, be possible to post button events
      *        from devices without valuators. */
     if (!pDev->valuator)
@@ -693,12 +693,12 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         return 0;
 
     /* fill up the raw event, after checking that it is large enough to
-     * accommodate all valuators. 
+     * accommodate all valuators.
      */
-    if (events->evlen < 
+    if (events->evlen <
             (sizeof(xEvent) + ((num_valuators - 4) * sizeof(CARD32))))
     {
-        events->evlen = sizeof(xEvent) + 
+        events->evlen = sizeof(xEvent) +
             ((num_valuators - 4) * sizeof(CARD32));
         events->event = realloc(events->event, events->evlen);
         if (!events->event)
@@ -886,11 +886,11 @@ SwitchCorePointer(DeviceIntPtr pDev)
  * to shift the pointer to get it inside the new bounds.
  */
 void
-PostSyntheticMotion(DeviceIntPtr pDev, 
-                    int x, 
-                    int y, 
+PostSyntheticMotion(DeviceIntPtr pDev,
+                    int x,
+                    int y,
                     int screen,
-                    unsigned long time) 
+                    unsigned long time)
 {
     xEvent xE;
 
commit 75e5e9f88c5f974d996dd81e672cd3709d361a44
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sat Nov 17 13:46:01 2007 +1030

    Xi: add missing XI_DeviceClassesChangedMask to XI filters array.

diff --git a/Xi/extinit.c b/Xi/extinit.c
index 07ef266..2d077b2 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -135,8 +135,9 @@ Mask ExtExclusiveMasks[EMASKSIZE];
  * Filters for various generic events.
  * Evtype is index, mask is value at index.
  */
-static Mask xi_filters[3] = {
+static Mask xi_filters[4] = {
     XI_DeviceHierarchyChangedMask,
+    XI_DeviceClassesChangedMask,
     XI_RawDeviceEventMask,
 };
 
commit 12dd6e9911de187e0ebee86434e8c24a67c990f9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 16 17:23:09 2007 +1030

    dix: reset MD's devPrivate classes to NULL before device initialisation.
    
    XkbInitKeyboardDefviceStruct may call FatalError if it fails. FatalError then
    cleans up all the devices, resulting in a segfault if the pointer is
    uninitialised.

diff --git a/dix/devices.c b/dix/devices.c
index 7512529..7d889a2 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -396,6 +396,8 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
         if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) ||
                 !(classes = xcalloc(1, sizeof(ClassesRec))))
 
+        pDev->devPrivates[MasterDevClassesPrivIdx].ptr = NULL;
+
         keySyms.minKeyCode = 8;
         keySyms.maxKeyCode = 255;
         keySyms.mapWidth = 4;
@@ -495,6 +497,8 @@ CorePointerProc(DeviceIntPtr pDev, int what)
                 !(classes = xcalloc(1, sizeof(ClassesRec))))
             return BadAlloc;
 
+        pDev->devPrivates[MasterDevClassesPrivIdx].ptr = NULL;
+
         for (i = 1; i <= 32; i++)
             map[i] = i;
         InitPointerDeviceStruct((DevicePtr)pDev, map, 32,
commit be3321c2e9fad228a9ee5fef47680a47bc9e39a4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 16 12:12:41 2007 +1030

    dix: Free both current classes and original classes when closing an MD.

diff --git a/dix/devices.c b/dix/devices.c
index bc3313c..7512529 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -817,10 +817,12 @@ CloseDevice(DeviceIntPtr dev)
     xfree(dev->name);
 
     if (dev->isMaster)
+    {
         classes = (ClassesPtr)dev->devPrivates[MasterDevClassesPrivIdx].ptr;
-    else
-        classes = (ClassesPtr)&dev->key;
+        FreeAllDeviceClasses(classes);
+    }
 
+    classes = (ClassesPtr)&dev->key;
     FreeAllDeviceClasses(classes);
 
 #ifdef XKB
commit 3c39dd19ec2a53b8854279e3b03131098031473a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 16 12:12:14 2007 +1030

    Xi: Deep-copy full list of FeedbackClasses.
    
    All feedback classes are linked lists and the whole list has to be duplicated,
    not just the first entry.
    
    Xkb stuff still missing.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 1cef825..d72f00a 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -205,6 +205,106 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
     }
 }
 
+/**
+ * Copies the feedback classes from device "from" into device "to". Classes
+ * are duplicated (not just flipping the pointers). All feedback classes are
+ * linked lists, the full list is duplicated.
+ *
+ * XXX: some XKB stuff is still missing.
+ */
+static void
+DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+    if (from->kbdfeed)
+    {
+        KbdFeedbackPtr *k, it;
+        k = &to->kbdfeed;
+        for(it = from->kbdfeed; it; it = it->next)
+        {
+            *k = xcalloc(1, sizeof(KbdFeedbackClassRec));
+            (*k)->BellProc = it->BellProc;
+            (*k)->CtrlProc = it->CtrlProc;
+            (*k)->ctrl     = it->ctrl;
+            /* XXX: xkb_sli needs to be copied */
+
+            k = &(*k)->next;
+        }
+    }
+
+    if (from->ptrfeed)
+    {
+        PtrFeedbackPtr *p, it;
+        p = &to->ptrfeed;
+        for (it = from->ptrfeed; it; it = it->next)
+        {
+            *p = xcalloc(1, sizeof(PtrFeedbackClassRec));
+            (*p)->CtrlProc = it->CtrlProc;
+            (*p)->ctrl     = it->ctrl;
+            /* XXX: xkb_sli needs to be copied */
+
+            p = &(*p)->next;
+        }
+    }
+
+    if (from->intfeed)
+    {
+        IntegerFeedbackPtr *i, it;
+        i = &to->intfeed;
+        for (it = from->intfeed; it; it = it->next)
+        {
+            *i = xcalloc(1, sizeof(IntegerFeedbackClassRec));
+            (*i)->CtrlProc = it->CtrlProc;
+            (*i)->ctrl     = it->ctrl;
+
+            i = &(*i)->next;
+        }
+    }
+
+    if (from->stringfeed)
+    {
+        StringFeedbackPtr *s, it;
+        s = &to->stringfeed;
+        for (it = from->stringfeed; it; it = it->next)
+        {
+            *s = xcalloc(1, sizeof(StringFeedbackClassRec));
+            (*s)->CtrlProc = it->CtrlProc;
+            (*s)->ctrl     = it->ctrl;
+
+            s = &(*s)->next;
+        }
+    }
+
+    if (from->bell)
+    {
+        BellFeedbackPtr *b, it;
+        b = &to->bell;
+        for (it = from->bell; it; it = it->next)
+        {
+            *b = xcalloc(1, sizeof(BellFeedbackClassRec));
+            (*b)->BellProc = it->BellProc;
+            (*b)->CtrlProc = it->CtrlProc;
+            (*b)->ctrl     = it->ctrl;
+
+            b = &(*b)->next;
+        }
+    }
+
+    if (from->leds)
+    {
+        LedFeedbackPtr *l, it;
+        l = &to->leds;
+        for (it = from->leds; it; it = it->next)
+        {
+            *l = xcalloc(1, sizeof(LedFeedbackClassRec));
+            (*l)->CtrlProc = it->CtrlProc;
+            (*l)->ctrl     = it->ctrl;
+            /* XXX: xkb_sli needs to be copied */
+
+            l = &(*l)->next;
+        }
+    }
+}
+
 _X_EXPORT void
 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 {
@@ -256,26 +356,24 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     ALLOC_COPY_CLASS_IF(focus, FocusClassRec);
     ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
     ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
+
     ALLOC_COPY_CLASS_IF(kbdfeed, KbdFeedbackClassRec);
 #ifdef XKB
     if (to->kbdfeed)
     {
         to->kbdfeed->xkb_sli = NULL;
         /* XXX: XkbSrvLedInfo needs to be copied*/
+        to->kbdfeed->next = NULL;
     }
 #endif
     ALLOC_COPY_CLASS_IF(ptrfeed, PtrFeedbackClassRec);
-    ALLOC_COPY_CLASS_IF(intfeed, IntegerFeedbackClassRec);
-    ALLOC_COPY_CLASS_IF(stringfeed, StringFeedbackClassRec);
-    ALLOC_COPY_CLASS_IF(bell, BellFeedbackClassRec);
-    ALLOC_COPY_CLASS_IF(leds, LedFeedbackClassRec);
-#ifdef XKB
-    if (to->leds)
+    if (to->ptrfeed)
     {
-        to->leds->xkb_sli = NULL;
-        /* XXX: XkbSrvLedInfo needs to be copied*/
+        to->ptrfeed->next = NULL;
     }
-#endif
+
+
+    DeepCopyFeedbackClasses(from, to);
 }
 
 static void
@@ -296,7 +394,7 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
 
     master->public.devicePrivate = device->public.devicePrivate;
 
-    FreeAllDeviceClasses(&master->key);
+    FreeAllDeviceClasses((ClassesPtr)&master->key);
     DeepCopyDeviceClasses(device, master);
 
     /* event is already correct size, see comment in GetPointerEvents */
commit 497862df2fcd67531fbe0f876c20a09884ee74df
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 16 11:20:22 2007 +1030

    dix: explicitly float all attached SDs before closing down devices.
    
    Some drivers flush on shutdown, if our SD is still attached we'd be trying to
    route an event through a non-existing device.

diff --git a/dix/devices.c b/dix/devices.c
index 045f74f..bc3313c 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -859,6 +859,17 @@ CloseDownDevices(void)
 {
     DeviceIntPtr dev, next;
 
+    /* Float all SDs before closing them. Note that at this point resources
+     * (e.g. cursors) have been freed already, so we can't just call
+     * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master
+     * to NULL and pretend nothing happened.
+     */
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+    {
+        if (!dev->isMaster && dev->u.master)
+            dev->u.master = NULL;
+    }
+
     for (dev = inputInfo.devices; dev; dev = next)
     {
 	next = dev->next;
commit 9de1ebe2a80164507cbe2ef688f284225e0ec808
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 16 10:45:28 2007 +1030

    dix: Fix up class restoring when last SD disconnects.
    
    Old code was fundamentally broken, fixes now are:
    - free the MDs current device classes
    - copy the device classes instead of flipping the pointers
    - check for the old MD, not the new one.

diff --git a/dix/devices.c b/dix/devices.c
index 1792e9e..045f74f 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2390,6 +2390,7 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
 int
 AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 {
+    DeviceIntPtr oldmaster;
     if (!dev || dev->isMaster)
         return BadDevice;
 
@@ -2409,6 +2410,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
     if (!dev->u.master && dev->spriteInfo->sprite)
         xfree(dev->spriteInfo->sprite);
 
+    oldmaster = dev->u.master;
     dev->u.master = master;
 
     /* If device is set to floating, we need to create a sprite for it,
@@ -2417,52 +2419,49 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
      */
     if (!master)
     {
-        DeviceIntPtr it;
                               /* current root window */
         InitializeSprite(dev, dev->spriteInfo->sprite->spriteTrace[0]);
         dev->spriteInfo->spriteOwner = FALSE;
 
-        /* the master may need to restore the original classes, search for a
-         * device that is still paired with our master. */
+    } else
+        dev->spriteInfo->sprite = master->spriteInfo->sprite;
+
+    /* If we were connected to master device before, this MD may need to
+     * change back to it's original classes.
+     */
+    if (oldmaster)
+    {
+        DeviceIntPtr it;
         for (it = inputInfo.devices; it; it = it->next)
-            if (!it->isMaster && it->u.master == master)
+            if (!it->isMaster && it->u.master == oldmaster)
                 break;
 
-        if (!it)  /* no dev is paired with our master */
+        if (!it)  /* no dev is paired with old master */
         {
             ClassesPtr classes;
             EventList event = { NULL, 0};
             char* classbuf;
+            DeviceIntRec dummy;
 
-            classes = master->devPrivates[MasterDevClassesPrivIdx].ptr;
-            master->key = classes->key;
-            master->valuator = classes->valuator;
-            master->button = classes->button;
-            master->focus = classes->focus;
-            master->proximity = classes->proximity;
-            master->absolute = classes->absolute;
-            master->kbdfeed = classes->kbdfeed;
-            master->ptrfeed = classes->ptrfeed;
-            master->intfeed = classes->intfeed;
-            master->stringfeed = classes->stringfeed;
-            master->bell = classes->bell;
-            master->leds = classes->leds;
+            FreeAllDeviceClasses((ClassesPtr)&oldmaster->key);
+            classes = oldmaster->devPrivates[MasterDevClassesPrivIdx].ptr;
+            memcpy(&dummy.key, classes, sizeof(ClassesRec));
+            DeepCopyDeviceClasses(&dummy, oldmaster);
 
             /* Send event to clients */
-            CreateClassesChangedEvent(&event, master, master);
+            CreateClassesChangedEvent(&event, oldmaster, oldmaster);
             deviceClassesChangedEvent *dcce =
-                        (deviceClassesChangedEvent*)event.event;
-            dcce->deviceid = master->id;
+                (deviceClassesChangedEvent*)event.event;
+            dcce->deviceid = oldmaster->id;
             dcce->num_classes = 0;
             classbuf = (char*)&event.event[1];
-            CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuf);
-            SendEventToAllWindows(master, XI_DeviceClassesChangedMask,
+            CopySwapClasses(NullClient, oldmaster,
+                    &dcce->num_classes, &classbuf);
+            SendEventToAllWindows(oldmaster, XI_DeviceClassesChangedMask,
                     event.event, 1);
             xfree(event.event);
         }
-
-    } else
-        dev->spriteInfo->sprite = master->spriteInfo->sprite;
+    }
 
     return Success;
 }
commit 83926cb8bef6288b89e801c5e60b3f40e923e16e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 17:41:07 2007 +1030

    Xi: Only alloc modifierKeyMap if <slave device>->maxKeysPerModifier > 0
    
    Sometimes (e.g. on my debian ppc box) maxKeysPerModifier of the SD is 0. So we
    try to malloc(0), bringing the whole server down with a FatalError because it
    looks as if the malloc failed. This is bad, so only alloc if we actually have
    something to alloc.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 837afa3..1cef825 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -147,11 +147,14 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
     if (master->devPrivates[CoreDevicePrivatesIndex].ptr != device) {
         memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH);
 
-        mk->modifierKeyMap = xcalloc(8, dk->maxKeysPerModifier);
-        if (!mk->modifierKeyMap)
-            FatalError("[Xi] no memory for class shift.\n");
-        memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
-                (8 * dk->maxKeysPerModifier));
+        if (dk->maxKeysPerModifier)
+        {
+            mk->modifierKeyMap = xcalloc(8, dk->maxKeysPerModifier);
+            if (!mk->modifierKeyMap)
+                FatalError("[Xi] no memory for class shift.\n");
+            memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
+                    (8 * dk->maxKeysPerModifier));
+        }
 
         mk->maxKeysPerModifier = dk->maxKeysPerModifier;
         mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode;
commit 070195dbf88eb121e65f802e023aa37ed1f2c2ac
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 16:27:18 2007 +1030

    Xi: fix up sloppy class copying causing segfaults.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 5395011..837afa3 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -220,6 +220,7 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
 #ifdef XKB
         to->key->xkbInfo = NULL;
 #endif
+        to->key->curKeySyms.map = NULL;
         CopyKeyClass(from, to);
     }
 
@@ -233,8 +234,12 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
         if (!v)
             FatalError("[Xi] no memory for class shift.\n");
         memcpy(v, from->valuator, sizeof(ValuatorClassRec));
+        v->motion = NULL;
+
         v->axes = (AxisInfoPtr)&v[1];
         memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
+
+        v->axisVal = (int*)(v->axes + from->valuator->numAxes);
     }
 
     ALLOC_COPY_CLASS_IF(button, ButtonClassRec);
commit 53539688cab990a7df1851d64f3ee4e11920a86b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 16:23:48 2007 +1030

    dix: SetKeySymMap should alloc the map if dst doesn't have one already.

diff --git a/dix/devices.c b/dix/devices.c
index bf1126f..1792e9e 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1046,10 +1046,9 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
         KeySym *map;
 	int bytes = sizeof(KeySym) * src->mapWidth *
 		    (dst->maxKeyCode - dst->minKeyCode + 1);
-        map = (KeySym *)xalloc(bytes);
+        map = (KeySym *)xcalloc(1, bytes);
 	if (!map)
 	    return FALSE;
-	bzero((char *)map, bytes);
         if (dst->map)
 	{
             for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++)
@@ -1060,6 +1059,15 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
 	}
 	dst->mapWidth = src->mapWidth;
 	dst->map = map;
+    } else if (!dst->map)
+    {
+        KeySym *map;
+	int bytes = sizeof(KeySym) * src->mapWidth *
+		    (dst->maxKeyCode - dst->minKeyCode + 1);
+        map = (KeySym *)xcalloc(1, bytes);
+        if (!map)
+            return FALSE;
+        dst->map = map;
     }
     memmove((char *)&dst->map[rowDif * dst->mapWidth],
 	    (char *)src->map,
commit b40646dc104fb03ea7cc0b27fae573aecaab486e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 15:43:44 2007 +1030

    dix: Add FreeDeviceClass and FreeFeedbackClass for centralised xfree.
    
    Ensures that we only have one way of freeing a device class to avoid leaks in
    ChangeMasterDeviceClasses and other places.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f9ea1c9..5395011 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -288,34 +288,7 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
 
     master->public.devicePrivate = device->public.devicePrivate;
 
-    if (master->key)
-        xfree(master->key->modifierKeyMap);
-#ifdef XKB
-    if (master->key && master->key->xkbInfo)
-        XkbFreeInfo(master->key->xkbInfo);
-#endif
-    xfree(master->key);         master->key = NULL;
-    xfree(master->valuator);    master->valuator = NULL;
-    /* XXX: xkb_acts needs to be freed for master->button */
-    xfree(master->button);      master->button = NULL;
-    xfree(master->focus);       master->focus = NULL;
-    xfree(master->proximity);   master->proximity = NULL;
-    xfree(master->absolute);    master->absolute = NULL;
-#ifdef XKB
-    if (master->kbdfeed && master->kbdfeed->xkb_sli)
-        XkbFreeSrvLedInfo(master->kbdfeed->xkb_sli);
-#endif
-    xfree(master->kbdfeed);     master->kbdfeed = NULL;
-    xfree(master->ptrfeed);     master->ptrfeed = NULL;
-    xfree(master->stringfeed);  master->stringfeed = NULL;
-    xfree(master->bell);        master->bell = NULL;
-#ifdef XKB
-    if (master->leds && master->leds->xkb_sli)
-        XkbFreeSrvLedInfo(master->leds->xkb_sli);
-#endif
-    xfree(master->leds);        master->leds = NULL;
-    xfree(master->intfeed);     master->intfeed = NULL;
-
+    FreeAllDeviceClasses(&master->key);
     DeepCopyDeviceClasses(device, master);
 
     /* event is already correct size, see comment in GetPointerEvents */
diff --git a/dix/devices.c b/dix/devices.c
index 65d1980..bf1126f 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -85,22 +85,6 @@ SOFTWARE.
  * This file handles input device-related stuff.
  */
 
-typedef struct {
-    KeyClassPtr		key;
-    ValuatorClassPtr	valuator;
-    ButtonClassPtr	button;
-    FocusClassPtr	focus;
-    ProximityClassPtr	proximity;
-    AbsoluteClassPtr    absolute;
-    KbdFeedbackPtr	kbdfeed;
-    PtrFeedbackPtr	ptrfeed;
-    IntegerFeedbackPtr	intfeed;
-    StringFeedbackPtr	stringfeed;
-    BellFeedbackPtr	bell;
-    LedFeedbackPtr	leds;
-} ClassesRec, *ClassesPtr;
-
-
 int CoreDevicePrivatesIndex = 0;
 static int CoreDevicePrivatesGeneration = -1;
 int MasterDevClassesPrivIdx = -1;
@@ -638,6 +622,174 @@ InitAndStartDevices(WindowPtr root)
     return Success;
 }
 
+_X_EXPORT void
+FreeAllDeviceClasses(ClassesPtr classes)
+{
+    if (!classes)
+        return;
+
+    FreeDeviceClass(KeyClass, (pointer)&classes->key);
+    FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
+    FreeDeviceClass(ButtonClass, (pointer)&classes->button);
+    FreeDeviceClass(FocusClass, (pointer)&classes->focus);
+    FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
+
+    FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed);
+    FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed);
+    FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed);
+    FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed);
+    FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell);
+    FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds);
+
+}
+
+/**
+ * Free the given device class and reset the pointer to NULL.
+ */
+_X_EXPORT void
+FreeDeviceClass(int type, pointer *class)
+{
+    if (!(*class))
+        return;
+
+    switch(type)
+    {
+        case KeyClass:
+            {
+                KeyClassPtr* k = (KeyClassPtr*)class;
+#ifdef XKB
+                if ((*k)->xkbInfo)
+                    XkbFreeInfo((*k)->xkbInfo);
+#endif
+
+                xfree((*k)->curKeySyms.map);
+                xfree((*k)->modifierKeyMap);
+                xfree((*k));
+                break;
+            }
+        case ButtonClass:
+            {
+                ButtonClassPtr *b = (ButtonClassPtr*)class;
+#ifdef XKB
+                if ((*b)->xkb_acts)
+                    xfree((*b)->xkb_acts);
+#endif
+                xfree((*b));
+                break;
+            }
+        case ValuatorClass:
+            {
+                ValuatorClassPtr *v = (ValuatorClassPtr*)class;
+
+                /* Counterpart to 'biggest hack ever' in init. */
+                if ((*v)->motion && (*v)->GetMotionProc == GetMotionHistory)
+                    xfree((*v)->motion);
+                xfree((*v));
+                break;
+            }
+        case FocusClass:
+            {
+                FocusClassPtr *f = (FocusClassPtr*)class;
+                xfree((*f)->trace);
+                xfree((*f));
+                break;
+            }
+        case ProximityClass:
+            {
+                ProximityClassPtr *p = (ProximityClassPtr*)class;
+                xfree((*p));
+                break;
+            }
+
+    }
+    *class = NULL;
+}
+_X_EXPORT void
+FreeFeedbackClass(int type, pointer *class)
+{
+    if (!(*class))
+        return;
+
+    switch(type)
+    {
+        case KbdFeedbackClass:
+            {
+                KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class;
+                KbdFeedbackPtr k, knext;
+                for (k = (*kbdfeed); k; k = knext) {
+                    knext = k->next;
+#ifdef XKB
+                    if (k->xkb_sli)
+                        XkbFreeSrvLedInfo(k->xkb_sli);
+#endif
+                    xfree(k);
+                }
+                break;
+            }
+        case PtrFeedbackClass:
+            {
+                PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class;
+                PtrFeedbackPtr p, pnext;
+
+                for (p = (*ptrfeed); p; p = pnext) {
+                    pnext = p->next;
+                    xfree(p);
+                }
+                break;
+            }
+        case IntegerFeedbackClass:
+            {
+                IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class;
+                IntegerFeedbackPtr i, inext;
+
+                for (i = (*intfeed); i; i = inext) {
+                    inext = i->next;
+                    xfree(i);
+                }
+                break;
+            }
+        case StringFeedbackClass:
+            {
+                StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class;
+                StringFeedbackPtr s, snext;
+
+                for (s = (*stringfeed); s; s = snext) {
+                    snext = s->next;
+                    xfree(s->ctrl.symbols_supported);
+                    xfree(s->ctrl.symbols_displayed);
+                    xfree(s);
+                }
+                break;
+            }
+        case BellFeedbackClass:
+            {
+                BellFeedbackPtr *bell = (BellFeedbackPtr*)class;
+                BellFeedbackPtr b, bnext;
+
+                for (b = (*bell); b; b = bnext) {
+                    bnext = b->next;
+                    xfree(b);
+                }
+                break;
+            }
+        case LedFeedbackClass:
+            {
+                LedFeedbackPtr *leds = (LedFeedbackPtr*)class;
+                LedFeedbackPtr l, lnext;
+
+                for (l = (*leds); l; l = lnext) {
+                    lnext = l->next;
+#ifdef XKB
+                    if (l->xkb_sli)
+                        XkbFreeSrvLedInfo(l->xkb_sli);
+#endif
+                    xfree(l);
+                }
+                break;
+            }
+    }
+    *class = NULL;
+}
 /**
  * Close down a device and free all resources.
  * Once closed down, the driver will probably not expect you that you'll ever
@@ -648,12 +800,6 @@ InitAndStartDevices(WindowPtr root)
 static void
 CloseDevice(DeviceIntPtr dev)
 {
-    KbdFeedbackPtr k, knext;
-    PtrFeedbackPtr p, pnext;
-    IntegerFeedbackPtr i, inext;
-    StringFeedbackPtr s, snext;
-    BellFeedbackPtr b, bnext;
-    LedFeedbackPtr l, lnext;
     ScreenPtr screen = screenInfo.screens[0];
     ClassesPtr classes;
     int j;
@@ -675,79 +821,7 @@ CloseDevice(DeviceIntPtr dev)
     else
         classes = (ClassesPtr)&dev->key;
 
-    if (classes->key) {
-#ifdef XKB
-	if (classes->key->xkbInfo)
-	    XkbFreeInfo(classes->key->xkbInfo);
-#endif
-	xfree(classes->key->curKeySyms.map);
-	xfree(classes->key->modifierKeyMap);
-	xfree(classes->key);
-    }
-
-    if (classes->valuator) {
-        /* Counterpart to 'biggest hack ever' in init. */
-        if (classes->valuator->motion &&
-            classes->valuator->GetMotionProc == GetMotionHistory)
-            xfree(classes->valuator->motion);
-        xfree(classes->valuator);
-    }
-
-    if (classes->button) {
-#ifdef XKB
-        if (classes->button->xkb_acts)
-            xfree(classes->button->xkb_acts);
-#endif
-        xfree(classes->button);
-    }
-
-    if (classes->focus) {
-	xfree(classes->focus->trace);
-	xfree(classes->focus);
-    }
-
-    if (classes->proximity)
-        xfree(classes->proximity);
-
-    for (k = classes->kbdfeed; k; k = knext) {
-	knext = k->next;
-#ifdef XKB
-	if (k->xkb_sli)
-	    XkbFreeSrvLedInfo(k->xkb_sli);
-#endif
-	xfree(k);
-    }
-
-    for (p = classes->ptrfeed; p; p = pnext) {
-	pnext = p->next;
-	xfree(p);
-    }
-
-    for (i = classes->intfeed; i; i = inext) {
-	inext = i->next;
-	xfree(i);
-    }
-
-    for (s = classes->stringfeed; s; s = snext) {
-	snext = s->next;
-	xfree(s->ctrl.symbols_supported);
-	xfree(s->ctrl.symbols_displayed);
-	xfree(s);
-    }
-
-    for (b = classes->bell; b; b = bnext) {
-	bnext = b->next;
-	xfree(b);
-    }
-
-    for (l = classes->leds; l; l = lnext) {
-	lnext = l->next;
-#ifdef XKB
-	if (l->xkb_sli)
-	    XkbFreeSrvLedInfo(l->xkb_sli);
-#endif
-	xfree(l);
-    }
+    FreeAllDeviceClasses(classes);
 
 #ifdef XKB
     while (dev->xkb_interest)
diff --git a/include/input.h b/include/input.h
index 91ce4ee..9e73dc2 100644
--- a/include/input.h
+++ b/include/input.h
@@ -84,6 +84,7 @@ typedef unsigned long Leds;
 typedef struct _OtherClients *OtherClientsPtr;
 typedef struct _InputClients *InputClientsPtr;
 typedef struct _DeviceIntRec *DeviceIntPtr;
+typedef struct _ClassesRec *ClassesPtr;
 
 typedef struct _EventList {
     xEvent* event;
@@ -484,6 +485,9 @@ extern int AllocMasterDevice(char* name,
                              DeviceIntPtr* keybd);
 extern void DeepCopyDeviceClasses(DeviceIntPtr from,
                                   DeviceIntPtr to);
+extern void FreeDeviceClass(int type, pointer* class);
+extern void FreeFeedbackClass(int type, pointer* class);
+extern void FreeAllDeviceClasses(ClassesPtr classes);
 
 /* Window/device based access control */
 extern Bool ACRegisterClient(ClientPtr client);
diff --git a/include/inputstr.h b/include/inputstr.h
index 507e7b0..0589097 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -283,6 +283,22 @@ typedef struct _LedFeedbackClassRec {
 } LedFeedbackClassRec;
 
 
+typedef struct _ClassesRec {
+    KeyClassPtr		key;
+    ValuatorClassPtr	valuator;
+    ButtonClassPtr	button;
+    FocusClassPtr	focus;
+    ProximityClassPtr	proximity;
+    AbsoluteClassPtr    absolute;
+    KbdFeedbackPtr	kbdfeed;
+    PtrFeedbackPtr	ptrfeed;
+    IntegerFeedbackPtr	intfeed;
+    StringFeedbackPtr	stringfeed;
+    BellFeedbackPtr	bell;
+    LedFeedbackPtr	leds;
+} ClassesRec;
+
+
 /**
  * Sprite information for a device.
  */
commit 18833d648fd7e1a5e962b93636bbbb38aca9c454
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 12:13:59 2007 +1030

    Xi: reset xkb-stuff to NULL after copying (DeepCopyDeviceClasses)
    
    Having two devices point to the same xkb stuff causes SIGABRTs.
    
    Also, don't init a MD's xkbInfo unless the SD has an xkbInfo.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 158f523..f9ea1c9 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -178,9 +178,9 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
             mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
 
 #ifdef XKB
-        if (!mk->xkbInfo || !mk->xkbInfo->desc)
-            XkbInitDevice(master);
         if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) {
+            if (!mk->xkbInfo || !mk->xkbInfo->desc)
+                XkbInitDevice(master);
             if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True))
                 FatalError("Couldn't pivot keymap from device to core!\n");
         }
@@ -238,18 +238,36 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
     }
 
     ALLOC_COPY_CLASS_IF(button, ButtonClassRec);
+#ifdef XKB
+    if (to->button)
+    {
+        to->button->xkb_acts = NULL;
         /* XXX: XkbAction needs to be copied */
+    }
+#endif
     ALLOC_COPY_CLASS_IF(focus, FocusClassRec);
     ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
     ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
     ALLOC_COPY_CLASS_IF(kbdfeed, KbdFeedbackClassRec);
+#ifdef XKB
+    if (to->kbdfeed)
+    {
+        to->kbdfeed->xkb_sli = NULL;
         /* XXX: XkbSrvLedInfo needs to be copied*/
+    }
+#endif
     ALLOC_COPY_CLASS_IF(ptrfeed, PtrFeedbackClassRec);
     ALLOC_COPY_CLASS_IF(intfeed, IntegerFeedbackClassRec);
     ALLOC_COPY_CLASS_IF(stringfeed, StringFeedbackClassRec);
     ALLOC_COPY_CLASS_IF(bell, BellFeedbackClassRec);
     ALLOC_COPY_CLASS_IF(leds, LedFeedbackClassRec);
-        /* XXX: XkbSrvLedInfo needs to be copied. */
+#ifdef XKB
+    if (to->leds)
+    {
+        to->leds->xkb_sli = NULL;
+        /* XXX: XkbSrvLedInfo needs to be copied*/
+    }
+#endif
 }
 
 static void
commit 1635832c1635374033686d3a943b77adbd60bb98
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 11:35:07 2007 +1030

    Revert "xkb: disable xkb key repeats (temporarily)"
    
    This reverts commit 2b1d946392ce28b96941341778b2b526aa0fb126.

diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c
index 147df3e..f007f75 100644
--- a/xkb/xkbPrKeyEv.c
+++ b/xkb/xkbPrKeyEv.c
@@ -76,7 +76,6 @@ int             xiEvent;
     if ((behavior.type&XkbKB_Permanent)==0) {
 	switch (behavior.type) {
 	    case XkbKB_Default:
-#if 0
 		if (( xE->u.u.type == KeyPress || 
                             xE->u.u.type == DeviceKeyPress) && 
 		    (keyc->down[key>>3] & (1<<(key&7)))) {
@@ -113,7 +112,6 @@ int             xiEvent;
 		    XkbLastRepeatEvent= NULL;
 		    return;
 		}
-#endif
 		break;
 	    case XkbKB_Lock:
 		if ( xE->u.u.type == KeyRelease || 
commit b05246696d14bd35aa53b49302707b51206c72a6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 11:31:43 2007 +1030

    Xi: free XkbSrvLedInfos as well when freeing an MD's device classes.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 1bf6c51..158f523 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -278,14 +278,23 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
 #endif
     xfree(master->key);         master->key = NULL;
     xfree(master->valuator);    master->valuator = NULL;
+    /* XXX: xkb_acts needs to be freed for master->button */
     xfree(master->button);      master->button = NULL;
     xfree(master->focus);       master->focus = NULL;
     xfree(master->proximity);   master->proximity = NULL;
     xfree(master->absolute);    master->absolute = NULL;
+#ifdef XKB
+    if (master->kbdfeed && master->kbdfeed->xkb_sli)
+        XkbFreeSrvLedInfo(master->kbdfeed->xkb_sli);
+#endif
     xfree(master->kbdfeed);     master->kbdfeed = NULL;
     xfree(master->ptrfeed);     master->ptrfeed = NULL;
     xfree(master->stringfeed);  master->stringfeed = NULL;
     xfree(master->bell);        master->bell = NULL;
+#ifdef XKB
+    if (master->leds && master->leds->xkb_sli)
+        XkbFreeSrvLedInfo(master->leds->xkb_sli);
+#endif
     xfree(master->leds);        master->leds = NULL;
     xfree(master->intfeed);     master->intfeed = NULL;
 
commit c758e5a664a52045ad419340044beebb6774a336
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 10:47:20 2007 +1030

    dix: Make sure core MDs copy their initial classes before they are used.
    
    Anything in dev->key, dev->valuator etc. of a MD must always be a copy of the
    original class. The intial classes of an MD (the ones set up before an SD is
    attached) as well, as we may have to restore them if no SD is attached
    anymore.

diff --git a/dix/devices.c b/dix/devices.c
index 2960e09..65d1980 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -402,6 +402,7 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
     XkbComponentNamesRec names;
 #endif
     ClassesPtr classes;
+    DeviceIntRec dummy;
 
     switch (what) {
     case DEVICE_INIT:
@@ -460,6 +461,19 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
         classes->stringfeed = pDev->stringfeed;
         classes->bell = pDev->bell;
         classes->leds = pDev->leds;
+
+        /* Each time we switch classes we free the MD's classes and copy the
+         * SD's classes into the MD. We mustn't lose the first set of classes
+         * though as we need it to restore them when the last SD disconnects.
+         *
+         * So we create a fake device, seem to copy from the fake to the real
+         * one, thus ending up with a copy of the original ones in our MD.
+         *
+         * If we don't do that, we're in SIGABRT territory (double-frees, etc)
+         */
+        memcpy(&dummy, pDev, sizeof(DeviceIntRec));
+        DeepCopyDeviceClasses(&dummy, pDev);
+
         pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes;
         break;
 
@@ -485,6 +499,7 @@ CorePointerProc(DeviceIntPtr pDev, int what)
     BYTE map[33];
     int i = 0;
     ClassesPtr classes;
+    DeviceIntRec dummy;
 
 
     switch (what) {
@@ -519,6 +534,10 @@ CorePointerProc(DeviceIntPtr pDev, int what)
         classes->bell = pDev->bell;
         classes->leds = pDev->leds;
 
+        /* See comment in CoreKeyboardProc. */
+        memcpy(&dummy, pDev, sizeof(DeviceIntRec));
+        DeepCopyDeviceClasses(&dummy, pDev);
+
         pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes;
         break;
 
@@ -568,7 +587,6 @@ InitCoreDevices(void)
 
     ActivateDevice(inputInfo.keyboard);
     ActivateDevice(inputInfo.pointer);
-
 }
 
 /**
commit a08665d4d3b0a7d567a90bb9bbfe4abafd6f3887
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 10:42:29 2007 +1030

    mi: don't call SwitchCoreKeyboard, we switch during event processing now.

diff --git a/mi/mieq.c b/mi/mieq.c
index 11439cf..5dcc404 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -331,23 +331,13 @@ mieqProcessInputEvents(void)
                 return;
             }
 
-            /* Make sure our keymap, et al, is changed to suit. */
-            if ((e->events->event[0].u.u.type == DeviceKeyPress ||
-                e->events->event[0].u.u.type == DeviceKeyRelease ||
-                e->events->event[0].u.u.type == KeyPress ||
-                e->events->event[0].u.u.type == KeyRelease) &&
-                    !e->pDev->isMaster)
-            {
-                SwitchCoreKeyboard(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;
@@ -372,7 +362,7 @@ mieqProcessInputEvents(void)
 
             if (!e->pDev->isMaster && e->pDev->u.master)
             {
-                e->pDev->u.master->public.processInputProc(master_event, 
+                e->pDev->u.master->public.processInputProc(master_event,
                         e->pDev->u.master, e->nevents);
             }
 
@@ -382,7 +372,7 @@ mieqProcessInputEvents(void)
         }
 
         /* Update the sprite now. Next event may be from different device. */
-        if (e->events->event[0].u.u.type == DeviceMotionNotify 
+        if (e->events->event[0].u.u.type == DeviceMotionNotify
                 && e->pDev->coreEvents)
         {
             miPointerUpdateSprite(e->pDev);
commit 64711a094893e83764bbeda538c6e877ebe2af79
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 15 10:41:34 2007 +1030

    Xi: When switching MD classes, make a deep copy instead of pointer flip.
    
    Turns out it's really really hard synchronising device state across multiple
    duplicated events if they all share the same struct. So instead of doing so,
    when the SD changes deep-copy all it's classes into the MD. The MD then has
    the same capabilities, but the state can be set separately. This should fix
    xkb, key state, repeat etc. problems.
    
    Updating the device state allows us to remove the SwitchCoreKeyboard from the
    event gathering, it's all done during event processing now.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 91035c7..1bf6c51 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -76,7 +76,9 @@ SOFTWARE.
 #include "listdev.h" /* for CopySwapXXXClass */
 
 #ifdef XKB
+#include <X11/extensions/XKBproto.h>
 #include "xkbsrv.h"
+extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
 #endif
 
 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
@@ -102,6 +104,154 @@ RegisterOtherDevice(DeviceIntPtr device)
     device->public.realInputProc = ProcessOtherEvent;
 }
 
+/**
+ * Copy the device->key into master->key and send a mapping notify to the
+ * clients if appropriate.
+ * master->key needs to be allocated by the caller.
+ *
+ * Device is the slave device. If it is attached to a master device, we may
+ * need to send a mapping notify to the client because it causes the MD
+ * to change state.
+ *
+ * Mapping notify needs to be sent in the following cases:
+ *      - different slave device on same master
+ *      - different master
+ *
+ * XXX: They way how the code is we also send a map notify if the slave device
+ * stays the same, but the master changes. This isn't really necessary though.
+ *
+ * XXX: this gives you funny behaviour with the ClientPointer. When a
+ * MappingNotify is sent to the client, the client usually responds with a
+ * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
+ * mapping, regardless of which keyboard sent the last mapping notify request.
+ * So depending on the CP setting, your keyboard may change layout in each
+ * app...
+ *
+ * This code is basically the old SwitchCoreKeyboard.
+ */
+
+static void
+CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
+{
+    static DeviceIntPtr lastMapNotifyDevice = NULL;
+    KeyClassPtr mk, dk; /* master, device */
+    BOOL sendNotify = FALSE;
+    int i;
+
+    if (device == master)
+        return;
+
+    dk = device->key;
+    mk = master->key;
+
+    if (master->devPrivates[CoreDevicePrivatesIndex].ptr != device) {
+        memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH);
+
+        mk->modifierKeyMap = xcalloc(8, dk->maxKeysPerModifier);
+        if (!mk->modifierKeyMap)
+            FatalError("[Xi] no memory for class shift.\n");
+        memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
+                (8 * dk->maxKeysPerModifier));
+
+        mk->maxKeysPerModifier = dk->maxKeysPerModifier;
+        mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode;
+        mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode;
+        SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms);
+
+        /*
+         * Copy state from the extended keyboard to core.  If you omit this,
+         * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
+         * cause your app to quit.  This feels wrong to me, hence the below
+         * code.
+         *
+         * XXX: If you synthesise core modifier events, the state will get
+         *      clobbered here.  You'll have to work out something sensible
+         *      to fix that.  Good luck.
+         */
+
+#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
+        Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
+        mk->state &= ~(KEYBOARD_MASK);
+        mk->state |= (dk->state & KEYBOARD_MASK);
+#undef KEYBOARD_MASK
+        for (i = 0; i < 8; i++)
+            mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
+
+#ifdef XKB
+        if (!mk->xkbInfo || !mk->xkbInfo->desc)
+            XkbInitDevice(master);
+        if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) {
+            if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True))
+                FatalError("Couldn't pivot keymap from device to core!\n");
+        }
+#endif
+
+        master->devPrivates[CoreDevicePrivatesIndex].ptr = device;
+        sendNotify = TRUE;
+    } else if (lastMapNotifyDevice != master)
+        sendNotify = TRUE;
+
+    if (sendNotify)
+    {
+        SendMappingNotify(master, MappingKeyboard,
+                           mk->curKeySyms.minKeyCode,
+                          (mk->curKeySyms.maxKeyCode -
+                           mk->curKeySyms.minKeyCode),
+                          serverClient);
+        lastMapNotifyDevice = master;
+    }
+}
+
+_X_EXPORT void
+DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
+{
+#define ALLOC_COPY_CLASS_IF(field, type) \
+    if (from->field)\
+    { \
+        to->field = xcalloc(1, sizeof(type)); \
+        if (!to->field) \
+            FatalError("[Xi] no memory for class shift.\n"); \
+        memcpy(to->field, from->field, sizeof(type)); \
+    }
+
+    ALLOC_COPY_CLASS_IF(key, KeyClassRec);
+    if (to->key)
+    {
+#ifdef XKB
+        to->key->xkbInfo = NULL;
+#endif
+        CopyKeyClass(from, to);
+    }
+
+    if (from->valuator)
+    {
+        ValuatorClassPtr v;
+        to->valuator = xalloc(sizeof(ValuatorClassRec) +
+                from->valuator->numAxes * sizeof(AxisInfo) +
+                from->valuator->numAxes * sizeof(unsigned int));
+        v = to->valuator;
+        if (!v)
+            FatalError("[Xi] no memory for class shift.\n");
+        memcpy(v, from->valuator, sizeof(ValuatorClassRec));
+        v->axes = (AxisInfoPtr)&v[1];
+        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
+    }
+
+    ALLOC_COPY_CLASS_IF(button, ButtonClassRec);
+        /* XXX: XkbAction needs to be copied */
+    ALLOC_COPY_CLASS_IF(focus, FocusClassRec);
+    ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
+    ALLOC_COPY_CLASS_IF(absolute, AbsoluteClassRec);
+    ALLOC_COPY_CLASS_IF(kbdfeed, KbdFeedbackClassRec);
+        /* XXX: XkbSrvLedInfo needs to be copied*/
+    ALLOC_COPY_CLASS_IF(ptrfeed, PtrFeedbackClassRec);
+    ALLOC_COPY_CLASS_IF(intfeed, IntegerFeedbackClassRec);
+    ALLOC_COPY_CLASS_IF(stringfeed, StringFeedbackClassRec);
+    ALLOC_COPY_CLASS_IF(bell, BellFeedbackClassRec);
+    ALLOC_COPY_CLASS_IF(leds, LedFeedbackClassRec);
+        /* XXX: XkbSrvLedInfo needs to be copied. */
+}
+
 static void
 ChangeMasterDeviceClasses(DeviceIntPtr device,
                           deviceClassesChangedEvent *dcce)
@@ -119,21 +269,31 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
     dcce->num_classes  = 0;
 
     master->public.devicePrivate = device->public.devicePrivate;
-    master->key        = device->key;
-    master->valuator   = device->valuator;
-    master->button     = device->button;
-    master->focus      = device->focus;
-    master->proximity  = device->proximity;
-    master->absolute   = device->absolute;
-    master->kbdfeed    = device->kbdfeed;
-    master->ptrfeed    = device->ptrfeed;
-    master->intfeed    = device->intfeed;
-    master->stringfeed = device->stringfeed;
-    master->bell       = device->bell;
-    master->leds       = device->leds;
+
+    if (master->key)
+        xfree(master->key->modifierKeyMap);
+#ifdef XKB
+    if (master->key && master->key->xkbInfo)
+        XkbFreeInfo(master->key->xkbInfo);
+#endif
+    xfree(master->key);         master->key = NULL;
+    xfree(master->valuator);    master->valuator = NULL;
+    xfree(master->button);      master->button = NULL;
+    xfree(master->focus);       master->focus = NULL;
+    xfree(master->proximity);   master->proximity = NULL;
+    xfree(master->absolute);    master->absolute = NULL;
+    xfree(master->kbdfeed);     master->kbdfeed = NULL;
+    xfree(master->ptrfeed);     master->ptrfeed = NULL;
+    xfree(master->stringfeed);  master->stringfeed = NULL;
+    xfree(master->bell);        master->bell = NULL;
+    xfree(master->leds);        master->leds = NULL;
+    xfree(master->intfeed);     master->intfeed = NULL;
+
+    DeepCopyDeviceClasses(device, master);
 
     /* event is already correct size, see comment in GetPointerEvents */
     classbuff = (char*)&dcce[1];
+
     /* we don't actually swap if there's a NullClient, swapping is done
      * later when event is delivered. */
     CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff);
@@ -159,9 +319,9 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
     int key = 0,
         bit = 0;
 
-    KeyClassPtr k       = device->key;
-    ButtonClassPtr b    = device->button;
-    ValuatorClassPtr v  = device->valuator;
+    KeyClassPtr k       = NULL;
+    ButtonClassPtr b    = NULL;
+    ValuatorClassPtr v  = NULL;
     deviceValuator *xV  = (deviceValuator *) xE;
     BYTE *kptr          = NULL;
     CARD16 modifiers    = 0,
@@ -181,6 +341,11 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
     if (xE->u.u.type == GenericEvent)
         return DEFAULT;
 
+    k = device->key;
+    v = device->valuator;
+    b = device->button;
+
+
     if (xE->u.u.type != DeviceValuator)
     {
         key = xE->u.u.detail;
@@ -272,10 +437,9 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 	*kptr |= bit;
 	if (device->valuator)
 	    device->valuator->motionHintWindow = NullWindow;
-        if (!device->isMaster)
-            b->buttonsDown++;
+        b->buttonsDown++;
 	b->motionMask = DeviceButtonMotionMask;
-        if (!device->isMaster && !b->map[key]) /* bit already unset for MDs */
+        if (!b->map[key])
             return DONT_PROCESS;
         if (b->map[key] <= 5)
 	    b->state |= (Button1Mask >> 1) << b->map[key];
@@ -290,9 +454,7 @@ UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
 	*kptr &= ~bit;
 	if (device->valuator)
 	    device->valuator->motionHintWindow = NullWindow;
-        if (!device->isMaster)
-            b->buttonsDown--;
-        if (b->buttonsDown >= 1 && !b->buttonsDown)
+        if (b->buttonsDown >= 1 && !--b->buttonsDown)
 	    b->motionMask = 0;
         if (!b->map[key])
             return DONT_PROCESS;
@@ -323,9 +485,9 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     GrabPtr grab = device->deviceGrab.grab;
     Bool deactivateDeviceGrab = FALSE;
     int key = 0, rootX, rootY;
-    ButtonClassPtr b = device->button;
-    KeyClassPtr k = device->key;
-    ValuatorClassPtr v  = device->valuator;
+    ButtonClassPtr b;
+    KeyClassPtr k;
+    ValuatorClassPtr v;
     deviceValuator *xV  = (deviceValuator *) xE;
     BOOL sendCore = FALSE;
     xEvent core;
@@ -336,6 +498,10 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     if (ret == DONT_PROCESS)
         return;
 
+    v = device->valuator;
+    b = device->button;
+    k = device->key;
+
     coretype = XItoCoreType(xE->u.u.type);
     if (device->isMaster && device->coreEvents && coretype)
         sendCore = TRUE;
diff --git a/dix/getevents.c b/dix/getevents.c
index b0211b6..20beff3 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -865,63 +865,6 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
     return num_events;
 }
 
-
-/**
- * pDev is the slave device that is about to send an event. If it is attached
- * to a master device, then we need to send a mapping notify to the client.
- * To do so, we need to remember the last master device that sent a mapping
- * event.
- *
- * Mapping notify needs to be sent in the following cases:
- *      - different slave device on same master
- *      - different master
- *
- * Call this just before processInputProc.
- *
- * XXX: They way how the code is we also send a map notify if the slave device
- * stays the same, but the master changes. This isn't really necessary though.
- *
- * XXX: this gives you funny behaviour with the ClientPointer. When a
- * MappingNotify is sent to the client, the client usually responds with a
- * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
- * mapping, regardless of which keyboard sent the last mapping notify request.
- * So depending on the CP setting, your keyboard may change layout in each
- * app...
- */
-_X_EXPORT void
-SwitchCoreKeyboard(DeviceIntPtr pDev)
-{
-    static DeviceIntPtr lastMapNotifyDevice = NULL;
-    DeviceIntPtr master;
-    KeyClassPtr ckeyc;
-    int i = 0;
-    BOOL sendNotify = FALSE;
-
-    if (pDev->isMaster || !pDev->u.master)
-        return;
-
-    master = pDev->u.master;
-    ckeyc = master->key;
-
-    if (master->devPrivates[CoreDevicePrivatesIndex].ptr != pDev) {
-        master->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
-        sendNotify = TRUE;
-    }
-
-    if (lastMapNotifyDevice != master)
-        sendNotify = TRUE;
-
-    if (sendNotify)
-    {
-        SendMappingNotify(pDev, MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
-                          (ckeyc->curKeySyms.maxKeyCode -
-                           ckeyc->curKeySyms.minKeyCode),
-                          serverClient);
-        lastMapNotifyDevice = master;
-    }
-}
-
-
 /**
  * Note that pDev was the last function to send a core pointer event.
  * Currently a no-op.
diff --git a/include/input.h b/include/input.h
index dbf6aee..91ce4ee 100644
--- a/include/input.h
+++ b/include/input.h
@@ -458,7 +458,6 @@ extern int GetMotionHistory(
     unsigned long stop,
     ScreenPtr pScreen);
 
-extern void SwitchCoreKeyboard(DeviceIntPtr pDev);
 extern void SwitchCorePointer(DeviceIntPtr pDev);
 
 extern DeviceIntPtr LookupDeviceIntRec(
@@ -483,6 +482,8 @@ extern DeviceIntPtr NextFreePointerDevice(void);
 extern int AllocMasterDevice(char* name,
                              DeviceIntPtr* ptr,
                              DeviceIntPtr* keybd);
+extern void DeepCopyDeviceClasses(DeviceIntPtr from,
+                                  DeviceIntPtr to);
 
 /* Window/device based access control */
 extern Bool ACRegisterClient(ClientPtr client);
commit cc4586df600af571815d5cdda2028c0d074c8469
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 14 14:27:52 2007 +1030

    Xi: toggle the public.devPrivate as well when switching device classes.
    
    The master needs to have the same devPrivate as the slave, in case a client
    issues a request that goes down to the driver.
    Example: if a driver wants to ring the keyboard bell, it'll pick a keyboard.
    The KeyClassPtr will direct it to the matching method in the driver, but
    because the MD doesn't have the devPrivate set the driver segfaults.
    Even if all drivers were updated to not dereference the nullpointer, nothing
    would actually ever happen.
    
    To avoid this, we flip the master's public.devPrivate to the last SDs
    devPrivate.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f60f634..91035c7 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -118,6 +118,7 @@ ChangeMasterDeviceClasses(DeviceIntPtr device,
     dcce->deviceid     = master->id;
     dcce->num_classes  = 0;
 
+    master->public.devicePrivate = device->public.devicePrivate;
     master->key        = device->key;
     master->valuator   = device->valuator;
     master->button     = device->button;
commit b44c1118f3bab6d5f28fa42e0c322fbaec005012
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 14 14:08:21 2007 +1030

    dix: Return Success from ProcBell if no BellProc is set.
    
    We must not return BadDevice, this causes applications to crash. If no
    BellProc is set, just quietly do nothing and report a Success.

diff --git a/dix/devices.c b/dix/devices.c
index fa80a0c..2960e09 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2011,8 +2011,13 @@ ProcBell(ClientPtr client)
     REQUEST(xBellReq);
     REQUEST_SIZE_MATCH(xBellReq);
 
+    /* Seems like no keyboard actually has the BellProc set. Returning
+     * BadDevice (previous code) will make apps crash badly. The man pages
+     * doesn't say anything about a BadDevice being returned either.
+     * So just quietly do nothing and pretend everything has worked.
+     */
     if (!keybd->kbdfeed->BellProc)
-        return BadDevice;
+        return Success;
 
     if (stuff->percent < -100 || stuff->percent > 100) {
 	client->errorValue = stuff->percent;
commit 240b10fa9c32510a380a73a8acdd8267c81e538b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 14 12:18:08 2007 +1030

    Xi: Move updating the device state from POE into separate function.
    
    POE now only deals with processing the event and calling the appropriate
    delivery methods. Actually modifying the device state is done in
    UpdateDeviceState. This separation should make it easier to avoid setting the
    state twice when master events are processed.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 511930b..f60f634 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -102,6 +102,210 @@ RegisterOtherDevice(DeviceIntPtr device)
     device->public.realInputProc = ProcessOtherEvent;
 }
 
+static void
+ChangeMasterDeviceClasses(DeviceIntPtr device,
+                          deviceClassesChangedEvent *dcce)
+{
+    DeviceIntPtr master = device->u.master;
+    char* classbuff;
+
+    if (device->isMaster)
+        return;
+
+    if (!master) /* if device was set floating between SIGIO and now */
+        return;
+
+    dcce->deviceid     = master->id;
+    dcce->num_classes  = 0;
+
+    master->key        = device->key;
+    master->valuator   = device->valuator;
+    master->button     = device->button;
+    master->focus      = device->focus;
+    master->proximity  = device->proximity;
+    master->absolute   = device->absolute;
+    master->kbdfeed    = device->kbdfeed;
+    master->ptrfeed    = device->ptrfeed;
+    master->intfeed    = device->intfeed;
+    master->stringfeed = device->stringfeed;
+    master->bell       = device->bell;
+    master->leds       = device->leds;
+
+    /* event is already correct size, see comment in GetPointerEvents */
+    classbuff = (char*)&dcce[1];
+    /* we don't actually swap if there's a NullClient, swapping is done
+     * later when event is delivered. */
+    CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff);
+    SendEventToAllWindows(master, XI_DeviceClassesChangedMask,
+                          (xEvent*)dcce, 1);
+}
+
+/**
+ * Update the device state according to the data in the event.
+ *
+ * return values are
+ *   DEFAULT ... process as normal
+ *   DONT_PROCESS ... return immediately from caller
+ *   IS_REPEAT .. event is a repeat event.
+ */
+#define DEFAULT 0
+#define DONT_PROCESS 1
+#define IS_REPEAT 2
+static int
+UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
+{
+    int i;
+    int key = 0,
+        bit = 0;
+
+    KeyClassPtr k       = device->key;
+    ButtonClassPtr b    = device->button;
+    ValuatorClassPtr v  = device->valuator;
+    deviceValuator *xV  = (deviceValuator *) xE;
+    BYTE *kptr          = NULL;
+    CARD16 modifiers    = 0,
+           mask         = 0;
+
+    /* This event is always the first we get, before the actual events with
+     * the data. However, the way how the DDX is set up, "device" will
+     * actually be the slave device that caused the event.
+     */
+    if (GEIsType(xE, IReqCode, XI_DeviceClassesChangedNotify))
+    {
+        ChangeMasterDeviceClasses(device, (deviceClassesChangedEvent*)xE);
+        return DONT_PROCESS; /* event has been sent already */
+    }
+
+    /* currently no other generic event modifies the device */
+    if (xE->u.u.type == GenericEvent)
+        return DEFAULT;
+
+    if (xE->u.u.type != DeviceValuator)
+    {
+        key = xE->u.u.detail;
+        bit = 1 << (key & 7);
+    }
+
+    /* Update device axis */
+    for (i = 1; i < count; i++) {
+	if ((++xV)->type == DeviceValuator) {
+	    int *axisvals;
+            int first = xV->first_valuator;
+
+	    if (xV->num_valuators &&
+                (!v || (xV->num_valuators &&
+                      (first + xV->num_valuators > v->numAxes))))
+		FatalError("Bad valuators reported for device %s\n",
+			   device->name);
+	    if (v && v->axisVal) {
+		axisvals = v->axisVal;
+		switch (xV->num_valuators) {
+		case 6:
+		    *(axisvals + first + 5) = xV->valuator5;
+		case 5:
+		    *(axisvals + first + 4) = xV->valuator4;
+		case 4:
+		    *(axisvals + first + 3) = xV->valuator3;
+		case 3:
+		    *(axisvals + first + 2) = xV->valuator2;
+		case 2:
+		    *(axisvals + first + 1) = xV->valuator1;
+		case 1:
+		    *(axisvals + first) = xV->valuator0;
+		case 0:
+		default:
+		    break;
+		}
+	    }
+	}
+    }
+
+    if (xE->u.u.type == DeviceKeyPress) {
+        if (!k)
+            return DONT_PROCESS;
+
+	modifiers = k->modifierMap[key];
+	kptr = &k->down[key >> 3];
+	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
+	    return IS_REPEAT;
+	}
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
+	*kptr |= bit;
+	k->prev_state = k->state;
+	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
+	    if (mask & modifiers) {
+		/* This key affects modifier "i" */
+		k->modifierKeyCount[i]++;
+		k->state |= mask;
+		modifiers &= ~mask;
+	    }
+	}
+    } else if (xE->u.u.type == DeviceKeyRelease) {
+        if (!k)
+            return DONT_PROCESS;
+
+	kptr = &k->down[key >> 3];
+	if (!(*kptr & bit))	/* guard against duplicates */
+	    return DONT_PROCESS;
+	modifiers = k->modifierMap[key];
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
+	*kptr &= ~bit;
+	k->prev_state = k->state;
+	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
+	    if (mask & modifiers) {
+		/* This key affects modifier "i" */
+		if (--k->modifierKeyCount[i] <= 0) {
+		    k->modifierKeyCount[i] = 0;
+		    k->state &= ~mask;
+		}
+		modifiers &= ~mask;
+	    }
+	}
+    } else if (xE->u.u.type == DeviceButtonPress) {
+        if (!b)
+            return DONT_PROCESS;
+
+	kptr = &b->down[key >> 3];
+	*kptr |= bit;
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
+        if (!device->isMaster)
+            b->buttonsDown++;
+	b->motionMask = DeviceButtonMotionMask;
+        if (!device->isMaster && !b->map[key]) /* bit already unset for MDs */
+            return DONT_PROCESS;
+        if (b->map[key] <= 5)
+	    b->state |= (Button1Mask >> 1) << b->map[key];
+	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
+    } else if (xE->u.u.type == DeviceButtonRelease) {
+        if (!b)
+            return DONT_PROCESS;
+
+	kptr = &b->down[key >> 3];
+        if (!(*kptr & bit))
+            return DONT_PROCESS;
+	*kptr &= ~bit;
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
+        if (!device->isMaster)
+            b->buttonsDown--;
+        if (b->buttonsDown >= 1 && !b->buttonsDown)
+	    b->motionMask = 0;
+        if (!b->map[key])
+            return DONT_PROCESS;
+	if (b->map[key] <= 5)
+	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
+	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
+    } else if (xE->u.u.type == ProximityIn)
+	device->valuator->mode &= ~OutOfProximity;
+    else if (xE->u.u.type == ProximityOut)
+	device->valuator->mode |= OutOfProximity;
+
+    return DEFAULT;
+}
+
 /**
  * Main device event processing function.
  * Called from when processing the events from the event queue.
@@ -113,61 +317,23 @@ RegisterOtherDevice(DeviceIntPtr device)
 void
 ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 {
-    BYTE *kptr;
     int i;
     CARD16 modifiers;
-    CARD16 mask;
     GrabPtr grab = device->deviceGrab.grab;
     Bool deactivateDeviceGrab = FALSE;
-    int key = 0, bit = 0, rootX, rootY;
+    int key = 0, rootX, rootY;
     ButtonClassPtr b = device->button;
     KeyClassPtr k = device->key;
-    ValuatorClassPtr v = device->valuator;
-    deviceValuator *xV = (deviceValuator *) xE;
+    ValuatorClassPtr v  = device->valuator;
+    deviceValuator *xV  = (deviceValuator *) xE;
     BOOL sendCore = FALSE;
     xEvent core;
     int coretype = 0;
+    int ret = 0;
 
-    /* This event is always the first we get, before the actual events with
-     * the data. However, the way how the DDX is set up, "device" will
-     * actually be the slave device that caused the event.
-     */
-    if (GEIsType(xE, IReqCode, XI_DeviceClassesChangedNotify))
-    {
-        deviceClassesChangedEvent* dcce = (deviceClassesChangedEvent*)xE;
-        DeviceIntPtr master = device->u.master;
-        char* classbuff;
-
-        if (device->isMaster)
-            return;
-
-        if (!master) /* if device was set floating between SIGIO and now */
-            return;
-
-        dcce->deviceid     = master->id;
-        dcce->num_classes  = 0;
-
-        master->key        = device->key;
-        master->valuator   = device->valuator;
-        master->button     = device->button;
-        master->focus      = device->focus;
-        master->proximity  = device->proximity;
-        master->absolute   = device->absolute;
-        master->kbdfeed    = device->kbdfeed;
-        master->ptrfeed    = device->ptrfeed;
-        master->intfeed    = device->intfeed;
-        master->stringfeed = device->stringfeed;
-        master->bell       = device->bell;
-        master->leds       = device->leds;
-
-        /* event is already correct size, see comment in GetPointerEvents */
-        classbuff = (char*)&xE[1];
-        /* we don't actually swap if there's a NullClient, swapping is done
-         * later when event is delivered. */
-        CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff);
-        SendEventToAllWindows(master, XI_DeviceClassesChangedMask, xE, 1);
+    ret = UpdateDeviceState(device, xE, count);
+    if (ret == DONT_PROCESS)
         return;
-    }
 
     coretype = XItoCoreType(xE->u.u.type);
     if (device->isMaster && device->coreEvents && coretype)
@@ -181,7 +347,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	GetSpritePosition(device, &rootX, &rootY);
 	xE->u.keyButtonPointer.rootX = rootX;
 	xE->u.keyButtonPointer.rootY = rootY;
-	key = xE->u.u.detail;
 	NoticeEventTime(xE);
 
         /* If 'device' is a pointer device, we need to get the paired keyboard
@@ -202,7 +367,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
         xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0;
         xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0;
 
-	bit = 1 << (key & 7);
+        key = xE->u.u.detail;
     }
     if (DeviceEventCallback) {
 	DeviceEventInfoRec eventinfo;
@@ -211,11 +376,11 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	eventinfo.count = count;
 	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
     }
-    for (i = 1; i < count; i++)
+
+    /* Valuator event handling */
+    for (i = 1; i < count; i++) {
 	if ((++xV)->type == DeviceValuator) {
 	    int first = xV->first_valuator;
-	    int *axisvals;
-
 	    if (xV->num_valuators
 		&& (!v
 		    || (xV->num_valuators
@@ -227,35 +392,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 		xV->device_state |= k->state;
 	    if (b)
 		xV->device_state |= b->state;
-	    if (v && v->axisVal) {
-		axisvals = v->axisVal;
-		switch (xV->num_valuators) {
-		case 6:
-		    *(axisvals + first + 5) = xV->valuator5;
-		case 5:
-		    *(axisvals + first + 4) = xV->valuator4;
-		case 4:
-		    *(axisvals + first + 3) = xV->valuator3;
-		case 3:
-		    *(axisvals + first + 2) = xV->valuator2;
-		case 2:
-		    *(axisvals + first + 1) = xV->valuator1;
-		case 1:
-		    *(axisvals + first) = xV->valuator0;
-		case 0:
-		default:
-		    break;
-		}
-	    }
 	}
+    }
 
     if (xE->u.u.type == DeviceKeyPress) {
-        if (!k)
-            return;
-
-	modifiers = k->modifierMap[key];
-	kptr = &k->down[key >> 3];
-	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
+        if (ret == IS_REPEAT) {	/* allow ddx to generate multiple downs */
+            modifiers = k->modifierMap[key];
 	    if (!modifiers) {
 		xE->u.u.type = DeviceKeyRelease;
 		ProcessOtherEvent(xE, device, count);
@@ -265,18 +407,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	    }
 	    return;
 	}
-	if (device->valuator)
-	    device->valuator->motionHintWindow = NullWindow;
-	*kptr |= bit;
-	k->prev_state = k->state;
-	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
-	    if (mask & modifiers) {
-		/* This key affects modifier "i" */
-		k->modifierKeyCount[i]++;
-		k->state |= mask;
-		modifiers &= ~mask;
-	    }
-	}
         /* XI grabs have priority */
         core = *xE;
         core.u.u.type = coretype;
@@ -287,47 +417,13 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	    return;
 	}
     } else if (xE->u.u.type == DeviceKeyRelease) {
-        if (!k)
-            return;
-
-	kptr = &k->down[key >> 3];
-	if (!(*kptr & bit))	/* guard against duplicates */
-	    return;
-	modifiers = k->modifierMap[key];
-	if (device->valuator)
-	    device->valuator->motionHintWindow = NullWindow;
-	*kptr &= ~bit;
-	k->prev_state = k->state;
-	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
-	    if (mask & modifiers) {
-		/* This key affects modifier "i" */
-		if (--k->modifierKeyCount[i] <= 0) {
-		    k->modifierKeyCount[i] = 0;
-		    k->state &= ~mask;
-		}
-		modifiers &= ~mask;
-	    }
-	}
-
 	if (device->deviceGrab.fromPassiveGrab &&
             (key == device->deviceGrab.activatingKey))
 	    deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == DeviceButtonPress) {
-        if (!b)
-            return;
-
-	kptr = &b->down[key >> 3];
-	*kptr |= bit;
-	if (device->valuator)
-	    device->valuator->motionHintWindow = NullWindow;
-	b->buttonsDown++;
-	b->motionMask = DeviceButtonMotionMask;
 	xE->u.u.detail = b->map[key];
 	if (xE->u.u.detail == 0)
 	    return;
-	if (xE->u.u.detail <= 5)
-	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
-	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
         if (!grab)
         {
             core = *xE;
@@ -342,28 +438,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
         }
 
     } else if (xE->u.u.type == DeviceButtonRelease) {
-        if (!b)
-            return;
-
-	kptr = &b->down[key >> 3];
-	*kptr &= ~bit;
-	if (device->valuator)
-	    device->valuator->motionHintWindow = NullWindow;
-        if (b->buttonsDown >= 1 && !--b->buttonsDown)
-	    b->motionMask = 0;
 	xE->u.u.detail = b->map[key];
 	if (xE->u.u.detail == 0)
 	    return;
-	if (xE->u.u.detail <= 5)
-	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
-	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
-        if (!b->state
-            && device->deviceGrab.fromPassiveGrab)
+        if (!b->state && device->deviceGrab.fromPassiveGrab)
             deactivateDeviceGrab = TRUE;
-    } else if (xE->u.u.type == ProximityIn)
-	device->valuator->mode &= ~OutOfProximity;
-    else if (xE->u.u.type == ProximityOut)
-	device->valuator->mode |= OutOfProximity;
+    }
 
     if (sendCore)
     {
commit 0bdfeb55fc559ffe0334df69ba6e9e711b26dc18
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 13 17:31:20 2007 +1030

    Xi: remove RegisterPairingClient handling. Deprecated with device hierarchy.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 407928d..9c5658d 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -76,8 +76,6 @@ libXi_la_SOURCES =	\
 	queryst.h \
 	qryacces.c \
 	qryacces.h \
-	regpair.c \
-	regpair.h \
 	selectev.c \
 	selectev.h \
 	sendexev.c \
diff --git a/Xi/extinit.c b/Xi/extinit.c
index aed0083..07ef266 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -109,7 +109,6 @@ SOFTWARE.
 #include "qryacces.c"
 #include "querydp.h"
 #include "queryst.h"
-#include "regpair.h"
 #include "selectev.h"
 #include "sendexev.h"
 #include "chgkmap.h"
@@ -329,8 +328,6 @@ ProcIDispatch(ClientPtr client)
         return (ProcXChangeDeviceHierarchy(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)
         return (ProcXGrabAccessControl(client));
     else if (stuff->data == X_ChangeWindowAccess)
@@ -446,8 +443,6 @@ SProcIDispatch(ClientPtr client)
         return (SProcXChangeDeviceHierarchy(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)
         return (SProcXGrabAccessControl(client));
     else if (stuff->data == X_ChangeWindowAccess)
@@ -539,9 +534,6 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
     else if (rep->RepType == X_QueryDevicePointer)
 	SRepXQueryDevicePointer(client, len,
 				(xQueryDevicePointerReply *) rep);
-    else if (rep->RepType == X_RegisterPairingClient)
-	SRepXRegisterPairingClient(client, len,
-				  (xRegisterPairingClientReply *) rep);
     else if (rep->RepType == X_GrabAccessControl)
         SRepXGrabAccessControl(client, len,
                                   (xGrabAccessControlReply*) rep);
diff --git a/Xi/regpair.c b/Xi/regpair.c
deleted file mode 100644
index 3fe4591..0000000
--- a/Xi/regpair.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-
-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 authenticate as pairing client
- *
- */
-
-#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 <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "extnsionst.h"
-#include "exevents.h"
-#include "exglobals.h"
-
-#include "regpair.h"
-
-/***********************************************************************
- *
- * This procedure allows a client to register the pairing of a pointer
- * with a keyboard.
- *
- */
-
-int
-SProcXRegisterPairingClient(ClientPtr client)
-{
-    char n;
-    REQUEST(xRegisterPairingClientReq);
-    swaps(&stuff->length, n);
-    return ProcXRegisterPairingClient(client);
-}
-
-int
-ProcXRegisterPairingClient(ClientPtr client)
-{
-    xRegisterPairingClientReply rep;
-
-    REQUEST(xRegisterPairingClientReq);
-    REQUEST_SIZE_MATCH(xRegisterPairingClientReq);
-
-    if (stuff->disable)
-        UnregisterPairingClient(client);
-
-    rep.repType = X_Reply;
-    rep.RepType = X_RegisterPairingClient;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-    rep.success = stuff->disable || RegisterPairingClient(client);
-
-    WriteReplyToClient(client, sizeof(xRegisterPairingClientReply), &rep);
-    return Success;
-}
-
-/***********************************************************************
- *
- * This procedure writes the reply for the XRegisterPairingClient function,
- * if the client and server have a different byte ordering.
- *
- */
-
-void
-SRepXRegisterPairingClient(ClientPtr client, int size,
-        xRegisterPairingClientReply* rep)
-{
-    register char n;
-
-    swaps(&rep->sequenceNumber, n);
-    swapl(&rep->length, n);
-    WriteToClient(client, size, (char *)rep);
-}
-
diff --git a/Xi/regpair.h b/Xi/regpair.h
deleted file mode 100644
index b2bfaff..0000000
--- a/Xi/regpair.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-
-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 REGPAIR_H
-#define REGPAIR_H 1
-
-int SProcXRegisterPairingClient(ClientPtr /* client */);
-int ProcXRegisterPairingClient(ClientPtr /* client */);
-
-void SRepXRegisterPairingClient(ClientPtr /* client */, 
-                                int /* size */,
-                                xRegisterPairingClientReply* /* rep */);
-
-#endif /* REGPAIR_H */
commit e96d926d64f7fb63f6bf2aa0ea0a8440a188947b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 13 17:14:35 2007 +1030

    Xi: remove trailing whitespaces.

diff --git a/Xi/chaccess.c b/Xi/chaccess.c
index 2a0e5fa..9baa871 100644
--- a/Xi/chaccess.c
+++ b/Xi/chaccess.c
@@ -50,9 +50,9 @@ from the author.
  * This procedure allows a client to change window access control.
  */
 
-int 
+int
 SProcXChangeWindowAccess(ClientPtr client)
-{    
+{
     char n;
     REQUEST(xChangeWindowAccessReq);
 
@@ -61,7 +61,7 @@ SProcXChangeWindowAccess(ClientPtr client)
     return ProcXChangeWindowAccess(client);
 }
 
-int 
+int
 ProcXChangeWindowAccess(ClientPtr client)
 {
     int padding, err, i;
@@ -71,14 +71,14 @@ ProcXChangeWindowAccess(ClientPtr client)
     DeviceIntPtr* deny_devices = NULL;
     REQUEST(xChangeWindowAccessReq);
     REQUEST_AT_LEAST_SIZE(xChangeWindowAccessReq);
-    
+
 
     padding = (4 - (((stuff->npermit + stuff->ndeny) * sizeof(XID)) % 4)) % 4;
 
-    if (stuff->length != ((sizeof(xChangeWindowAccessReq)  + 
+    if (stuff->length != ((sizeof(xChangeWindowAccessReq)  +
             (((stuff->npermit + stuff->ndeny) * sizeof(XID)) + padding)) >> 2))
     {
-        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
+        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
                 0, BadLength);
         return Success;
     }
@@ -87,7 +87,7 @@ ProcXChangeWindowAccess(ClientPtr client)
     err = dixLookupWindow(&win, stuff->win, client, DixWriteAccess);
     if (err != Success)
     {
-        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
+        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
                           stuff->win, err);
         return Success;
     }
@@ -106,12 +106,12 @@ ProcXChangeWindowAccess(ClientPtr client)
 
     if (stuff->npermit)
     {
-        perm_devices = 
+        perm_devices =
             (DeviceIntPtr*)xalloc(stuff->npermit * sizeof(DeviceIntPtr));
         if (!perm_devices)
         {
             ErrorF("[Xi] ProcXChangeWindowAccess: alloc failure.\n");
-            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, 
+            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0,
                     BadImplementation);
             return Success;
         }
@@ -123,8 +123,8 @@ ProcXChangeWindowAccess(ClientPtr client)
             if (!perm_devices[i])
             {
                 xfree(perm_devices);
-                SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
-                        deviceids[i], BadDevice); 
+                SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
+                        deviceids[i], BadDevice);
                 return Success;
             }
         }
@@ -132,12 +132,12 @@ ProcXChangeWindowAccess(ClientPtr client)
 
     if (stuff->ndeny)
     {
-        deny_devices = 
+        deny_devices =
             (DeviceIntPtr*)xalloc(stuff->ndeny * sizeof(DeviceIntPtr));
         if (!deny_devices)
         {
             ErrorF("[Xi] ProcXChangeWindowAccecss: alloc failure.\n");
-            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, 
+            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0,
                     BadImplementation);
 
             xfree(perm_devices);
@@ -146,15 +146,15 @@ ProcXChangeWindowAccess(ClientPtr client)
 
         for (i = 0; i < stuff->ndeny; i++)
         {
-            deny_devices[i] = 
+            deny_devices[i] =
                 LookupDeviceIntRec(deviceids[i+stuff->npermit]);
-            
+
             if (!deny_devices[i])
             {
                 xfree(perm_devices);
                 xfree(deny_devices);
-                SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
-                        deviceids[i + stuff->npermit], BadDevice); 
+                SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
+                        deviceids[i + stuff->npermit], BadDevice);
                 return Success;
             }
         }
@@ -165,11 +165,11 @@ ProcXChangeWindowAccess(ClientPtr client)
                                deny_devices, stuff->ndeny);
     if (err != Success)
     {
-        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
+        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess,
                           stuff->win, err);
         return Success;
     }
-    
+
     xfree(perm_devices);
     xfree(deny_devices);
     return Success;
diff --git a/Xi/chdevcur.c b/Xi/chdevcur.c
index e69a266..dfa45ee 100644
--- a/Xi/chdevcur.c
+++ b/Xi/chdevcur.c
@@ -82,7 +82,7 @@ int ProcXChangeDeviceCursor(ClientPtr client)
     pDev = LookupDeviceIntRec(stuff->deviceid);
     if (pDev == NULL) {
         SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 0,
-                BadDevice); 
+                BadDevice);
         return Success;
     }
 
@@ -91,7 +91,7 @@ int ProcXChangeDeviceCursor(ClientPtr client)
         err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
         if (err != Success)
         {
-            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 
+            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor,
                     stuff->win, err);
             return Success;
         }
@@ -103,18 +103,18 @@ int ProcXChangeDeviceCursor(ClientPtr client)
             pCursor = rootCursor;
         else
             pCursor = (CursorPtr)None;
-    } 
-    else 
+    }
+    else
     {
         pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
-                                RT_CURSOR, DixReadAccess); 
+                                RT_CURSOR, DixReadAccess);
         if (!pCursor)
         {
-            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 
+            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor,
                     stuff->cursor, BadCursor);
             return Success;
         }
-    } 
+    }
 
     ChangeWindowDeviceCursor(pWin, pDev, pCursor);
 
diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
index 338c074..ac912f7 100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@ -90,7 +90,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
 
     /* XXX: check if client is allowed to change hierarch */
 
-    
+
     any = (xAnyHierarchyChangeInfo*)&stuff[1];
     while(stuff->num_changes--)
     {
@@ -108,7 +108,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                     xCreateMasterInfo* c = (xCreateMasterInfo*)any;
                     char* name;
                     int ret;
-                    
+
                     SWAPIF(swaps(&c->namelen, n));
                     name = xcalloc(c->namelen + 1, sizeof(char));
                     strncpy(name, (char*)&c[1], c->namelen);
@@ -138,7 +138,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                 {
                     xRemoveMasterInfo* r = (xRemoveMasterInfo*)any;
 
-                    if (r->returnMode != AttachToMaster && 
+                    if (r->returnMode != AttachToMaster &&
                             r->returnMode != Floating)
                         return BadValue;
 
@@ -164,8 +164,8 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                      * desired. */
                     if (r->returnMode == AttachToMaster)
                     {
-                        DeviceIntPtr attached, 
-                                     newptr, 
+                        DeviceIntPtr attached,
+                                     newptr,
                                      newkeybd;
 
                         newptr = LookupDeviceIntRec(r->returnPointer);
@@ -174,8 +174,8 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                                 !newkeybd || !newkeybd->isMaster)
                             return BadDevice;
 
-                        for (attached = inputInfo.devices; 
-                                attached; 
+                        for (attached = inputInfo.devices;
+                                attached;
                                 attached = attached->next)
                         {
                             if (!attached->isMaster) {
@@ -216,7 +216,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
                         if ((IsPointerDevice(newmaster) &&
                                     !IsPointerDevice(ptr)) ||
                                 (IsKeyboardDevice(newmaster) &&
-                                 !IsKeyboardDevice(ptr))) 
+                                 !IsKeyboardDevice(ptr)))
                                 return BadDevice;
                         AttachDevice(client, ptr, newmaster);
                     }
@@ -234,7 +234,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
     ev.evtype = XI_DeviceHierarchyChangedNotify;
     ev.time = GetTimeInMillis();
 
-    SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask, 
+    SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask,
             (xEvent*)&ev, 1);
     return Success;
 }
diff --git a/Xi/chpkpair.c b/Xi/chpkpair.c
index db8e7f6..c44a263 100644
--- a/Xi/chpkpair.c
+++ b/Xi/chpkpair.c
@@ -77,7 +77,7 @@ ProcXChangePointerKeyboardPairing(ClientPtr client)
 {
     DeviceIntPtr pPointer, pKeyboard;
     int ret;
-    pairingChangedNotify ev; 
+    pairingChangedNotify ev;
 
     REQUEST(xChangePointerKeyboardPairingReq);
     REQUEST_SIZE_MATCH(xChangePointerKeyboardPairingReq);
@@ -87,16 +87,16 @@ ProcXChangePointerKeyboardPairing(ClientPtr client)
     pPointer = LookupDeviceIntRec(stuff->pointer);
     if (pPointer == NULL)
     {
-        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing, 
-                stuff->pointer, BadDevice); 
+        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing,
+                stuff->pointer, BadDevice);
         return Success;
     }
 
     pKeyboard = LookupDeviceIntRec(stuff->keyboard);
     if (pKeyboard == NULL)
     {
-        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing, 
-                stuff->keyboard, BadDevice); 
+        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing,
+                stuff->keyboard, BadDevice);
         return Success;
     }
 
@@ -116,15 +116,15 @@ ProcXChangePointerKeyboardPairing(ClientPtr client)
     ev.keyboard = pKeyboard->id;
     ev.length = 0;
     ev.time = currentTime.milliseconds;
-    SendEventToAllWindows(inputInfo.pointer, 
+    SendEventToAllWindows(inputInfo.pointer,
             XI_PointerKeyboardPairingChangedMask,
             (xEvent*)&ev, 1);
     return Success;
 }
 
 /* Event swap proc */
-void 
-SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify *from, 
+void
+SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify *from,
                                                 pairingChangedNotify *to)
 {
     char n;
diff --git a/Xi/closedev.c b/Xi/closedev.c
index cd6e537..f9a0f4f 100644
--- a/Xi/closedev.c
+++ b/Xi/closedev.c
@@ -154,7 +154,7 @@ ProcXCloseDevice(ClientPtr client)
     if (d->deviceGrab.grab && SameClient(d->deviceGrab.grab, client))
 	(*d->deviceGrab.DeactivateGrab) (d);	/* release active grab */
 
-    /* Remove event selections from all windows for events from this device 
+    /* Remove event selections from all windows for events from this device
      * and selected by this client.
      * Delete passive grabs from all windows for this device.      */
 
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 3ef3200..511930b 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -103,10 +103,10 @@ RegisterOtherDevice(DeviceIntPtr device)
 }
 
 /**
- * Main device event processing function. 
- * Called from when processing the events from the event queue. 
+ * Main device event processing function.
+ * Called from when processing the events from the event queue.
  * Generates core events for XI events as needed.
- * 
+ *
  * Note that these core events are then delivered first. For passive grabs, XI
  * events have preference over core.
  */
@@ -309,7 +309,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	    }
 	}
 
-	if (device->deviceGrab.fromPassiveGrab && 
+	if (device->deviceGrab.fromPassiveGrab &&
             (key == device->deviceGrab.activatingKey))
 	    deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == DeviceButtonPress) {
@@ -357,7 +357,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	if (xE->u.u.detail <= 5)
 	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
-        if (!b->state 
+        if (!b->state
             && device->deviceGrab.fromPassiveGrab)
             deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == ProximityIn)
@@ -413,7 +413,7 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
 		       int resolution, int min_res, int max_res)
 {
     AxisInfoPtr ax;
-   
+  
     if (!dev || !dev->valuator)
         return;
 
@@ -1122,7 +1122,7 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
     if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
 	(*dev->deviceGrab.DeactivateGrab) (dev);
 
-    /* If the focus window is a root window (ie. has no parent) 
+    /* If the focus window is a root window (ie. has no parent)
      * then don't delete the focus from it. */
 
     if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
index c4011f5..7cafdba 100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@ -55,7 +55,7 @@ from the author.
 
 #include "extgrbdev.h"
 
-int 
+int
 SProcXExtendedGrabDevice(ClientPtr client)
 {
     char        n;
@@ -89,15 +89,15 @@ SProcXExtendedGrabDevice(ClientPtr client)
 }
 
 
-int 
+int
 ProcXExtendedGrabDevice(ClientPtr client)
 {
     xExtendedGrabDeviceReply rep;
     DeviceIntPtr             dev;
-    int                      err = Success, 
+    int                      err = Success,
                              errval = 0,
                              i;
-    WindowPtr                grab_window, 
+    WindowPtr                grab_window,
                              confineTo = 0;
     CursorPtr                cursor = NULL;
     struct tmask             tmp[EMASKSIZE];
@@ -119,7 +119,7 @@ ProcXExtendedGrabDevice(ClientPtr client)
     rep.length          = 0;
 
     if (!stuff->ungrab && /* other fields are undefined for ungrab */
-            (stuff->length != (sizeof(xExtendedGrabDeviceReq) >> 2) + 
+            (stuff->length != (sizeof(xExtendedGrabDeviceReq) >> 2) +
             stuff->event_count + 2 * stuff->generic_event_count))
     {
         errval = 0;
@@ -141,21 +141,21 @@ ProcXExtendedGrabDevice(ClientPtr client)
         goto cleanup;
     }
 
-    err = dixLookupWindow(&grab_window, 
-                          stuff->grab_window, 
-                          client, 
+    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, 
+        err = dixLookupWindow(&confineTo,
+                              stuff->confine_to,
+                              client,
                               DixReadAccess);
         if (err != Success)
         {
@@ -166,10 +166,10 @@ ProcXExtendedGrabDevice(ClientPtr client)
 
     if (stuff->cursor)
     {
-        cursor = (CursorPtr)SecurityLookupIDByType(client, 
+        cursor = (CursorPtr)SecurityLookupIDByType(client,
                                                     stuff->cursor,
-                                                    RT_CURSOR, 
-                                                    DixReadAccess); 
+                                                    RT_CURSOR,
+                                                    DixReadAccess);
         if (!cursor)
         {
             errval = stuff->cursor;
@@ -178,11 +178,11 @@ ProcXExtendedGrabDevice(ClientPtr client)
         }
     }
 
-    if (CreateMaskFromList(client, 
+    if (CreateMaskFromList(client,
                            (XEventClass*)&stuff[1],
-                           stuff->event_count, 
-                           tmp, 
-                           dev, 
+                           stuff->event_count,
+                           tmp,
+                           dev,
                            X_GrabDevice) != Success)
         return Success;
 
@@ -190,7 +190,7 @@ ProcXExtendedGrabDevice(ClientPtr client)
 
     if (stuff->generic_event_count)
     {
-        xgeMask = 
+        xgeMask =
             (XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
 
         gemasks = xcalloc(1, sizeof(GenericMaskRec));
@@ -203,16 +203,16 @@ ProcXExtendedGrabDevice(ClientPtr client)
             gemasks->eventMask[xgeMask->extension & 0x7F]= xgeMask->evmask;
     }
 
-    ExtGrabDevice(client, dev, stuff->device_mode, 
-                  grab_window, confineTo, time, stuff->owner_events, 
-                  cursor, tmp[stuff->deviceid].mask, 
+    ExtGrabDevice(client, dev, stuff->device_mode,
+                  grab_window, confineTo, time, stuff->owner_events,
+                  cursor, tmp[stuff->deviceid].mask,
                   gemasks);
 
     if (err != Success) {
         errval = 0;
         goto cleanup;
     }
-    
+
 cleanup:
 
     if (gemasks)
@@ -221,18 +221,18 @@ cleanup:
     if (err == Success)
     {
         WriteReplyToClient(client, sizeof(xGrabDeviceReply), &rep);
-    } 
-    else 
+    }
+    else
     {
-        SendErrorToClient(client, IReqCode, 
-                          X_ExtendedGrabDevice, 
+        SendErrorToClient(client, IReqCode,
+                          X_ExtendedGrabDevice,
                           errval, err);
     }
     return Success;
 }
 
 void
-SRepXExtendedGrabDevice(ClientPtr client, int size, 
+SRepXExtendedGrabDevice(ClientPtr client, int size,
                         xExtendedGrabDeviceReply* rep)
 {
     char n;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 017b693..aed0083 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -133,7 +133,7 @@ Mask ExtExclusiveMasks[EMASKSIZE];
 
 
 /**
- * Filters for various generic events. 
+ * Filters for various generic events.
  * Evtype is index, mask is value at index.
  */
 static Mask xi_filters[3] = {
@@ -355,7 +355,7 @@ ProcIDispatch(ClientPtr client)
 
 /*******************************************************************************
  *
- * SProcXDispatch 
+ * SProcXDispatch
  *
  * Main swapped dispatch routine for requests to this extension.
  * This routine is used if server and client do not have the same byte ordering.
@@ -659,7 +659,7 @@ SDevicePresenceNotifyEvent (devicePresenceNotify *from, devicePresenceNotify *to
     swaps(&to->control, n);
 }
 
-static void 
+static void
 SDeviceEnterNotifyEvent (deviceEnterNotify *from, deviceEnterNotify *to)
 {
     char n;
@@ -669,7 +669,7 @@ SDeviceEnterNotifyEvent (deviceEnterNotify *from, deviceEnterNotify *to)
     swapl(&to->time, n);
 }
 
-static void 
+static void
 SDeviceLeaveNotifyEvent (deviceLeaveNotify *from, deviceLeaveNotify *to)
 {
     char n;
@@ -692,7 +692,7 @@ SRawDeviceEvent(rawDeviceEvent* from, rawDeviceEvent *to)
     char n;
     int i;
     CARD32* valptr;
-    
+   
 
     *to = *from;
     swaps(&to->sequenceNumber, n);
@@ -704,7 +704,7 @@ SRawDeviceEvent(rawDeviceEvent* from, rawDeviceEvent *to)
 }
 
 static void
-SDeviceClassesChangedEvent(deviceClassesChangedEvent* from, 
+SDeviceClassesChangedEvent(deviceClassesChangedEvent* from,
                            deviceClassesChangedEvent* to)
 {
     char n;
@@ -717,7 +717,7 @@ SDeviceClassesChangedEvent(deviceClassesChangedEvent* from,
     swaps(&to->sequenceNumber, n);
     swapl(&to->length, n);
     swapl(&to->time, n);
-    
+   
     /* now swap the actual classes */
     any = (xAnyClassPtr)&to[1];
     for (i = 0; i < to->num_classes; i++)
@@ -796,7 +796,7 @@ GetNextExtEventMask(void)
  *
  * Since extension event types will never be less than 64, we can use
  * 0-63 in the EventInfo array as the "type" to be used to look up this
- * mask.  This means that the corresponding macros such as 
+ * mask.  This means that the corresponding macros such as
  * DevicePointerMotionHint must have access to the same constants.
  *
  */
@@ -973,7 +973,7 @@ FixExtensionEvents(ExtensionEntry * extEntry)
 
 /************************************************************************
  *
- * This function restores extension event types and masks to their 
+ * This function restores extension event types and masks to their
  * initial state.
  *
  */
@@ -1189,7 +1189,7 @@ SEventIDispatch(xEvent * from, xEvent * to)
  * EventSwap for generic events coming from the GE extension.
  */
 
-static void 
+static void
 XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
 {
     int n;
@@ -1201,7 +1201,7 @@ XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
             SRawDeviceEvent((rawDeviceEvent*)from, (rawDeviceEvent*)to);
             break;
         case XI_DeviceClassesChangedNotify:
-            SDeviceClassesChangedEvent((deviceClassesChangedEvent*)from, 
+            SDeviceClassesChangedEvent((deviceClassesChangedEvent*)from,
                                        (deviceClassesChangedEvent*)to);
             break;
     }
@@ -1211,8 +1211,8 @@ XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
  * EventFill to fill various fields for events before they are delivered to
  * the client.
  */
-static void 
-XIGEEventFill(xGenericEvent* ev, DeviceIntPtr pDev, 
+static void
+XIGEEventFill(xGenericEvent* ev, DeviceIntPtr pDev,
               WindowPtr pWin, GrabPtr grab)
 {
 }
diff --git a/Xi/fakedevdata.c b/Xi/fakedevdata.c
index 64f2ea6..2ebb7c3 100644
--- a/Xi/fakedevdata.c
+++ b/Xi/fakedevdata.c
@@ -74,7 +74,7 @@ SProcXFakeDeviceData(ClientPtr client)
     return ProcXFakeDeviceData(client);;
 }
 
-int 
+int
 ProcXFakeDeviceData(ClientPtr client)
 {
     DeviceIntPtr dev;
@@ -92,7 +92,7 @@ ProcXFakeDeviceData(ClientPtr client)
 
     dev = LookupDeviceIntRec(stuff->deviceid);
     if (dev == NULL) {
-        SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadDevice); 
+        SendErrorToClient(client, IReqCode, X_FakeDeviceData, 0, BadDevice);
         return Success;
     }
 
diff --git a/Xi/getcptr.c b/Xi/getcptr.c
index d9ca4d3..ba69f9c 100644
--- a/Xi/getcptr.c
+++ b/Xi/getcptr.c
@@ -74,8 +74,8 @@ int ProcXGetClientPointer(ClientPtr client)
     err = dixLookupWindow(&win, stuff->win, client, DixReadAccess);
     if (err != Success)
     {
-        SendErrorToClient(client, IReqCode, X_GetClientPointer, 
-                stuff->win, err); 
+        SendErrorToClient(client, IReqCode, X_GetClientPointer,
+                stuff->win, err);
         return Success;
     }
 
@@ -99,8 +99,8 @@ int ProcXGetClientPointer(ClientPtr client)
  *
  */
 
-void 
-SRepXGetClientPointer(ClientPtr client, int size, 
+void
+SRepXGetClientPointer(ClientPtr client, int size,
         xGetClientPointerReply* rep)
 {
     char n;
diff --git a/Xi/grabacc.c b/Xi/grabacc.c
index 59888ee..83b8736 100644
--- a/Xi/grabacc.c
+++ b/Xi/grabacc.c
@@ -62,7 +62,7 @@ SProcXGrabAccessControl(ClientPtr client)
     return ProcXGrabAccessControl(client);
 }
 
-int 
+int
 ProcXGrabAccessControl(ClientPtr client)
 {
     xGrabAccessControlReply rep;
@@ -90,7 +90,7 @@ ProcXGrabAccessControl(ClientPtr client)
  */
 
 void
-SRepXGrabAccessControl(ClientPtr client, int size, 
+SRepXGrabAccessControl(ClientPtr client, int size,
         xGrabAccessControlReply* rep)
 {
     char n;
diff --git a/Xi/grabdev.c b/Xi/grabdev.c
index 16f4b7e..a963aa4 100644
--- a/Xi/grabdev.c
+++ b/Xi/grabdev.c
@@ -147,12 +147,12 @@ ProcXGrabDevice(ClientPtr client)
  *
  * This procedure creates an event mask from a list of XEventClasses.
  *
- * Procedure is as follows: 
+ * 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. 
- * If an error occurs, it is sent to the client. Errors are generated if 
+ * event mask for the given event type was.
+ * If an error occurs, it is sent to the client. Errors are generated if
  *  - if the device given in the event classs is invalid
  *  - if the device in the class list is not the device given as parameter (no
  *  error if parameter is NULL)
diff --git a/Xi/listdev.c b/Xi/listdev.c
index 1810c9b..a0be219 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -186,7 +186,7 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
         dev->use = IsXExtensionPointer;
     else
 	dev->use = IsXExtensionDevice;
-    if (!d->isMaster) 
+    if (!d->isMaster)
         dev->attached = (d->u.master) ? d->u.master->id : IsFloating;
 
     if (client->swapped) {
@@ -225,7 +225,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
  *
  * Devices may have up to 255 valuators.  The length of a ValuatorClass is
  * defined to be sizeof(ValuatorClassInfo) + num_axes * sizeof (xAxisInfo).
- * The maximum length is therefore (8 + 255 * 12) = 3068.  However, the 
+ * The maximum length is therefore (8 + 255 * 12) = 3068.  However, the
  * length field is one byte.  If a device has more than 20 valuators, we
  * must therefore return multiple valuator classes to the client.
  *
diff --git a/Xi/qryacces.c b/Xi/qryacces.c
index 95f2dd0..673028c 100644
--- a/Xi/qryacces.c
+++ b/Xi/qryacces.c
@@ -78,8 +78,8 @@ ProcXQueryWindowAccess(ClientPtr client)
     err = dixLookupWindow(&win, stuff->win, client, DixReadAccess);
     if (err != Success)
     {
-        SendErrorToClient(client, IReqCode, X_QueryWindowAccess, 
-                          stuff->win, err); 
+        SendErrorToClient(client, IReqCode, X_QueryWindowAccess,
+                          stuff->win, err);
         return Success;
     }
 
@@ -100,8 +100,8 @@ ProcXQueryWindowAccess(ClientPtr client)
         if (!deviceids)
         {
             ErrorF("[Xi] ProcXQueryWindowAccess: xalloc failure.\n");
-            SendErrorToClient(client, IReqCode, X_QueryWindowAccess, 
-                    0, BadImplementation); 
+            SendErrorToClient(client, IReqCode, X_QueryWindowAccess,
+                    0, BadImplementation);
             return Success;
         }
 
@@ -117,8 +117,8 @@ ProcXQueryWindowAccess(ClientPtr client)
 }
 
 void
-SRepXQueryWindowAccess(ClientPtr client, 
-                      int size, 
+SRepXQueryWindowAccess(ClientPtr client,
+                      int size,
                       xQueryWindowAccessReply* rep)
 {
     char n;
diff --git a/Xi/querydp.c b/Xi/querydp.c
index 6224f13..85b4802 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -86,14 +86,14 @@ ProcXQueryDevicePointer(ClientPtr client)
     pDev = LookupDeviceIntRec(stuff->deviceid);
     if (pDev == NULL || pDev->valuator == NULL) {
         SendErrorToClient(client, IReqCode, X_QueryDevicePointer,
-                stuff->deviceid, BadDevice); 
+                stuff->deviceid, BadDevice);
         return Success;
     }
 
     rc = dixLookupWindow(&pWin, stuff->win, client, DixReadAccess);
     if (rc != Success)
     {
-        SendErrorToClient(client, IReqCode, X_QueryDevicePointer, 
+        SendErrorToClient(client, IReqCode, X_QueryDevicePointer,
                 stuff->win, rc);
         return Success;
     }
@@ -111,7 +111,7 @@ ProcXQueryDevicePointer(ClientPtr client)
     rep.rootX = pSprite->hot.x;
     rep.rootY = pSprite->hot.y;
     rep.child = None;
-    rep.shared = (pDev->spriteInfo->spriteOwner) ? xFalse : xTrue; 
+    rep.shared = (pDev->spriteInfo->spriteOwner) ? xFalse : xTrue;
 
     if (pSprite->hot.pScreen == pWin->drawable.pScreen)
     {
@@ -155,7 +155,7 @@ ProcXQueryDevicePointer(ClientPtr client)
  */
 
 void
-SRepXQueryDevicePointer(ClientPtr client, int size, 
+SRepXQueryDevicePointer(ClientPtr client, int size,
         xQueryDevicePointerReply * rep)
 {
     char n;
diff --git a/Xi/regpair.c b/Xi/regpair.c
index cfaddb8..3fe4591 100644
--- a/Xi/regpair.c
+++ b/Xi/regpair.c
@@ -53,12 +53,12 @@ from the author.
 
 /***********************************************************************
  *
- * This procedure allows a client to register the pairing of a pointer 
+ * This procedure allows a client to register the pairing of a pointer
  * with a keyboard.
  *
  */
 
-int 
+int
 SProcXRegisterPairingClient(ClientPtr client)
 {
     char n;
@@ -67,7 +67,7 @@ SProcXRegisterPairingClient(ClientPtr client)
     return ProcXRegisterPairingClient(client);
 }
 
-int 
+int
 ProcXRegisterPairingClient(ClientPtr client)
 {
     xRegisterPairingClientReply rep;
@@ -96,7 +96,7 @@ ProcXRegisterPairingClient(ClientPtr client)
  */
 
 void
-SRepXRegisterPairingClient(ClientPtr client, int size, 
+SRepXRegisterPairingClient(ClientPtr client, int size,
         xRegisterPairingClientReply* rep)
 {
     register char n;
diff --git a/Xi/sendexev.c b/Xi/sendexev.c
index 20b415a..12fe7d2 100644
--- a/Xi/sendexev.c
+++ b/Xi/sendexev.c
@@ -110,7 +110,7 @@ SProcXSendExtensionEvent(ClientPtr client)
 
 /***********************************************************************
  *
- * Send an event to some client, as if it had come from an extension input 
+ * Send an event to some client, as if it had come from an extension input
  * device.
  *
  */
diff --git a/Xi/stubs.c b/Xi/stubs.c
index 40cd02f..744447a 100644
--- a/Xi/stubs.c
+++ b/Xi/stubs.c
@@ -88,7 +88,7 @@ CloseInputDevice(DeviceIntPtr d, ClientPtr client)
  *
  * Caller:	ProcXListInputDevices
  *
- * This is the implementation-dependent routine to initialize an input 
+ * This is the implementation-dependent routine to initialize an input
  * device to the point that information about it can be listed.
  * Some implementations open all input devices when the server is first
  * initialized, and never close them.  Other implementations open only
@@ -100,12 +100,12 @@ CloseInputDevice(DeviceIntPtr d, ClientPtr client)
  * This procedure should be used by implementations that do not initialize
  * all input devices at server startup.  It should do device-dependent
  * initialization for any devices not previously initialized, and call
- * AddInputDevice for each of those devices so that a DeviceIntRec will be 
+ * AddInputDevice for each of those devices so that a DeviceIntRec will be
  * created for them.
  *
  * The default implementation is to do nothing (assume all input devices
  * are initialized during X server initialization and kept open).
- * The commented-out sample code shows what you might do if you don't want 
+ * The commented-out sample code shows what you might do if you don't want
  * the default.
  *
  */
@@ -114,7 +114,7 @@ void
 AddOtherInputDevices(void)
 {
     /**********************************************************************
-     for each uninitialized device, do something like: 
+     for each uninitialized device, do something like:
 
     DeviceIntPtr dev;
     DeviceProc deviceProc;
@@ -137,7 +137,7 @@ AddOtherInputDevices(void)
  * initialized, and never close them.  Other implementations open only
  * the X pointer and keyboard devices during server initialization,
  * and only open other input devices when some client makes an
- * XOpenDevice request.  This entry point is for the latter type of 
+ * XOpenDevice request.  This entry point is for the latter type of
  * implementation.
  *
  * If the physical device is not already open, do it here.  In this case,
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index 82d71d5..a675bdc 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -87,7 +87,7 @@ ProcXWarpDevicePointer(ClientPtr client)
     if (pDev == NULL) {
         SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
                 stuff->deviceid,
-                BadDevice); 
+                BadDevice);
         return Success;
     }
 
@@ -96,7 +96,7 @@ ProcXWarpDevicePointer(ClientPtr client)
         err = dixLookupWindow(&dest, stuff->dst_win, client, DixReadAccess);
         if (err != Success)
         {
-            SendErrorToClient(client, IReqCode, X_WarpDevicePointer, 
+            SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
                     stuff->dst_win, err);
             return Success;
         }
@@ -114,14 +114,14 @@ ProcXWarpDevicePointer(ClientPtr client)
         err = dixLookupWindow(&src, stuff->src_win, client, DixReadAccess);
         if (err != Success)
         {
-            SendErrorToClient(client, IReqCode, X_WarpDevicePointer, 
+            SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
                     stuff->src_win, err);
             return Success;
         }
 
         winX = src->drawable.x;
         winY = src->drawable.y;
-        if (src->drawable.pScreen != pSprite->hotPhys.pScreen || 
+        if (src->drawable.pScreen != pSprite->hotPhys.pScreen ||
                 x < winX + stuff->src_x ||
                 y < winY + stuff->src_y ||
                 (stuff->src_width != 0 &&
commit 5031238aad2b6b7511aab0f9d15edfbdd2b4cce7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 13 16:58:23 2007 +1030

    dix: remove trailing/wrong whitespaces from devices.c and events.c

diff --git a/dix/devices.c b/dix/devices.c
index 7841e64..fa80a0c 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -27,13 +27,13 @@ Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
                         All Rights Reserved
 
-Permission to use, copy, modify, and distribute this software and its 
-documentation for any purpose and without fee is hereby granted, 
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
 provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in 
+both that copyright notice and this permission notice appear in
 supporting documentation, and that the name of Digital not be
 used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.  
+software without specific, written prior permission.
 
 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
@@ -203,7 +203,7 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
  *
  * A master pointer device needs to be enabled before a master keyboard
  * device.
- * 
+ *
  * @param The device to be enabled.
  * @return TRUE on success or FALSE otherwise.
  */
@@ -300,7 +300,7 @@ DisableDevice(DeviceIntPtr dev)
         {
             if (other->spriteInfo->paired == dev)
             {
-                ErrorF("[dix] cannot disable device, still paired. " 
+                ErrorF("[dix] cannot disable device, still paired. "
                         "This is a bug. \n");
                 return FALSE;
             }
@@ -316,7 +316,7 @@ DisableDevice(DeviceIntPtr dev)
     /* float attached devices */
     if (dev->isMaster)
     {
-        for (other = inputInfo.devices; other; other = other->next) 
+        for (other = inputInfo.devices; other; other = other->next)
         {
             if (other->u.master == dev)
                 AttachDevice(NULL, dev, NULL);
@@ -337,7 +337,7 @@ DisableDevice(DeviceIntPtr dev)
 /**
  * Initialise a new device through the driver and tell all clients about the
  * new device.
- * 
+ *
  * Must be called before EnableDevice.
  * The device will NOT send events until it is enabled!
  *
@@ -360,7 +360,7 @@ ActivateDevice(DeviceIntPtr dev)
     /* Initialize memory for sprites. */
     if (dev->isMaster && dev->spriteInfo->spriteOwner)
         pScreen->DeviceCursorInitialize(dev, pScreen);
-    
+
     ev.type = DevicePresenceNotify;
     ev.time = currentTime.milliseconds;
     ev.devchange = DeviceAdded;
@@ -391,7 +391,7 @@ CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
 }
 
 /**
- * Device control function for the Virtual Core Keyboard. 
+ * Device control function for the Virtual Core Keyboard.
  */
 static int
 CoreKeyboardProc(DeviceIntPtr pDev, int what)
@@ -475,7 +475,7 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
 
 /**
  * Device control function for the Virtual Core Pointer.
- * 
+ *
  * Aside from initialisation, it backs up the original device classes into the
  * devicePrivates. This only needs to be done for master devices.
  */
@@ -492,7 +492,7 @@ CorePointerProc(DeviceIntPtr pDev, int what)
         if (MasterDevClassesPrivIdx == -1)
             MasterDevClassesPrivIdx = AllocateDevicePrivateIndex();
 
-        if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) || 
+        if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) ||
                 !(classes = xcalloc(1, sizeof(ClassesRec))))
             return BadAlloc;
 
@@ -553,8 +553,8 @@ InitCoreDevices(void)
         CoreDevicePrivatesGeneration = serverGeneration;
     }
 
-    if (AllocMasterDevice("Virtual core", 
-                          &inputInfo.pointer, 
+    if (AllocMasterDevice("Virtual core",
+                          &inputInfo.pointer,
                           &inputInfo.keyboard) == BadAlloc)
         FatalError("Failed to allocate core devices");
 
@@ -573,14 +573,14 @@ InitCoreDevices(void)
 
 /**
  * Activate all switched-off devices and then enable all those devices.
- * 
+ *
  * Will return an error if no core keyboard or core pointer is present.
  * In theory this should never happen if you call InitCoreDevices() first.
  *
  * InitAndStartDevices needs to be called AFTER the windows are initialized.
  * Devices will start sending events after InitAndStartDevices() has
  * completed.
- * 
+ *
  * @return Success or error code on failure.
  */
 int
@@ -621,7 +621,7 @@ InitAndStartDevices(WindowPtr root)
 }
 
 /**
- * Close down a device and free all resources. 
+ * Close down a device and free all resources.
  * Once closed down, the driver will probably not expect you that you'll ever
  * enable it again and free associated structs. If you want the device to just
  * be disabled, DisableDevice().
@@ -654,7 +654,7 @@ CloseDevice(DeviceIntPtr dev)
 
     if (dev->isMaster)
         classes = (ClassesPtr)dev->devPrivates[MasterDevClassesPrivIdx].ptr;
-    else 
+    else
         classes = (ClassesPtr)&dev->key;
 
     if (classes->key) {
@@ -704,7 +704,7 @@ CloseDevice(DeviceIntPtr dev)
 	pnext = p->next;
 	xfree(p);
     }
-    
+
     for (i = classes->intfeed; i; i = inext) {
 	inext = i->next;
 	xfree(i);
@@ -735,7 +735,7 @@ CloseDevice(DeviceIntPtr dev)
     while (dev->xkb_interest)
 	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
 #endif
-    
+
     if (DevHasCursor(dev)) {
         xfree(dev->spriteInfo->sprite->spriteTrace);
         xfree(dev->spriteInfo->sprite);
@@ -759,7 +759,7 @@ CloseDevice(DeviceIntPtr dev)
 }
 
 /**
- * Shut down all devices, free all resources, etc. 
+ * Shut down all devices, free all resources, etc.
  * Only useful if you're shutting down the server!
  */
 void
@@ -788,7 +788,7 @@ CloseDownDevices(void)
  * Remove the cursor sprite for all devices. This needs to be done before any
  * resources are freed or any device is deleted.
  */
-void 
+void
 UndisplayDevices()
 {
     DeviceIntPtr dev;
@@ -802,7 +802,7 @@ UndisplayDevices()
 
 /**
  * Remove a device from the device list, closes it and thus frees all
- * resources. 
+ * resources.
  * Removes both enabled and disabled devices and notifies all devices about
  * the removal of the device.
  */
@@ -855,7 +855,7 @@ RemoveDevice(DeviceIntPtr dev)
             ret = Success;
 	}
     }
-    
+
     if (ret == Success) {
         inputInfo.numDevices--;
         ev.type = DevicePresenceNotify;
@@ -873,7 +873,7 @@ RemoveDevice(DeviceIntPtr dev)
 int
 NumMotionEvents(void)
 {
-    /* only called to fill data in initial connection reply. 
+    /* only called to fill data in initial connection reply.
      * VCP is ok here, it is the only fixed device we have. */
     return inputInfo.pointer->valuator->numMotionEvents;
 }
@@ -1023,7 +1023,7 @@ InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers
 {
     int i;
     KeyClassPtr keyc;
-    
+
     keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec));
     if (!keyc)
 	return FALSE;
@@ -1058,7 +1058,7 @@ InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers
 }
 
 _X_EXPORT Bool
-InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, 
+InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons,
                             CARD8 *map)
 {
     ButtonClassPtr butc;
@@ -1082,8 +1082,8 @@ InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons,
 }
 
 _X_EXPORT Bool
-InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, 
-                              ValuatorMotionProcPtr motionProc, 
+InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
+                              ValuatorMotionProcPtr motionProc,
                               int numMotionEvents, int mode)
 {
     int i;
@@ -1176,7 +1176,7 @@ InitFocusClassDeviceStruct(DeviceIntPtr dev)
 }
 
 _X_EXPORT Bool
-InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, 
+InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc,
                                  KbdCtrlProcPtr controlProc)
 {
     KbdFeedbackPtr feedc;
@@ -1240,7 +1240,7 @@ static IntegerCtrl defaultIntegerControl = {
 
 _X_EXPORT Bool
 InitStringFeedbackClassDeviceStruct (
-      DeviceIntPtr dev, StringCtrlProcPtr controlProc, 
+      DeviceIntPtr dev, StringCtrlProcPtr controlProc,
       int max_symbols, int num_symbols_supported, KeySym *symbols)
 {
     int i;
@@ -1253,9 +1253,9 @@ InitStringFeedbackClassDeviceStruct (
     feedc->ctrl.num_symbols_supported = num_symbols_supported;
     feedc->ctrl.num_symbols_displayed = 0;
     feedc->ctrl.max_symbols = max_symbols;
-    feedc->ctrl.symbols_supported = (KeySym *) 
+    feedc->ctrl.symbols_supported = (KeySym *)
 	xalloc (sizeof (KeySym) * num_symbols_supported);
-    feedc->ctrl.symbols_displayed = (KeySym *) 
+    feedc->ctrl.symbols_displayed = (KeySym *)
 	xalloc (sizeof (KeySym) * max_symbols);
     if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed)
     {
@@ -1279,7 +1279,7 @@ InitStringFeedbackClassDeviceStruct (
 }
 
 _X_EXPORT Bool
-InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, 
+InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc,
                                    BellCtrlProcPtr controlProc)
 {
     BellFeedbackPtr feedc;
@@ -1338,8 +1338,8 @@ InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr contr
 }
 
 _X_EXPORT Bool
-InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, 
-                        ValuatorMotionProcPtr motionProc, 
+InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons,
+                        ValuatorMotionProcPtr motionProc,
                         PtrCtrlProcPtr controlProc, int numMotionEvents,
                         int numAxes)
 {
@@ -1352,9 +1352,9 @@ InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons,
 }
 
 _X_EXPORT Bool
-InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, 
-                         CARD8 pModifiers[], BellProcPtr bellProc, 
-                         KbdCtrlProcPtr controlProc) 
+InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms,
+                         CARD8 pModifiers[], BellProcPtr bellProc,
+                         KbdCtrlProcPtr controlProc)
 {
     DeviceIntPtr dev = (DeviceIntPtr)device;
 
@@ -1525,13 +1525,13 @@ DoSetModifierMapping(ClientPtr client, KeyCode *inputMap,
     return Success;
 }
 
-int 
+int
 ProcSetModifierMapping(ClientPtr client)
 {
     xSetModifierMappingReply rep;
     DeviceIntPtr dev;
     REQUEST(xSetModifierMappingReq);
-    
+
     REQUEST_AT_LEAST_SIZE(xSetModifierMappingReq);
 
     if (client->req_len != ((stuff->numKeyPerModifier << 1) +
@@ -1583,7 +1583,7 @@ ProcChangeKeyboardMapping(ClientPtr client)
     DeviceIntPtr pDev = NULL;
     REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
 
-    len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2);  
+    len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2);
     if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
             return BadLength;
 
@@ -1671,7 +1671,7 @@ ProcSetPointerMapping(ClientPtr client)
     rep.sequenceNumber = client->sequence;
     rep.success = MappingSuccess;
     map = (BYTE *)&stuff[1];
-    
+
     /* So we're bounded here by the number of core buttons.  This check
      * probably wants disabling through XFixes. */
     /* MPX: With ClientPointer, we can return the right number of buttons.
@@ -1750,7 +1750,7 @@ ProcGetPointerMapping(ClientPtr client)
     rep.length = ((unsigned)rep.nElts + (4-1))/4;
     WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep);
     (void)WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]);
-    return Success;    
+    return Success;
 }
 
 void
@@ -1790,7 +1790,7 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
 	index2 = (BITS32) lowbit (vmask);
 	vmask &= ~index2;
 	switch (index2) {
-	case KBKeyClickPercent: 
+	case KBKeyClickPercent:
 	    t = (INT8)*vlist;
 	    vlist++;
 	    if (t == -1) {
@@ -1940,7 +1940,7 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
     return Success;
 
 #undef DO_ALL
-} 
+}
 
 int
 ProcChangeKeyboardControl (ClientPtr client)
@@ -2000,7 +2000,7 @@ ProcGetKeyboardControl (ClientPtr client)
 	rep.map[i] = ctrl->autoRepeats[i];
     WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep);
     return Success;
-} 
+}
 
 int
 ProcBell(ClientPtr client)
@@ -2013,7 +2013,7 @@ ProcBell(ClientPtr client)
 
     if (!keybd->kbdfeed->BellProc)
         return BadDevice;
-    
+
     if (stuff->percent < -100 || stuff->percent > 100) {
 	client->errorValue = stuff->percent;
 	return BadValue;
@@ -2023,7 +2023,7 @@ ProcBell(ClientPtr client)
     if (stuff->percent < 0)
         newpercent = base + newpercent;
     else
-    	newpercent = base - newpercent + stuff->percent;
+	newpercent = base - newpercent + stuff->percent;
 
     for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
         if ((keybd->coreEvents || keybd == inputInfo.keyboard) &&
@@ -2040,7 +2040,7 @@ ProcBell(ClientPtr client)
     }
 
     return Success;
-} 
+}
 
 int
 ProcChangePointerControl(ClientPtr client)
@@ -2050,10 +2050,10 @@ ProcChangePointerControl(ClientPtr client)
     REQUEST(xChangePointerControlReq);
 
     REQUEST_SIZE_MATCH(xChangePointerControlReq);
-    
+
     if (!mouse->ptrfeed->CtrlProc)
         return BadDevice;
-    
+
     ctrl = mouse->ptrfeed->ctrl;
     if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
 	client->errorValue = stuff->doAccel;
@@ -2109,7 +2109,7 @@ ProcChangePointerControl(ClientPtr client)
     }
 
     return Success;
-} 
+}
 
 int
 ProcGetPointerControl(ClientPtr client)
@@ -2231,17 +2231,17 @@ ProcQueryKeymap(ClientPtr client)
 	bzero((char *)&rep.map[0], 32);
 
     WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
- 
+
    return Success;
 }
 
 /* Pair the keyboard to the pointer device. Keyboard events will follow the
- * pointer sprite. Only applicable for master devices. 
+ * pointer sprite. Only applicable for master devices.
  * If the client is set, the request to pair comes from some client. In this
  * case, we need to check for access. If the client is NULL, it's from an
  * internal automatic pairing, we must always permit this.
  */
-int 
+int
 PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
 {
     if (!ptr)
@@ -2277,15 +2277,15 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
  * Client is set to the client that issued the request, or NULL if it comes
  * from some internal automatic pairing.
  *
- * Master may be NULL to set the device floating. 
+ * Master may be NULL to set the device floating.
  *
  * We don't allow multi-layer hierarchies right now. You can't attach a slave
- * to another slave. 
+ * to another slave.
  */
 int
 AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 {
-    if (!dev || dev->isMaster) 
+    if (!dev || dev->isMaster)
         return BadDevice;
 
     if (master && !master->isMaster) /* can't attach to slaves */
@@ -2345,13 +2345,13 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 
             /* Send event to clients */
             CreateClassesChangedEvent(&event, master, master);
-            deviceClassesChangedEvent *dcce = 
+            deviceClassesChangedEvent *dcce =
                         (deviceClassesChangedEvent*)event.event;
             dcce->deviceid = master->id;
             dcce->num_classes = 0;
             classbuf = (char*)&event.event[1];
             CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuf);
-            SendEventToAllWindows(master, XI_DeviceClassesChangedMask, 
+            SendEventToAllWindows(master, XI_DeviceClassesChangedMask,
                     event.event, 1);
             xfree(event.event);
         }
@@ -2380,7 +2380,7 @@ GetPairedDevice(DeviceIntPtr dev)
 }
 
 /*
- * Register a client to be able to pair devices. 
+ * Register a client to be able to pair devices.
  */
 Bool
 RegisterPairingClient(ClientPtr client)
@@ -2398,22 +2398,22 @@ RegisterPairingClient(ClientPtr client)
 /*
  * Unregister pairing client;
  */
-Bool 
+Bool
 UnregisterPairingClient(ClientPtr client)
 {
-    if (pairingClient) 
+    if (pairingClient)
     {
         if ( pairingClient == client)
         {
             pairingClient = NULL;
-        } else 
+        } else
             return False;
     }
     return True;
 }
 
 /* Guess a pointer that could be a good one for pairing. Any pointer that is
- * not yet paired with keyboard is considered a good one. 
+ * not yet paired with keyboard is considered a good one.
  * If no pointer is found, the last real pointer is chosen. If that doesn't
  * work either, we take the core pointer.
  */
@@ -2422,7 +2422,7 @@ GuessFreePointerDevice()
 {
     DeviceIntPtr it, it2;
     DeviceIntPtr lastRealPtr = NULL;
-        
+
     it = inputInfo.devices;
 
     while(it)
@@ -2436,7 +2436,7 @@ GuessFreePointerDevice()
             while(it2)
             {
                 /* something paired with it? */
-                if (it != it2 && 
+                if (it != it2 &&
                         it2->spriteInfo->sprite == it->spriteInfo->sprite)
                     break;
 
@@ -2458,8 +2458,8 @@ NextFreePointerDevice()
 {
     DeviceIntPtr dev;
     for (dev = inputInfo.devices; dev; dev = dev->next)
-        if (dev->isMaster && 
-                dev->spriteInfo->spriteOwner && 
+        if (dev->isMaster &&
+                dev->spriteInfo->spriteOwner &&
                 !dev->spriteInfo->paired)
             return dev;
     return NULL;
diff --git a/dix/events.c b/dix/events.c
index daebe35..88ce501 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -27,13 +27,13 @@ Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
                         All Rights Reserved
 
-Permission to use, copy, modify, and distribute this software and its 
-documentation for any purpose and without fee is hereby granted, 
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
 provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in 
+both that copyright notice and this permission notice appear in
 supporting documentation, and that the name of Digital not be
 used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.  
+software without specific, written prior permission.
 
 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
@@ -107,7 +107,7 @@ of the copyright holder.
 
 ******************************************************************/
 
-/* 
+/*
  * MPX additions
  * Copyright 2006 by Peter Hutterer
  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
@@ -239,22 +239,22 @@ static int DontPropagateRefCnts[DNPMCOUNT];
 
 
 /**
- * Main input device struct. 
- *     inputInfo.pointer 
+ * Main input device struct.
+ *     inputInfo.pointer
  *     is the core pointer. Referred to as "virtual core pointer", "VCP",
  *     "core pointer" or inputInfo.pointer. There is exactly one core pointer,
  *     but multiple devices may send core events. The VCP is only used if no
- *     physical device is connected and does not have a visible cursor. 
+ *     physical device is connected and does not have a visible cursor.
  *     Before the integration of MPX, any core request would operate on the
  *     VCP/VCK. Core events would always come from one of those two. Now both
  *     are only fallback devices if no physical devices are available.
- * 
+ *
  *     inputInfo.keyboard
  *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
  *     See inputInfo.pointer.
- * 
+ *
  *     inputInfo.devices
- *     linked list containing all devices BUT NOT INCLUDING VCK and VCP. 
+ *     linked list containing all devices BUT NOT INCLUDING VCK and VCP.
  *
  *     inputInfo.off_devices
  *     Devices that have not been initialized and are thus turned off.
@@ -316,12 +316,12 @@ XItoCoreType(int xitype)
     return coretype;
 }
 
-/** 
+/**
  * True if device owns a cursor, false if device shares a cursor sprite with
  * another device.
  */
 _X_EXPORT Bool
-DevHasCursor(DeviceIntPtr pDev) 
+DevHasCursor(DeviceIntPtr pDev)
 {
     return pDev->spriteInfo->spriteOwner;
 }
@@ -352,11 +352,11 @@ _X_EXPORT HotSpot xeviehot;
 #endif
 
 static void DoEnterLeaveEvents(
-    DeviceIntPtr pDev, 
+    DeviceIntPtr pDev,
     WindowPtr fromWin,
     WindowPtr toWin,
     int mode
-); 
+);
 
 static WindowPtr XYToWindow(
     DeviceIntPtr pDev,
@@ -416,9 +416,9 @@ static Mask filters[128] =
 };
 
 
-/** 
+/**
  * same principle as filters, but one set of filters for each extension.
- * The extension is responsible for setting the filters by calling 
+ * The extension is responsible for setting the filters by calling
  * SetGenericFilter().
  */
 static Mask* generic_filters[MAXEXTENSIONS];
@@ -441,8 +441,8 @@ static void PostNewCursor(DeviceIntPtr pDev);
 static Bool
 XineramaSetCursorPosition(
     DeviceIntPtr pDev,
-    int x, 
-    int y, 
+    int x,
+    int y,
     Bool generateEvent
 ){
     ScreenPtr pScreen;
@@ -451,7 +451,7 @@ XineramaSetCursorPosition(
     SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     /* x,y are in Screen 0 coordinates.  We need to decide what Screen
-       to send the message too and what the coordinates relative to 
+       to send the message too and what the coordinates relative to
        that screen are. */
 
     pScreen = pSprite->screen;
@@ -459,11 +459,11 @@ XineramaSetCursorPosition(
     y += panoramiXdataPtr[0].y;
 
     if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
-								x, y, &box)) 
+								x, y, &box))
     {
-	FOR_NSCREENS(i) 
+	FOR_NSCREENS(i)
 	{
-	    if(i == pScreen->myNum) 
+	    if(i == pScreen->myNum)
 		continue;
 	    if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box))
 	    {
@@ -514,7 +514,7 @@ XineramaCheckPhysLimits(
 
     if (!cursor)
 	return;
- 
+
     new = pSprite->hotPhys;
 
     /* I don't care what the DDX has to say about it */
@@ -553,7 +553,7 @@ XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
     SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if(pWin == WindowTable[0]) {
-	    memcpy(pSprite->windows, WindowTable, 
+	    memcpy(pSprite->windows, WindowTable,
 				PanoramiXNumScreens*sizeof(WindowPtr));
     } else {
 	PanoramiXRes *win;
@@ -577,7 +577,7 @@ static void
 XineramaCheckVirtualMotion(
    DeviceIntPtr pDev,
    QdEventPtr qe,
-   WindowPtr pWin) 
+   WindowPtr pWin)
 {
     SpritePtr pSprite = pDev->spriteInfo->sprite;
 
@@ -598,9 +598,9 @@ XineramaCheckVirtualMotion(
 	    return;
 
 	i = PanoramiXNumScreens - 1;
-	
-	REGION_COPY(pSprite->screen, &pSprite->Reg2, 
-					&pSprite->windows[i]->borderSize); 
+
+	REGION_COPY(pSprite->screen, &pSprite->Reg2,
+					&pSprite->windows[i]->borderSize);
 	off_x = panoramiXdataPtr[i].x;
 	off_y = panoramiXdataPtr[i].y;
 
@@ -610,8 +610,8 @@ XineramaCheckVirtualMotion(
 
 	    if(x || y)
 		REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, x, y);
-		
-	    REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2, 
+
+	    REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2,
 					&pSprite->windows[i]->borderSize);
 
 	    off_x = panoramiXdataPtr[i].x;
@@ -629,8 +629,8 @@ XineramaCheckVirtualMotion(
         else if (pSprite->hot.y >= lims.y2)
             pSprite->hot.y = lims.y2 - 1;
 
-	if (REGION_NUM_RECTS(&pSprite->Reg2) > 1) 
-	    ConfineToShape(pDev, &pSprite->Reg2, 
+	if (REGION_NUM_RECTS(&pSprite->Reg2) > 1)
+	    ConfineToShape(pDev, &pSprite->Reg2,
                     &pSprite->hot.x, &pSprite->hot.y);
 
 	if (qe)
@@ -658,7 +658,7 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
     if (xE && !syncEvents.playingEvents)
     {
 	/* Motion events entering DIX get translated to Screen 0
-	   coordinates.  Replayed events have already been 
+	   coordinates.  Replayed events have already been
 	   translated since they've entered DIX before */
 	XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
 			  panoramiXdataPtr[0].x;
@@ -675,7 +675,7 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	else if (pSprite->hot.y >= pSprite->physLimits.y2)
 	    pSprite->hot.y = pSprite->physLimits.y2 - 1;
 
-	if (pSprite->hotShape) 
+	if (pSprite->hotShape)
 	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
 
 	pSprite->hotPhys = pSprite->hot;
@@ -702,7 +702,7 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	    if (!xE)
 		UpdateCurrentTimeIf();
             DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win,
-                               NotifyNormal); 
+                               NotifyNormal);
         }
 	PostNewCursor(pDev);
         return FALSE;
@@ -712,8 +712,8 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 
 
 static void
-XineramaConfineCursorToWindow(DeviceIntPtr pDev, 
-                              WindowPtr pWin, 
+XineramaConfineCursorToWindow(DeviceIntPtr pDev,
+                              WindowPtr pWin,
                               Bool generateEvents)
 {
     SpritePtr pSprite = pDev->spriteInfo->sprite;
@@ -731,9 +731,9 @@ XineramaConfineCursorToWindow(DeviceIntPtr pDev,
 	    return;
 
 	i = PanoramiXNumScreens - 1;
-	
-	REGION_COPY(pSprite->screen, &pSprite->Reg1, 
-					&pSprite->windows[i]->borderSize); 
+
+	REGION_COPY(pSprite->screen, &pSprite->Reg1,
+					&pSprite->windows[i]->borderSize);
 	off_x = panoramiXdataPtr[i].x;
 	off_y = panoramiXdataPtr[i].y;
 
@@ -743,8 +743,8 @@ XineramaConfineCursorToWindow(DeviceIntPtr pDev,
 
 	    if(x || y)
 		REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, x, y);
-		
-	    REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1, 
+
+	    REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1,
 					&pSprite->windows[i]->borderSize);
 
 	    off_x = panoramiXdataPtr[i].x;
@@ -757,12 +757,12 @@ XineramaConfineCursorToWindow(DeviceIntPtr pDev,
 	   pSprite->hotShape = &pSprite->Reg1;
 	else
 	   pSprite->hotShape = NullRegion;
-	
+
 	pSprite->confined = FALSE;
 	pSprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
 
         XineramaCheckPhysLimits(pDev, pSprite->current,
-                                generateEvents); 
+                                generateEvents);
     }
 }
 
@@ -777,7 +777,7 @@ XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
 		(pSprite->current->bits->yhot != cursor->bits->yhot))
 	    XineramaCheckPhysLimits(pDev, cursor, FALSE);
-    	(*pSprite->screen->DisplayCursor)(pDev, pSprite->screen, cursor);
+	(*pSprite->screen->DisplayCursor)(pDev, pSprite->screen, cursor);
 	FreeCursor(pSprite->current, (Cursor)0);
 	pSprite->current = cursor;
 	pSprite->current->refcnt++;
@@ -823,7 +823,7 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
     BoxRec box;
     int x = *px, y = *py;
     int incx = 1, incy = 1;
-    SpritePtr pSprite; 
+    SpritePtr pSprite;
 
     pSprite = pDev->spriteInfo->sprite;
     if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box))
@@ -858,7 +858,7 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
 
 static void
 CheckPhysLimits(
-    DeviceIntPtr pDev, 
+    DeviceIntPtr pDev,
     CursorPtr cursor,
     Bool generateEvents,
     Bool confineToScreen,
@@ -890,15 +890,15 @@ CheckPhysLimits(
 	    new.y = pSprite->physLimits.y2 - 1;
 #ifdef SHAPE
     if (pSprite->hotShape)
-	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 
+	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
 #endif
     if ((pScreen != pSprite->hotPhys.pScreen) ||
 	(new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
     {
 	if (pScreen != pSprite->hotPhys.pScreen)
 	    pSprite->hotPhys = new;
-        (*pScreen->SetCursorPosition) 
-            (pDev, pScreen, new.x, new.y, generateEvents); 
+        (*pScreen->SetCursorPosition)
+            (pDev, pScreen, new.x, new.y, generateEvents);
         if (!generateEvents)
 	    SyntheticMotion(pDev, new.x, new.y);
     }
@@ -945,7 +945,7 @@ CheckVirtualMotion(
 	    pSprite->hot.y = lims.y2 - 1;
 #ifdef SHAPE
 	if (wBoundingShape(pWin))
-	    ConfineToShape(pDev, &pWin->borderSize, 
+	    ConfineToShape(pDev, &pWin->borderSize,
                     &pSprite->hot.x, &pSprite->hot.y);
 #endif
 	if (qe)
@@ -972,7 +972,7 @@ ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bo
     if(!noPanoramiXExtension) {
 	XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
 	return;
-    }	
+    }
 #endif
 
     if (syncEvents.playingEvents)
@@ -1033,7 +1033,7 @@ ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 }
 
 /**
- * @returns true if b is a descendent of a 
+ * @returns true if b is a descendent of a
  */
 Bool
 IsParent(WindowPtr a, WindowPtr b)
@@ -1046,7 +1046,7 @@ IsParent(WindowPtr a, WindowPtr b)
 /**
  * Update the cursor displayed on the screen.
  *
- * Called whenever a cursor may have changed shape or position.  
+ * Called whenever a cursor may have changed shape or position.
  */
 static void
 PostNewCursor(DeviceIntPtr pDev)
@@ -1074,7 +1074,7 @@ PostNewCursor(DeviceIntPtr pDev)
 	win = pSprite->win;
     for (; win; win = win->parent)
     {
-	if (win->optional) 
+	if (win->optional)
         {
             pCursor = WindowGetDeviceCursor(win, pDev);
             if (!pCursor && win->optional->cursor != NullCursor)
@@ -1173,16 +1173,16 @@ NoticeEventTime(xEvent *xE)
  **************************************************************************/
 
 /**
- * EnqueueEvent is a device's processInputProc if a device is frozen. 
+ * EnqueueEvent is a device's processInputProc if a device is frozen.
  * Instead of delivering the events to the client, the event is tacked onto a
  * linked list for later delivery.
  */
 void
 EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 {
-    QdEventPtr 	tail = *syncEvents.pendtail;
-    QdEventPtr 	qe;
-    SpritePtr 	pSprite = device->spriteInfo->sprite;
+    QdEventPtr	tail = *syncEvents.pendtail;
+    QdEventPtr	qe;
+    SpritePtr	pSprite = device->spriteInfo->sprite;
     int		eventlen;
 
 
@@ -1190,7 +1190,7 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 
 #ifdef XKB
     /* Fix for key repeating bug. */
-    if (device->key != NULL && device->key->xkbInfo != NULL && 
+    if (device->key != NULL && device->key->xkbInfo != NULL &&
 	xE->u.u.type == KeyRelease)
 	AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail);
 #endif
@@ -1271,9 +1271,9 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 
 /**
  * Run through the list of events queued up in syncEvents.
- * For each event do: 
+ * For each event do:
  * If the device for this event is not frozen anymore, take it and process it
- * as usually. 
+ * as usually.
  * After that, check if there's any devices in the list that are not frozen.
  * If there is none, we're done. If there is at least one device that is not
  * frozen, then re-run from the beginning of the event queue.
@@ -1315,11 +1315,11 @@ PlayReleasedEvents(void)
 	      to the DIX layer */
             /* XXX: we can't do that for generic events */
 	    if(!noPanoramiXExtension) {
-		qe->event->u.keyButtonPointer.rootX += 
-			panoramiXdataPtr[0].x - 
+		qe->event->u.keyButtonPointer.rootX +=
+			panoramiXdataPtr[0].x -
 			panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].x;
-		qe->event->u.keyButtonPointer.rootY += 
-			panoramiXdataPtr[0].y - 
+		qe->event->u.keyButtonPointer.rootY +=
+			panoramiXdataPtr[0].y -
 			panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].y;
 	    }
 #endif
@@ -1336,7 +1336,7 @@ PlayReleasedEvents(void)
 	}
 	else
 	    prev = &qe->next;
-    } 
+    }
 }
 
 /**
@@ -1378,7 +1378,7 @@ ComputeFreezes(void)
     BOOL sendCore;
 
     for (dev = inputInfo.devices; dev; dev = dev->next)
-	FreezeThaw(dev, dev->deviceGrab.sync.other || 
+	FreezeThaw(dev, dev->deviceGrab.sync.other ||
                 (dev->deviceGrab.sync.state >= FROZEN));
     if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
 	return;
@@ -1412,7 +1412,7 @@ ComputeFreezes(void)
                         core = *xE;
                         core.u.u.type = XItoCoreType(xE->u.u.type);
                         /* * XXX: Not sure if this is correct: we need to
-                         * check inferior windows for core passive grabs. 
+                         * check inferior windows for core passive grabs.
                          */
                         if (CheckDeviceGrabs(replayDev, &core, i+1, 1))
                         {
@@ -1458,12 +1458,12 @@ playmore:
     {
         if (DevHasCursor(dev))
         {
-            /* the following may have been skipped during replay, 
+            /* the following may have been skipped during replay,
               so do it now */
             if ((grab = dev->deviceGrab.grab) && grab->confineTo)
             {
                 if (grab->confineTo->drawable.pScreen !=
-                        dev->spriteInfo->sprite->hotPhys.pScreen) 
+                        dev->spriteInfo->sprite->hotPhys.pScreen)
                     dev->spriteInfo->sprite->hotPhys.x =
                         dev->spriteInfo->sprite->hotPhys.y = 0;
                 ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
@@ -1491,13 +1491,13 @@ ScreenRestructured (ScreenPtr pScreen)
          * worry about it. */
         if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
         {
-            if (grab->confineTo->drawable.pScreen 
+            if (grab->confineTo->drawable.pScreen
                     != pDev->spriteInfo->sprite->hotPhys.pScreen)
                 pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
             ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
         }
         else
-            ConfineCursorToWindow(pDev, 
+            ConfineCursorToWindow(pDev,
                     WindowTable[pDev->spriteInfo->sprite->hotPhys.pScreen->myNum],
                     TRUE, FALSE);
     }
@@ -1521,7 +1521,7 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
 	    thisDev->deviceGrab.sync.other = NullGrab;
     }
     /* XXX: other should only work on the paired keyboard, not on all other
-       devices 
+       devices
      */
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
@@ -1591,25 +1591,25 @@ RestoreOldMaster(DeviceIntPtr dev)
 
 /**
  * Activate a pointer grab on the given device. A pointer grab will cause all
- * core pointer events of this device to be delivered to the grabbing client only. 
+ * core pointer events of this device to be delivered to the grabbing client only.
  * No other device will send core events to the grab client while the grab is
  * on, but core events will be sent to other clients.
  * Can cause the cursor to change if a grab cursor is set.
- * 
+ *
  * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
  * is an implicit grab caused by a ButtonPress event.
- * 
+ *
  * @param mouse The device to grab.
  * @param grab The grab structure, needs to be setup.
  * @param autoGrab True if the grab was caused by a button down event and not
- * explicitely by a client. 
+ * explicitely by a client.
  */
 void
-ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 
+ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
                     TimeStamp time, Bool autoGrab)
 {
     GrabInfoPtr grabinfo = &mouse->deviceGrab;
-    WindowPtr oldWin = (grabinfo->grab) ? 
+    WindowPtr oldWin = (grabinfo->grab) ?
                         grabinfo->grab->window
                         : mouse->spriteInfo->sprite->win;
     Bool isPassive = autoGrab & ~ImplicitGrabMask;
@@ -1623,9 +1623,9 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
 
     if (grab->confineTo)
     {
-	if (grab->confineTo->drawable.pScreen 
+	if (grab->confineTo->drawable.pScreen
                 != mouse->spriteInfo->sprite->hotPhys.pScreen)
-	    mouse->spriteInfo->sprite->hotPhys.x = 
+	    mouse->spriteInfo->sprite->hotPhys.x =
                 mouse->spriteInfo->sprite->hotPhys.y = 0;
 	ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
     }
@@ -1666,7 +1666,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
 	if (dev->deviceGrab.sync.other == grab)
 	    dev->deviceGrab.sync.other = NullGrab;
     }
-    DoEnterLeaveEvents(mouse, grab->window, 
+    DoEnterLeaveEvents(mouse, grab->window,
                        mouse->spriteInfo->sprite->win, NotifyUngrab);
     if (grab->confineTo)
 	ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE);
@@ -1681,7 +1681,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
 }
 
 /**
- * Activate a keyboard grab on the given device. 
+ * Activate a keyboard grab on the given device.
  *
  * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
  */
@@ -1720,7 +1720,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass
 }
 
 /**
- * Delete keyboard grab for the given device. 
+ * Delete keyboard grab for the given device.
  */
 void
 DeactivateKeyboardGrab(DeviceIntPtr keybd)
@@ -1752,16 +1752,16 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
 }
 
 void
-AllowSome(ClientPtr client, 
-          TimeStamp time, 
-          DeviceIntPtr thisDev, 
-          int newState, 
+AllowSome(ClientPtr client,
+          TimeStamp time,
+          DeviceIntPtr thisDev,
+          int newState,
           Bool core)
 {
     Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
     TimeStamp grabTime;
     DeviceIntPtr dev;
-    GrabInfoPtr devgrabinfo, 
+    GrabInfoPtr devgrabinfo,
                 grabinfo = &thisDev->deviceGrab;
 
     thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
@@ -1796,7 +1796,7 @@ AllowSome(ClientPtr client,
 	return;
     switch (newState)
     {
-	case THAWED:	 	       /* Async */
+	case THAWED:		       /* Async */
 	    if (thisGrabbed)
 		grabinfo->sync.state = THAWED;
 	    if (thisSynced)
@@ -1818,10 +1818,10 @@ AllowSome(ClientPtr client,
 		for (dev = inputInfo.devices; dev; dev = dev->next)
 		{
                     devgrabinfo = &dev->deviceGrab;
-		    if (devgrabinfo->grab 
+		    if (devgrabinfo->grab
                             && SameClient(devgrabinfo->grab, client))
 			devgrabinfo->sync.state = THAWED;
-		    if (devgrabinfo->sync.other && 
+		    if (devgrabinfo->sync.other &&
                             SameClient(devgrabinfo->sync.other, client))
 			devgrabinfo->sync.other = NullGrab;
 		}
@@ -1834,10 +1834,10 @@ AllowSome(ClientPtr client,
 		for (dev = inputInfo.devices; dev; dev = dev->next)
 		{
                     devgrabinfo = &dev->deviceGrab;
-		    if (devgrabinfo->grab 
+		    if (devgrabinfo->grab
                             && SameClient(devgrabinfo->grab, client))
 			devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
-		    if (devgrabinfo->sync.other 
+		    if (devgrabinfo->sync.other
                             && SameClient(devgrabinfo->sync.other, client))
 			devgrabinfo->sync.other = NullGrab;
 		}
@@ -1863,10 +1863,10 @@ AllowSome(ClientPtr client,
 		    if (dev == thisDev)
 			continue;
                     devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
-		    if (devgrabinfo->grab 
+		    if (devgrabinfo->grab
                             && SameClient(devgrabinfo->grab, client))
 			devgrabinfo->sync.state = THAWED;
-		    if (devgrabinfo->sync.other 
+		    if (devgrabinfo->sync.other
                             && SameClient(devgrabinfo->sync.other, client))
 			devgrabinfo->sync.other = NullGrab;
 		}
@@ -1879,8 +1879,8 @@ AllowSome(ClientPtr client,
 /**
  * Server-side protocol handling for AllowEvents request.
  *
- * Release some events from a frozen device. 
- * 
+ * Release some events from a frozen device.
+ *
  * In some cases, the grab the client has is not on the ClientPointer but on
  * some other device (see ProcGrabPointer comments). To cover this case, we
  * need to run through all devices to ensure we don't forget the device we
@@ -1909,7 +1909,7 @@ ProcAllowEvents(ClientPtr client)
             else if (IsKeyboardDevice(grabbed))
                 keybd = grabbed;
 
-	    if (mouse && keybd) 
+	    if (mouse && keybd)
 		break;
         }
     }
@@ -1924,19 +1924,19 @@ ProcAllowEvents(ClientPtr client)
 	case ReplayPointer:
 	    AllowSome(client, time, mouse, NOT_GRABBED, True);
 	    break;
-	case SyncPointer: 
+	case SyncPointer:
 	    AllowSome(client, time, mouse, FREEZE_NEXT_EVENT, True);
 	    break;
-	case AsyncPointer: 
+	case AsyncPointer:
 	    AllowSome(client, time, mouse, THAWED, True);
 	    break;
-	case ReplayKeyboard: 
+	case ReplayKeyboard:
 	    AllowSome(client, time, keybd, NOT_GRABBED, True);
 	    break;
-	case SyncKeyboard: 
+	case SyncKeyboard:
 	    AllowSome(client, time, keybd, FREEZE_NEXT_EVENT, True);
 	    break;
-	case AsyncKeyboard: 
+	case AsyncKeyboard:
 	    AllowSome(client, time, keybd, THAWED, True);
 	    break;
 	case SyncBoth:
@@ -1945,7 +1945,7 @@ ProcAllowEvents(ClientPtr client)
 	case AsyncBoth:
 	    AllowSome(client, time, keybd, THAWED_BOTH, True);
 	    break;
-	default: 
+	default:
 	    client->errorValue = stuff->mode;
 	    return BadValue;
     }
@@ -1965,21 +1965,21 @@ ReleaseActiveGrabs(ClientPtr client)
      * releasing active grabs.
      */
     do {
-    	done = TRUE;
-    	for (dev = inputInfo.devices; dev; dev = dev->next)
-    	{
+	done = TRUE;
+	for (dev = inputInfo.devices; dev; dev = dev->next)
+	{
 	    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
 	    {
-	    	(*dev->deviceGrab.DeactivateGrab)(dev);
-	    	done = FALSE;
+		(*dev->deviceGrab.DeactivateGrab)(dev);
+		done = FALSE;
 	    }
 
 	    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
 	    {
-	    	(*dev->deviceGrab.DeactivateGrab)(dev);
-	    	done = FALSE;
+		(*dev->deviceGrab.DeactivateGrab)(dev);
+		done = FALSE;
 	    }
-    	}
+	}
     } while (!done);
 }
 
@@ -1995,24 +1995,24 @@ ReleaseActiveGrabs(ClientPtr client)
  *
  * TryClientEvents() is the last station before actually writing the events to
  * the socket. Anything that is not filtered here, will get delivered to the
- * client. 
- * An event is only delivered if 
+ * client.
+ * An event is only delivered if
  *   - mask and filter match up.
  *   - no other client has a grab on the device that caused the event.
- * 
+ *
  *
  * @param client The target client to deliver to.
  * @param pEvents The events to be delivered.
  * @param count Number of elements in pEvents.
  * @param mask Event mask as set by the window.
  * @param filter Mask based on event type.
- * @param grab Possible grab on the device that caused the event. 
+ * @param grab Possible grab on the device that caused the event.
  *
  * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
  * client.
  */
 _X_EXPORT int
-TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, 
+TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
                  Mask filter, GrabPtr grab)
 {
     int i;
@@ -2093,19 +2093,19 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
  * Deliver events to a window. At this point, we do not yet know if the event
  * actually needs to be delivered. May activate a grab if the event is a
  * button press.
- * 
+ *
  * Core events are always delivered to the window owner. If the filter is
  * something other than CantBeFiltered, the event is also delivered to other
  * clients with the matching mask on the window.
  *
  * More than one event may be delivered at a time. This is the case with
  * DeviceMotionNotifies which may be followed by DeviceValuator events.
- * 
+ *
  * @param pWin The window that would get the event.
  * @param pEvents The events to be delivered.
  * @param count Number of elements in pEvents.
  * @param filter Mask based on event type.
- * @param grab Possible grab on the device that caused the event. 
+ * @param grab Possible grab on the device that caused the event.
  * @param mskidx Mask index, depending on device that caused event.
  *
  * @return Number of events delivered to various clients.
@@ -2121,7 +2121,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
     Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
 		              this mask is the mask of the grab. */
     int type = pEvents->u.u.type;
-    
+
     /* if a  is denied, we return 0. This could cause the caller to
      * traverse the parent. May be bad! (whot) */
     if (!ACDeviceAllowed(pWin, pDev, pEvents))
@@ -2130,15 +2130,15 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
     }
 
     /* CantBeFiltered means only window owner gets the event */
-    if ((filter == CantBeFiltered) || 
+    if ((filter == CantBeFiltered) ||
             (!(type & EXTENSION_EVENT_BASE) && type != GenericEvent))
     {
 	/* if nobody ever wants to see this event, skip some work */
 	if (filter != CantBeFiltered &&
 	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
 	    return 0;
-        
-        if (!(type & EXTENSION_EVENT_BASE) && 
+
+        if (!(type & EXTENSION_EVENT_BASE) &&
             IsInterferingGrab(wClient(pWin), pDev, pEvents))
                 return 0;
 
@@ -2177,11 +2177,11 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
             {
                 if (pClient->eventMask[GEEXTIDX(pEvents)] & filter)
                 {
-                    if (TryClientEvents(pClient->client, pEvents, count, 
+                    if (TryClientEvents(pClient->client, pEvents, count,
                             pClient->eventMask[GEEXTIDX(pEvents)], filter, grab) > 0)
                     {
                         deliveries++;
-                    } else 
+                    } else
                         nondeliveries--;
                 }
             }
@@ -2248,7 +2248,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
         inputMasks = wOtherInputMasks(pWin);
         tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
 
-        /* get the XGE event mask. 
+        /* get the XGE event mask.
          * FIXME: needs to be freed somewhere too.
          */
         tempGrab.genericMasks = NULL;
@@ -2294,11 +2294,11 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 */
 
 #ifdef PANORAMIX
-static int 
+static int
 XineramaTryClientEventsResult(
     ClientPtr client,
     GrabPtr grab,
-    Mask mask, 
+    Mask mask,
     Mask filter
 ){
     if ((client) && (client != serverClient) && (!client->clientGone) &&
@@ -2321,7 +2321,7 @@ XineramaTryClientEventsResult(
  * @param dontClient Don't deliver to the dontClient.
  */
 int
-MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 
+MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
                            int count, Mask filter, ClientPtr dontClient)
 {
     OtherClients *other;
@@ -2332,7 +2332,7 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
         if (wClient(pWin) == dontClient)
 	    return 0;
 #ifdef PANORAMIX
-	if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 
+	if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
 	    return XineramaTryClientEventsResult(
 			wClient(pWin), NullGrab, pWin->eventMask, filter);
 #endif
@@ -2346,7 +2346,7 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
             if (SameClient(other, dontClient))
 		return 0;
 #ifdef PANORAMIX
-	    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 
+	    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
 	      return XineramaTryClientEventsResult(
 			rClient(other), NullGrab, other->mask, filter);
 #endif
@@ -2381,29 +2381,29 @@ FixUpEventFromWindow(
     if (calcChild)
     {
         WindowPtr w= pSprite->spriteTrace[pSprite->spriteTraceGood-1];
-	/* If the search ends up past the root should the child field be 
-	 	set to none or should the value in the argument be passed 
-		through. It probably doesn't matter since everyone calls 
+	/* If the search ends up past the root should the child field be
+		set to none or should the value in the argument be passed
+		through. It probably doesn't matter since everyone calls
 		this function with child == None anyway. */
 
-        while (w) 
+        while (w)
         {
             /* If the source window is same as event window, child should be
 		none.  Don't bother going all all the way back to the root. */
 
- 	    if (w == pWin)
-	    { 
-   		child = None;
- 		break;
+	    if (w == pWin)
+	    {
+		child = None;
+		break;
 	    }
-	    
+
 	    if (w->parent == pWin)
 	    {
 		child = w->drawable.id;
 		break;
             }
- 	    w = w->parent;
-        } 	    
+	    w = w->parent;
+        }
     }
     XE_KBPTR.root = RootWindow(pDev)->drawable.id;
     XE_KBPTR.event = pWin->drawable.id;
@@ -2427,7 +2427,7 @@ FixUpEventFromWindow(
 
 /**
  * Deliver events caused by input devices. Called for both core input events
- * and XI events. 
+ * and XI events.
  * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
  * called directly from the processInputProc.
  * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
@@ -2446,7 +2446,7 @@ FixUpEventFromWindow(
  * @see DeliverFocusedEvent
  */
 int
-DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, 
+DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
                     WindowPtr stopAt, DeviceIntPtr dev, int count)
 {
     Window child = None;
@@ -2503,7 +2503,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
                 {
                     if (GEExtensions[GEEXTIDX(xE)].evfill)
                         GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, pWin, grab);
-                    deliveries = DeliverEventsToWindow(dev, pWin, xE, count, 
+                    deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
                                                         filter, grab, 0);
                     if (deliveries > 0)
                         return deliveries;
@@ -2511,7 +2511,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
 
                 pWin = pWin->parent;
             }
-        } 
+        }
         else
         {
             /* core protocol events */
@@ -2542,7 +2542,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
 /**
  * Deliver event to a window and it's immediate parent. Used for most window
  * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
- * propagate up the tree or extension events 
+ * propagate up the tree or extension events
  *
  * In case of a ReparentNotify event, the event will be delivered to the
  * otherParent as well.
@@ -2553,7 +2553,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
  * @param otherParent Used for ReparentNotify events.
  */
 _X_EXPORT int
-DeliverEvents(WindowPtr pWin, xEvent *xE, int count, 
+DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
               WindowPtr otherParent)
 {
     Mask filter;
@@ -2591,7 +2591,7 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
 }
 
 
-static Bool 
+static Bool
 PointInBorderSize(WindowPtr pWin, int x, int y)
 {
     BoxRec box;
@@ -2601,15 +2601,15 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
 	return TRUE;
 
 #ifdef PANORAMIX
-    if(!noPanoramiXExtension && 
+    if(!noPanoramiXExtension &&
             XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
 	int i;
 
 	for(i = 1; i < PanoramiXNumScreens; i++) {
-	   if(POINT_IN_REGION(pSprite->screen, 
-			&pSprite->windows[i]->borderSize, 
-			x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, 
-			y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, 
+	   if(POINT_IN_REGION(pSprite->screen,
+			&pSprite->windows[i]->borderSize,
+			x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x,
+			y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y,
 			&box))
 		return TRUE;
 	}
@@ -2629,7 +2629,7 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
  *
  * @returns the window at the given coordinates.
  */
-static WindowPtr 
+static WindowPtr
 XYToWindow(DeviceIntPtr pDev, int x, int y)
 {
     WindowPtr  pWin;
@@ -2689,7 +2689,7 @@ XYToWindow(DeviceIntPtr pDev, int x, int y)
  * CheckMotion() will not do anything and return FALSE if the event is not a
  * pointer event.
  *
- * @return TRUE if the sprite has moved or FALSE otherwise. 
+ * @return TRUE if the sprite has moved or FALSE otherwise.
  */
 Bool
 CheckMotion(xEvent *xE, DeviceIntPtr pDev)
@@ -2697,7 +2697,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
     INT16     *rootX, *rootY;
     WindowPtr prevSpriteWin;
     SpritePtr pSprite = pDev->spriteInfo->sprite;
-        
+
     prevSpriteWin = pSprite->win;
 
 #ifdef PANORAMIX
@@ -2785,7 +2785,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	    if (!xE)
 		UpdateCurrentTimeIf();
             DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win,
-                               NotifyNormal); 
+                               NotifyNormal);
         }
 	PostNewCursor(pDev);
         return FALSE;
@@ -2835,7 +2835,7 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
             pSprite->hotPhys.x    -= xoff;
             pSprite->hotPhys.y    -= yoff;
 
-            pSprite->hotLimits.x1 -= xoff; 
+            pSprite->hotLimits.x1 -= xoff;
             pSprite->hotLimits.y1 -= yoff;
             pSprite->hotLimits.x2 -= xoff;
             pSprite->hotLimits.y2 -= yoff;
@@ -2847,7 +2847,7 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
 
             /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
             if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
-                if (grab->confineTo->drawable.pScreen 
+                if (grab->confineTo->drawable.pScreen
                         != pSprite->hotPhys.pScreen)
                     pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
                 ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
@@ -2889,13 +2889,13 @@ DefineInitialRootWindow(WindowPtr win)
  *
  * @param pDev The device to initialize.
  * @param pWin The window where to generate the sprite in.
- * 
+ *
  */
-void 
+void
 InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
 {
     SpritePtr pSprite;
-    ScreenPtr pScreen; 
+    ScreenPtr pScreen;
 
     if (!pDev->spriteInfo->sprite)
     {
@@ -2941,7 +2941,7 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
     {
         pSprite->current = wCursor(pWin);
         pSprite->current->refcnt++;
- 	pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr));
+	pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr));
 	if (!pSprite->spriteTrace)
 	    FatalError("Failed to allocate spriteTrace");
 	pSprite->spriteTraceSize = 32;
@@ -2971,7 +2971,7 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
                                      &pSprite->physLimits);
         (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
                                        pSprite->hot.y,
-                                       FALSE); 
+                                       FALSE);
         (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
     }
 #ifdef PANORAMIX
@@ -3082,33 +3082,33 @@ NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
     pSprite->hotPhys.y = y;
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
-	pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - 
+	pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x -
 			    panoramiXdataPtr[0].x;
-	pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - 
+	pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y -
 			    panoramiXdataPtr[0].y;
 	if (newScreen != pSprite->screen) {
 	    pSprite->screen = newScreen;
 	    /* Make sure we tell the DDX to update its copy of the screen */
 	    if(pSprite->confineWin)
-		XineramaConfineCursorToWindow(pDev, 
+		XineramaConfineCursorToWindow(pDev,
                         pSprite->confineWin, TRUE);
 	    else
 		XineramaConfineCursorToWindow(pDev, WindowTable[0], TRUE);
-	    /* if the pointer wasn't confined, the DDX won't get 
+	    /* if the pointer wasn't confined, the DDX won't get
 	       told of the pointer warp so we reposition it here */
 	    if(!syncEvents.playingEvents)
 		(*pSprite->screen->SetCursorPosition)(
                                                       pDev,
                                                       pSprite->screen,
-		    pSprite->hotPhys.x + panoramiXdataPtr[0].x - 
+		    pSprite->hotPhys.x + panoramiXdataPtr[0].x -
 			panoramiXdataPtr[pSprite->screen->myNum].x,
-		    pSprite->hotPhys.y + panoramiXdataPtr[0].y - 
+		    pSprite->hotPhys.y + panoramiXdataPtr[0].y -
 			panoramiXdataPtr[pSprite->screen->myNum].y, FALSE);
 	}
-    } else 
+    } else
 #endif
     if (newScreen != pSprite->hotPhys.pScreen)
-	ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum], 
+	ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum],
                 TRUE, FALSE);
 }
 
@@ -3129,11 +3129,11 @@ XineramaPointInWindowIsVisible(
 
     if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
         return TRUE;
-    
+
     if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
 
-    xoff = x + panoramiXdataPtr[0].x;  
-    yoff = y + panoramiXdataPtr[0].y;  
+    xoff = x + panoramiXdataPtr[0].x;
+    yoff = y + panoramiXdataPtr[0].y;
 
     for(i = 1; i < PanoramiXNumScreens; i++) {
 	pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
@@ -3145,7 +3145,7 @@ XineramaPointInWindowIsVisible(
 	   && (!wInputShape(pWin) ||
 	       POINT_IN_REGION(pWin->drawable.pScreen,
 			       wInputShape(pWin),
-			       x - pWin->drawable.x, 
+			       x - pWin->drawable.x,
 			       y - pWin->drawable.y, &box)))
             return TRUE;
 
@@ -3175,9 +3175,9 @@ XineramaWarpPointer(ClientPtr client)
     if (stuff->srcWid != None)
     {
 	int     winX, winY;
- 	XID 	winID = stuff->srcWid;
+	XID	winID = stuff->srcWid;
         WindowPtr source;
-	
+
 	rc = dixLookupWindow(&source, winID, client, DixReadAccess);
 	if (rc != Success)
 	    return rc;
@@ -3204,7 +3204,7 @@ XineramaWarpPointer(ClientPtr client)
 	    x -= panoramiXdataPtr[0].x;
 	    y -= panoramiXdataPtr[0].y;
 	}
-    } 
+    }
 
     x += stuff->dstX;
     y += stuff->dstY;
@@ -3260,9 +3260,9 @@ ProcWarpPointer(ClientPtr client)
     if (stuff->srcWid != None)
     {
 	int     winX, winY;
- 	XID 	winID = stuff->srcWid;
+	XID	winID = stuff->srcWid;
         WindowPtr source;
-	
+
 	rc = dixLookupWindow(&source, winID, client, DixReadAccess);
 	if (rc != Success)
 	    return rc;
@@ -3279,12 +3279,12 @@ ProcWarpPointer(ClientPtr client)
 	    !PointInWindowIsVisible(source, x, y))
 	    return Success;
     }
-    if (dest) 
+    if (dest)
     {
 	x = dest->drawable.x;
 	y = dest->drawable.y;
 	newScreen = dest->drawable.pScreen;
-    } else 
+    } else
 	newScreen = pSprite->hotPhys.pScreen;
 
     x += stuff->dstX;
@@ -3314,7 +3314,7 @@ ProcWarpPointer(ClientPtr client)
 	    ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
 #endif
         (*newScreen->SetCursorPosition)(PickPointer(client), newScreen, x, y,
-                                        TRUE); 
+                                        TRUE);
     }
     else if (!PointerConfinedToScreen(PickPointer(client)))
     {
@@ -3323,7 +3323,7 @@ ProcWarpPointer(ClientPtr client)
     return Success;
 }
 
-static Bool 
+static Bool
 BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
 {
      if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->hotPhys.pScreen, &pWin->borderSize))
@@ -3334,7 +3334,7 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
 	int i;
 
 	for(i = 1; i < PanoramiXNumScreens; i++) {
-	    if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen, 
+	    if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen,
                         &pDev->spriteInfo->sprite->windows[i]->borderSize))
 		return TRUE;
 	}
@@ -3343,11 +3343,11 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
      return FALSE;
 }
 
-/** 
+/**
  * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
- * passive grab set on the window to be activated. 
+ * passive grab set on the window to be activated.
  * If a passive grab is activated, the event will be delivered to the client.
- * 
+ *
  * @param pWin The window that may be subject to a passive grab.
  * @param device Device that caused the event.
  * @param xE List of events (multiple ones for DeviceMotionNotify)
@@ -3419,7 +3419,7 @@ CheckPassiveGrabsOnWindow(
             /* ignore the device for core events when comparing grabs */
 	if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) &&
 	    (!grab->confineTo ||
-	     (grab->confineTo->realized && 
+	     (grab->confineTo->realized &&
 				BorderSizeNotEmpty(device, grab->confineTo))))
 	{
 	    if (!XaceHook(XACE_DEVICE_ACCESS, wClient(pWin), device, FALSE))
@@ -3440,10 +3440,10 @@ CheckPassiveGrabsOnWindow(
                modifierDevice explicitly, we don't override this choice.
                This essentially requires a client to re-create all
                passiveGrabs when the pairing changes... oh well.
-             */ 
+             */
             if (xE->u.u.type < LASTEvent)
             {
-                grab->device = device; 
+                grab->device = device;
                 grab->modifierDevice = GetPairedDevice(device);
             }
 
@@ -3477,7 +3477,7 @@ CheckPassiveGrabsOnWindow(
 
 
 	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
- 
+
 	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
 
 	    (void) TryClientEvents(rClient(grab), xE, count,
@@ -3497,8 +3497,8 @@ CheckPassiveGrabsOnWindow(
 		grabinfo->sync.evcount = count;
 		for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++)
 		    *dxE = *xE;
-	    	grabinfo->sync.state = FROZEN_WITH_EVENT;
-            }	
+		grabinfo->sync.state = FROZEN_WITH_EVENT;
+            }
 	    return TRUE;
 	}
     }
@@ -3507,14 +3507,14 @@ CheckPassiveGrabsOnWindow(
 
 /**
  * CheckDeviceGrabs handles both keyboard and pointer events that may cause
- * a passive grab to be activated.  
+ * a passive grab to be activated.
  *
  * If the event is a keyboard event, the ancestors of the focus window are
  * traced down and tried to see if they have any passive grabs to be
  * activated.  If the focus window itself is reached and it's descendants
  * contain the pointer, the ancestors of the window that the pointer is in
  * are then traced down starting at the focus window, otherwise no grabs are
- * activated.  
+ * activated.
  * If the event is a pointer event, the ancestors of the window that the
  * pointer is in are traced down starting at the root until CheckPassiveGrabs
  * causes a passive grab to activate or all the windows are
@@ -3529,7 +3529,7 @@ CheckPassiveGrabsOnWindow(
 */
 
 Bool
-CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, 
+CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
                  int checkFirst, int count)
 {
     int i;
@@ -3554,7 +3554,7 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
 		CheckPassiveGrabsOnWindow(pWin, device, xE, count))
 		return TRUE;
 	}
-  
+
 	if ((focus->win == NoneWin) ||
 	    (i >= device->spriteInfo->sprite->spriteTraceGood) ||
 	    ((i > checkFirst) &&
@@ -3620,7 +3620,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
  * @param deactivateGrab True if the device's grab should be deactivated.
  */
 void
-DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, 
+DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                     Bool deactivateGrab, int count)
 {
     GrabPtr grab;
@@ -3646,9 +3646,9 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
 	else
 	    focus = PointerRootWin;
 	if (focus == PointerRootWin)
-	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, 
+	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab,
                                              NullWindow, thisDev, count);
-	else if (focus && (focus == pSprite->win || 
+	else if (focus && (focus == pSprite->win ||
                     IsParent(focus, pSprite->win)))
 	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, focus,
 					     thisDev, count);
@@ -3671,15 +3671,15 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
 
                 if (GEEventFill(xE))
                     GEEventFill(xE)(ge, thisDev, grab->window, grab);
-                deliveries = TryClientEvents(rClient(grab), xE, count, 
+                deliveries = TryClientEvents(rClient(grab), xE, count,
                         gemask->eventMask[GEEXTIDX(ge)],
                         generic_filters[GEEXTIDX(ge)][ge->evtype],
                         grab);
-            } else 
+            } else
             {
                 Mask mask = grab->eventMask;
                 if (grabinfo->fromPassiveGrab  &&
-                        grabinfo->implicitGrab && 
+                        grabinfo->implicitGrab &&
                         (xE->u.u.type & EXTENSION_EVENT_BASE))
                     mask = grab->deviceMask;
 
@@ -3739,7 +3739,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
 }
 
 /**
- * Main keyboard event processing function for core keyboard events. 
+ * Main keyboard event processing function for core keyboard events.
  * Updates the events fields from the current pointer state and delivers the
  * event.
  *
@@ -3852,11 +3852,11 @@ drawable.id:0;
 
     switch (xE->u.u.type)
     {
-	case KeyPress: 
+	case KeyPress:
             /* We MUST NOT change the device itself here.  All device state
              * changes must be performed in ProcessOtherEvents. We're dealing
              * with the same device struct, so if we change it in POE and
-             * here, we've just screwed up the state by setting it twice. 
+             * here, we've just screwed up the state by setting it twice.
              *
              * Devices may not send core events but always send XI events, so
              * the state must be changed in POE, not here.
@@ -3867,14 +3867,14 @@ drawable.id:0;
 		return;
 	    }
 	    break;
-	case KeyRelease: 
+	case KeyRelease:
 	    if (!(*kptr & bit)) /* guard against duplicates */
 		return;
             /* No device state changes, see comment for KeyPress */
 	    if (grabinfo->fromPassiveGrab && (key == grabinfo->activatingKey))
 		deactivateGrab = TRUE;
 	    break;
-	default: 
+	default:
 	    FatalError("Impossible keyboard event");
     }
     if (grab)
@@ -3889,7 +3889,7 @@ drawable.id:0;
 
 #ifdef XKB
 /* This function is used to set the key pressed or key released state -
-   this is only used when the pressing of keys does not cause 
+   this is only used when the pressing of keys does not cause
    the device's processInputProc to be called, as in for example Mouse Keys.
 */
 void
@@ -3919,8 +3919,8 @@ FixKeyState (xEvent *xE, DeviceIntPtr keybd)
 }
 #endif
 
-/** 
- * Main pointer event processing function for core pointer events. 
+/**
+ * Main pointer event processing function for core pointer events.
  * For motion events: update the sprite.
  * For all other events: Update the event fields based on the current sprite
  * state.
@@ -4003,7 +4003,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 	bit = 1 << (key & 7);
 	switch (xE->u.u.type)
 	{
-	case ButtonPress: 
+	case ButtonPress:
             /*
              * We rely on the fact that ButtonMotionMask is the same as
              * DeviceButtonMotionMask, so setting the motionMask
@@ -4016,14 +4016,14 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 		if (CheckDeviceGrabs(mouse, xE, 0, count))
 		    return;
 	    break;
-	case ButtonRelease: 
+	case ButtonRelease:
 	    if (xE->u.u.detail == 0)
 		return;
 	    filters[MotionNotify] = Motion_Filter(butc);
 	    if (!butc->state && mouse->deviceGrab.fromPassiveGrab)
 		deactivateGrab = TRUE;
 	    break;
-	default: 
+	default:
 	    FatalError("bogus pointer event from ddx");
 	}
     }
@@ -4184,7 +4184,7 @@ EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
 	if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
 	    return BadAlloc;
     }
-maskSet: 
+maskSet:
     if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
 	(mask & PointerMotionHintMask) &&
 	!(check & PointerMotionHintMask) &&
@@ -4195,7 +4195,7 @@ maskSet:
 }
 
 int
-EventSuppressForWindow(WindowPtr pWin, ClientPtr client, 
+EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
                        Mask mask, Bool *checkOptional)
 {
     int i, free;
@@ -4253,7 +4253,7 @@ EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
 /**
  * @return The window that is the first ancestor of both a and b.
  */
-static WindowPtr 
+static WindowPtr
 CommonAncestor(
     WindowPtr a,
     WindowPtr b)
@@ -4264,7 +4264,7 @@ CommonAncestor(
 }
 
 /**
- * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 
+ * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
  * Uses the paired keyboard to get some additional information.
  */
 static void
@@ -4283,7 +4283,7 @@ EnterLeaveEvent(
     GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
     int*                inWindow; /* no of sprites inside pWin */
-    Bool                sendevent = FALSE;        
+    Bool                sendevent = FALSE;
 
     deviceEnterNotify   *devEnterLeave;
     int                 mskidx;
@@ -4320,7 +4320,7 @@ EnterLeaveEvent(
     if (!noXkbExtension) {
         event.u.enterLeave.state = mouse->button->state & 0x1f00;
         if (keybd)
-            event.u.enterLeave.state |= 
+            event.u.enterLeave.state |=
                 XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
     } else
 #endif
@@ -4339,29 +4339,29 @@ EnterLeaveEvent(
 
     /*
      * Sending multiple core enter/leave events to the same window confuse the
-     * client.  
+     * client.
      * We can send multiple events that have detail NotifyVirtual or
      * NotifyNonlinearVirtual however. For most clients anyway.
      *
      * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
      * we only send an enter event for the first pointer to enter. A leave
-     * event is sent for the last pointer to leave. 
+     * event is sent for the last pointer to leave.
      *
      * For events with Virtual detail, we send them only to a window that does
      * not have a pointer inside.
      *
-     * For a window tree in the form of 
+     * For a window tree in the form of
      *
-     * A -> Bp -> C -> D 
+     * A -> Bp -> C -> D
      *  \               (where B and E have pointers)
-     *    -> Ep         
-     *    
+     *    -> Ep
+     *
      * If the pointer moves from E into D, a LeaveNotify is sent to E, an
      * EnterNotify is sent to D, an EnterNotify with detail
      * NotifyNonlinearVirtual to C and nothing to B.
      */
 
-    if (event.u.u.detail != NotifyVirtual && 
+    if (event.u.u.detail != NotifyVirtual &&
             event.u.u.detail != NotifyNonlinearVirtual)
     {
         if (((*inWindow) == (LeaveNotify - type)))
@@ -4382,7 +4382,7 @@ EnterLeaveEvent(
                                         NullGrab, 0);
     }
 
-    /* we don't have enough bytes, so we squash flags and mode into 
+    /* 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 :
@@ -4393,15 +4393,15 @@ EnterLeaveEvent(
     devEnterLeave->deviceid = mouse->id;
     mskidx = mouse->id;
     inputMasks = wOtherInputMasks(pWin);
-    if (inputMasks && 
+    if (inputMasks &&
        (filters[devEnterLeave->type] & inputMasks->deliverableEvents[mskidx]))
     {
         if (devgrab)
             (void)TryClientEvents(rClient(devgrab), (xEvent*)devEnterLeave, 1,
                                 mask, filters[devEnterLeave->type], devgrab);
 	else
-	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave, 
-                                        1, filters[devEnterLeave->type], 
+	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave,
+                                        1, filters[devEnterLeave->type],
                                         NullGrab, mouse->id);
     }
 
@@ -4430,11 +4430,11 @@ EnterLeaveEvent(
  * This function recurses.
  */
 static void
-EnterNotifies(DeviceIntPtr pDev, 
-              WindowPtr ancestor, 
-              WindowPtr child, 
-              int mode, 
-              int detail) 
+EnterNotifies(DeviceIntPtr pDev,
+              WindowPtr ancestor,
+              WindowPtr child,
+              int mode,
+              int detail)
 {
     WindowPtr	parent = child->parent;
 
@@ -4450,10 +4450,10 @@ EnterNotifies(DeviceIntPtr pDev,
  * This function recurses.
  */
 static void
-LeaveNotifies(DeviceIntPtr pDev, 
-              WindowPtr child, 
-              WindowPtr ancestor, 
-              int mode, 
+LeaveNotifies(DeviceIntPtr pDev,
+              WindowPtr child,
+              WindowPtr ancestor,
+              int mode,
               int detail)
 {
     WindowPtr  pWin;
@@ -4463,7 +4463,7 @@ LeaveNotifies(DeviceIntPtr pDev,
     for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
     {
         EnterLeaveEvent(pDev, LeaveNotify, mode, detail, pWin,
-                        child->drawable.id); 
+                        child->drawable.id);
         child = pWin;
     }
 }
@@ -4478,7 +4478,7 @@ LeaveNotifies(DeviceIntPtr pDev,
         } \
     }
 #define ENTER_LEAVE_SEMAPHORE_UP(win, mode)  \
-        FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode, 1); 
+        FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode, 1);
 
 #define ENTER_LEAVE_SEMAPHORE_DOWN(win, mode) \
         FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode,  -1);
@@ -4487,23 +4487,23 @@ LeaveNotifies(DeviceIntPtr pDev,
 /**
  * Figure out if enter/leave events are necessary and send them to the
  * appropriate windows.
- * 
+ *
  * @param fromWin Window the sprite moved out of.
  * @param toWin Window the sprite moved into.
  */
 static void
-DoEnterLeaveEvents(DeviceIntPtr pDev, 
-        WindowPtr fromWin, 
-        WindowPtr toWin, 
-        int mode) 
+DoEnterLeaveEvents(DeviceIntPtr pDev,
+        WindowPtr fromWin,
+        WindowPtr toWin,
+        int mode)
 {
     if (fromWin == toWin)
 	return;
     if (IsParent(fromWin, toWin))
     {
-        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode); 
+        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
         EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin,
-                        None); 
+                        None);
         EnterNotifies(pDev, fromWin, toWin, mode,
                       NotifyVirtual);
         ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
@@ -4511,8 +4511,8 @@ DoEnterLeaveEvents(DeviceIntPtr pDev,
     }
     else if (IsParent(toWin, fromWin))
     {
-        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode); 
-	EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin, 
+        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
+	EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin,
                         None);
 	LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual);
         ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
@@ -4522,14 +4522,14 @@ DoEnterLeaveEvents(DeviceIntPtr pDev,
     { /* neither fromWin nor toWin is descendent of the other */
 	WindowPtr common = CommonAncestor(toWin, fromWin);
 	/* common == NullWindow ==> different screens */
-        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode); 
+        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
         EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin,
-                        None); 
+                        None);
         LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual);
 	EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual);
         ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
         EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin,
-                        None); 
+                        None);
     }
 }
 
@@ -4547,7 +4547,7 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
      * Same procedure as for Enter/Leave events.
      *
      * Sending multiple core FocusIn/Out events to the same window may confuse
-     * the client.  
+     * the client.
      * We can send multiple events that have detail NotifyVirtual,
      * NotifyNonlinearVirtual, NotifyPointerRoot, NotifyDetailNone or
      * NotifyPointer however.
@@ -4560,12 +4560,12 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
      * For events with Virtual detail, we send them only to a window that does
      * not have a focus from another keyboard.
      *
-     * For a window tree in the form of 
+     * For a window tree in the form of
      *
-     * A -> Bf -> C -> D 
+     * A -> Bf -> C -> D
      *  \               (where B and E have focus)
-     *    -> Ef         
-     *    
+     *    -> Ef
+     *
      * If the focus changes from E into D, a FocusOut is sent to E, a
      * FocusIn is sent to D, a FocusIn with detail
      * NotifyNonlinearVirtual to C and nothing to B.
@@ -4575,8 +4575,8 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
         &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout;
     if (mode == NotifyGrab || mode == NotifyUngrab)
         sendevent = TRUE;
-    else if (detail != NotifyVirtual && 
-            detail != NotifyNonlinearVirtual && 
+    else if (detail != NotifyVirtual &&
+            detail != NotifyNonlinearVirtual &&
             detail != NotifyPointer &&
             detail != NotifyPointerRoot &&
             detail != NotifyDetailNone)
@@ -4677,15 +4677,15 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
     if ((toWin == NullWindow) || (toWin == PointerRootWin))
     {
 	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
-   	{
+	{
 	    if (fromWin == PointerRootWin)
                 FocusOutEvents(dev, pSprite->win, RootWindow(dev), mode,
                                NotifyPointer, TRUE);
 	    /* Notify all the roots */
 #ifdef PANORAMIX
- 	    if ( !noPanoramiXExtension )
+	    if ( !noPanoramiXExtension )
 	        FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
-	    else 
+	    else
 #endif
 	        for (i=0; i<screenInfo.numScreens; i++)
 	            FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
@@ -4704,7 +4704,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 #ifdef PANORAMIX
 	if ( !noPanoramiXExtension )
 	    FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
-	else 
+	else
 #endif
 	    for (i=0; i<screenInfo.numScreens; i++)
 	        FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
@@ -4720,9 +4720,9 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 		FocusOutEvents(dev, pSprite->win, RootWindow(dev), mode,
 			       NotifyPointer, TRUE);
 #ifdef PANORAMIX
- 	    if ( !noPanoramiXExtension )
+	    if ( !noPanoramiXExtension )
 	        FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
-	    else 
+	    else
 #endif
 	        for (i=0; i<screenInfo.numScreens; i++)
 	            FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
@@ -4731,7 +4731,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 				  NotifyNonlinearVirtual, TRUE);
 	    FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
 	    if (IsParent(toWin, pSprite->win))
-    	       (void)FocusInEvents(dev, toWin, pSprite->win, NullWindow, mode,
+	       (void)FocusInEvents(dev, toWin, pSprite->win, NullWindow, mode,
 				   NotifyPointer, FALSE);
 	}
 	else
@@ -4790,14 +4790,14 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 /**
  * Set the input focus to the given window. Subsequent keyboard events will be
  * delivered to the given window.
- * 
+ *
  * Usually called from ProcSetInputFocus as result of a client request. If so,
  * the device is the inputInfo.keyboard.
  * If called from ProcXSetInputFocus as result of a client xinput request, the
  * device is set to the device specified by the client.
  *
  * @param client Client that requested input focus change.
- * @param dev Focus device. 
+ * @param dev Focus device.
  * @param focusID The window to obtain the focus. Can be PointerRoot or None.
  * @param revertTo Specifies where the focus reverts to when window becomes
  * unviewable.
@@ -4846,7 +4846,7 @@ SetInputFocus(
 	rc = dixLookupWindow(&focusWin, focusID, client, DixReadAccess);
 	if (rc != Success)
 	    return rc;
- 	/* It is a match error to try to set the input focus to an 
+	/* It is a match error to try to set the input focus to an
 	unviewable window. */
 	if(!focusWin->realized)
 	    return(BadMatch);
@@ -4884,7 +4884,7 @@ SetInputFocus(
 	    Must_have_memory = FALSE; /* XXX */
 	}
 	focus->traceGood = depth;
-        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 
+        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
 	    focus->trace[depth] = pWin;
     }
     return Success;
@@ -4913,7 +4913,7 @@ ProcSetInputFocus(client)
 
 /**
  * Server-side protocol handling for GetInputFocus request.
- * 
+ *
  * Sends the current input focus for the client's keyboard back to the
  * client.
  */
@@ -4993,7 +4993,7 @@ ProcGrabPointer(ClientPtr client)
 	return rc;
     if (stuff->confineTo == None)
 	confineTo = NullWindow;
-    else 
+    else
     {
 	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
 			     DixReadAccess);
@@ -5037,11 +5037,11 @@ ProcGrabPointer(ClientPtr client)
 	rep.status = AlreadyGrabbed;
     else if ((!pWin->realized) ||
              (confineTo &&
-                !(confineTo->realized 
+                !(confineTo->realized
                     && BorderSizeNotEmpty(device, confineTo))))
 	rep.status = GrabNotViewable;
     else if (device->deviceGrab.sync.frozen &&
-	     device->deviceGrab.sync.other && 
+	     device->deviceGrab.sync.other &&
              !SameClient(device->deviceGrab.sync.other, client))
 	rep.status = GrabFrozen;
     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
@@ -5053,7 +5053,7 @@ ProcGrabPointer(ClientPtr client)
 
 	oldCursor = NullCursor;
 	if (grab)
- 	{
+	{
 	    if (grab->confineTo && !confineTo)
 		ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE);
 	    oldCursor = grab->cursor;
@@ -5086,11 +5086,11 @@ ProcGrabPointer(ClientPtr client)
  * Server-side protocol handling for ChangeActivePointerGrab request.
  *
  * Changes properties of the grab hold by the client. If the client does not
- * hold an active grab on the device, nothing happens. 
+ * hold an active grab on the device, nothing happens.
  *
  * Works on the client's ClientPointer, but in some cases the client may have
  * a grab on a device that isn't the ClientPointer (see ProcGrabPointer
- * comments). 
+ * comments).
  */
 int
 ProcChangeActivePointerGrab(ClientPtr client)
@@ -5223,25 +5223,25 @@ ProcUngrabPointer(ClientPtr client)
 
 /**
  * Sets a grab on the given device.
- * 
+ *
  * Called from ProcGrabKeyboard to work on the client's keyboard.
  * Called from ProcXGrabDevice to work on the device specified by the client.
- * 
+ *
  * The parameters this_mode and other_mode represent the keyboard_mode and
- * pointer_mode parameters of XGrabKeyboard(). 
+ * pointer_mode parameters of XGrabKeyboard().
  * See man page for details on all the parameters
- * 
+ *
  * @param client Client that owns the grab.
- * @param dev The device to grab. 
+ * @param dev The device to grab.
  * @param this_mode GrabModeSync or GrabModeAsync
  * @param other_mode GrabModeSync or GrabModeAsync
  * @param status Return code to be returned to the caller.
- * 
+ *
  * @returns Success or BadValue.
  */
 int
-GrabDevice(ClientPtr client, DeviceIntPtr dev, 
-           unsigned this_mode, unsigned other_mode, Window grabWindow, 
+GrabDevice(ClientPtr client, DeviceIntPtr dev,
+           unsigned this_mode, unsigned other_mode, Window grabWindow,
            unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status,
            Bool coreGrab)
 {
@@ -5317,7 +5317,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
  * Grabs are only removed if the other device matches the type of device. If
  * dev is a pointer device, only other pointer grabs are removed. Likewise, if
  * dev is a keyboard device, only keyboard grabs are removed.
- * 
+ *
  * If dev doesn't have a grab, do nothing and go for a beer.
  *
  * @param client The client that is to be limited.
@@ -5462,7 +5462,7 @@ ProcUngrabKeyboard(ClientPtr client)
  * Server-side protocol handling for QueryPointer request.
  *
  * Returns the current state and position of the client's ClientPointer to the
- * client. 
+ * client.
  */
 int
 ProcQueryPointer(ClientPtr client)
@@ -5521,7 +5521,7 @@ ProcQueryPointer(ClientPtr client)
 
     WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
 
-    return(Success);    
+    return(Success);
 }
 
 /**
@@ -5579,7 +5579,7 @@ CloseDownEvents(void)
 /**
  * Server-side protocol handling for SendEvent request.
  *
- * Locates the window to send the event to and forwards the event. 
+ * Locates the window to send the event to and forwards the event.
  */
 int
 ProcSendEvent(ClientPtr client)
@@ -5595,7 +5595,7 @@ ProcSendEvent(ClientPtr client)
 	extension. */
 
     if ( ! ((stuff->event.u.u.type > X_Reply &&
-	     stuff->event.u.u.type < LASTEvent) || 
+	     stuff->event.u.u.type < LASTEvent) ||
 	    (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
 	     stuff->event.u.u.type < (unsigned)lastEvent)))
     {
@@ -5627,7 +5627,7 @@ ProcSendEvent(ClientPtr client)
 
 	/* If the input focus is PointerRootWin, send the event to where
 	the pointer is if possible, then perhaps propogate up to root. */
-   	if (inputFocus == PointerRootWin)
+	if (inputFocus == PointerRootWin)
 	    inputFocus = pSprite->spriteTrace[0]; /* Root window! */
 
 	if (IsParent(inputFocus, pSprite->win))
@@ -5722,7 +5722,7 @@ ProcUngrabKey(ClientPtr client)
  * Server-side protocol handling for GrabKey request.
  *
  * Creates a grab for the client's keyboard and adds it to the list of passive
- * grabs. 
+ * grabs.
  */
 int
 ProcGrabKey(ClientPtr client)
@@ -5768,10 +5768,10 @@ ProcGrabKey(ClientPtr client)
     if (rc != Success)
 	return rc;
 
-    grab = CreateGrab(client->index, keybd, pWin, 
+    grab = CreateGrab(client->index, keybd, pWin,
 	(Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents,
 	(Bool)stuff->keyboardMode, (Bool)stuff->pointerMode,
-	keybd, stuff->modifiers, KeyPress, stuff->key, 
+	keybd, stuff->modifiers, KeyPress, stuff->key,
 	NullWindow, NullCursor);
     if (!grab)
 	return BadAlloc;
@@ -5851,7 +5851,7 @@ ProcGrabButton(ClientPtr client)
     pointer = PickPointer(client);
     modifierDevice = GetPairedDevice(pointer);
 
-    grab = CreateGrab(client->index, pointer, pWin, 
+    grab = CreateGrab(client->index, pointer, pWin,
         (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
         (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode,
         modifierDevice, stuff->modifiers, ButtonPress,
@@ -5920,7 +5920,7 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
     FocusClassPtr	focus;
     OtherClientsPtr	oc;
     GrabPtr		passive;
-    GrabPtr             grab; 
+    GrabPtr             grab;
 
 
     /* Deactivate any grabs performed on this window, before making any
@@ -5951,7 +5951,7 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
         {
             focus = keybd->focus;
 
-            /* If the focus window is a root window (ie. has no parent) then don't 
+            /* If the focus window is a root window (ie. has no parent) then don't
                delete the focus from it. */
 
             if ((pWin == focus->win) && (pWin->parent != NullWindow))
@@ -6077,14 +6077,14 @@ ProcRecolorCursor(ClientPtr client)
     CursorPtr pCursor;
     int		nscr;
     ScreenPtr	pscr;
-    Bool 	displayed;
+    Bool	displayed;
     SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
     REQUEST(xRecolorCursorReq);
 
     REQUEST_SIZE_MATCH(xRecolorCursorReq);
     pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
 					RT_CURSOR, DixWriteAccess);
-    if ( !pCursor) 
+    if ( !pCursor)
     {
 	client->errorValue = stuff->cursor;
 	return (BadCursor);
@@ -6119,10 +6119,10 @@ ProcRecolorCursor(ClientPtr client)
  * the given event type.
  *
  * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
- * can be more than one. Usually it's just one event. 
+ * can be more than one. Usually it's just one event.
  *
  * Do not modify the event structure passed in. See comment below.
- * 
+ *
  * @param pClient Client to send events to.
  * @param count Number of events.
  * @param events The event list.
@@ -6143,8 +6143,8 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
 #endif
 
 #ifdef PANORAMIX
-    if(!noPanoramiXExtension && 
-       (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) 
+    if(!noPanoramiXExtension &&
+       (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y))
     {
 	switch(events->u.u.type) {
 	case MotionNotify:
@@ -6154,17 +6154,17 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
 	case KeyRelease:
 	case EnterNotify:
 	case LeaveNotify:
-	/* 
+	/*
 	   When multiple clients want the same event DeliverEventsToWindow
-	   passes the same event structure multiple times so we can't 
-	   modify the one passed to us 
+	   passes the same event structure multiple times so we can't
+	   modify the one passed to us
         */
 	    count = 1;  /* should always be 1 */
 	    memcpy(&eventCopy, events, sizeof(xEvent));
 	    eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x;
 	    eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y;
-	    if(eventCopy.u.keyButtonPointer.event == 
-	       eventCopy.u.keyButtonPointer.root) 
+	    if(eventCopy.u.keyButtonPointer.event ==
+	       eventCopy.u.keyButtonPointer.root)
 	    {
 		eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x;
 		eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y;
@@ -6191,7 +6191,7 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
 	    XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
 	}
     }
-#endif	
+#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++)
@@ -6199,7 +6199,7 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
         if (events[i].u.u.type == GenericEvent)
         {
             ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
-            return; 
+            return;
         }
     }
 
@@ -6249,7 +6249,7 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
  * A client can have exactly one ClientPointer. Each time a
  * request/reply/event is processed and the choice of devices is ambiguous
  * (e.g. QueryPointer request), the server will pick the ClientPointer (see
- * PickPointer()). 
+ * PickPointer()).
  * If a keyboard is needed, the first keyboard paired with the CP is used.
  */
 _X_EXPORT Bool
@@ -6261,7 +6261,7 @@ SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device)
         return FALSE;
     } else if (!device->spriteInfo->spriteOwner)
     {
-        ErrorF("[dix] Device %d does not have a sprite. " 
+        ErrorF("[dix] Device %d does not have a sprite. "
                 "Cannot be ClientPointer\n", device->id);
         return FALSE;
     }
@@ -6303,7 +6303,7 @@ PickKeyboard(ClientPtr client)
 
     if (!kbd)
     {
-        ErrorF("[dix] ClientPointer not paired with a keyboard. This " 
+        ErrorF("[dix] ClientPointer not paired with a keyboard. This "
                 "is a bug.\n");
     }
 
@@ -6318,7 +6318,7 @@ PickKeyboard(ClientPtr client)
  * Return true if a core event from the device would interfere and should not
  * be delivered.
  */
-Bool 
+Bool
 IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
 {
     DeviceIntPtr it = inputInfo.devices;
@@ -6359,13 +6359,13 @@ IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
 }
 
 /**
- * Set the filters for a extension. 
+ * 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 
+_X_EXPORT void
 SetGenericFilter(int extension, Mask* filters)
 {
     generic_filters[extension & 0x7f] = filters;
@@ -6377,15 +6377,15 @@ SetGenericFilter(int extension, Mask* filters)
  * grabmode is used to ungrab a device.
  */
 _X_EXPORT int
-ExtGrabDevice(ClientPtr client, 
-              DeviceIntPtr dev, 
+ExtGrabDevice(ClientPtr client,
+              DeviceIntPtr dev,
               int device_mode,
-              WindowPtr grabWindow, 
-              WindowPtr confineTo, 
-              TimeStamp ctime, 
-              Bool ownerEvents, 
-              CursorPtr cursor, 
-              Mask xi_mask, 
+              WindowPtr grabWindow,
+              WindowPtr confineTo,
+              TimeStamp ctime,
+              Bool ownerEvents,
+              CursorPtr cursor,
+              Mask xi_mask,
               GenericMaskPtr ge_masks)
 {
     GrabInfoPtr grabinfo;
commit c703849e79391bb1bb01a994bb8d5cf2eb64e48b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 13 16:50:18 2007 +1030

    dix: Attach spriteInfoRec to same memory block as the DeviceIntRec.
    
    No need to alloc a separate one, we never do anything special with it anyway.

diff --git a/dix/devices.c b/dix/devices.c
index 2c6d3e1..7841e64 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -134,7 +134,7 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
 
     if (devid >= MAX_DEVICES)
 	return (DeviceIntPtr)NULL;
-    dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec), 1);
+    dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), 1);
     if (!dev)
 	return (DeviceIntPtr)NULL;
     dev->name = (char *)NULL;
@@ -183,9 +183,7 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
     dev->enabled = FALSE;
 
     /* sprite defaults */
-    dev->spriteInfo = (SpriteInfoPtr)xcalloc(sizeof(SpriteInfoRec), 1);
-    if (!dev->spriteInfo)
-        return (DeviceIntPtr)NULL;
+    dev->spriteInfo = (SpriteInfoPtr)&dev[1];
     dev->spriteInfo->sprite = NULL;
     dev->spriteInfo->spriteOwner = FALSE;
 
@@ -757,7 +755,6 @@ CloseDevice(DeviceIntPtr dev)
 	xfree(dev->devPrivates);
 
     xfree(dev->deviceGrab.sync.event);
-    xfree(dev->spriteInfo);
     xfree(dev);
 }
 
commit 51239f87ce42ad564ceee1761980391947294511
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 13 11:26:16 2007 +1030

    dix: Send MappingNotify when keyboard maps change.
    
    If a slave device is attached to a master device, then we need to send a
    mapping notify to the client.
    Mapping notify needs to be sent if
     - different slave device but on same master
     - different master
    
    This gives you funny behaviour with the ClientPointer. When a
    MappingNotify is sent to the client, the client usually responds with a
    GetKeyboardMapping. This will retrieve the ClientPointer's keyboard mapping,
    regardless of which keyboard sent the last mapping notify request. So
    depending on the CP setting, your keyboard may change layout in each app...

diff --git a/dix/getevents.c b/dix/getevents.c
index d9adadf..b0211b6 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -867,63 +867,57 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
 
 
 /**
- * Note that pDev was the last device to send a core event.  This function
- * copies the complete keymap from the originating device to the core
- * device, and makes sure the appropriate notifications are generated.
+ * pDev is the slave device that is about to send an event. If it is attached
+ * to a master device, then we need to send a mapping notify to the client.
+ * To do so, we need to remember the last master device that sent a mapping
+ * event.
+ *
+ * Mapping notify needs to be sent in the following cases:
+ *      - different slave device on same master
+ *      - different master
  *
  * Call this just before processInputProc.
+ *
+ * XXX: They way how the code is we also send a map notify if the slave device
+ * stays the same, but the master changes. This isn't really necessary though.
+ *
+ * XXX: this gives you funny behaviour with the ClientPointer. When a
+ * MappingNotify is sent to the client, the client usually responds with a
+ * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
+ * mapping, regardless of which keyboard sent the last mapping notify request.
+ * So depending on the CP setting, your keyboard may change layout in each
+ * app...
  */
 _X_EXPORT void
 SwitchCoreKeyboard(DeviceIntPtr pDev)
 {
-    KeyClassPtr ckeyc = inputInfo.keyboard->key;
+    static DeviceIntPtr lastMapNotifyDevice = NULL;
+    DeviceIntPtr master;
+    KeyClassPtr ckeyc;
     int i = 0;
+    BOOL sendNotify = FALSE;
 
-    if (inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr != pDev) {
-        memcpy(ckeyc->modifierMap, pDev->key->modifierMap, MAP_LENGTH);
-        if (ckeyc->modifierKeyMap)
-            xfree(ckeyc->modifierKeyMap);
-        ckeyc->modifierKeyMap = xalloc(8 * pDev->key->maxKeysPerModifier);
-        memcpy(ckeyc->modifierKeyMap, pDev->key->modifierKeyMap,
-                (8 * pDev->key->maxKeysPerModifier));
-
-        ckeyc->maxKeysPerModifier = pDev->key->maxKeysPerModifier;
-        ckeyc->curKeySyms.minKeyCode = pDev->key->curKeySyms.minKeyCode;
-        ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode;
-        SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms);
-
-        /*
-         * Copy state from the extended keyboard to core.  If you omit this,
-         * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
-         * cause your app to quit.  This feels wrong to me, hence the below
-         * code.
-         *
-         * XXX: If you synthesise core modifier events, the state will get
-         *      clobbered here.  You'll have to work out something sensible
-         *      to fix that.  Good luck.
-         */
-
-#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
-                       Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
-        ckeyc->state &= ~(KEYBOARD_MASK);
-        ckeyc->state |= (pDev->key->state & KEYBOARD_MASK);
-#undef KEYBOARD_MASK
-        for (i = 0; i < 8; i++)
-            ckeyc->modifierKeyCount[i] = pDev->key->modifierKeyCount[i];
+    if (pDev->isMaster || !pDev->u.master)
+        return;
 
-#ifdef XKB
-        if (!noXkbExtension && pDev->key->xkbInfo && pDev->key->xkbInfo->desc) {
-            if (!XkbCopyKeymap(pDev->key->xkbInfo->desc, ckeyc->xkbInfo->desc,
-                               True))
-                FatalError("Couldn't pivot keymap from device to core!\n");
-        }
-#endif
+    master = pDev->u.master;
+    ckeyc = master->key;
+
+    if (master->devPrivates[CoreDevicePrivatesIndex].ptr != pDev) {
+        master->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
+        sendNotify = TRUE;
+    }
+
+    if (lastMapNotifyDevice != master)
+        sendNotify = TRUE;
 
+    if (sendNotify)
+    {
         SendMappingNotify(pDev, MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
                           (ckeyc->curKeySyms.maxKeyCode -
                            ckeyc->curKeySyms.minKeyCode),
                           serverClient);
-        inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = pDev;
+        lastMapNotifyDevice = master;
     }
 }
 
diff --git a/mi/mieq.c b/mi/mieq.c
index f0af4b0..11439cf 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -335,8 +335,9 @@ mieqProcessInputEvents(void)
             if ((e->events->event[0].u.u.type == DeviceKeyPress ||
                 e->events->event[0].u.u.type == DeviceKeyRelease ||
                 e->events->event[0].u.u.type == KeyPress ||
-                e->events->event[0].u.u.type == KeyRelease) && 
-                    e->pDev->coreEvents) {
+                e->events->event[0].u.u.type == KeyRelease) &&
+                    !e->pDev->isMaster)
+            {
                 SwitchCoreKeyboard(e->pDev);
             }
 
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index e87064a..d49a3c6 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -935,7 +935,10 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
     xkbMapNotify mn;
     xkbNewKeyboardNotify nkn;
 
-    if (!src || !dst || src == dst)
+    if (src == dst)
+        return TRUE;
+
+    if (!src || !dst)
         return FALSE;
 
     /* client map */
commit 2b1d946392ce28b96941341778b2b526aa0fb126
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 13 09:51:33 2007 +1030

    xkb: disable xkb key repeats (temporarily)
    
    Haven't quite figured out yet how to make these repeats work. Because we share
    the class between devices, the key state is already set when we process the
    master device's event, causing a repeat on each event.

diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c
index f007f75..147df3e 100644
--- a/xkb/xkbPrKeyEv.c
+++ b/xkb/xkbPrKeyEv.c
@@ -76,6 +76,7 @@ int             xiEvent;
     if ((behavior.type&XkbKB_Permanent)==0) {
 	switch (behavior.type) {
 	    case XkbKB_Default:
+#if 0
 		if (( xE->u.u.type == KeyPress || 
                             xE->u.u.type == DeviceKeyPress) && 
 		    (keyc->down[key>>3] & (1<<(key&7)))) {
@@ -112,6 +113,7 @@ int             xiEvent;
 		    XkbLastRepeatEvent= NULL;
 		    return;
 		}
+#endif
 		break;
 	    case XkbKB_Lock:
 		if ( xE->u.u.type == KeyRelease || 
commit 70b4087c4dd1904d9d655f4afb9dfcea4f137f7a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 12 13:10:39 2007 +1030

    dix: don't unconditionally update valuators during key events.
    
    Master may not have valuators, device may not have valuators.

diff --git a/dix/getevents.c b/dix/getevents.c
index e366d22..d9adadf 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -485,8 +485,11 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
     {
         CreateClassesChangedEvent(events, master, pDev);
 
-        pDev->valuator->lastx = master->valuator->lastx;
-        pDev->valuator->lasty = master->valuator->lasty;
+        if (master->valuator && pDev->valuator)
+        {
+            pDev->valuator->lastx = master->valuator->lastx;
+            pDev->valuator->lasty = master->valuator->lasty;
+        }
         master->u.lastSlave = pDev;
         numEvents++;
         events++;
commit 23365d28651f7942fdafb889bcbbd019470a4274
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 12 13:08:38 2007 +1030

    dix: allow grab modifier device to be NULL.
    
    This can happen if we check for a passive core grab and our device is a
    floating slave device. Doesn't really change anything as SDs can't send core
    events but it stops the server from segfaulting.

diff --git a/dix/events.c b/dix/events.c
index c3589f0..daebe35 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3379,7 +3379,7 @@ CheckPassiveGrabsOnWindow(
     {
 #ifdef XKB
 	DeviceIntPtr	gdev;
-	XkbSrvInfoPtr	xkbi;
+	XkbSrvInfoPtr	xkbi = NULL;
 
 	gdev= grab->modifierDevice;
         if (grab->coreGrab)
@@ -3389,7 +3389,8 @@ CheckPassiveGrabsOnWindow(
             else
                 gdev = device;
         }
-	xkbi= gdev->key->xkbInfo;
+        if (gdev)
+            xkbi= gdev->key->xkbInfo;
 #endif
 	tempGrab.modifierDevice = grab->modifierDevice;
 	if ((device == grab->modifierDevice) &&
@@ -3400,16 +3401,20 @@ CheckPassiveGrabsOnWindow(
 	     ))
 	    tempGrab.modifiersDetail.exact =
 #ifdef XKB
-		(noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods);
+                (noXkbExtension) ?
+                        ((gdev) ? gdev->key->prev_state : 0) :
+                        ((xkbi) ?  xkbi->state.grab_mods : 0);
 #else
-		grab->modifierDevice->key->prev_state;
+                (gdev) ? gdev->key->prev_state : 0;
 #endif
 	else
 	    tempGrab.modifiersDetail.exact =
 #ifdef XKB
-		(noXkbExtension ? gdev->key->state : xkbi->state.grab_mods);
+                (noXkbExtension) ?
+                        ((gdev) ? gdev->key->state : 0) :
+                        ((xkbi) ? xkbi->state.grab_mods : 0);
 #else
-		grab->modifierDevice->key->state;
+                (gdev) ? gdev->key->state : 0;
 #endif
             /* ignore the device for core events when comparing grabs */
 	if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) &&
commit 5a7a65a3c978a65e8ff39d0cc9878527ec42adc9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 12 12:37:39 2007 +1030

    mi: avoid SIGABRT by setting master_event to NULL.

diff --git a/mi/mieq.c b/mi/mieq.c
index 7ea12fe..f0af4b0 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -363,7 +363,8 @@ mieqProcessInputEvents(void)
             {
                 CopyGetMasterEvent(e->pDev->u.master, event,
                                    &master_event, e->nevents);
-            }
+            } else
+                master_event = NULL;
 
             /* process slave first, then master */
             e->pDev->public.processInputProc(event, e->pDev, e->nevents);
commit a05f43bf3e9629df98e93c366d4327f20ed81e6c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 12 11:35:18 2007 +1030

    dix: When the last slave is removed, set master to the original classes.
    
    DeviceClassesChangedEvent is sent to the client, where device == new slave.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 617aef7..3ef3200 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -162,25 +162,10 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 
         /* event is already correct size, see comment in GetPointerEvents */
         classbuff = (char*)&xE[1];
-        if (master->key) 
-        {
-            /* we don't actually swap here, swapping is done later */
-            CopySwapKeyClass(NullClient, master->key, &classbuff);
-            dcce->num_classes++;
-        }
-        if (master->button) 
-        {
-            CopySwapButtonClass(NullClient, master->button, &classbuff);
-            dcce->num_classes++;
-        }
-        if (master->valuator)
-        {
-            CopySwapValuatorClass(NullClient, master->valuator, &classbuff);
-            dcce->num_classes++;
-        }
-
-        SendEventToAllWindows(master, XI_DeviceClassesChangedMask,
-                              xE, 1);
+        /* we don't actually swap if there's a NullClient, swapping is done
+         * later when event is delivered. */
+        CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff);
+        SendEventToAllWindows(master, XI_DeviceClassesChangedMask, xE, 1);
         return;
     }
 
diff --git a/Xi/listdev.c b/Xi/listdev.c
index 962998e..1810c9b 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -142,7 +142,7 @@ CopyDeviceName(char **namebuf, char *name)
  *
  */
 
-void
+static void
 CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf)
 {
     char n;
@@ -201,7 +201,7 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
  *
  */
 
-void
+static void
 CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
 {
     char n;
@@ -231,7 +231,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
  *
  */
 
-int
+static int
 CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf)
 {
     int i, j, axes, t_axes;
@@ -286,17 +286,24 @@ ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev,
 {
     CopyDeviceName(namebuf, d->name);
     CopySwapDevice(client, d, 0, devbuf);
-    if (d->key != NULL) {
-	CopySwapKeyClass(client, d->key, classbuf);
-	dev->num_classes++;
+    CopySwapClasses(client, d, &dev->num_classes, classbuf);
+}
+
+void
+CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes,
+                char** classbuf)
+{
+    if (dev->key != NULL) {
+	CopySwapKeyClass(client, dev->key, classbuf);
+	(*num_classes)++;
     }
-    if (d->button != NULL) {
-	CopySwapButtonClass(client, d->button, classbuf);
-	dev->num_classes++;
+    if (dev->button != NULL) {
+	CopySwapButtonClass(client, dev->button, classbuf);
+	(*num_classes)++;
     }
-    if (d->valuator != NULL) {
-	dev->num_classes +=
-	    CopySwapValuatorClass(client, d->valuator, classbuf);
+    if (dev->valuator != NULL) {
+	(*num_classes) +=
+	    CopySwapValuatorClass(client, dev->valuator, classbuf);
     }
 }
 
diff --git a/Xi/listdev.h b/Xi/listdev.h
index afdcd69..22a0d91 100644
--- a/Xi/listdev.h
+++ b/Xi/listdev.h
@@ -44,15 +44,9 @@ void SRepXListInputDevices(ClientPtr /* client */ ,
     );
 
 void
-CopySwapKeyClass(ClientPtr /* client */, 
-                 KeyClassPtr /* k */, 
-                 char** /* buf */);
-void
-CopySwapButtonClass(ClientPtr /* client */, 
-                    ButtonClassPtr /* b */, 
-                    char** /* buf */);
-int
-CopySwapValuatorClass(ClientPtr /* client */, 
-                      ValuatorClassPtr /* v */, 
-                      char** /* buf */);
+CopySwapClasses(ClientPtr /* client */,
+                DeviceIntPtr /* dev */,
+                CARD8* /* num_classes */,
+                char** /* classbuf */);
+
 #endif /* LISTDEV_H */
diff --git a/dix/devices.c b/dix/devices.c
index b423378..2c6d3e1 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -79,6 +79,7 @@ SOFTWARE.
 #include <X11/extensions/XIproto.h>
 #include "exglobals.h"
 #include "exevents.h"
+#include "listdev.h" /* for CopySwapXXXClass */
 
 /** @file
  * This file handles input device-related stuff.
@@ -2314,9 +2315,50 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
      */
     if (!master)
     {
+        DeviceIntPtr it;
                               /* current root window */
         InitializeSprite(dev, dev->spriteInfo->sprite->spriteTrace[0]);
         dev->spriteInfo->spriteOwner = FALSE;
+
+        /* the master may need to restore the original classes, search for a
+         * device that is still paired with our master. */
+        for (it = inputInfo.devices; it; it = it->next)
+            if (!it->isMaster && it->u.master == master)
+                break;
+
+        if (!it)  /* no dev is paired with our master */
+        {
+            ClassesPtr classes;
+            EventList event = { NULL, 0};
+            char* classbuf;
+
+            classes = master->devPrivates[MasterDevClassesPrivIdx].ptr;
+            master->key = classes->key;
+            master->valuator = classes->valuator;
+            master->button = classes->button;
+            master->focus = classes->focus;
+            master->proximity = classes->proximity;
+            master->absolute = classes->absolute;
+            master->kbdfeed = classes->kbdfeed;
+            master->ptrfeed = classes->ptrfeed;
+            master->intfeed = classes->intfeed;
+            master->stringfeed = classes->stringfeed;
+            master->bell = classes->bell;
+            master->leds = classes->leds;
+
+            /* Send event to clients */
+            CreateClassesChangedEvent(&event, master, master);
+            deviceClassesChangedEvent *dcce = 
+                        (deviceClassesChangedEvent*)event.event;
+            dcce->deviceid = master->id;
+            dcce->num_classes = 0;
+            classbuf = (char*)&event.event[1];
+            CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuf);
+            SendEventToAllWindows(master, XI_DeviceClassesChangedMask, 
+                    event.event, 1);
+            xfree(event.event);
+        }
+
     } else
         dev->spriteInfo->sprite = master->spriteInfo->sprite;
 
diff --git a/dix/getevents.c b/dix/getevents.c
index 425b602..e366d22 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -111,7 +111,7 @@ key_autorepeats(DeviceIntPtr pDev, int key_code)
               (1 << (key_code & 7)));
 }
 
-static void
+void
 CreateClassesChangedEvent(EventList* event, 
                           DeviceIntPtr master, 
                           DeviceIntPtr slave)
diff --git a/include/input.h b/include/input.h
index d6a38e6..dbf6aee 100644
--- a/include/input.h
+++ b/include/input.h
@@ -402,6 +402,9 @@ extern int GetMaximumEventsNum(void);
 extern EventListPtr InitEventList(int num_events);
 extern void FreeEventList(EventListPtr list, int num_events);
 
+extern void CreateClassesChangedEvent(EventListPtr event, 
+                                      DeviceIntPtr master,
+                                      DeviceIntPtr slave);
 extern int GetPointerEvents(
     EventListPtr events,
     DeviceIntPtr pDev,
commit 7a81bafc9bc7048560b17483e6addf58469a05d0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 9 23:10:24 2007 +1030

    Xi, dix: Add ability to change MD classes + send event when doing so.
    
    Each time a different slave device sends through a master, an
    DeviceClassesChangedEvent is enqueued. When this event is processed, all
    classes of the matching master device are changed, and the event is sent to
    the clients.
    
    Next time the master is queried, it thus shows the evclasses of the last slave
    device. The original classes are stored in the devPrivates.
    
    TODO: if all slave devices are removed, the master's original classes need to
    be restored.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 4c57fd0..617aef7 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -73,6 +73,7 @@ SOFTWARE.
 #include "dixevents.h"	/* DeliverFocusedEvent */
 #include "dixgrabs.h"	/* CreateGrab() */
 #include "scrnintstr.h"
+#include "listdev.h" /* for CopySwapXXXClass */
 
 #ifdef XKB
 #include "xkbsrv.h"
@@ -127,6 +128,62 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     xEvent core;
     int coretype = 0;
 
+    /* This event is always the first we get, before the actual events with
+     * the data. However, the way how the DDX is set up, "device" will
+     * actually be the slave device that caused the event.
+     */
+    if (GEIsType(xE, IReqCode, XI_DeviceClassesChangedNotify))
+    {
+        deviceClassesChangedEvent* dcce = (deviceClassesChangedEvent*)xE;
+        DeviceIntPtr master = device->u.master;
+        char* classbuff;
+
+        if (device->isMaster)
+            return;
+
+        if (!master) /* if device was set floating between SIGIO and now */
+            return;
+
+        dcce->deviceid     = master->id;
+        dcce->num_classes  = 0;
+
+        master->key        = device->key;
+        master->valuator   = device->valuator;
+        master->button     = device->button;
+        master->focus      = device->focus;
+        master->proximity  = device->proximity;
+        master->absolute   = device->absolute;
+        master->kbdfeed    = device->kbdfeed;
+        master->ptrfeed    = device->ptrfeed;
+        master->intfeed    = device->intfeed;
+        master->stringfeed = device->stringfeed;
+        master->bell       = device->bell;
+        master->leds       = device->leds;
+
+        /* event is already correct size, see comment in GetPointerEvents */
+        classbuff = (char*)&xE[1];
+        if (master->key) 
+        {
+            /* we don't actually swap here, swapping is done later */
+            CopySwapKeyClass(NullClient, master->key, &classbuff);
+            dcce->num_classes++;
+        }
+        if (master->button) 
+        {
+            CopySwapButtonClass(NullClient, master->button, &classbuff);
+            dcce->num_classes++;
+        }
+        if (master->valuator)
+        {
+            CopySwapValuatorClass(NullClient, master->valuator, &classbuff);
+            dcce->num_classes++;
+        }
+
+        SendEventToAllWindows(master, XI_DeviceClassesChangedMask,
+                              xE, 1);
+        return;
+    }
+
     coretype = XItoCoreType(xE->u.u.type);
     if (device->isMaster && device->coreEvents && coretype)
         sendCore = TRUE;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 0ecb421..017b693 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -703,6 +703,53 @@ SRawDeviceEvent(rawDeviceEvent* from, rawDeviceEvent *to)
         swapl(valptr, n);
 }
 
+static void
+SDeviceClassesChangedEvent(deviceClassesChangedEvent* from, 
+                           deviceClassesChangedEvent* to)
+{
+    char n;
+    int i, j;
+    xAnyClassPtr any;
+
+    *to = *from;
+    memcpy(&to[1], &from[1], from->length * 4);
+
+    swaps(&to->sequenceNumber, n);
+    swapl(&to->length, n);
+    swapl(&to->time, n);
+    
+    /* now swap the actual classes */
+    any = (xAnyClassPtr)&to[1];
+    for (i = 0; i < to->num_classes; i++)
+    {
+        switch(any->class)
+        {
+            case KeyClass:
+                swaps(&((xKeyInfoPtr)any)->num_keys, n);
+                break;
+            case ButtonClass:
+                swaps(&((xButtonInfoPtr)any)->num_buttons, n);
+                break;
+            case ValuatorClass:
+                {
+                    xValuatorInfoPtr v = (xValuatorInfoPtr)any;
+                    xAxisInfoPtr a = (xAxisInfoPtr)&v[1];
+
+                    swapl(&v->motion_buffer_size, n);
+                    for (j = 0; j < v->num_axes; j++)
+                    {
+                        swapl(&a->min_value, n);
+                        swapl(&a->max_value, n);
+                        swapl(&a->resolution, n);
+                        a++;
+                    }
+                }
+                break;
+        }
+        any = (xAnyClassPtr)((char*)any + any->length);
+    }
+}
+
 /**************************************************************************
  *
  * Allow the specified event to have its propagation suppressed.
@@ -1153,6 +1200,10 @@ XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
         case XI_RawDeviceEvent:
             SRawDeviceEvent((rawDeviceEvent*)from, (rawDeviceEvent*)to);
             break;
+        case XI_DeviceClassesChangedNotify:
+            SDeviceClassesChangedEvent((deviceClassesChangedEvent*)from, 
+                                       (deviceClassesChangedEvent*)to);
+            break;
     }
 }
 
diff --git a/Xi/listdev.c b/Xi/listdev.c
index 8753b29..962998e 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -68,7 +68,6 @@ SOFTWARE.
 
 #include "listdev.h"
 
-#define VPC	20	/* Max # valuators per chunk */
 
 /***********************************************************************
  *
@@ -143,7 +142,7 @@ CopyDeviceName(char **namebuf, char *name)
  *
  */
 
-static void
+void
 CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf)
 {
     char n;
@@ -153,7 +152,7 @@ CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf)
     b2->class = ButtonClass;
     b2->length = sizeof(xButtonInfo);
     b2->num_buttons = b->numButtons;
-    if (client->swapped) {
+    if (client && client->swapped) {
 	swaps(&b2->num_buttons, n);	/* macro - braces are required */
     }
     *buf += sizeof(xButtonInfo);
@@ -202,7 +201,7 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
  *
  */
 
-static void
+void
 CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
 {
     char n;
@@ -214,7 +213,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
     k2->min_keycode = k->curKeySyms.minKeyCode;
     k2->max_keycode = k->curKeySyms.maxKeyCode;
     k2->num_keys = k2->max_keycode - k2->min_keycode + 1;
-    if (client->swapped) {
+    if (client && client->swapped) {
 	swaps(&k2->num_keys, n);
     }
     *buf += sizeof(xKeyInfo);
@@ -232,7 +231,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf)
  *
  */
 
-static int
+int
 CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf)
 {
     int i, j, axes, t_axes;
@@ -252,7 +251,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf)
 	v2->num_axes = t_axes;
 	v2->mode = v->mode & DeviceMode;
 	v2->motion_buffer_size = v->numMotionEvents;
-	if (client->swapped) {
+	if (client && client->swapped) {
 	    swapl(&v2->motion_buffer_size, n);
 	}
 	*buf += sizeof(xValuatorInfo);
@@ -262,7 +261,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf)
 	    a2->min_value = a->min_value;
 	    a2->max_value = a->max_value;
 	    a2->resolution = a->resolution;
-	    if (client->swapped) {
+	    if (client && client->swapped) {
 		swapl(&a2->min_value, n);
 		swapl(&a2->max_value, n);
 		swapl(&a2->resolution, n);
diff --git a/Xi/listdev.h b/Xi/listdev.h
index db376de..afdcd69 100644
--- a/Xi/listdev.h
+++ b/Xi/listdev.h
@@ -30,6 +30,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #ifndef LISTDEV_H
 #define LISTDEV_H 1
 
+#define VPC	20	/* Max # valuators per chunk */
+
 int SProcXListInputDevices(ClientPtr	/* client */
     );
 
@@ -41,4 +43,16 @@ void SRepXListInputDevices(ClientPtr /* client */ ,
 			   xListInputDevicesReply *	/* rep */
     );
 
+void
+CopySwapKeyClass(ClientPtr /* client */, 
+                 KeyClassPtr /* k */, 
+                 char** /* buf */);
+void
+CopySwapButtonClass(ClientPtr /* client */, 
+                    ButtonClassPtr /* b */, 
+                    char** /* buf */);
+int
+CopySwapValuatorClass(ClientPtr /* client */, 
+                      ValuatorClassPtr /* v */, 
+                      char** /* buf */);
 #endif /* LISTDEV_H */
diff --git a/dix/devices.c b/dix/devices.c
index c9831ea..b423378 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -84,8 +84,25 @@ SOFTWARE.
  * This file handles input device-related stuff.
  */
 
+typedef struct {
+    KeyClassPtr		key;
+    ValuatorClassPtr	valuator;
+    ButtonClassPtr	button;
+    FocusClassPtr	focus;
+    ProximityClassPtr	proximity;
+    AbsoluteClassPtr    absolute;
+    KbdFeedbackPtr	kbdfeed;
+    PtrFeedbackPtr	ptrfeed;
+    IntegerFeedbackPtr	intfeed;
+    StringFeedbackPtr	stringfeed;
+    BellFeedbackPtr	bell;
+    LedFeedbackPtr	leds;
+} ClassesRec, *ClassesPtr;
+
+
 int CoreDevicePrivatesIndex = 0;
 static int CoreDevicePrivatesGeneration = -1;
+int MasterDevClassesPrivIdx = -1;
 
 /* The client that is allowed to change pointer-keyboard pairings. */
 static ClientPtr pairingClient = NULL;
@@ -385,9 +402,16 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
 #ifdef XKB
     XkbComponentNamesRec names;
 #endif
+    ClassesPtr classes;
 
     switch (what) {
     case DEVICE_INIT:
+        if (MasterDevClassesPrivIdx == -1)
+            MasterDevClassesPrivIdx = AllocateDevicePrivateIndex();
+
+        if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) ||
+                !(classes = xcalloc(1, sizeof(ClassesRec))))
+
         keySyms.minKeyCode = 8;
         keySyms.maxKeyCode = 255;
         keySyms.mapWidth = 4;
@@ -425,6 +449,19 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
         xfree(keySyms.map);
         xfree(modMap);
 
+        classes->key = pDev->key;
+        classes->valuator = pDev->valuator;
+        classes->button = pDev->button;
+        classes->focus = pDev->focus;
+        classes->proximity = pDev->proximity;
+        classes->absolute = pDev->absolute;
+        classes->kbdfeed = pDev->kbdfeed;
+        classes->ptrfeed = pDev->ptrfeed;
+        classes->intfeed = pDev->intfeed;
+        classes->stringfeed = pDev->stringfeed;
+        classes->bell = pDev->bell;
+        classes->leds = pDev->leds;
+        pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes;
         break;
 
     case DEVICE_CLOSE:
@@ -439,15 +476,27 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
 
 /**
  * Device control function for the Virtual Core Pointer.
+ * 
+ * Aside from initialisation, it backs up the original device classes into the
+ * devicePrivates. This only needs to be done for master devices.
  */
 static int
 CorePointerProc(DeviceIntPtr pDev, int what)
 {
     BYTE map[33];
     int i = 0;
+    ClassesPtr classes;
+
 
     switch (what) {
     case DEVICE_INIT:
+        if (MasterDevClassesPrivIdx == -1)
+            MasterDevClassesPrivIdx = AllocateDevicePrivateIndex();
+
+        if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) || 
+                !(classes = xcalloc(1, sizeof(ClassesRec))))
+            return BadAlloc;
+
         for (i = 1; i <= 32; i++)
             map[i] = i;
         InitPointerDeviceStruct((DevicePtr)pDev, map, 32,
@@ -457,6 +506,21 @@ CorePointerProc(DeviceIntPtr pDev, int what)
         pDev->valuator->lastx = pDev->valuator->axisVal[0];
         pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
         pDev->valuator->lasty = pDev->valuator->axisVal[1];
+
+        classes->key = pDev->key;
+        classes->valuator = pDev->valuator;
+        classes->button = pDev->button;
+        classes->focus = pDev->focus;
+        classes->proximity = pDev->proximity;
+        classes->absolute = pDev->absolute;
+        classes->kbdfeed = pDev->kbdfeed;
+        classes->ptrfeed = pDev->ptrfeed;
+        classes->intfeed = pDev->intfeed;
+        classes->stringfeed = pDev->stringfeed;
+        classes->bell = pDev->bell;
+        classes->leds = pDev->leds;
+
+        pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes;
         break;
 
     case DEVICE_CLOSE:
@@ -574,6 +638,7 @@ CloseDevice(DeviceIntPtr dev)
     BellFeedbackPtr b, bnext;
     LedFeedbackPtr l, lnext;
     ScreenPtr screen = screenInfo.screens[0];
+    ClassesPtr classes;
     int j;
 
     if (!dev)
@@ -588,41 +653,46 @@ CloseDevice(DeviceIntPtr dev)
 
     xfree(dev->name);
 
-    if (dev->key) {
+    if (dev->isMaster)
+        classes = (ClassesPtr)dev->devPrivates[MasterDevClassesPrivIdx].ptr;
+    else 
+        classes = (ClassesPtr)&dev->key;
+
+    if (classes->key) {
 #ifdef XKB
-	if (dev->key->xkbInfo)
-	    XkbFreeInfo(dev->key->xkbInfo);
+	if (classes->key->xkbInfo)
+	    XkbFreeInfo(classes->key->xkbInfo);
 #endif
-	xfree(dev->key->curKeySyms.map);
-	xfree(dev->key->modifierKeyMap);
-	xfree(dev->key);
+	xfree(classes->key->curKeySyms.map);
+	xfree(classes->key->modifierKeyMap);
+	xfree(classes->key);
     }
 
-    if (dev->valuator) {
+    if (classes->valuator) {
         /* Counterpart to 'biggest hack ever' in init. */
-        if (dev->valuator->motion &&
-            dev->valuator->GetMotionProc == GetMotionHistory)
-            xfree(dev->valuator->motion);
-        xfree(dev->valuator);
+        if (classes->valuator->motion &&
+            classes->valuator->GetMotionProc == GetMotionHistory)
+            xfree(classes->valuator->motion);
+        xfree(classes->valuator);
     }
 
-    if (dev->button) {
+    if (classes->button) {
 #ifdef XKB
-        if (dev->button->xkb_acts)
-            xfree(dev->button->xkb_acts);
+        if (classes->button->xkb_acts)
+            xfree(classes->button->xkb_acts);
 #endif
-        xfree(dev->button);
+        xfree(classes->button);
     }
 
-    if (dev->focus) {
-	xfree(dev->focus->trace);
-	xfree(dev->focus);
+    if (classes->focus) {
+	xfree(classes->focus->trace);
+	xfree(classes->focus);
     }
 
-    if (dev->proximity)
-        xfree(dev->proximity);
+    if (classes->proximity)
+        xfree(classes->proximity);
 
-    for (k = dev->kbdfeed; k; k = knext) {
+    for (k = classes->kbdfeed; k; k = knext) {
 	knext = k->next;
 #ifdef XKB
 	if (k->xkb_sli)
@@ -631,29 +701,29 @@ CloseDevice(DeviceIntPtr dev)
 	xfree(k);
     }
 
-    for (p = dev->ptrfeed; p; p = pnext) {
+    for (p = classes->ptrfeed; p; p = pnext) {
 	pnext = p->next;
 	xfree(p);
     }
     
-    for (i = dev->intfeed; i; i = inext) {
+    for (i = classes->intfeed; i; i = inext) {
 	inext = i->next;
 	xfree(i);
     }
 
-    for (s = dev->stringfeed; s; s = snext) {
+    for (s = classes->stringfeed; s; s = snext) {
 	snext = s->next;
 	xfree(s->ctrl.symbols_supported);
 	xfree(s->ctrl.symbols_displayed);
 	xfree(s);
     }
 
-    for (b = dev->bell; b; b = bnext) {
+    for (b = classes->bell; b; b = bnext) {
 	bnext = b->next;
 	xfree(b);
     }
 
-    for (l = dev->leds; l; l = lnext) {
+    for (l = classes->leds; l; l = lnext) {
 	lnext = l->next;
 #ifdef XKB
 	if (l->xkb_sli)
diff --git a/dix/getevents.c b/dix/getevents.c
index a23eabe..425b602 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -67,6 +67,7 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
 #include "exevents.h"
 #include "exglobals.h"
 #include "extnsionst.h"
+#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
 
 /* Maximum number of valuators, divided by six, rounded up, to get number
  * of events. */
@@ -110,6 +111,52 @@ key_autorepeats(DeviceIntPtr pDev, int key_code)
               (1 << (key_code & 7)));
 }
 
+static void
+CreateClassesChangedEvent(EventList* event, 
+                          DeviceIntPtr master, 
+                          DeviceIntPtr slave)
+{
+    deviceClassesChangedEvent *dcce; 
+    int len = sizeof(xEvent);
+    CARD32 ms = GetTimeInMillis();
+
+    /* XXX: ok, this is a bit weird. We need to alloc enough size for the
+     * event so it can be filled in in POE lateron. Reason being that if
+     * we realloc the event in POE we can get SIGABRT when we try to free
+     * or realloc the original pointer. 
+     * We can only do it here as we don't have the EventList in the event
+     * processing any more.
+     *
+     * Code is basically same as in Xi/listdev.c
+     */
+    if (slave->key)
+        len += sizeof(xKeyInfo);
+    if (slave->button)
+        len += sizeof(xButtonInfo);
+    if (slave->valuator)
+    {
+        int chunks = ((int)slave->valuator->numAxes + 19) / VPC;
+        len += (chunks * sizeof(xValuatorInfo) +
+                slave->valuator->numAxes * sizeof(xAxisInfo));
+    }
+    if (event->evlen < len)
+    {
+        event->event = realloc(event->event, len);
+        if (!event->event)
+            FatalError("[dix] Cannot allocate memory for "
+                    "DeviceClassesChangedEvent.\n");
+        event->evlen = len;
+    }
+
+    dcce = (deviceClassesChangedEvent*)event->event;
+    dcce->type = GenericEvent;
+    dcce->extension = IReqCode;
+    dcce->evtype = XI_DeviceClassesChangedNotify;
+    dcce->time = ms;
+    dcce->new_slave = slave->id;
+    dcce->length = (len - sizeof(xEvent))/4;
+}
+
 /**
  * Allocate the motion history buffer.
  */
@@ -415,6 +462,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
     KeySym *map = pDev->key->curKeySyms.map;
     KeySym sym = map[key_code * pDev->key->curKeySyms.mapWidth];
     deviceKeyButtonPointer *kbp = NULL;
+    DeviceIntPtr master;
 
     if (!events)
         return 0;
@@ -432,6 +480,18 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
     if (key_code < 8 || key_code > 255)
         return 0;
 
+    master = pDev->u.master;
+    if (master && master->u.lastSlave != pDev)
+    {
+        CreateClassesChangedEvent(events, master, pDev);
+
+        pDev->valuator->lastx = master->valuator->lastx;
+        pDev->valuator->lasty = master->valuator->lasty;
+        master->u.lastSlave = pDev;
+        numEvents++;
+        events++;
+    }
+
     if (num_valuators) {
         if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS)
             num_valuators = MAX_VALUATOR_EVENTS;
@@ -606,37 +666,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     master = pDev->u.master;
     if (master && master->u.lastSlave != pDev)
     {
-#if 0
-        /* XXX: we should enqueue the state changed event here */
-        devStateEvent *state; 
-        num_events++;
-        state = events->event;
-
-        state->type = GenericEvent;
-        state->extension = IReqCode;
-        state->evtype = XI_DeviceStateChangedNotify;
-        state->deviceid = master->deviceid;
-        state->new_slave = pDev->id;
-        state->time = ms;
-        events++;
-
-#endif
+        CreateClassesChangedEvent(events, master, pDev);
 
-        /* now we need to update our device to the master's device - welcome
-         * to hell. 
-         * We need to match each device's capabilities to the previous
-         * capabilities as used by the master. Valuator[N] of master has to
-         * be written into valuator[N] of pDev. For all relative valuators.
-         * Otherwise we get jumpy valuators.
-         *
-         * However, this if iffy, if pDev->num_valuators !=
-         * master->num_valuators. What do we do with the others? 
-         * 
-         * XXX: just do lastx/y for now.
-         */
         pDev->valuator->lastx = master->valuator->lastx;
         pDev->valuator->lasty = master->valuator->lasty;
         master->u.lastSlave = pDev;
+
+        num_events++;
+        events++;
     }
 
     /* Do we need to send a DeviceValuator event? */
@@ -652,8 +689,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes)
         return 0;
 
-
-
     /* fill up the raw event, after checking that it is large enough to
      * accommodate all valuators. 
      */
diff --git a/mi/mieq.c b/mi/mieq.c
index 26eab6f..7ea12fe 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -243,12 +243,13 @@ ChangeDeviceID(DeviceIntPtr dev, xEvent* event)
     else if (type == GenericEvent)
     {
         /* FIXME: need to put something into XGE to make this saner */
-        xGenericEvent* generic = (xGenericEvent*)event;
-        if (generic->extension == IReqCode
-                && generic->evtype == XI_RawDeviceEvent)
+        if (GEIsType(event, IReqCode, XI_RawDeviceEvent))
         {
             rawDeviceEvent* raw = (rawDeviceEvent*)event;
             raw->deviceid = dev->id;
+        } else if (GEIsType(event, IReqCode, XI_DeviceClassesChangedNotify))
+        {
+            // do nothing or drink a beer. your choice.
         } else
             ErrorF("[mi] Unknown generic event, cannot change id.\n");
     } else
commit c0a05805783ee3d38fbcc0fb45f4aa3c511785f0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 9 23:07:10 2007 +1030

    Xext: add simple macro to easily check a generic event's type.

diff --git a/Xext/geext.h b/Xext/geext.h
index f3352c2..1ba71e0 100644
--- a/Xext/geext.h
+++ b/Xext/geext.h
@@ -87,6 +87,12 @@ extern GEExtension GEExtensions[MAXEXTENSIONS];
 #define GEEventFill(ev) \
     GEExtensions[GEEXTIDX(xE)].evfill
 
+#define GEIsType(ev, ext, ev_type) \
+        ((ev->u.u.type == GenericEvent) &&  \
+         ((xGenericEvent*)(ev))->extension == ext && \
+         ((xGenericEvent*)(ev))->evtype == ev_type)
+
+
 /* Interface for other extensions */
 void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask);
 void GERegisterExtension(
commit 5bbc468b702f62d7c91d41aabcc27eeb553f6959
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 9 11:33:27 2007 +1030

    dix: grabbing an attached SD sets it floating for the duration of the grab.

diff --git a/dix/events.c b/dix/events.c
index 8a87618..c3589f0 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -237,6 +237,7 @@ _X_EXPORT CallbackListPtr DeviceEventCallback;
 Mask DontPropagateMasks[DNPMCOUNT];
 static int DontPropagateRefCnts[DNPMCOUNT];
 
+
 /**
  * Main input device struct. 
  *     inputInfo.pointer 
@@ -1540,6 +1541,54 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
     ComputeFreezes();
 }
 
+/* Only ever used if a grab is called on an attached slave device. */
+static int GrabPrivateIndex = -1;
+typedef struct _GrabMemoryRec {
+    DeviceIntPtr oldmaster;
+} GrabMemoryRec, *GrabMemoryPtr;
+
+/**
+ * Save the device's master device in the devPrivates. This needs to be done
+ * if a client directly grabs a slave device that is attached to a master. For
+ * the duration of the grab, the device is detached, ungrabbing re-attaches it
+ * though.
+ */
+static void
+SaveOldMaster(DeviceIntPtr dev)
+{
+    GrabMemoryPtr gm;
+
+    if (GrabPrivateIndex == -1)
+        GrabPrivateIndex = AllocateDevicePrivateIndex();
+
+    if (!AllocateDevicePrivate(dev, GrabPrivateIndex) ||
+            !(gm = xalloc(sizeof(GrabMemoryRec))))
+    {
+        ErrorF("[dix] Cannot allocate grab private. Grab not "
+                "possible on device.\n");
+        return;
+    }
+    gm->oldmaster = dev->u.master;
+    dev->devPrivates[GrabPrivateIndex].ptr = gm;
+}
+
+static void
+RestoreOldMaster(DeviceIntPtr dev)
+{
+    GrabMemoryPtr gm;
+
+    if (dev->isMaster || GrabPrivateIndex == -1)
+        return;
+
+    gm = ((GrabMemoryPtr)dev->devPrivates[GrabPrivateIndex].ptr);
+    if (gm)
+    {
+        dev->u.master = gm->oldmaster;
+        xfree(gm);
+        dev->devPrivates[GrabPrivateIndex].ptr = NULL;
+    }
+}
+
 /**
  * Activate a pointer grab on the given device. A pointer grab will cause all
  * core pointer events of this device to be delivered to the grabbing client only. 
@@ -1563,6 +1612,14 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
     WindowPtr oldWin = (grabinfo->grab) ? 
                         grabinfo->grab->window
                         : mouse->spriteInfo->sprite->win;
+    Bool isPassive = autoGrab & ~ImplicitGrabMask;
+
+    /* slave devices need to float for the duration of the grab. */
+    if (!isPassive && !mouse->isMaster)
+    {
+        SaveOldMaster(mouse);
+        AttachDevice(NULL, mouse, NULL);
+    }
 
     if (grab->confineTo)
     {
@@ -1582,7 +1639,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
 	grab->cursor->refcnt++;
     grabinfo->activeGrab = *grab;
     grabinfo->grab = &grabinfo->activeGrab;
-    grabinfo->fromPassiveGrab = autoGrab & ~ImplicitGrabMask;
+    grabinfo->fromPassiveGrab = isPassive;
     grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
     PostNewCursor(mouse);
     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
@@ -1598,6 +1655,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
 {
     GrabPtr grab = mouse->deviceGrab.grab;
     DeviceIntPtr dev;
+    Bool  wasPassive= mouse->deviceGrab.fromPassiveGrab;
 
     mouse->valuator->motionHintWindow = NullWindow;
     mouse->deviceGrab.grab = NullGrab;
@@ -1615,6 +1673,10 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
     PostNewCursor(mouse);
     if (grab->cursor)
 	FreeCursor(grab->cursor, (Cursor)0);
+
+    if (!wasPassive)
+        RestoreOldMaster(mouse);
+
     ComputeFreezes();
 }
 
@@ -1629,6 +1691,13 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass
     GrabInfoPtr grabinfo = &keybd->deviceGrab;
     WindowPtr oldWin;
 
+    /* slave devices need to float for the duration of the grab. */
+    if (!passive && !keybd->isMaster)
+    {
+        SaveOldMaster(keybd);
+        AttachDevice(NULL, keybd, NULL);
+    }
+
     if (grabinfo->grab)
 	oldWin = grabinfo->grab->window;
     else if (keybd->focus)
@@ -1660,9 +1729,7 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
     DeviceIntPtr dev;
     WindowPtr focusWin = keybd->focus ? keybd->focus->win
                                            : keybd->spriteInfo->sprite->win;
-
-    if (!grab)
-        grab = keybd->deviceGrab.grab;
+    Bool wasPassive = keybd->deviceGrab.fromPassiveGrab;
 
     if (focusWin == FollowKeyboardWin)
 	focusWin = inputInfo.keyboard->focus->win;
@@ -1677,6 +1744,10 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
 	    dev->deviceGrab.sync.other = NullGrab;
     }
     DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
+
+    if (!wasPassive)
+        RestoreOldMaster(keybd);
+
     ComputeFreezes();
 }
 
@@ -4243,13 +4314,17 @@ EnterLeaveEvent(
 #ifdef XKB
     if (!noXkbExtension) {
         event.u.enterLeave.state = mouse->button->state & 0x1f00;
-        event.u.enterLeave.state |= 
-            XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
+        if (keybd)
+            event.u.enterLeave.state |= 
+                XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
     } else
 #endif
-        event.u.enterLeave.state = keybd->key->state | mouse->button->state;
+    {
+        event.u.enterLeave.state = (keybd) ? keybd->key->state : 0;
+        event.u.enterLeave.state |+ mouse->button->state;
+    }
     event.u.enterLeave.mode = mode;
-    focus = keybd->focus->win;
+    focus = (keybd) ? keybd->focus->win : None;
     if ((focus != NoneWin) &&
             ((pWin == focus) || (focus == PointerRootWin) ||
              IsParent(focus, pWin)))
commit 676b26ca3e9b142cf007af3f439aa1993f2247c4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 8 17:54:17 2007 +1030

    Xi: notify the clients when the device hierarchy has been changed.

diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
index c916c0f..338c074 100644
--- a/Xi/chdevhier.c
+++ b/Xi/chdevhier.c
@@ -79,9 +79,11 @@ int
 ProcXChangeDeviceHierarchy(ClientPtr client)
 {
     DeviceIntPtr ptr, keybd;
+    DeviceIntRec dummyDev;
     xAnyHierarchyChangeInfo *any;
     int required_len = sizeof(xChangeDeviceHierarchyReq);
     char n;
+    deviceHierarchyChangedEvent ev;
 
     REQUEST(xChangeDeviceHierarchyReq);
     REQUEST_AT_LEAST_SIZE(xChangeDeviceHierarchyReq);
@@ -226,6 +228,14 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
         any = (xAnyHierarchyChangeInfo*)((char*)any + any->length);
     }
 
+    ev.type = GenericEvent;
+    ev.extension = IReqCode;
+    ev.length = 0;
+    ev.evtype = XI_DeviceHierarchyChangedNotify;
+    ev.time = GetTimeInMillis();
+
+    SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask, 
+            (xEvent*)&ev, 1);
     return Success;
 }
 
diff --git a/Xi/extinit.c b/Xi/extinit.c
index de2653f..0ecb421 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -137,9 +137,8 @@ Mask ExtExclusiveMasks[EMASKSIZE];
  * Evtype is index, mask is value at index.
  */
 static Mask xi_filters[3] = {
-    XI_PointerKeyboardPairingChangedMask,
-    XI_RandomStringMask,
-    XI_RawDeviceEventMask,  
+    XI_DeviceHierarchyChangedMask,
+    XI_RawDeviceEventMask,
 };
 
 static struct dev_type
commit cb75f09146a3c17b1a67b636bbf7229c65c83b35
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 9 11:29:18 2007 +1030

    dix: calloc root window's Generic Event mask, stops segfaults.

diff --git a/dix/window.c b/dix/window.c
index 23acbd6..51891a8 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -455,7 +455,12 @@ CreateRootWindow(ScreenPtr pScreen)
 #ifdef XINPUT
     pWin->optional->inputMasks = NULL;
     pWin->optional->deviceCursors = NULL;
-    pWin->optional->geMasks = NULL;
+    pWin->optional->geMasks = (GenericClientMasksPtr)xcalloc(1, sizeof(GenericClientMasksRec));
+    if (!pWin->optional->geMasks)
+    {
+        xfree(pWin->optional);
+        return FALSE;
+    }
 #endif
 
     pWin->optional->access.perm = NULL;
commit 59b304d8a24fecd094296feb217823f0c73d6f82
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 8 15:44:18 2007 +1030

    dix, mi: stop segfaults when a floating device emits events.
    
    For pointers: don't try to set master->valuator fields if there is no master.
    For keyboards: check if device is valid before trying to access the fields in
    miPointerGetScreen (btw. this disables DGA events for floating keyboards).
    
    Also stop the hideous number of ErrorFs if we request the paired device for a
    floating dev.

diff --git a/dix/devices.c b/dix/devices.c
index 30fc7b3..c9831ea 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2265,11 +2265,8 @@ GetPairedDevice(DeviceIntPtr dev)
         dev = dev->u.master;
 
     if (!dev->spriteInfo->paired)
-    {
-        ErrorF("[dix] No device paired with %d (%s).\n", 
-                dev->id, dev->name);
         return NULL;
-    }
+
     return dev->spriteInfo->paired;
 }
 
diff --git a/dix/getevents.c b/dix/getevents.c
index 3044301..a23eabe 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -736,8 +736,11 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     pDev->valuator->lastx = x;
     pDev->valuator->lasty = y;
-    master->valuator->lastx = x;
-    master->valuator->lasty = y;
+    if (master)
+    {
+        master->valuator->lastx = x;
+        master->valuator->lasty = y;
+    }
 
     if (!coreOnly)
     {
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 7b56579..b2f31c1 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -529,7 +529,7 @@ miPointerCurrentScreen ()
 _X_EXPORT ScreenPtr
 miPointerGetScreen(DeviceIntPtr pDev)
 {
-    if (!pDev->isMaster && !pDev->u.master)
+    if (!pDev || (!pDev->isMaster && !pDev->u.master))
         return NULL;
 
     return MIPOINTER(pDev)->pScreen;
commit 3063f0c6679bdbea13f360cff8d09a88b9871da9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 8 11:51:03 2007 +1030

    mi: change the device id to the master devices' when duplicating the event.
    
    Move the event duplication into a CopyGetMasterEvent(), makes the code a bit
    better to read.

diff --git a/mi/mieq.c b/mi/mieq.c
index 20004f3..26eab6f 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -226,6 +226,68 @@ mieqSetHandler(int event, mieqHandler handler)
     miEventQueue.handlers[event] = handler;
 }
 
+/**
+ * Change the device id of the given event to the given device's id.
+ */
+static void
+ChangeDeviceID(DeviceIntPtr dev, xEvent* event)
+{
+    int type = event->u.u.type;
+
+    if (type == DeviceKeyPress || type == DeviceKeyRelease ||
+            type == DeviceButtonPress || type == DeviceButtonRelease ||
+            type == DeviceMotionNotify)
+        ((deviceKeyButtonPointer*)event)->deviceid = dev->id;
+    else if (type == DeviceValuator)
+        ((deviceValuator*)event)->deviceid = dev->id;
+    else if (type == GenericEvent)
+    {
+        /* FIXME: need to put something into XGE to make this saner */
+        xGenericEvent* generic = (xGenericEvent*)event;
+        if (generic->extension == IReqCode
+                && generic->evtype == XI_RawDeviceEvent)
+        {
+            rawDeviceEvent* raw = (rawDeviceEvent*)event;
+            raw->deviceid = dev->id;
+        } else
+            ErrorF("[mi] Unknown generic event, cannot change id.\n");
+    } else
+        ErrorF("[mi] Unknown event type, cannot change id.\n");
+}
+
+/**
+ * Copy the given event into master.
+ * @param mdev The master device
+ * @param original The event as it came from the EQ
+ * @param master The event after being copied
+ * @param count Number of events in original.
+ */
+static void
+CopyGetMasterEvent(DeviceIntPtr mdev, xEvent* original,
+                   xEvent** master, int count)
+{
+    if (count > 1) {
+        *master = xcalloc(count, sizeof(xEvent));
+        if (!*master)
+            FatalError("[mi] No memory left for master event.\n");
+        while(count--)
+        {
+            memcpy(&(*master)[count], &original[count], sizeof(xEvent));
+            ChangeDeviceID(mdev, &(*master)[count]);
+        }
+    } else
+    {
+        int len = sizeof(xEvent);
+        if (original->u.u.type == GenericEvent)
+            len += GEV(original)->length * 4;
+        *master = xalloc(len);
+        if (!*master)
+            FatalError("[mi] No memory left for master event.\n");
+        memcpy(*master, original, len);
+        ChangeDeviceID(mdev, *master);
+    }
+}
+
 /* Call this from ProcessInputEvents(). */
 void
 mieqProcessInputEvents(void)
@@ -233,7 +295,7 @@ mieqProcessInputEvents(void)
     EventRec *e = NULL;
     int x = 0, y = 0;
     xEvent* event,
-            *master_event;
+            *master_event = NULL;
 
     while (miEventQueue.head != miEventQueue.tail) {
         if (screenIsSaved == SCREEN_SAVER_ON)
@@ -284,39 +346,32 @@ mieqProcessInputEvents(void)
              * copy. Eventually the interface for the processInputProc needs
              * to be changed. (whot)
              */ 
-
-            /* The event is changed during event processing, so we need to
-             * memcpy the event we have and pass the copy through for master
-             */
             if (e->nevents > 1)
             {
                 int i;
                 event = xcalloc(e->nevents, sizeof(xEvent));
-                master_event = xcalloc(e->nevents, sizeof(xEvent));
-                if (!event || !master_event)
+                if (!event)
                     FatalError("[mi] No memory left for event processing.\n");
                 for (i = 0; i < e->nevents; i++)
                 {
                     memcpy(&event[i], e->events[i].event, sizeof(xEvent));
-                    memcpy(&master_event[i], e->events[i].event, sizeof(xEvent));
                 }
-            }
-            else 
-            {
-                int len = sizeof(xEvent); 
+            } else
                 event = e->events->event;
-                if (event->u.u.type == GenericEvent) 
-                        len += GEV(event)->length * 4;
-                master_event = xalloc(len);
-                if (!master_event)
-                    FatalError("[mi] No memory left for master event.\n");
-                memcpy(master_event, event, len);
+            if (!e->pDev->isMaster && e->pDev->u.master)
+            {
+                CopyGetMasterEvent(e->pDev->u.master, event,
+                                   &master_event, e->nevents);
             }
 
+            /* process slave first, then master */
             e->pDev->public.processInputProc(event, e->pDev, e->nevents);
+
             if (!e->pDev->isMaster && e->pDev->u.master)
+            {
                 e->pDev->u.master->public.processInputProc(master_event, 
                         e->pDev->u.master, e->nevents);
+            }
 
             if (e->nevents > 1)
                 xfree(event);
@@ -331,3 +386,4 @@ mieqProcessInputEvents(void)
         }
     }
 }
+
commit 180220f284823c486e7001ef00f1279dc548c9c7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 8 10:00:35 2007 +1030

    Xi: return BadDevice for slave devices on ProcXSetClientPointer
    
    Also clean up to return error codes instead of sending the error manually.

diff --git a/Xi/setcptr.c b/Xi/setcptr.c
index 66c8981..ad8f571 100644
--- a/Xi/setcptr.c
+++ b/Xi/setcptr.c
@@ -78,11 +78,10 @@ ProcXSetClientPointer(ClientPtr client)
 
 
     pDev = LookupDeviceIntRec(stuff->deviceid);
-    if (pDev == NULL || !IsPointerDevice(pDev))
+    if (pDev == NULL || !IsPointerDevice(pDev) || !pDev->isMaster)
     {
-        SendErrorToClient(client, IReqCode, X_SetClientPointer, 0,
-                BadDevice); 
-        return Success;
+        client->errorValue = stuff->deviceid;
+        return BadDevice;
     }
 
     if (stuff->win != None)
@@ -90,19 +89,18 @@ ProcXSetClientPointer(ClientPtr client)
         err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
         if (err != Success)
         {
-            SendErrorToClient(client, IReqCode, X_SetClientPointer, 
-                    stuff->win, err);
-            return Success;
+            client->errorValue = stuff->win;
+            return err;
         }
         targetClient= wClient(pWin);
     } else
         targetClient = client;
-    
+
     if (!SetClientPointer(targetClient, client, pDev))
     {
-        SendErrorToClient(client, IReqCode, X_SetClientPointer, 
-                stuff->win, BadAccess);
-        return Success;
+        client->errorValue = stuff->win;
+        return BadAccess;
     }
+
     return Success;
 }
commit 184a7b8917a15bb2c719153b9b016c03aab42101
Merge: a8808ac... 0b72905...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 8 09:34:35 2007 +1030

    Merge branch 'mpx' into mdsd
    
    Conflicts:
    
    	Xi/opendev.c

diff --cc xkb/xkbActions.c
index 32b9e0d,ea7913a..ebc5bfd
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@@ -1273,9 -1272,8 +1272,8 @@@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICE
  	    keyc->modifierMap[key] = 0;
              tmpdev = dev;
          } else
 -            tmpdev = GetPairedPointer(dev);
 +            tmpdev = GetPairedDevice(dev);
  
- 
          UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
          dev->public.processInputProc(xE,tmpdev,count);
          COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
commit 0b729051c04da7068f1e6dd319190bd0a362b2c0
Merge: b7ee005... d7c5e8b...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 7 15:37:23 2007 +1030

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	Xi/extinit.c
    	Xi/grabdev.c
    	Xi/setmode.c
    	Xi/ungrdev.c
    	dix/devices.c
    	dix/events.c
    	dix/getevents.c
    	include/dix.h
    	mi/midispcur.c
    	mi/misprite.c
    	xkb/xkbActions.c
    	xkb/xkbEvents.c
    	xkb/xkbPrKeyEv.c

diff --cc Xi/allowev.c
index 449d881,cf075e1..12aeab3
--- a/Xi/allowev.c
+++ b/Xi/allowev.c
@@@ -111,27 -106,26 +106,26 @@@ ProcXAllowDeviceEvents(ClientPtr client
  
      switch (stuff->mode) {
      case ReplayThisDevice:
 -	AllowSome(client, time, thisdev, NOT_GRABBED);
 +	AllowSome(client, time, thisdev, NOT_GRABBED, FALSE);
  	break;
      case SyncThisDevice:
 -	AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT);
 +	AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT, FALSE);
  	break;
      case AsyncThisDevice:
 -	AllowSome(client, time, thisdev, THAWED);
 +	AllowSome(client, time, thisdev, THAWED, FALSE);
  	break;
      case AsyncOtherDevices:
 -	AllowSome(client, time, thisdev, THAW_OTHERS);
 +	AllowSome(client, time, thisdev, THAW_OTHERS, FALSE);
  	break;
      case SyncAll:
 -	AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT);
 +	AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT, FALSE);
  	break;
      case AsyncAll:
 -	AllowSome(client, time, thisdev, THAWED_BOTH);
 +	AllowSome(client, time, thisdev, THAWED_BOTH, FALSE);
  	break;
      default:
- 	SendErrorToClient(client, IReqCode, X_AllowDeviceEvents, 0, BadValue);
  	client->errorValue = stuff->mode;
- 	return Success;
+ 	return BadValue;
      }
      return Success;
  }
diff --cc Xi/closedev.c
index 8aebe10,1ec3fa1..cd6e537
--- a/Xi/closedev.c
+++ b/Xi/closedev.c
@@@ -151,13 -148,11 +148,11 @@@ ProcXCloseDevice(ClientPtr client
      REQUEST_SIZE_MATCH(xCloseDeviceReq);
  
      d = LookupDeviceIntRec(stuff->deviceid);
-     if (d == NULL) {
- 	SendErrorToClient(client, IReqCode, X_CloseDevice, 0, BadDevice);
- 	return Success;
-     }
+     if (d == NULL)
+ 	return BadDevice;
  
 -    if (d->grab && SameClient(d->grab, client))
 -	(*d->DeactivateGrab) (d);	/* release active grab */
 +    if (d->deviceGrab.grab && SameClient(d->deviceGrab.grab, client))
 +	(*d->deviceGrab.DeactivateGrab) (d);	/* release active grab */
  
      /* Remove event selections from all windows for events from this device 
       * and selected by this client.
diff --cc Xi/extinit.c
index c1b6eed,73bae5e..3b384ee
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@@ -1213,12 -976,7 +1211,13 @@@ XInputExtensionInit(void
  	EventSwapVector[DeviceButtonStateNotify] = SEventIDispatch;
  	EventSwapVector[DeviceMappingNotify] = SEventIDispatch;
  	EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
+ 	EventSwapVector[DevicePresenceNotify] = SEventIDispatch;
 +	EventSwapVector[DeviceEnterNotify] = SEventIDispatch;
 +	EventSwapVector[DeviceLeaveNotify] = SEventIDispatch;
 +
 +        /* init GE events */
 +        GERegisterExtension(IReqCode, XIGEEventSwap, XIGEEventFill);
 +        SetGenericFilter(IReqCode, xi_filters);
      } else {
  	FatalError("IExtensionInit: AddExtensions failed\n");
      }
diff --cc Xi/grabdev.c
index f2227bc,b303695..16f4b7e
--- a/Xi/grabdev.c
+++ b/Xi/grabdev.c
@@@ -128,25 -123,22 +123,22 @@@ ProcXGrabDevice(ClientPtr client
      rep.length = 0;
  
      dev = LookupDeviceIntRec(stuff->deviceid);
-     if (dev == NULL) {
- 	SendErrorToClient(client, IReqCode, X_GrabDevice, 0, BadDevice);
- 	return Success;
-     }
+     if (dev == NULL)
+ 	return BadDevice;
  
-     if (CreateMaskFromList(client, (XEventClass *) & stuff[1],
- 			   stuff->event_count, tmp, dev,
- 			   X_GrabDevice) != Success)
- 	return Success;
+     if ((rc = CreateMaskFromList(client, (XEventClass *) & stuff[1],
+ 				 stuff->event_count, tmp, dev,
+ 				 X_GrabDevice)) != Success)
+ 	return rc;
  
-     error = GrabDevice(client, dev, stuff->this_device_mode,
- 		       stuff->other_devices_mode, stuff->grabWindow,
- 		       stuff->ownerEvents, stuff->time,
- 		       tmp[stuff->deviceid].mask, &rep.status, FALSE);
+     rc = GrabDevice(client, dev, stuff->this_device_mode,
+ 		    stuff->other_devices_mode, stuff->grabWindow,
+ 		    stuff->ownerEvents, stuff->time,
 -		    tmp[stuff->deviceid].mask, &rep.status);
++		    tmp[stuff->deviceid].mask, &rep.status, FALSE);
+ 
+     if (rc != Success)
+ 	return rc;
  
-     if (error != Success) {
- 	SendErrorToClient(client, IReqCode, X_GrabDevice, 0, error);
- 	return Success;
-     }
      WriteReplyToClient(client, sizeof(xGrabDeviceReply), &rep);
      return Success;
  }
@@@ -190,15 -164,12 +182,12 @@@ CreateMaskFromList(ClientPtr client, XE
  
      for (i = 0; i < count; i++, list++) {
  	device = *list >> 8;
- 	if (device > 255) { /* FIXME: we only use 7 bit for devices? */
- 	    SendErrorToClient(client, IReqCode, req, 0, BadClass);
 -	if (device > 255)
++	if (device > 255) /* FIXME: we only use 7 bit for devices? */
  	    return BadClass;
- 	}
+ 
  	tdev = LookupDeviceIntRec(device);
- 	if (tdev == NULL || (dev != NULL && tdev != dev)) {
- 	    SendErrorToClient(client, IReqCode, req, 0, BadClass);
+ 	if (tdev == NULL || (dev != NULL && tdev != dev))
  	    return BadClass;
- 	}
  
  	for (j = 0; j < ExtEventIndex; j++)
  	    if (EventInfo[j].type == (*list & 0xff)) {
diff --cc Xi/grabdevb.c
index 0b8a978,21e46fc..7ef8ad7
--- a/Xi/grabdevb.c
+++ b/Xi/grabdevb.c
@@@ -117,30 -114,21 +114,21 @@@ ProcXGrabDeviceButton(ClientPtr client
      REQUEST_AT_LEAST_SIZE(xGrabDeviceButtonReq);
  
      if (stuff->length !=
- 	(sizeof(xGrabDeviceButtonReq) >> 2) + stuff->event_count) {
- 	SendErrorToClient(client, IReqCode, X_GrabDeviceButton, 0, BadLength);
- 	return Success;
-     }
+ 	(sizeof(xGrabDeviceButtonReq) >> 2) + stuff->event_count)
+ 	return BadLength;
  
      dev = LookupDeviceIntRec(stuff->grabbed_device);
-     if (dev == NULL) {
- 	SendErrorToClient(client, IReqCode, X_GrabDeviceButton, 0, BadDevice);
- 	return Success;
-     }
+     if (dev == NULL)
+ 	return BadDevice;
+ 
      if (stuff->modifier_device != UseXKeyboard) {
  	mdev = LookupDeviceIntRec(stuff->modifier_device);
- 	if (mdev == NULL) {
- 	    SendErrorToClient(client, IReqCode, X_GrabDeviceButton, 0,
- 			      BadDevice);
- 	    return Success;
- 	}
- 	if (mdev->key == NULL) {
- 	    SendErrorToClient(client, IReqCode, X_GrabDeviceButton, 0,
- 			      BadMatch);
- 	    return Success;
- 	}
+ 	if (mdev == NULL)
+ 	    return BadDevice;
+ 	if (mdev->key == NULL)
+ 	    return BadMatch;
      } else
 -	mdev = (DeviceIntPtr) LookupKeyboardDevice();
 +	mdev = PickKeyboard(client);
  
      class = (XEventClass *) (&stuff[1]);	/* first word of values */
  
diff --cc Xi/grabdevk.c
index 297072b,8da36ba..d38c053
--- a/Xi/grabdevk.c
+++ b/Xi/grabdevk.c
@@@ -128,16 -121,12 +121,12 @@@ ProcXGrabDeviceKey(ClientPtr client
  
      if (stuff->modifier_device != UseXKeyboard) {
  	mdev = LookupDeviceIntRec(stuff->modifier_device);
- 	if (mdev == NULL) {
- 	    SendErrorToClient(client, IReqCode, X_GrabDeviceKey, 0, BadDevice);
- 	    return Success;
- 	}
- 	if (mdev->key == NULL) {
- 	    SendErrorToClient(client, IReqCode, X_GrabDeviceKey, 0, BadMatch);
- 	    return Success;
- 	}
+ 	if (mdev == NULL)
+ 	    return BadDevice;
+ 	if (mdev->key == NULL)
+ 	    return BadMatch;
      } else
 -	mdev = (DeviceIntPtr) LookupKeyboardDevice();
 +	mdev = PickKeyboard(client);
  
      class = (XEventClass *) (&stuff[1]);	/* first word of values */
  
diff --cc Xi/setdval.c
index 61b98c7,cb35b91..bbab34e
--- a/Xi/setdval.c
+++ b/Xi/setdval.c
@@@ -106,26 -103,19 +103,19 @@@ ProcXSetDeviceValuators(ClientPtr clien
      rep.sequenceNumber = client->sequence;
  
      if (stuff->length != (sizeof(xSetDeviceValuatorsReq) >> 2) +
- 	stuff->num_valuators) {
- 	SendErrorToClient(client, IReqCode, X_SetDeviceValuators, 0, BadLength);
- 	return Success;
-     }
+ 	stuff->num_valuators)
+ 	return BadLength;
+ 
      dev = LookupDeviceIntRec(stuff->deviceid);
-     if (dev == NULL) {
- 	SendErrorToClient(client, IReqCode, X_SetDeviceValuators, 0, BadDevice);
- 	return Success;
-     }
-     if (dev->valuator == NULL) {
- 	SendErrorToClient(client, IReqCode, X_SetDeviceValuators, 0, BadMatch);
- 	return Success;
-     }
- 
-     if (stuff->first_valuator + stuff->num_valuators > dev->valuator->numAxes) {
- 	SendErrorToClient(client, IReqCode, X_SetDeviceValuators, 0, BadValue);
- 	return Success;
-     }
+     if (dev == NULL)
+ 	return BadDevice;
+     if (dev->valuator == NULL)
+ 	return BadMatch;
+ 
+     if (stuff->first_valuator + stuff->num_valuators > dev->valuator->numAxes)
+ 	return BadValue;
  
 -    if ((dev->grab) && !SameClient(dev->grab, client))
 +    if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client))
  	rep.status = AlreadyGrabbed;
      else
  	rep.status = SetDeviceValuators(client, dev, (int *)&stuff[1],
diff --cc Xi/setmode.c
index 00d3400,957721c..d8a5695
--- a/Xi/setmode.c
+++ b/Xi/setmode.c
@@@ -105,15 -102,11 +102,11 @@@ ProcXSetDeviceMode(ClientPtr client
      rep.sequenceNumber = client->sequence;
  
      dev = LookupDeviceIntRec(stuff->deviceid);
-     if (dev == NULL) {
- 	SendErrorToClient(client, IReqCode, X_SetDeviceMode, 0, BadDevice);
- 	return Success;
-     }
-     if (dev->valuator == NULL) {
- 	SendErrorToClient(client, IReqCode, X_SetDeviceMode, 0, BadMatch);
- 	return Success;
-     }
+     if (dev == NULL)
+ 	return BadDevice;
+     if (dev->valuator == NULL)
+ 	return BadMatch;
 -    if ((dev->grab) && !SameClient(dev->grab, client))
 +    if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client))
  	rep.status = AlreadyGrabbed;
      else
  	rep.status = SetDeviceMode(client, dev, stuff->mode);
diff --cc Xi/ungrdev.c
index e056ce6,505d669..3b6b252
--- a/Xi/ungrdev.c
+++ b/Xi/ungrdev.c
@@@ -102,11 -99,9 +99,9 @@@ ProcXUngrabDevice(ClientPtr client
      REQUEST_SIZE_MATCH(xUngrabDeviceReq);
  
      dev = LookupDeviceIntRec(stuff->deviceid);
-     if (dev == NULL) {
- 	SendErrorToClient(client, IReqCode, X_UngrabDevice, 0, BadDevice);
- 	return Success;
-     }
+     if (dev == NULL)
+ 	return BadDevice;
 -    grab = dev->grab;
 +    grab = dev->deviceGrab.grab;
  
      time = ClientTimeToServerTime(stuff->time);
      if ((CompareTimeStamps(time, currentTime) != LATER) &&
diff --cc Xi/ungrdevb.c
index 5e0a663,0dfe805..46d3250
--- a/Xi/ungrdevb.c
+++ b/Xi/ungrdevb.c
@@@ -122,30 -115,20 +115,20 @@@ ProcXUngrabDeviceButton(ClientPtr clien
  
      if (stuff->modifier_device != UseXKeyboard) {
  	mdev = LookupDeviceIntRec(stuff->modifier_device);
- 	if (mdev == NULL) {
- 	    SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0,
- 			      BadDevice);
- 	    return Success;
- 	}
- 	if (mdev->key == NULL) {
- 	    SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0,
- 			      BadMatch);
- 	    return Success;
- 	}
+ 	if (mdev == NULL)
+ 	    return BadDevice;
+ 	if (mdev->key == NULL)
+ 	    return BadMatch;
      } else
 -	mdev = (DeviceIntPtr) LookupKeyboardDevice();
 +	mdev = PickKeyboard(client);
  
      rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixUnknownAccess);
-     if (rc != Success) {
- 	SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0, rc);
- 	return Success;
-     }
+     if (rc != Success)
+ 	return rc;
  
      if ((stuff->modifiers != AnyModifier) &&
- 	(stuff->modifiers & ~AllModifiersMask)) {
- 	SendErrorToClient(client, IReqCode, X_UngrabDeviceButton, 0, BadValue);
- 	return Success;
-     }
+ 	(stuff->modifiers & ~AllModifiersMask))
+ 	return BadValue;
  
      temporaryGrab.resource = client->clientAsMask;
      temporaryGrab.device = dev;
diff --cc Xi/ungrdevk.c
index 7b06d6e,e6307af..7df4095
--- a/Xi/ungrdevk.c
+++ b/Xi/ungrdevk.c
@@@ -122,34 -115,25 +115,25 @@@ ProcXUngrabDeviceKey(ClientPtr client
  
      if (stuff->modifier_device != UseXKeyboard) {
  	mdev = LookupDeviceIntRec(stuff->modifier_device);
- 	if (mdev == NULL) {
- 	    SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0,
- 			      BadDevice);
- 	    return Success;
- 	}
- 	if (mdev->key == NULL) {
- 	    SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, BadMatch);
- 	    return Success;
- 	}
+ 	if (mdev == NULL)
+ 	    return BadDevice;
+ 	if (mdev->key == NULL)
+ 	    return BadMatch;
      } else
 -	mdev = (DeviceIntPtr) LookupKeyboardDevice();
 +	mdev = PickKeyboard(client);
  
      rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixUnknownAccess);
-     if (rc != Success) {
- 	SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, rc);
- 	return Success;
-     }
+     if (rc != Success)
+ 	return rc;
+ 
      if (((stuff->key > dev->key->curKeySyms.maxKeyCode) ||
  	 (stuff->key < dev->key->curKeySyms.minKeyCode))
- 	&& (stuff->key != AnyKey)) {
- 	SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, BadValue);
- 	return Success;
-     }
+ 	&& (stuff->key != AnyKey))
+ 	return BadValue;
+ 
      if ((stuff->modifiers != AnyModifier) &&
- 	(stuff->modifiers & ~AllModifiersMask)) {
- 	SendErrorToClient(client, IReqCode, X_UngrabDeviceKey, 0, BadValue);
- 	return Success;
-     }
+ 	(stuff->modifiers & ~AllModifiersMask))
+ 	return BadValue;
  
      temporaryGrab.resource = client->clientAsMask;
      temporaryGrab.device = dev;
diff --cc dix/devices.c
index 37a98a0,9798b97..c61ccc0
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -1504,8 -1374,10 +1506,9 @@@ ProcSetModifierMapping(ClientPtr client
      rep.success = DoSetModifierMapping(client, (KeyCode *)&stuff[1],
                                         stuff->numKeyPerModifier);
  
-     /* FIXME: Send mapping notifies for all the extended devices as well. */
-     SendMappingNotify(inputInfo.keyboard, MappingModifier, 0, 0, client);
 -    SendMappingNotify(MappingModifier, 0, 0, client);
+     for (dev = inputInfo.devices; dev; dev = dev->next)
+         if (dev->key && dev->coreEvents)
+             SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev);
      WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
      return client->noClientException;
  }
@@@ -1568,16 -1440,19 +1571,17 @@@ ProcChangeKeyboardMapping(ClientPtr cli
      keysyms.maxKeyCode = stuff->firstKeyCode + stuff->keyCodes - 1;
      keysyms.mapWidth = stuff->keySymsPerKeyCode;
      keysyms.map = (KeySym *)&stuff[1];
-     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
-         if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
+     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+         if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key)
              if (!SetKeySymsMap(&pDev->key->curKeySyms, &keysyms))
                  return BadAlloc;
-         }
-     }
  
-     /* FIXME: Send mapping notifies for all the extended devices as well. */
-     SendMappingNotify(inputInfo.keyboard, MappingKeyboard,
-             stuff->firstKeyCode, stuff->keyCodes, client);
 -    SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes,
 -                      client);
+     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+         if (pDev->key && pDev->coreEvents)
+             SendDeviceMappingNotify(client, MappingKeyboard,
+                                     stuff->firstKeyCode, stuff->keyCodes,
+                                     pDev);
+ 
      return client->noClientException;
  }
  
diff --cc dix/events.c
index 2032b42,12c299a..23ef861
--- a/dix/events.c
+++ b/dix/events.c
@@@ -2922,6 -2353,61 +2922,69 @@@ InitializeSprite(DeviceIntPtr pDev, Win
  #endif
  }
  
+ /**
+  * Update the mouse sprite info when the server switches from a pScreen to another.
+  * Otherwise, the pScreen of the mouse sprite is never updated when we switch
+  * from a pScreen to another. Never updating the pScreen of the mouse sprite
+  * implies that windows that are in pScreen whose pScreen->myNum >0 will never
+  * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
+  * always points to the first pScreen it has been set by
+  * DefineInitialRootWindow().
+  *
+  * Calling this function is useful for use cases where the server
+  * has more than one pScreen.
+  * This function is similar to DefineInitialRootWindow() but it does not
+  * reset the mouse pointer position.
+  * @param win must be the new pScreen we are switching to.
+  */
+ void
 -UpdateSpriteForScreen(ScreenPtr pScreen)
++UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
+ {
++    SpritePtr pSprite = NULL;
+     WindowPtr win = NULL;
+     if (!pScreen)
+         return ;
++
++    if (!pDev->spriteInfo->sprite)
++        return;
++
++    pSprite = pDev->spriteInfo->sprite;
++
+     win = WindowTable[pScreen->myNum];
+ 
 -    sprite.hotPhys.pScreen = pScreen;
 -    sprite.hot = sprite.hotPhys;
 -    sprite.hotLimits.x2 = pScreen->width;
 -    sprite.hotLimits.y2 = pScreen->height;
++    pSprite->hotPhys.pScreen = pScreen;
++    pSprite->hot = pSprite->hotPhys;
++    pSprite->hotLimits.x2 = pScreen->width;
++    pSprite->hotLimits.y2 = pScreen->height;
+ #ifdef XEVIE
+     xeviewin =
+ #endif
 -    sprite.win = win;
 -    sprite.current = wCursor (win);
 -    sprite.current->refcnt++;
 -    spriteTraceGood = 1;
 -    ROOT = win;
 -    (*pScreen->CursorLimits) (pScreen,
 -                              sprite.current,
 -                              &sprite.hotLimits,
 -                              &sprite.physLimits);
 -    sprite.confined = FALSE;
 -    (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
 -    (*pScreen->DisplayCursor) (pScreen, sprite.current);
++    pSprite->win = win;
++    pSprite->current = wCursor (win);
++    pSprite->current->refcnt++;
++    pSprite->spriteTraceGood = 1;
++    pSprite->spriteTrace[0] = win;
++    (*pScreen->CursorLimits) (pDev,
++                              pScreen,
++                              pSprite->current,
++                              &pSprite->hotLimits,
++                              &pSprite->physLimits);
++    pSprite->confined = FALSE;
++    (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
++    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
+ 
+ #ifdef PANORAMIX
+     if(!noPanoramiXExtension) {
 -        sprite.hotLimits.x1 = -panoramiXdataPtr[0].x;
 -        sprite.hotLimits.y1 = -panoramiXdataPtr[0].y;
 -        sprite.hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
 -        sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
 -        sprite.physLimits = sprite.hotLimits;
 -        sprite.screen = pScreen;
++        pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
++        pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
++        pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
++        pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
++        pSprite->physLimits = pSprite->hotLimits;
++        pSprite->screen = pScreen;
+     }
+ #endif
+ }
+ 
  /*
   * This does not take any shortcuts, and even ignores its argument, since
   * it does not happen very often, and one has to walk up the tree since
diff --cc dix/getevents.c
index 7457078,ffcdf17..934b0e9
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -402,8 -417,14 +427,11 @@@ GetKeyboardValuatorEvents(EventList *ev
          (pDev->coreEvents && !inputInfo.keyboard->key))
          return 0;
  
 +    numEvents = 1;
 +
+     if (key_code < 8 || key_code > 255)
+         return 0;
+ 
 -    if (pDev->coreEvents)
 -        numEvents = 2;
 -    else
 -        numEvents = 1;
 -
      if (num_valuators) {
          if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS)
              num_valuators = MAX_VALUATOR_EVENTS;
diff --cc dix/main.c
index d78d7e8,e5c5578..0bb823d
--- a/dix/main.c
+++ b/dix/main.c
@@@ -453,10 -449,10 +453,12 @@@ main(int argc, char *argv[], char *envp
  	    }
  	}
  
+ 	NotifyParentProcess();
+ 
  	Dispatch();
  
 +        UndisplayDevices();
 +
  	/* Now free up whatever must be freed */
  	if (screenIsSaved == SCREEN_SAVER_ON)
  	    SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
diff --cc hw/xfree86/common/xf86Priv.h
index 2f542a3,3da102f..6bba837
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@@ -36,9 -36,10 +36,11 @@@
  #ifndef _XF86PRIV_H
  #define _XF86PRIV_H
  
+ #include <pciaccess.h>
+ 
  #include "xf86Privstr.h"
  #include "propertyst.h"
 +#include "input.h"
  
  /*
   * Parameters set ONLY from the command line options
diff --cc hw/xfree86/common/xf86Xinput.c
index c6df92c,b939fb7..94edac5
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@@ -176,22 -162,13 +176,24 @@@ xf86ActivateDevice(LocalDevicePtr local
          dev->public.devicePrivate = (pointer) local;
          local->dev = dev;      
          
 -        dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
 -        RegisterOtherDevice(dev);
 +        dev->coreEvents = local->flags & XI86_ALWAYS_CORE; 
 +        dev->spriteInfo->spriteOwner = !(local->flags & XI86_SHARED_POINTER);
 +
 +        if (DeviceIsPointerType(dev))
 +        {
 +            dev->deviceGrab.ActivateGrab = ActivatePointerGrab;
 +            dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
 +        } else 
 +        {
 +            dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
 +            dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
 +        }
  
 +        RegisterOtherDevice(dev);
+ #ifdef XKB
          if (!noXkbExtension)
-             XkbSetExtension(dev, (DeviceIsPointerType(dev)) ? ProcessPointerEvent : ProcessKeyboardEvent);
+             XkbSetExtension(dev, ProcessKeyboardEvent);
+ #endif
  
          if (serverGeneration == 1) 
              xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n",
diff --cc include/dix.h
index 34abb2d,6a67d14..db90579
--- a/include/dix.h
+++ b/include/dix.h
@@@ -427,14 -415,9 +427,18 @@@ extern int DeliverDeviceEvents
  extern void DefineInitialRootWindow(
      WindowPtr /* win */);
  
 +extern void SetupSprite(
 +    DeviceIntPtr /* pDev */,
 +    ScreenPtr    /* pScreen */);
 +
 +extern void InitializeSprite(
 +    DeviceIntPtr /* pDev */,
 +    WindowPtr    /* pWin */);
 +
+ extern void UpdateSpriteForScreen(
 -     ScreenPtr /* pScreen */);
++    DeviceIntPtr /* pDev */,
++    ScreenPtr /* pScreen */);
+ 
  extern void WindowHasNewCursor(
      WindowPtr /* pWin */);
  
diff --cc mi/midispcur.c
index d7a8964,7b203f7..6f80f68
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@@ -567,8 -527,8 +566,8 @@@ miDCSaveUnderCursor (pDev, pScreen, x, 
      {
  	if (pSave)
  	    (*pScreen->DestroyPixmap) (pSave);
 -	pScreenPriv->pSave = pSave =
 +	pBuffer->pSave = pSave =
- 		(*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth);
+ 		(*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
  	if (!pSave)
  	    return FALSE;
      }
@@@ -807,14 -731,14 +806,14 @@@ miDCMoveCursor (pDev, pScreen, pCursor
  	if (pTemp)
  	    (*pScreen->DestroyPixmap) (pTemp);
  #ifdef ARGB_CURSOR
 -	if (pScreenPriv->pTempPicture)
 +	if (pBuffer->pTempPicture)
  	{
 -	    FreePicture (pScreenPriv->pTempPicture, 0);
 -	    pScreenPriv->pTempPicture = 0;
 +	    FreePicture (pBuffer->pTempPicture, 0);
 +	    pBuffer->pTempPicture = 0;
  	}
  #endif
 -	pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap)
 -	    (pScreen, w, h, pScreenPriv->pSave->drawable.depth, 0);
 +	pBuffer->pTemp = pTemp = (*pScreen->CreatePixmap)
- 	    (pScreen, w, h, pBuffer->pSave->drawable.depth);
++	    (pScreen, w, h, pBuffer->pSave->drawable.depth, 0);
  	if (!pTemp)
  	    return FALSE;
      }
diff --cc mi/mipointer.c
index 8dc7c7f,24ff4cc..4439ffc
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@@ -361,17 -251,18 +361,18 @@@ miPointerWarpCursor (pDev, pScreen, x, 
      {
  	/* everything from miPointerMove except the event and history */
  
 -    	if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
 +    	if (!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
      	{
 -	    miPointer.devx = x;
 -	    miPointer.devy = y;
 -	    if(!miPointer.pCursor->bits->emptyMask)
 -		(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
 +	    pPointer->devx = x;
 +	    pPointer->devy = y;
 +	    if(!pPointer->pCursor->bits->emptyMask)
 +		(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
      	}
 -	miPointer.x = x;
 -	miPointer.y = y;
 -	miPointer.pScreen = pScreen;
 +	pPointer->x = x;
 +	pPointer->y = y;
 +	pPointer->pScreen = pScreen;
      }
 -    UpdateSpriteForScreen (pScreen) ;
++    UpdateSpriteForScreen (pDev, pScreen) ;
  }
  
  /*
diff --cc mi/misprite.c
index 6e42152,0b402fa..6a2fd37
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@@ -106,16 -89,7 +106,13 @@@ static void	    miSpriteInstallColormap
  static void	    miSpriteStoreColors(ColormapPtr pMap, int ndef,
  					xColorItem *pdef);
  
- static void	    miSpriteSaveDoomedAreas(WindowPtr pWin,
- 					    RegionPtr pObscured, int dx,
- 					    int dy);
 -static void	    miSpriteComputeSaved(ScreenPtr pScreen);
 +static void	    miSpriteComputeSaved(DeviceIntPtr pDev, 
 +                                         ScreenPtr pScreen);
 +
 +static Bool         miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, 
 +                                                   ScreenPtr pScreen);
 +static void         miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, 
 +                                                ScreenPtr pScreen);
  
  #define SCREEN_PROLOGUE(pScreen, field)\
    ((pScreen)->field = \
@@@ -266,11 -220,9 +261,8 @@@ miSpriteInitialize (pScreen, cursorFunc
      pScreen->GetImage = miSpriteGetImage;
      pScreen->GetSpans = miSpriteGetSpans;
      pScreen->SourceValidate = miSpriteSourceValidate;
 -    
 +
      pScreen->CopyWindow = miSpriteCopyWindow;
- 
-     pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
- 
 -    
      pScreen->InstallColormap = miSpriteInstallColormap;
      pScreen->StoreColors = miSpriteStoreColors;
  
@@@ -309,9 -257,9 +301,8 @@@ miSpriteCloseScreen (i, pScreen
      pScreen->InstallColormap = pScreenPriv->InstallColormap;
      pScreen->StoreColors = pScreenPriv->StoreColors;
  
-     pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
 -    miSpriteIsUpFALSE (pScreen, pScreenPriv);
      DamageDestroy (pScreenPriv->pDamage);
 -    
 +
      xfree ((pointer) pScreenPriv);
  
      return (*pScreen->CloseScreen) (i, pScreen);
diff --cc xkb/xkbActions.c
index dd4d7c1,8ddbdba..ea7913a
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@@ -1271,14 -1277,11 +1270,13 @@@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICE
  	if (keyEvent) {
  	    realMods = keyc->modifierMap[key];
  	    keyc->modifierMap[key] = 0;
 -        }
 +            tmpdev = dev;
 +        } else
 +            tmpdev = GetPairedPointer(dev);
  
- 
 -        UNWRAP_PROCESS_INPUT_PROC(dev,xkbPrivPtr, backupproc);
 -        dev->public.processInputProc(xE,dev,count);
 -        COND_WRAP_PROCESS_INPUT_PROC(dev, xkbPrivPtr,
 +        UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
 +        dev->public.processInputProc(xE,tmpdev,count);
 +        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
                                       backupproc,xkbUnwrapProc);
          if (keyEvent)
  	    keyc->modifierMap[key] = realMods;
diff --cc xkb/xkbInit.c
index bcfd149,6301a32..0682cc4
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@@ -179,12 -179,12 +179,12 @@@ char *			pval
  
      name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
      if (name==None) {
 -	ErrorF("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
 +	ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
  	return True;
      }
-     pval= (char*) ALLOCATE_LOCAL(len);
+     pval= (char*) xalloc(len);
      if (!pval) {
 -	ErrorF("Allocation error: %s proprerty not created\n",
 +	ErrorF("[xkb] Allocation error: %s proprerty not created\n",
  						_XKB_RF_NAMES_PROP_ATOM);
  	return True;
      }
diff --cc xkb/xkbPrKeyEv.c
index 212ee94,3fec4f5..f007f75
--- a/xkb/xkbPrKeyEv.c
+++ b/xkb/xkbPrKeyEv.c
@@@ -193,23 -193,42 +193,42 @@@ int             xiEvent
  void
  ProcessKeyboardEvent(xEvent *xE,DeviceIntPtr keybd,int count)
  {
- KeyClassPtr	keyc = keybd->key;
- XkbSrvInfoPtr	xkbi;
  
-     xkbi= keyc->xkbInfo;
+     KeyClassPtr keyc = keybd->key;
+     XkbSrvInfoPtr xkbi = NULL;
+     ProcessInputProc backup_proc;
+     xkbDeviceInfoPtr xkb_priv = XKBDEVICEINFO(keybd);
+     int is_press = (xE->u.u.type == KeyPress || xE->u.u.type == DeviceKeyPress);
+     int is_release = (xE->u.u.type == KeyRelease ||
+                       xE->u.u.type == DeviceKeyRelease);
+ 
+     if (keyc)
+         xkbi = keyc->xkbInfo;
+ 
+     /* We're only interested in key events. */
+     if (!is_press && !is_release) {
+         UNWRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc);
+         keybd->public.processInputProc(xE, keybd, count);
+         COND_WRAP_PROCESS_INPUT_PROC(keybd, xkb_priv, backup_proc,
+                                      xkbUnwrapProc);
+         return;
+     }
  
- #ifdef DEBUG
-     if (xkbDebugFlags&0x8) {
- 	int key= xE->u.u.detail;
- 	ErrorF("[xkb] PKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
+     /* If AccessX filters are active, then pass it through to
+      * AccessXFilter{Press,Release}Event; else, punt to
+      * XkbProcessKeyboardEvent.
+      *
+      * If AXF[PK]E don't intercept anything (which they probably won't),
+      * they'll punt through XPKE anyway. */
+     if ((xkbi->desc->ctrls->enabled_ctrls & XkbAllFilteredEventsMask)) {
+         if (is_press)
+             AccessXFilterPressEvent(xE, keybd, count);
+         else if (is_release)
+             AccessXFilterReleaseEvent(xE, keybd, count);
 -    }
 -    else {
++
++    } else {
+         XkbProcessKeyboardEvent(xE, keybd, count);
      }
- #endif
-     if ((xkbi->desc->ctrls->enabled_ctrls&XkbAllFilteredEventsMask)==0)
- 	XkbProcessKeyboardEvent(xE,keybd,count);
-     else if (xE->u.u.type==KeyPress || xE->u.u.type==DeviceKeyPress)
- 	AccessXFilterPressEvent(xE,keybd,count);
-     else if (xE->u.u.type==KeyRelease || xE->u.u.type==DeviceKeyRelease)
- 	AccessXFilterReleaseEvent(xE,keybd,count);
+     
      return;
  }
- 
commit a8808ac3d093f33b39de109107d396fe0a02c4fc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 7 11:42:58 2007 +1030

    Xi: don't call CheckMotion for slave devices.
    
    This essentially disables enter/leave for slave devices, but re-enables them
    for master devices. Which is a good thing after all.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 3f096a6..cf73bfd 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -127,7 +127,8 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     if (device->isMaster && device->coreEvents && coretype)
         sendCore = TRUE;
 
-    CheckMotion(xE, device);
+    if (device->isMaster)
+        CheckMotion(xE, device);
 
     if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
         DeviceIntPtr mouse = NULL, kbd = NULL;
commit 15944b8f02752eedd61be34a6a29dd6b82a0ac97
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 7 11:33:24 2007 +1030

    mi: duplicate event before processing it, so master has original values
    
    Event values may get changed in the event processing stage, so we need to
    duplicate it to pump different events through for slave and master device.

diff --git a/mi/mieq.c b/mi/mieq.c
index 7d6d110..20004f3 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -232,7 +232,8 @@ mieqProcessInputEvents(void)
 {
     EventRec *e = NULL;
     int x = 0, y = 0;
-    xEvent* event;
+    xEvent* event,
+            *master_event;
 
     while (miEventQueue.head != miEventQueue.tail) {
         if (screenIsSaved == SCREEN_SAVER_ON)
@@ -283,25 +284,43 @@ mieqProcessInputEvents(void)
              * copy. Eventually the interface for the processInputProc needs
              * to be changed. (whot)
              */ 
+
+            /* The event is changed during event processing, so we need to
+             * memcpy the event we have and pass the copy through for master
+             */
             if (e->nevents > 1)
             {
                 int i;
                 event = xcalloc(e->nevents, sizeof(xEvent));
+                master_event = xcalloc(e->nevents, sizeof(xEvent));
+                if (!event || !master_event)
+                    FatalError("[mi] No memory left for event processing.\n");
                 for (i = 0; i < e->nevents; i++)
+                {
                     memcpy(&event[i], e->events[i].event, sizeof(xEvent));
+                    memcpy(&master_event[i], e->events[i].event, sizeof(xEvent));
+                }
             }
             else 
             {
+                int len = sizeof(xEvent); 
                 event = e->events->event;
+                if (event->u.u.type == GenericEvent) 
+                        len += GEV(event)->length * 4;
+                master_event = xalloc(len);
+                if (!master_event)
+                    FatalError("[mi] No memory left for master event.\n");
+                memcpy(master_event, event, len);
             }
 
             e->pDev->public.processInputProc(event, e->pDev, e->nevents);
             if (!e->pDev->isMaster && e->pDev->u.master)
-                e->pDev->u.master->public.processInputProc(event, 
+                e->pDev->u.master->public.processInputProc(master_event, 
                         e->pDev->u.master, e->nevents);
 
             if (e->nevents > 1)
                 xfree(event);
+            xfree(master_event);
         }
 
         /* Update the sprite now. Next event may be from different device. */
commit b7ee005d327372c1e414ee6c526f9f7aee14bc86
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 24 10:26:12 2007 +0930

    dix: Don't interfere grabs the interfering device is of different type.
    
    A pointer device should be able to send events while the client has a core
    grab on a keyboard device, and likewise.

diff --git a/dix/events.c b/dix/events.c
index 7a21af1..2032b42 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -6206,7 +6206,9 @@ IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
             if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
                         && !it->deviceGrab.fromPassiveGrab)
             {
-                return TRUE;
+                if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
+                        (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
+                    return TRUE;
             }
         }
         it = it->next;
commit 02508614b9f882ba1559fb4581dcf812118fdf89
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 24 10:09:18 2007 +0930

    dix: check for core passive grabs on inferiors when replaying events.

diff --git a/dix/events.c b/dix/events.c
index 8141a40..7a21af1 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1400,18 +1400,24 @@ ComputeFreezes(void)
                      * deliver it too.
                      * However, we might get here with a core event, in which
                      * case we mustn't emulate a core event.
-                     * XXX: I think this may break things. If a client has a
-                     * device grab, and another client a core grab on an
-                     * inferior window, we never get the core grab. (whot)
                      */
                     sendCore = (replayDev->coreEvents &&
                         (xE->u.u.type & EXTENSION_EVENT_BASE &&
                          XItoCoreType(xE->u.u.type)));
 
+
                     if (sendCore)
                     {
                         core = *xE;
                         core.u.u.type = XItoCoreType(xE->u.u.type);
+                        /* * XXX: Not sure if this is correct: we need to
+                         * check inferior windows for core passive grabs. 
+                         */
+                        if (CheckDeviceGrabs(replayDev, &core, i+1, 1))
+                        {
+                            syncEvents.playingEvents = FALSE;
+                            return;
+                        }
                     }
 		    if (replayDev->focus)
                     {
commit 7ef863720dc79107fc2cd17ce684366c87e001a4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 23 17:28:03 2007 +0930

    dix: Create new sprite for floating devices.
    
    Floating devices get sprites, but still aren't spriteOwners. This prevents
    them from getting rendered, and also stops segfaulting.
    (not really solving the problems with keyboards though)

diff --git a/dix/devices.c b/dix/devices.c
index d971339..7e7e646 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2205,16 +2205,18 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
  * Client is set to the client that issued the request, or NULL if it comes
  * from some internal automatic pairing.
  *
+ * Master may be NULL to set the device floating. 
+ *
  * We don't allow multi-layer hierarchies right now. You can't attach a slave
  * to another slave. 
  */
 int
 AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 {
-    if (!dev || !master)
+    if (!dev || dev->isMaster) 
         return BadDevice;
 
-    if (!master->isMaster) /* can't attach to slave device */
+    if (master && !master->isMaster) /* can't attach to slaves */
         return BadDevice;
 
     if (!pairingClient)
@@ -2222,8 +2224,27 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
     else if (client && pairingClient != client)
         return BadAccess;
 
+    /* set from floating to floating? */
+    if (!dev->u.master && !master)
+        return Success;
+
+    /* free the existing sprite. */
+    if (!dev->u.master && dev->spriteInfo->sprite)
+        xfree(dev->spriteInfo->sprite);
+
     dev->u.master = master;
-    dev->spriteInfo->sprite = master->spriteInfo->sprite;
+
+    /* If device is set to floating, we need to create a sprite for it,
+     * otherwise things go bad. However, we don't want to render the cursor,
+     * so we reset spriteOwner.
+     */
+    if (!master)
+    {
+                              /* current root window */
+        InitializeSprite(dev, dev->spriteInfo->sprite->spriteTrace[0]);
+        dev->spriteInfo->spriteOwner = FALSE;
+    } else
+        dev->spriteInfo->sprite = master->spriteInfo->sprite;
 
     return Success;
 }
commit d9caa469b9bb4eb6125b890820853062fc2c4441
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Oct 19 15:26:09 2007 +0930

    Xi: allow VCP/VCK to be OpenDevice'd as well.
    
    All devices deserve to be equal. Except master devices, they are a bit more
    equal than the others.

diff --git a/Xi/opendev.c b/Xi/opendev.c
index 0b0671d..192cddc 100644
--- a/Xi/opendev.c
+++ b/Xi/opendev.c
@@ -106,12 +106,6 @@ ProcXOpenDevice(ClientPtr client)
     REQUEST(xOpenDeviceReq);
     REQUEST_SIZE_MATCH(xOpenDeviceReq);
 
-    if (stuff->deviceid == inputInfo.pointer->id ||
-	stuff->deviceid == inputInfo.keyboard->id) {
-	SendErrorToClient(client, IReqCode, X_OpenDevice, 0, BadDevice);
-	return Success;
-    }
-
     if ((dev = LookupDeviceIntRec(stuff->deviceid)) == NULL) {	/* not open */
 	for (dev = inputInfo.off_devices; dev; dev = dev->next)
 	    if (dev->id == stuff->deviceid)
commit 155e2c559ed0dbf31b6d39d48648a3ee22b37635
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Oct 19 14:37:07 2007 +0930

    Xi: advertise as XInput v2 capable

diff --git a/Xi/extinit.c b/Xi/extinit.c
index c933e55..d02053c 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -236,8 +236,8 @@ Mask PropagateMask[MAX_DEVICES];
  */
 
 static XExtensionVersion thisversion = { XI_Present,
-    XI_Add_DevicePresenceNotify_Major,
-    XI_Add_DevicePresenceNotify_Minor
+    XI_2_Major,
+    XI_2_Minor
 };
 
 
commit 5ba738935f0d786e4670adf3b05ad42fc5e710fd
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Oct 19 14:36:37 2007 +0930

    Xi: remove ChangePointerKeyboardPairing in favour of ChangeDeviceHierarchy.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 2cf11a0..407928d 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -9,6 +9,8 @@ libXi_la_SOURCES =	\
         chdevcur.h \
 	chgdctl.c \
 	chgdctl.h \
+        chdevhier.c \
+        chdevhier.h \
 	chgfctl.c \
 	chgfctl.h \
 	chgkbd.c \
@@ -19,8 +21,6 @@ libXi_la_SOURCES =	\
 	chgprop.h \
 	chgptr.c \
 	chgptr.h \
-	chpkpair.c \
-	chpkpair.h \
 	chaccess.c \
 	chaccess.h \
 	closedev.c \
diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c
new file mode 100644
index 0000000..c916c0f
--- /dev/null
+++ b/Xi/chdevhier.c
@@ -0,0 +1,231 @@
+/*
+
+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 change in the device hierarchy.
+ *
+ */
+
+
+#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/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 "chdevhier.h"
+
+
+/***********************************************************************
+ *
+ * This procedure allows a client to change the device hierarchy through
+ * adding new master devices, removing them, etc.
+ *
+ */
+
+int SProcXChangeDeviceHierarchy(ClientPtr client)
+{
+    char n;
+
+    REQUEST(xChangeDeviceHierarchyReq);
+    swaps(&stuff->length, n);
+    return (ProcXChangeDeviceHierarchy(client));
+}
+
+#define SWAPIF(cmd) if (client->swapped) { cmd; }
+
+int
+ProcXChangeDeviceHierarchy(ClientPtr client)
+{
+    DeviceIntPtr ptr, keybd;
+    xAnyHierarchyChangeInfo *any;
+    int required_len = sizeof(xChangeDeviceHierarchyReq);
+    char n;
+
+    REQUEST(xChangeDeviceHierarchyReq);
+    REQUEST_AT_LEAST_SIZE(xChangeDeviceHierarchyReq);
+
+    /* XXX: check if client is allowed to change hierarch */
+
+    
+    any = (xAnyHierarchyChangeInfo*)&stuff[1];
+    while(stuff->num_changes--)
+    {
+        SWAPIF(swapl(&any->type, n));
+        SWAPIF(swaps(&any->length, n));
+
+        required_len += any->length;
+        if ((stuff->length * 4) < required_len)
+            return BadLength;
+
+        switch(any->type)
+        {
+            case CH_CreateMasterDevice:
+                {
+                    xCreateMasterInfo* c = (xCreateMasterInfo*)any;
+                    char* name;
+                    int ret;
+                    
+                    SWAPIF(swaps(&c->namelen, n));
+                    name = xcalloc(c->namelen + 1, sizeof(char));
+                    strncpy(name, (char*)&c[1], c->namelen);
+
+                    ret = AllocMasterDevice(name, &ptr, &keybd);
+                    if (ret != Success)
+                    {
+                        xfree(name);
+                        return ret;
+                    }
+
+                    if (!c->sendCore)
+                        ptr->coreEvents = keybd->coreEvents =  FALSE;
+
+                    ActivateDevice(ptr);
+                    ActivateDevice(keybd);
+
+                    if (c->enable)
+                    {
+                        EnableDevice(ptr);
+                        EnableDevice(keybd);
+                    }
+                    xfree(name);
+                }
+                break;
+            case CH_RemoveMasterDevice:
+                {
+                    xRemoveMasterInfo* r = (xRemoveMasterInfo*)any;
+
+                    if (r->returnMode != AttachToMaster && 
+                            r->returnMode != Floating)
+                        return BadValue;
+
+                    ptr = LookupDeviceIntRec(r->deviceid);
+                    if (!ptr || !ptr->isMaster)
+                        return BadDevice;
+
+                    /* XXX: For now, don't allow removal of VCP, VCK */
+                    if (ptr == inputInfo.pointer ||
+                            ptr == inputInfo.keyboard)
+                        return BadDevice;
+
+                    /* disable keyboards first */
+                    if (IsPointerDevice(ptr))
+                        keybd = ptr->spriteInfo->paired;
+                    else
+                    {
+                        keybd = ptr;
+                        ptr = keybd->spriteInfo->paired;
+                    }
+
+                    /* Disabling sends the devices floating, reattach them if
+                     * desired. */
+                    if (r->returnMode == AttachToMaster)
+                    {
+                        DeviceIntPtr attached, 
+                                     newptr, 
+                                     newkeybd;
+
+                        newptr = LookupDeviceIntRec(r->returnPointer);
+                        newkeybd = LookupDeviceIntRec(r->returnKeyboard);
+                        if (!newptr || !newptr->isMaster ||
+                                !newkeybd || !newkeybd->isMaster)
+                            return BadDevice;
+
+                        for (attached = inputInfo.devices; 
+                                attached; 
+                                attached = attached->next)
+                        {
+                            if (!attached->isMaster) {
+                                if (attached->u.master == ptr)
+                                    AttachDevice(client, attached, newptr);
+                                if (attached->u.master == keybd)
+                                    AttachDevice(client, attached, newkeybd);
+                            }
+                        }
+                    }
+
+                    /* can't disable until we removed pairing */
+                    keybd->spriteInfo->paired = NULL;
+                    ptr->spriteInfo->paired = NULL;
+                    DisableDevice(keybd);
+                    DisableDevice(ptr);
+
+                    RemoveDevice(keybd);
+                    RemoveDevice(ptr);
+                }
+                break;
+            case CH_ChangeAttachment:
+                {
+                    xChangeAttachmentInfo* c = (xChangeAttachmentInfo*)any;
+
+                    ptr = LookupDeviceIntRec(c->deviceid);
+                    if (!ptr || ptr->isMaster)
+                        return BadDevice;
+
+                    if (c->changeMode == Floating)
+                        AttachDevice(client, ptr, NULL);
+                    else
+                    {
+                        DeviceIntPtr newmaster = LookupDeviceIntRec(c->newMaster);
+                        if (!newmaster || !newmaster->isMaster)
+                            return BadDevice;
+
+                        if ((IsPointerDevice(newmaster) &&
+                                    !IsPointerDevice(ptr)) ||
+                                (IsKeyboardDevice(newmaster) &&
+                                 !IsKeyboardDevice(ptr))) 
+                                return BadDevice;
+                        AttachDevice(client, ptr, newmaster);
+                    }
+
+                }
+                break;
+        }
+
+        any = (xAnyHierarchyChangeInfo*)((char*)any + any->length);
+    }
+
+    return Success;
+}
+
diff --git a/Xi/chdevhier.h b/Xi/chdevhier.h
new file mode 100644
index 0000000..1853fa7
--- /dev/null
+++ b/Xi/chdevhier.h
@@ -0,0 +1,45 @@
+/*
+
+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 change in the device hierarchy.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef CHDEVHIER_H
+#define CHDEVHIER_H 1
+
+int SProcXChangeDeviceHierarchy(ClientPtr /* client */);
+int ProcXChangeDeviceHierarchy(ClientPtr /* client */);
+
+#endif
diff --git a/Xi/extinit.c b/Xi/extinit.c
index c1b6eed..c933e55 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -79,11 +79,11 @@ SOFTWARE.
 #include "chaccess.h"
 #include "chdevcur.h"
 #include "chgdctl.h"
+#include "chdevhier.h"
 #include "chgfctl.h"
 #include "chgkbd.h"
 #include "chgprop.h"
 #include "chgptr.h"
-#include "chpkpair.h"
 #include "closedev.h"
 #include "extgrbdev.h"
 #include "devbell.h"
@@ -328,8 +328,8 @@ ProcIDispatch(ClientPtr client)
         return (ProcXWarpDevicePointer(client));
     else if (stuff->data == X_ChangeDeviceCursor)
         return (ProcXChangeDeviceCursor(client));
-    else if (stuff->data == X_ChangePointerKeyboardPairing)
-        return (ProcXChangePointerKeyboardPairing(client));
+    else if (stuff->data == X_ChangeDeviceHierarchy)
+        return (ProcXChangeDeviceHierarchy(client));
     else if (stuff->data == X_XiSelectEvent)
         return (ProcXiSelectEvent(client));
     else if (stuff->data == X_RegisterPairingClient)
@@ -445,8 +445,8 @@ SProcIDispatch(ClientPtr client)
 	return (SProcXWarpDevicePointer(client));
     else if (stuff->data == X_ChangeDeviceCursor)
         return (SProcXChangeDeviceCursor(client));
-    else if (stuff->data == X_ChangePointerKeyboardPairing)
-        return (SProcXChangePointerKeyboardPairing(client));
+    else if (stuff->data == X_ChangeDeviceHierarchy)
+        return (SProcXChangeDeviceHierarchy(client));
     else if (stuff->data == X_XiSelectEvent)
         return (SProcXiSelectEvent(client));
     else if (stuff->data == X_RegisterPairingClient)
@@ -1153,10 +1153,6 @@ XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
     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;
diff --git a/dix/devices.c b/dix/devices.c
index af086a4..d971339 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2343,6 +2343,7 @@ AllocMasterDevice(char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
 {
     DeviceIntPtr pointer;
     DeviceIntPtr keyboard;
+    *ptr = *keybd = NULL;
 
     pointer = AddInputDevice(CorePointerProc, TRUE);
     if (!pointer)
commit 6dcde0e9c1d068d9fc4a772d29d1d4c6cc57aeb9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Oct 18 12:21:07 2007 +0930

    Xi: set master device's id in ListDevices Reply.

diff --git a/Xi/listdev.c b/Xi/listdev.c
index 5b5d26e..8753b29 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -187,6 +187,9 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
         dev->use = IsXExtensionPointer;
     else
 	dev->use = IsXExtensionDevice;
+    if (!d->isMaster) 
+        dev->attached = (d->u.master) ? d->u.master->id : IsFloating;
+
     if (client->swapped) {
 	swapl(&dev->type, n);	/* macro - braces are required */
     }
commit cfcc6e14b9a15f7979ba0df9c105cf563bef98fa
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Oct 19 11:28:44 2007 +0930

    Xi: return all master devices as type IsXPointer/Keyboard when listing devs.
    
    Slave devices are reported as IsXExtensionPointer/Keyboard.

diff --git a/Xi/listdev.c b/Xi/listdev.c
index a9fd401..5b5d26e 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -177,9 +177,9 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
     dev->id = d->id;
     dev->type = d->type;
     dev->num_classes = num_classes;
-    if (d == inputInfo.keyboard)
+    if (d->isMaster && IsKeyboardDevice(d))
 	dev->use = IsXKeyboard;
-    else if (d == inputInfo.pointer)
+    else if (d->isMaster && IsPointerDevice(d))
 	dev->use = IsXPointer;
     else if (d->key && d->kbdfeed)
         dev->use = IsXExtensionKeyboard;
@@ -328,10 +328,6 @@ ProcXListInputDevices(ClientPtr client)
 
     AddOtherInputDevices();
 
-    SizeDeviceInfo(inputInfo.keyboard, &namesize, &size);
-    SizeDeviceInfo(inputInfo.pointer, &namesize, &size);
-    numdevs = 2;
-
     for (d = inputInfo.devices; d; d = d->next) {
 	SizeDeviceInfo(d, &namesize, &size);
         numdevs++;
@@ -348,11 +344,6 @@ ProcXListInputDevices(ClientPtr client)
     savbuf = devbuf;
 
     dev = (xDeviceInfoPtr) devbuf;
-    ListDeviceInfo(client, inputInfo.keyboard, dev++, 
-                   &devbuf, &classbuf, &namebuf);
-    ListDeviceInfo(client, inputInfo.pointer, dev++,
-                   &devbuf, &classbuf, &namebuf);
-
     for (d = inputInfo.devices; d; d = d->next, dev++)
 	ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
     for (d = inputInfo.off_devices; d; d = d->next, dev++)
commit 9aadde377991bfbd88524d02106bec3dedd6e7c9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 17 12:05:50 2007 +0930

    mi: don't call UndisplayCursor for non-sprite-owners.
    
    Segfaults are bad.

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 0db4d2c..7a32578 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -229,7 +229,8 @@ miPointerUndisplayCursor(pDev, pScreen)
     ScreenPtr 	 pScreen;
 {
     SetupScreen(pScreen);
-    (*pScreenPriv->spriteFuncs->UndisplayCursor)(pDev, pScreen);
+    if (pDev->isMaster && pDev->spriteInfo->spriteOwner)
+        (*pScreenPriv->spriteFuncs->UndisplayCursor)(pDev, pScreen);
 }
 
 static void
commit 8b7c4249d82d07e852d8d8c15c7ab9977dd1f31c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 17 10:41:58 2007 +0930

    mi: call processInputProc for master devices after slave event processing.
    
    More work is needed to sort out grabs though.

diff --git a/mi/mieq.c b/mi/mieq.c
index f5e119e..7d6d110 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -296,6 +296,9 @@ mieqProcessInputEvents(void)
             }
 
             e->pDev->public.processInputProc(event, e->pDev, e->nevents);
+            if (!e->pDev->isMaster && e->pDev->u.master)
+                e->pDev->u.master->public.processInputProc(event, 
+                        e->pDev->u.master, e->nevents);
 
             if (e->nevents > 1)
                 xfree(event);
commit ae9fc10adec8f9bf0492d14d435f8f11e0163b27
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 17 10:41:04 2007 +0930

    Xi: don't send core events for slave devices.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 49400e8..3f096a6 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -124,7 +124,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     int coretype = 0;
 
     coretype = XItoCoreType(xE->u.u.type);
-    if (device->coreEvents && coretype)
+    if (device->isMaster && device->coreEvents && coretype)
         sendCore = TRUE;
 
     CheckMotion(xE, device);
commit de70cfdbe60eb6e7bf3e74dfd1ac34de554deff1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 17 09:52:30 2007 +0930

    mi: fix some macros to allow multiple cursors for master devices.
    
    Macros defaulted to inputInfo.pointe rfor devices that weren't spriteOwners.
    Changed to take the device's master device now.
    
    This includes sticking in a number of checks and warnings that cursor
    rendering won't be called for floating devices.

diff --git a/mi/midispcur.c b/mi/midispcur.c
index d7a8964..16ece10 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -85,7 +85,7 @@ typedef struct {
 #define MIDCBUFFER(dev) \
  ((DevHasCursor(dev)) ? \
   (miDCBufferPtr)dev->devPrivates[miDCSpriteIndex].ptr :\
-  (miDCBufferPtr)inputInfo.pointer->devPrivates[miDCSpriteIndex].ptr)
+  (miDCBufferPtr)dev->u.master->devPrivates[miDCSpriteIndex].ptr)
 
 /* 
  * The core pointer buffer will point to the index of the virtual core pointer
diff --git a/mi/mipointer.c b/mi/mipointer.c
index eabc435..0db4d2c 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -59,7 +59,7 @@ static int miPointerPrivatesIndex = 0;
 #define MIPOINTER(dev) \
     ((DevHasCursor((dev))) ? \
         (miPointerPtr) dev->devPrivates[miPointerPrivatesIndex].ptr : \
-        (miPointerPtr) inputInfo.pointer->devPrivates[miPointerPrivatesIndex].ptr)
+        (miPointerPtr) dev->u.master->devPrivates[miPointerPrivatesIndex].ptr)
 
 static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                    CursorPtr pCursor);
@@ -210,7 +210,12 @@ miPointerDisplayCursor (pDev, pScreen, pCursor)
     ScreenPtr 	 pScreen;
     CursorPtr	 pCursor;
 {
-    miPointerPtr pPointer = MIPOINTER(pDev);
+    miPointerPtr pPointer;
+    
+    if (!pDev->isMaster && !pDev->u.master)
+        return FALSE;
+
+    pPointer = MIPOINTER(pDev);
 
     pPointer->pCursor = pCursor;
     pPointer->pScreen = pScreen;
@@ -233,7 +238,12 @@ miPointerConstrainCursor (pDev, pScreen, pBox)
     ScreenPtr	pScreen;
     BoxPtr	pBox;
 {
-    miPointerPtr pPointer = MIPOINTER(pDev);
+    miPointerPtr pPointer;
+
+    if (!pDev->isMaster && !pDev->u.master)
+        return;
+    
+    pPointer = MIPOINTER(pDev);
 
     pPointer->limits = *pBox;
     pPointer->confined = PointerConfinedToScreen(pDev);
@@ -347,7 +357,11 @@ miPointerWarpCursor (pDev, pScreen, x, y)
     ScreenPtr	 pScreen;
     int	   	 x, y;
 {
-    miPointerPtr pPointer = MIPOINTER(pDev);
+    miPointerPtr pPointer;
+    
+    if (!pDev->isMaster && !pDev->u.master)
+        return;
+    pPointer = MIPOINTER(pDev);
     SetupScreen (pScreen);
 
     if (pPointer->pScreen != pScreen)
@@ -399,7 +413,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     int			x, y, devx, devy;
     miPointerPtr        pPointer;
 
-    if (!pDev || !pDev->coreEvents)
+    if (!pDev || !pDev->coreEvents || (!pDev->isMaster && !pDev->u.master))
         return;
 
     pPointer = MIPOINTER(pDev);
@@ -488,7 +502,12 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
 {
 	miPointerScreenPtr pScreenPriv;
 	ScreenPtr pScreen;
-        miPointerPtr pPointer = MIPOINTER(pDev);
+        miPointerPtr pPointer; 
+        
+        if (!pDev->isMaster && !pDev->u.master)
+            return;
+
+        pPointer = MIPOINTER(pDev);
 
 	pScreen = screenInfo.screens[screen_no];
 	pScreenPriv = GetScreenPrivate (pScreen);
@@ -508,8 +527,10 @@ miPointerCurrentScreen ()
 _X_EXPORT ScreenPtr
 miPointerGetScreen(DeviceIntPtr pDev)
 {
-    miPointerPtr pPointer = MIPOINTER(pDev);
-    return pPointer->pScreen;
+    if (!pDev->isMaster && !pDev->u.master)
+        return NULL;
+
+    return MIPOINTER(pDev)->pScreen;
 }
 
 /* Move the pointer to x, y on the current screen, update the sprite, and
@@ -526,9 +547,13 @@ static void
 miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
                      unsigned long time)
 {
-    miPointerPtr pPointer = MIPOINTER(pDev);
+    miPointerPtr pPointer;
     SetupScreen(pScreen);
 
+    if (!pDev->isMaster && !pDev->u.master) 
+        return;
+
+    pPointer = MIPOINTER(pDev);
 
     if (pDev && pDev->coreEvents 
         && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
@@ -551,8 +576,12 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     ScreenPtr		pScreen;
     ScreenPtr		newScreen;
 
-    miPointerPtr        pPointer = MIPOINTER(pDev);
+    miPointerPtr        pPointer; 
+    
+    if (!pDev->isMaster && !pDev->u.master)
+        return;
 
+    pPointer = MIPOINTER(pDev);
     pScreen = pPointer->pScreen;
     if (!pScreen)
 	return;	    /* called before ready */
@@ -605,9 +634,14 @@ miPointerPosition (int *x, int *y)
 _X_EXPORT void
 miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
 {
-    miPointerPtr pPointer = MIPOINTER(pDev);
-    *x = pPointer->x;
-    *y = pPointer->y;
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miPointerGetPosition called for floating device.\n");
+        return;
+    }
+
+    *x = MIPOINTER(pDev)->x;
+    *y = MIPOINTER(pDev)->y;
 }
 
 void
diff --git a/mi/misprite.c b/mi/misprite.c
index 6e42152..6aad36c 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -77,7 +77,7 @@ static int miSpriteDevPrivatesIndex;
 #define MISPRITE(dev) \
     ((DevHasCursor(dev)) ? \
        (miCursorInfoPtr) dev->devPrivates[miSpriteDevPrivatesIndex].ptr : \
-       (miCursorInfoPtr) inputInfo.pointer->devPrivates[miSpriteDevPrivatesIndex].ptr)
+       (miCursorInfoPtr) dev->u.master->devPrivates[miSpriteDevPrivatesIndex].ptr)
 
 
 /*
@@ -759,6 +759,12 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     miCursorInfoPtr pCursorInfo;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miSpriteRealizeCursor called for floating device.\n");
+        return FALSE;
+    }
     pCursorInfo = MISPRITE(pDev);
 
     if (pCursor == pCursorInfo->pCursor)
@@ -790,7 +796,14 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
     miSpriteScreenPtr	pScreenPriv;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    miCursorInfoPtr pPointer = MISPRITE(pDev);
+    miCursorInfoPtr pPointer;
+    
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miSpriteSetCursor called for floating device.\n");
+        return;
+    }
+    pPointer = MISPRITE(pDev);
 
     if (!pCursor)
     {
@@ -905,6 +918,11 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
     CursorPtr pCursor;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miSpriteMoveCursor called for floating device.\n");
+        return;
+    }
     pCursor = MISPRITE(pDev)->pCursor;
 
     miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
@@ -972,6 +990,11 @@ miSpriteUndisplayCursor(pDev, pScreen)
     DeviceIntPtr pDev;
     ScreenPtr    pScreen;
 {
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miSpriteUndisplayCursor called for floating device.\n");
+        return;
+    }
     if (MISPRITE(pDev)->isUp)
         miSpriteRemoveCursor(pDev, pScreen);
 }
@@ -989,6 +1012,11 @@ miSpriteRemoveCursor (pDev, pScreen)
     miCursorInfoPtr     pCursorInfo;
 
 
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miSpriteRemoveCursor called for floating device.\n");
+        return;
+    }
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = MISPRITE(pDev);
@@ -1026,6 +1054,11 @@ miSpriteSaveUnderCursor(pDev, pScreen)
     CursorPtr		pCursor;
     miCursorInfoPtr     pCursorInfo;
 
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miSpriteSaveUnderCursor called for floating device.\n");
+        return;
+    }
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = MISPRITE(pDev);
@@ -1065,6 +1098,12 @@ miSpriteRestoreCursor (pDev, pScreen)
     int			x, y;
     CursorPtr		pCursor;
     miCursorInfoPtr     pCursorInfo;
+    
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miSpriteRestoreCursor called for floating device.\n");
+        return;
+    }
 
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
@@ -1106,6 +1145,11 @@ miSpriteComputeSaved (pDev, pScreen)
     CursorPtr	    pCursor;
     miCursorInfoPtr pCursorInfo;
 
+    if (!pDev->isMaster && !pDev->u.master)
+    {
+        ErrorF("[mi] miSpriteComputeSaved called for floating device.\n");
+        return;
+    }
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = MISPRITE(pDev);
 
commit 1d9ebbac8c589cae7e4952083692b6d148def9bc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 18:46:12 2007 +0930

    dix: Make InitCoreDevices use AllocMasterDevice.
    
    Also change naming a bit, append "pointer" and "keyboard" to master devices
    instead of -ptr and -keybd.

diff --git a/dix/devices.c b/dix/devices.c
index ef5ebf9..af086a4 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -485,68 +485,27 @@ CorePointerProc(DeviceIntPtr pDev, int what)
 void
 InitCoreDevices(void)
 {
-    DeviceIntPtr dev;
-
     if (CoreDevicePrivatesGeneration != serverGeneration) {
         CoreDevicePrivatesIndex = AllocateDevicePrivateIndex();
         CoreDevicePrivatesGeneration = serverGeneration;
     }
 
-    if (!inputInfo.keyboard) {
-        dev = AddInputDevice(CoreKeyboardProc, TRUE);
-        if (!dev)
-            FatalError("Failed to allocate core keyboard");
-        dev->name = strdup("Virtual core keyboard");
-#ifdef XKB
-        dev->public.processInputProc = ProcessOtherEvent;
-        dev->public.realInputProc = ProcessOtherEvent;
-        if (!noXkbExtension)
-            XkbSetExtension(dev, ProcessKeyboardEvent);
-#else
-        dev->public.processInputProc = ProcessKeyboardEvent;
-        dev->public.realInputProc = ProcessKeyboardEvent;
-#endif
-        dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
-        dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
-        dev->coreEvents = TRUE;
-        dev->spriteInfo->spriteOwner = FALSE;
-        if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
-            FatalError("Couldn't allocate keyboard devPrivates\n");
-        dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
-        dev->u.lastSlave = NULL;
-        dev->isMaster = TRUE;
-        (void)ActivateDevice(dev);
-
-        inputInfo.keyboard = dev;
-    }
-
-    if (!inputInfo.pointer) {
-        dev = AddInputDevice(CorePointerProc, TRUE);
-        if (!dev)
-            FatalError("Failed to allocate core pointer");
-        dev->name = strdup("Virtual core pointer");
-#ifdef XKB
-        dev->public.processInputProc = ProcessOtherEvent;
-        dev->public.realInputProc = ProcessOtherEvent;
-        if (!noXkbExtension)
-           XkbSetExtension(dev, ProcessPointerEvent);
-#else
-        dev->public.processInputProc = ProcessPointerEvent;
-        dev->public.realInputProc = ProcessPointerEvent;
-#endif
-        dev->deviceGrab.ActivateGrab = ActivatePointerGrab;
-        dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
-        dev->coreEvents = TRUE;
-        dev->spriteInfo->spriteOwner = TRUE;
-        if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
-            FatalError("Couldn't allocate pointer devPrivates\n");
-        dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
-        dev->u.lastSlave = NULL;
-        dev->isMaster = TRUE;
-        (void)ActivateDevice(dev);
-
-        inputInfo.pointer = dev;
-    }
+    if (AllocMasterDevice("Virtual core", 
+                          &inputInfo.pointer, 
+                          &inputInfo.keyboard) == BadAlloc)
+        FatalError("Failed to allocate core devices");
+
+    if (!AllocateDevicePrivate(inputInfo.keyboard, CoreDevicePrivatesIndex))
+        FatalError("Couldn't allocate keyboard devPrivates\n");
+    inputInfo.keyboard->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
+
+    if (!AllocateDevicePrivate(inputInfo.pointer, CoreDevicePrivatesIndex))
+        FatalError("Couldn't allocate pointer devPrivates\n");
+    inputInfo.pointer->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
+
+    ActivateDevice(inputInfo.keyboard);
+    ActivateDevice(inputInfo.pointer);
+
 }
 
 /**
@@ -2389,9 +2348,9 @@ AllocMasterDevice(char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
     if (!pointer)
         return BadAlloc;
 
-    pointer->name = xcalloc(strlen(name) + strlen("-ptr") + 1, sizeof(char));
+    pointer->name = xcalloc(strlen(name) + strlen(" pointer") + 1, sizeof(char));
     strcpy(pointer->name, name);
-    strcat(pointer->name, "-ptr");
+    strcat(pointer->name, " pointer");
 
 #ifdef XKB
     pointer->public.processInputProc = ProcessOtherEvent;
@@ -2414,9 +2373,9 @@ AllocMasterDevice(char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
     if (!keyboard)
         return BadAlloc;
 
-    keyboard->name = xcalloc(strlen(name) + strlen("-keybd") + 1, sizeof(char));
+    keyboard->name = xcalloc(strlen(name) + strlen(" keyboard") + 1, sizeof(char));
     strcpy(keyboard->name, name);
-    strcat(keyboard->name, "-keybd");
+    strcat(keyboard->name, " keyboard");
 
 #ifdef XKB
     keyboard->public.processInputProc = ProcessOtherEvent;
commit 299573f4617c3b5599bb65069e96d050277b9471
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 18:40:15 2007 +0930

    dix: add AllocMasterDevice for creation of new master devices.
    
    Devices are initiated pretty much the same as the core devices.

diff --git a/dix/devices.c b/dix/devices.c
index 3e5405b..ef5ebf9 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2374,3 +2374,69 @@ NextFreePointerDevice()
             return dev;
     return NULL;
 }
+/**
+ * Create a new master device (== one pointer, one keyboard device).
+ * Only allocates the devices, you will need to call ActivateDevice() and
+ * EnableDevice() manually.
+ */
+int
+AllocMasterDevice(char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
+{
+    DeviceIntPtr pointer;
+    DeviceIntPtr keyboard;
+
+    pointer = AddInputDevice(CorePointerProc, TRUE);
+    if (!pointer)
+        return BadAlloc;
+
+    pointer->name = xcalloc(strlen(name) + strlen("-ptr") + 1, sizeof(char));
+    strcpy(pointer->name, name);
+    strcat(pointer->name, "-ptr");
+
+#ifdef XKB
+    pointer->public.processInputProc = ProcessOtherEvent;
+    pointer->public.realInputProc = ProcessOtherEvent;
+    if (!noXkbExtension)
+        XkbSetExtension(pointer, ProcessPointerEvent);
+#else
+    pointer->public.processInputProc = ProcessPointerEvent;
+    pointer->public.realInputProc = ProcessPointerEvent;
+#endif
+    pointer->deviceGrab.ActivateGrab = ActivatePointerGrab;
+    pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
+    pointer->coreEvents = TRUE;
+    pointer->spriteInfo->spriteOwner = TRUE;
+
+    pointer->u.lastSlave = NULL;
+    pointer->isMaster = TRUE;
+
+    keyboard = AddInputDevice(CoreKeyboardProc, TRUE);
+    if (!keyboard)
+        return BadAlloc;
+
+    keyboard->name = xcalloc(strlen(name) + strlen("-keybd") + 1, sizeof(char));
+    strcpy(keyboard->name, name);
+    strcat(keyboard->name, "-keybd");
+
+#ifdef XKB
+    keyboard->public.processInputProc = ProcessOtherEvent;
+    keyboard->public.realInputProc = ProcessOtherEvent;
+    if (!noXkbExtension)
+        XkbSetExtension(keyboard, ProcessKeyboardEvent);
+#else
+    keyboard->public.processInputProc = ProcessKeyboardEvent;
+    keyboard->public.realInputProc = ProcessKeyboardEvent;
+#endif
+    keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
+    keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
+    keyboard->coreEvents = TRUE;
+    keyboard->spriteInfo->spriteOwner = FALSE;
+
+    keyboard->u.lastSlave = NULL;
+    keyboard->isMaster = TRUE;
+
+    *ptr = pointer;
+    *keybd = keyboard;
+
+    return Success;
+}
diff --git a/include/input.h b/include/input.h
index a176bba..d6a38e6 100644
--- a/include/input.h
+++ b/include/input.h
@@ -477,6 +477,10 @@ extern Bool UnregisterPairingClient(ClientPtr client);
 extern DeviceIntPtr GuessFreePointerDevice(void);
 extern DeviceIntPtr NextFreePointerDevice(void);
 
+extern int AllocMasterDevice(char* name,
+                             DeviceIntPtr* ptr,
+                             DeviceIntPtr* keybd);
+
 /* Window/device based access control */
 extern Bool ACRegisterClient(ClientPtr client);
 extern Bool ACUnregisterClient(ClientPtr client);
commit 5fe9bfd23f17b84c3afaa82f75a7c517c9f8e0d3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 18:23:48 2007 +0930

    xfree86: NIDR: don't call PairDevices explicitly.
             set isMaster to FALSE explicitly.
    
    Pairing isn't necessary, attachment should be done in EnableDevices.

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 711bf94..fc846ba 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -172,6 +172,7 @@ xf86ActivateDevice(LocalDevicePtr local)
         local->dev = dev;      
         
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE; 
+        dev->isMaster = FALSE;
         dev->spriteInfo->spriteOwner = FALSE;
 
         if (DeviceIsPointerType(dev))
@@ -447,9 +448,6 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
         (!is_auto || xf86Info.autoEnableDevices))
         EnableDevice(dev);
 
-    if (!IsPointerDevice(dev))
-        PairDevices(NULL, GuessFreePointerDevice(), dev);
-
     /* send enter/leave event, update sprite window */
     CheckMotion(NULL, dev);
 
commit 5eb033835e92ea951cc385fd709af9656b3772d8
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 18:03:52 2007 +0930

    mi: don't exclude inputInfo.pointer from rendering.

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 8dc7c7f..eabc435 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -399,7 +399,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     int			x, y, devx, devy;
     miPointerPtr        pPointer;
 
-    if (!pDev || pDev == inputInfo.pointer || !pDev->coreEvents)
+    if (!pDev || !pDev->coreEvents)
         return;
 
     pPointer = MIPOINTER(pDev);
@@ -530,7 +530,7 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
     SetupScreen(pScreen);
 
 
-    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer)
+    if (pDev && pDev->coreEvents 
         && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
     {
 	pPointer->devx = x;
@@ -557,7 +557,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     if (!pScreen)
 	return;	    /* called before ready */
 
-    if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer))
+    if (!pDev || !pDev->coreEvents)
         return;
 
     if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
commit b697c4ed145968d3c3281bb85e628f1b068b09fc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 17:47:06 2007 +0930

    dix: CheckPassiveGrabOnWindow: only get paired device for non-keyboards.

diff --git a/dix/events.c b/dix/events.c
index 50d06c4..d342d36 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3243,7 +3243,12 @@ CheckPassiveGrabsOnWindow(
 
 	gdev= grab->modifierDevice;
         if (grab->coreGrab)
-            gdev = GetPairedDevice(device);
+        {
+            if (IsPointerDevice(device))
+                gdev = GetPairedDevice(device);
+            else
+                gdev = device;
+        }
 	xkbi= gdev->key->xkbInfo;
 #endif
 	tempGrab.modifierDevice = grab->modifierDevice;
commit caa69d8f7b92b80669df02e1001409d7c653e7e4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 17:38:13 2007 +0930

    dix: fix detritus from adding lastSlave field.

diff --git a/dix/devices.c b/dix/devices.c
index 75dfa69..3e5405b 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -302,7 +302,7 @@ DisableDevice(DeviceIntPtr dev)
     {
         for (other = inputInfo.devices; other; other = other->next) 
         {
-            if (other->master == dev)
+            if (other->u.master == dev)
                 AttachDevice(NULL, dev, NULL);
         }
     }
@@ -513,7 +513,7 @@ InitCoreDevices(void)
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate keyboard devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
-        dev->master = NULL;
+        dev->u.lastSlave = NULL;
         dev->isMaster = TRUE;
         (void)ActivateDevice(dev);
 
@@ -541,7 +541,7 @@ InitCoreDevices(void)
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate pointer devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
-        dev->master = NULL;
+        dev->u.lastSlave = NULL;
         dev->isMaster = TRUE;
         (void)ActivateDevice(dev);
 
@@ -2255,7 +2255,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
     if (!dev || !master)
         return BadDevice;
 
-    if (master->master) /* can't attach to slave device */
+    if (!master->isMaster) /* can't attach to slave device */
         return BadDevice;
 
     if (!pairingClient)
@@ -2263,7 +2263,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
     else if (client && pairingClient != client)
         return BadAccess;
 
-    dev->master = master;
+    dev->u.master = master;
     dev->spriteInfo->sprite = master->spriteInfo->sprite;
 
     return Success;
@@ -2277,8 +2277,8 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 _X_EXPORT DeviceIntPtr
 GetPairedDevice(DeviceIntPtr dev)
 {
-    if (!dev->isMaster && dev->master)
-        dev = dev->master;
+    if (!dev->isMaster && dev->u.master)
+        dev = dev->u.master;
 
     if (!dev->spriteInfo->paired)
     {
commit 90d077e537ac4cb7d79d67afcf3984a3e8d65fe8
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 17:37:33 2007 +0930

    dix: GetPointerEvents: get state from master device before applying valuators.
    
    We need to get lastx/y from the master device before we start applying
    acceleration etc. Otherwise we get jumping cursors, which is reasonably bad.

diff --git a/dix/getevents.c b/dix/getevents.c
index 7457078..694d404 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -544,6 +544,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     CARD32* valptr;
     deviceKeyButtonPointer *kbp = NULL;
     rawDeviceEvent* ev;
+    DeviceIntPtr master;
 
     /* Thanks to a broken lib, we _always_ have to chase DeviceMotionNotifies
      * with DeviceValuators. */
@@ -558,17 +559,55 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
         return 0;
-
+    
     /* FIXME: I guess it should, in theory, be possible to post button events
      *        from devices without valuators. */
     if (!pDev->valuator)
         return 0;
 
-    num_events = 2;
-
     if (type == MotionNotify && num_valuators <= 0)
         return 0;
 
+    ms = GetTimeInMillis();
+
+    num_events = 2;
+
+    master = pDev->u.master;
+    if (master && master->u.lastSlave != pDev)
+    {
+#if 0
+        /* XXX: we should enqueue the state changed event here */
+        devStateEvent *state; 
+        num_events++;
+        state = events->event;
+
+        state->type = GenericEvent;
+        state->extension = IReqCode;
+        state->evtype = XI_DeviceStateChangedNotify;
+        state->deviceid = master->deviceid;
+        state->new_slave = pDev->id;
+        state->time = ms;
+        events++;
+
+#endif
+
+        /* now we need to update our device to the master's device - welcome
+         * to hell. 
+         * We need to match each device's capabilities to the previous
+         * capabilities as used by the master. Valuator[N] of master has to
+         * be written into valuator[N] of pDev. For all relative valuators.
+         * Otherwise we get jumpy valuators.
+         *
+         * However, this if iffy, if pDev->num_valuators !=
+         * master->num_valuators. What do we do with the others? 
+         * 
+         * XXX: just do lastx/y for now.
+         */
+        pDev->valuator->lastx = master->valuator->lastx;
+        pDev->valuator->lasty = master->valuator->lasty;
+        master->u.lastSlave = pDev;
+    }
+
     /* Do we need to send a DeviceValuator event? */
     if (!coreOnly && sendValuators) {
         if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
@@ -582,7 +621,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes)
         return 0;
 
-    ms = GetTimeInMillis();
 
 
     /* fill up the raw event, after checking that it is large enough to
@@ -667,6 +705,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     pDev->valuator->lastx = x;
     pDev->valuator->lasty = y;
+    master->valuator->lastx = x;
+    master->valuator->lasty = y;
 
     if (!coreOnly)
     {
commit b6ccf721b0a582150858d68f91967fb4e319c340
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 17:35:06 2007 +0930

    include: add "lastSlave" field to DeviceIntRec.
    
    Set to the last slave device that routed events through the master.

diff --git a/include/inputstr.h b/include/inputstr.h
index d96e24a..b2304dd 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -400,7 +400,10 @@ typedef struct _DeviceIntRec {
     int			nPrivates;
     DeviceUnwrapProc    unwrapProc;
     SpriteInfoPtr       spriteInfo;
+    union {
     DeviceIntPtr        master;       /* master device */
+    DeviceIntPtr        lastSlave;    /* last slave device used */
+    } u;
 } DeviceIntRec;
 
 typedef struct {
commit e6bd8ae0608bd8379c5ac962f69cd0bcc54f9734
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 15:59:30 2007 +0930

    dix: set the device's sprite when using AttachDevice
    
    Sprite is set to the master device's sprite.

diff --git a/dix/devices.c b/dix/devices.c
index 0f43d12..75dfa69 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2264,6 +2264,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         return BadAccess;
 
     dev->master = master;
+    dev->spriteInfo->sprite = master->spriteInfo->sprite;
 
     return Success;
 }
commit 271d4c3d6255318aabb9ad1ea444f534ed456f0b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 15:50:07 2007 +0930

    xfree86: remove XI86_SHARED_POINTER flag.
    
    Not needed anymore. By default, all devices are slaves of first master device.

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index acc3ae6..711bf94 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -135,11 +135,6 @@ xf86ProcessCommonOptions(LocalDevicePtr local,
         xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name);
     }
 
-    if (xf86SetBoolOption(list, "SharedPointer", 0)) {
-        local->flags |= XI86_SHARED_POINTER;
-        xf86Msg(X_CONFIG, "%s: is shared device\n", local->name);
-    } 
-
     if (xf86SetBoolOption(list, "SendDragEvents", 1)) {
         local->flags |= XI86_SEND_DRAG_EVENTS;
     } else {
@@ -177,7 +172,7 @@ xf86ActivateDevice(LocalDevicePtr local)
         local->dev = dev;      
         
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE; 
-        dev->spriteInfo->spriteOwner = !(local->flags & XI86_SHARED_POINTER);
+        dev->spriteInfo->spriteOwner = FALSE;
 
         if (DeviceIsPointerType(dev))
         {
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 7fddfb1..d88bbbe 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -81,7 +81,6 @@
 #define XI86_CORE_KEYBOARD	0x20 /* device is the core keyboard */
 #define XI86_POINTER_CAPABLE	0x40 /* capable of being a core pointer */
 #define XI86_KEYBOARD_CAPABLE	0x80 /* capable of being a core keyboard */
-#define XI86_SHARED_POINTER     0x100 /* device shares core cursor */
 
 #define XI_PRIVATE(dev) \
 	(((LocalDevicePtr)((dev)->public.devicePrivate))->private)
commit c7b878b90406781c97db751a9b454e2b6baee0e1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 15:07:31 2007 +0930

    dix: don't treat VCK/VCP separately in DevHasCursor, IsPointer/KeyboardDevice.

diff --git a/dix/events.c b/dix/events.c
index 5bdf145..50d06c4 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -322,7 +322,7 @@ XItoCoreType(int xitype)
 _X_EXPORT Bool
 DevHasCursor(DeviceIntPtr pDev) 
 {
-    return (pDev != inputInfo.pointer && pDev->spriteInfo->spriteOwner);
+    return pDev->spriteInfo->spriteOwner;
 }
 
 /*
@@ -332,7 +332,7 @@ DevHasCursor(DeviceIntPtr pDev)
 _X_EXPORT Bool
 IsPointerDevice(DeviceIntPtr dev)
 {
-    return ((dev->valuator && dev->button) || dev == inputInfo.pointer);
+    return (dev->valuator && dev->button);
 }
 
 /*
@@ -342,7 +342,7 @@ IsPointerDevice(DeviceIntPtr dev)
 _X_EXPORT Bool
 IsKeyboardDevice(DeviceIntPtr dev)
 {
-    return ((dev->key && dev->kbdfeed) || dev == inputInfo.keyboard);
+    return (dev->key && dev->kbdfeed);
 }
 
 #ifdef XEVIE
commit e9f149fb56747f7eaa0f714dce97b067b007c47e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 14:24:20 2007 +0930

    Fix up detritus from removing GetPairedPointer/Keyboard.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 1bcc101..49400e8 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -144,12 +144,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
          */
         if (IsPointerDevice(device))
         {
-            kbd = GetPairedKeyboard(device);
+            kbd = GetPairedDevice(device);
             mouse = device;
         }
         else
         {
-            mouse = GetPairedPointer(device);
+            mouse = GetPairedDevice(device);
             kbd = device;
         }
         xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0;
diff --git a/Xi/getpairp.c b/Xi/getpairp.c
index 4f1ff03..1833a00 100644
--- a/Xi/getpairp.c
+++ b/Xi/getpairp.c
@@ -73,27 +73,20 @@ ProcXGetPairedPointer(ClientPtr client)
     REQUEST_SIZE_MATCH(xGetPairedPointerReq);
 
     kbd = LookupDeviceIntRec(stuff->deviceid);
-    if (!kbd || !kbd->key) {
+    if (!kbd || !kbd->key || !kbd->isMaster) {
         SendErrorToClient(client, IReqCode, X_GetPairedPointer,
                 stuff->deviceid, BadDevice);
         return Success;
     }
 
-    ptr = GetPairedPointer(kbd);
+    ptr = GetPairedDevice(kbd);
 
     rep.repType = X_Reply;
     rep.RepType = X_GetPairedPointer;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
-    if (ptr == inputInfo.pointer)
-    {
-        rep.paired = FALSE;
-        rep.deviceid = 0;
-    } else 
-    {
-        rep.paired = TRUE;
-        rep.deviceid = ptr->id;
-    }
+    rep.paired = TRUE;
+    rep.deviceid = ptr->id;
     WriteReplyToClient(client, sizeof(xGetPairedPointerReply), &rep);
     return Success;
 }
diff --git a/dix/events.c b/dix/events.c
index 58188c8..5bdf145 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3243,7 +3243,7 @@ CheckPassiveGrabsOnWindow(
 
 	gdev= grab->modifierDevice;
         if (grab->coreGrab)
-            gdev = GetPairedKeyboard(device);
+            gdev = GetPairedDevice(device);
 	xkbi= gdev->key->xkbInfo;
 #endif
 	tempGrab.modifierDevice = grab->modifierDevice;
@@ -3294,7 +3294,7 @@ CheckPassiveGrabsOnWindow(
             if (xE->u.u.type < LASTEvent)
             {
                 grab->device = device; 
-                grab->modifierDevice = GetPairedKeyboard(device);
+                grab->modifierDevice = GetPairedDevice(device);
             }
 
             /* In some cases a passive core grab may exist, but the client
@@ -3453,9 +3453,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
 	if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
 	    return;
     }
-    pointer = GetPairedPointer(keybd);
-    if (!pointer)
-        pointer = inputInfo.pointer;
+    pointer = GetPairedDevice(keybd);
     /* just deliver it to the focus window */
     FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
     if (xE->u.u.type & EXTENSION_EVENT_BASE)
@@ -3684,7 +3682,7 @@ drawable.id:0;
 #endif
     /* ProcessOtherEvent already updated the keyboard's state, so we need to
      * access prev_state here! */
-    XE_KBPTR.state = (keyc->prev_state | GetPairedPointer(keybd)->button->state);
+    XE_KBPTR.state = (keyc->prev_state | GetPairedDevice(keybd)->button->state);
     XE_KBPTR.rootX = keybd->spriteInfo->sprite->hot.x;
     XE_KBPTR.rootY = keybd->spriteInfo->sprite->hot.y;
     key = xE->u.u.detail;
@@ -3796,7 +3794,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
     SpritePtr           pSprite = mouse->spriteInfo->sprite;
 
 #ifdef XKB
-    XkbSrvInfoPtr xkbi= GetPairedKeyboard(mouse)->key->xkbInfo;
+    XkbSrvInfoPtr xkbi= GetPairedDevice(mouse)->key->xkbInfo;
 #endif
 #ifdef XEVIE
     if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState &&
@@ -4141,7 +4139,7 @@ EnterLeaveEvent(
     int                 mskidx;
     OtherInputMasks     *inputMasks;
 
-    keybd = GetPairedKeyboard(mouse);
+    keybd = GetPairedDevice(mouse);
 
     if ((pWin == mouse->valuator->motionHintWindow) &&
 	(detail != NotifyInferior))
@@ -4682,7 +4680,7 @@ SetInputFocus(
     if (IsKeyboardDevice(dev))
         keybd = dev;
     else
-        keybd = GetPairedKeyboard(dev);
+        keybd = GetPairedDevice(dev);
 
     if ((focusID == None) || (focusID == PointerRoot))
 	focusWin = (WindowPtr)(long)focusID;
@@ -5697,7 +5695,7 @@ ProcGrabButton(ClientPtr client)
     }
 
     pointer = PickPointer(client);
-    modifierDevice = GetPairedKeyboard(pointer);
+    modifierDevice = GetPairedDevice(pointer);
 
     grab = CreateGrab(client->index, pointer, pWin, 
         (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
index 553679d..74788be 100644
--- a/hw/xfree86/common/xf86DGA.c
+++ b/hw/xfree86/common/xf86DGA.c
@@ -1038,7 +1038,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
     xEvent	    core;
     KeyClassPtr	    keyc = keybd->key;
     DGAScreenPtr    pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
-    DeviceIntPtr    pointer = GetPairedPointer(keybd);
+    DeviceIntPtr    pointer = GetPairedDevice(keybd);
     
     coreEquiv = de->u.u.type - *XDGAEventBase;
 
@@ -1145,7 +1145,7 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
      * Fill in remaining event state
      */
     de->u.event.screen = pScreen->myNum;
-    de->u.event.state = butc->state | GetPairedKeyboard(mouse)->key->state;
+    de->u.event.state = butc->state | GetPairedDevice(mouse)->key->state;
     /*
      * Keep the core state in sync by duplicating what
      * CoreProcessPointerEvent does
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index c6df92c..acc3ae6 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -723,7 +723,7 @@ xf86PostKeyboardEvent(DeviceIntPtr      device,
     int index;
 
 #if XFreeXDGA
-    DeviceIntPtr pointer = GetPairedPointer(device);
+    DeviceIntPtr pointer = GetPairedDevice(device);
 
     if (miPointerGetScreen(pointer)) {
         index = miPointerGetScreen(pointer)->myNum;
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index dd4d7c1..32b9e0d 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1273,7 +1273,7 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 	    keyc->modifierMap[key] = 0;
             tmpdev = dev;
         } else
-            tmpdev = GetPairedPointer(dev);
+            tmpdev = GetPairedDevice(dev);
 
 
         UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
commit 840bde3d32f3627dfc3d7d8b6564a61a8014933b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 13:09:35 2007 +0930

    dix: GetPairedDevice: return dev paired with master for slave devices.

diff --git a/dix/devices.c b/dix/devices.c
index a4360e5..0f43d12 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2268,11 +2268,17 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
     return Success;
 }
 
-/* Return the device paired with the given device or NULL.
+/**
+ * Return the device paired with the given device or NULL.
+ * Returns the device paired with the parent master if the given device is a
+ * slave device.
  */
 _X_EXPORT DeviceIntPtr
 GetPairedDevice(DeviceIntPtr dev)
 {
+    if (!dev->isMaster && dev->master)
+        dev = dev->master;
+
     if (!dev->spriteInfo->paired)
     {
         ErrorF("[dix] No device paired with %d (%s).\n", 
commit 6c259a08d917f94fd7381453b625b07826d3ef9c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 13:09:19 2007 +0930

    include: remove unused GetPairedPointer/Keyboard declarations.

diff --git a/include/input.h b/include/input.h
index f41514a..a176bba 100644
--- a/include/input.h
+++ b/include/input.h
@@ -469,8 +469,7 @@ extern int AttachDevice(ClientPtr client,
                         DeviceIntPtr slave,
                         DeviceIntPtr master);
 
-extern DeviceIntPtr GetPairedPointer(DeviceIntPtr kbd);
-extern DeviceIntPtr GetPairedKeyboard(DeviceIntPtr ptr);
+extern DeviceIntPtr GetPairedDevice(DeviceIntPtr kbd);
 
 extern Bool RegisterPairingClient(ClientPtr client);
 extern Bool UnregisterPairingClient(ClientPtr client);
commit 9ecbbf198f4cec398897736e173e7e8c56bf6f94
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 08:00:06 2007 +0930

    dix: adjust PickPointer and PickKeyboard to get the first master device.
    
    Simplifies it a lot, since we always have at least one master device
    available at all times, so less mucking around.

diff --git a/dix/events.c b/dix/events.c
index b84d18d..58188c8 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -6117,34 +6117,22 @@ SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device)
     return TRUE;
 }
 
-/* PickPointer will pick an appropriate pointer for the given client.
- *
- * If a client pointer is set, it will pick the client pointer, otherwise the
- * first available pointer in the list. If no physical device is attached, it
- * will pick the core pointer, but will not store it on the client.
- */
+/* PickPointer will pick an appropriate pointer for the given client.  */
 _X_EXPORT DeviceIntPtr
 PickPointer(ClientPtr client)
 {
     if (!client->clientPtr)
     {
-        /* look if there is a real device attached */
         DeviceIntPtr it = inputInfo.devices;
         while (it)
         {
-            if (it != inputInfo.pointer && it->spriteInfo->spriteOwner)
+            if (it->isMaster && it->spriteInfo->spriteOwner)
             {
                 client->clientPtr = it;
                 break;
             }
             it = it->next;
         }
-
-        if (!it)
-        {
-            ErrorF("[dix] Picking VCP\n");
-            return inputInfo.pointer;
-        }
     }
     return client->clientPtr;
 }
@@ -6159,18 +6147,15 @@ _X_EXPORT DeviceIntPtr
 PickKeyboard(ClientPtr client)
 {
     DeviceIntPtr ptr = PickPointer(client);
-    DeviceIntPtr kbd = inputInfo.devices;
+    DeviceIntPtr kbd = ptr->spriteInfo->paired;
 
-    while(kbd)
+    if (!kbd)
     {
-        if (ptr != kbd && 
-            IsKeyboardDevice(kbd) && 
-            ptr->spriteInfo->sprite == kbd->spriteInfo->sprite)
-            return kbd;
-        kbd = kbd->next;
+        ErrorF("[dix] ClientPointer not paired with a keyboard. This " 
+                "is a bug.\n");
     }
 
-    return (kbd) ? kbd : inputInfo.keyboard;
+    return kbd;
 }
 
 /* A client that has one or more core grabs does not get core events from
commit 0c5f65ecd3ad11fbdb1cab3cb1d0eb4f33bb4e35
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 07:57:24 2007 +0930

    dix: don't allow slave devices as ClientPointer

diff --git a/dix/events.c b/dix/events.c
index 8141a40..b84d18d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -6103,6 +6103,16 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
 _X_EXPORT Bool
 SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device)
 {
+    if (!device->isMaster)
+    {
+        ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
+        return FALSE;
+    } else if (!device->spriteInfo->spriteOwner)
+    {
+        ErrorF("[dix] Device %d does not have a sprite. " 
+                "Cannot be ClientPointer\n", device->id);
+        return FALSE;
+    }
     client->clientPtr = device;
     return TRUE;
 }
commit 9ccc9ab6f29f68298b68cdb5c9b4bd57a095f05a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 07:53:00 2007 +0930

    dix: don't call CloseDevice on VCP/VCK separately.

diff --git a/dix/devices.c b/dix/devices.c
index b47ae59..a4360e5 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -751,9 +751,6 @@ CloseDownDevices(void)
 	CloseDevice(dev);
     }
 
-    CloseDevice(inputInfo.keyboard);
-    CloseDevice(inputInfo.pointer);
-
     inputInfo.devices = NULL;
     inputInfo.off_devices = NULL;
     inputInfo.keyboard = NULL;
commit e4fd981b48723b77a6c1a528638a771b9cc35472
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 07:52:11 2007 +0930

    dix: check for isMaster before calling DeviceCursorCleanup.

diff --git a/dix/devices.c b/dix/devices.c
index 7a9932a..b47ae59 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -624,7 +624,7 @@ CloseDevice(DeviceIntPtr dev)
 	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
 
     /* free sprite memory */
-    if (IsPointerDevice(dev))
+    if (dev->isMaster && dev->spriteInfo->sprite)
         screen->DeviceCursorCleanup(dev, screen);
 
     xfree(dev->name);
commit 7503d1340726e0a529f04304d177ed2ceb8fbc91
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 07:50:13 2007 +0930

    dix: don't check VCK and VCP separately when looking for device ids.
    
    Both are part of the device list again, so we cover them there.

diff --git a/dix/devices.c b/dix/devices.c
index b4d04b4..7a9932a 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -107,10 +107,6 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
 
     /* 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)
commit 032e906711202d376af95b37bb0cdf14a3648256
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 11:57:42 2007 +0930

    dix: Remove GetPairedPointer, GetPairedKeyboard in favour of GetPairedDevice.

diff --git a/dix/devices.c b/dix/devices.c
index f886120..b4d04b4 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2274,46 +2274,19 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
 
     return Success;
 }
-/* Return the pointer that is paired with the given keyboard. If no pointer is
- * paired, return the virtual core pointer 
- */ 
-DeviceIntPtr
-GetPairedPointer(DeviceIntPtr kbd)
-{
-    DeviceIntPtr ptr = inputInfo.devices;
-    while(ptr)
-    {
-        if (ptr->spriteInfo->sprite == kbd->spriteInfo->sprite && 
-                ptr->spriteInfo->spriteOwner)
-        {
-            return ptr;
-        }
-        ptr = ptr->next;
-    }
 
-    return inputInfo.pointer;
-}
-
-/* Find the keyboard device that is paired with the given pointer. If none is
- * found, return the VCK.
+/* Return the device paired with the given device or NULL.
  */
 _X_EXPORT DeviceIntPtr
-GetPairedKeyboard(DeviceIntPtr ptr)
+GetPairedDevice(DeviceIntPtr dev)
 {
-    DeviceIntPtr dev = inputInfo.devices;
-
-    if (IsKeyboardDevice(ptr))
-        return ptr;
-
-    while(dev)
+    if (!dev->spriteInfo->paired)
     {
-        if (ptr != dev && 
-            IsKeyboardDevice(dev) &&
-            ptr->spriteInfo->sprite == dev->spriteInfo->sprite)
-            return dev;
-        dev = dev->next;
+        ErrorF("[dix] No device paired with %d (%s).\n", 
+                dev->id, dev->name);
+        return NULL;
     }
-    return (dev) ? dev : inputInfo.keyboard;
+    return dev->spriteInfo->paired;
 }
 
 /*
commit 3e07e73fefc100e491d1e465cb162373d1d82425
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 11:34:29 2007 +0930

    dix: remove pairing/attachment from InitAndStartDevices.
    
    If we enabled in the correct order, this has all been done already.

diff --git a/dix/devices.c b/dix/devices.c
index 7be0d69..f886120 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -215,7 +215,10 @@ EnableDevice(DeviceIntPtr dev)
         {
             /* Sprites appear on first root window, so we can hardcode it */
             if (dev->spriteInfo->spriteOwner)
+            {
                 InitializeSprite(dev, WindowTable[0]);
+                ((FocusSemaphoresPtr)(WindowTable[0])->devPrivates[FocusPrivatesIndex].ptr)->enterleave++;
+            }
             else if ((other = NextFreePointerDevice()) == NULL)
             {
                 ErrorF("[dix] cannot find pointer to pair with. "
@@ -596,23 +599,6 @@ InitAndStartDevices(WindowPtr root)
 	    (void)EnableDevice(dev);
     }
 
-    /* All of the devices are started up now. Pair VCK with VCP, then
-     * attach each device to the initial master.
-     */ 
-    PairDevices(NULL, inputInfo.pointer, inputInfo.keyboard);
-
-    for (dev = inputInfo.devices; dev; dev = dev->next)
-    {
-        if (!DevHasCursor(dev))
-            AttachDevice(NULL, dev, inputInfo.keyboard);
-        else
-        {
-            AttachDevice(NULL, dev, inputInfo.pointer);
-            /* enter/leave counter on root window */
-            ((FocusSemaphoresPtr)root->devPrivates[FocusPrivatesIndex].ptr)->enterleave++;
-        }
-    }
-
     return Success;
 }
 
commit 38baac71bdbb8c7e882e3e39133615cfed894a6b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 04:21:42 2007 +0930

    dix: Set bidirectional pairing, don't allow pairing with already paired devs.

diff --git a/dix/devices.c b/dix/devices.c
index 2dd3f9e..7be0d69 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2238,7 +2238,10 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
         return BadDevice;
 
     /* Don't allow pairing for slave devices */
-    if (ptr->master || kbd->master)
+    if (!ptr->isMaster || !kbd->isMaster)
+        return BadDevice;
+
+    if (ptr->spriteInfo->paired)
         return BadDevice;
 
     if (!pairingClient)
@@ -2255,6 +2258,7 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
 
     kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
     kbd->spriteInfo->paired = ptr;
+    ptr->spriteInfo->paired = kbd;
     return Success;
 }
 
commit 70efd3d06a15093661933bda4ec21e306dece4a4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 11:30:32 2007 +0930

    dix: fix up Activate/Enable/Disable device.
    
    Set isMaster for VCP/VCK.
    Init sprites for master pointer devices.
    Pair master kbds with master pointers (1:1 pairing!).
    Attach other devices to VCP/VCK.

diff --git a/dix/devices.c b/dix/devices.c
index c41fa0c..2dd3f9e 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -189,8 +189,9 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
  * list. Initialize the DIX sprite or pair the device. All clients are
  * notified about the device being enabled.
  *
- * A device will send events once enabled.
- *
+ * A master pointer device needs to be enabled before a master keyboard
+ * device.
+ * 
  * @param The device to be enabled.
  * @return TRUE on success or FALSE otherwise.
  */
@@ -200,6 +201,7 @@ EnableDevice(DeviceIntPtr dev)
     DeviceIntPtr *prev;
     int ret;
     DeviceIntRec dummyDev;
+    DeviceIntPtr other;
     devicePresenceNotify ev;
 
     for (prev = &inputInfo.off_devices;
@@ -207,15 +209,26 @@ EnableDevice(DeviceIntPtr dev)
 	 prev = &(*prev)->next)
 	;
 
-    /* Sprites pop up on the first root window, so we can supply it directly
-     * here. 
-     */
     if (!dev->spriteInfo->sprite)
     {
-        if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
-            InitializeSprite(dev, WindowTable[0]);
-        else
-            PairDevices(NULL, inputInfo.pointer, dev);
+        if (dev->isMaster)
+        {
+            /* Sprites appear on first root window, so we can hardcode it */
+            if (dev->spriteInfo->spriteOwner)
+                InitializeSprite(dev, WindowTable[0]);
+            else if ((other = NextFreePointerDevice()) == NULL)
+            {
+                ErrorF("[dix] cannot find pointer to pair with. "
+                       "This is a bug.\n");
+                return FALSE;
+            } else
+                PairDevices(NULL, other, dev);
+        } else
+        {
+            other = (IsPointerDevice(dev)) ? inputInfo.pointer :
+                inputInfo.keyboard;
+            AttachDevice(NULL, dev, other);
+        }
     }
 
     if ((*prev != dev) || !dev->inited ||
@@ -247,12 +260,15 @@ EnableDevice(DeviceIntPtr dev)
  * list. A device will not send events while disabled. All clients are
  * notified about the device being disabled.
  *
+ * Master keyboard devices have to be disabled before master pointer devices
+ * otherwise things turn bad.
+ *
  * @return TRUE on success or FALSE otherwise.
  */
 Bool
 DisableDevice(DeviceIntPtr dev)
 {
-    DeviceIntPtr *prev, paired;
+    DeviceIntPtr *prev, other;
     DeviceIntRec dummyDev;
     devicePresenceNotify ev;
 
@@ -262,20 +278,34 @@ DisableDevice(DeviceIntPtr dev)
 	;
     if (*prev != dev)
 	return FALSE;
+
+    if (dev->isMaster && dev->spriteInfo->sprite)
+    {
+        for (other = inputInfo.devices; other; other = other->next)
+        {
+            if (other->spriteInfo->paired == dev)
+            {
+                ErrorF("[dix] cannot disable device, still paired. " 
+                        "This is a bug. \n");
+                return FALSE;
+            }
+        }
+    }
+
     (void)(*dev->deviceProc)(dev, DEVICE_OFF);
     dev->enabled = FALSE;
     *prev = dev->next;
     dev->next = inputInfo.off_devices;
     inputInfo.off_devices = dev;
 
-    /* Some other device may have been paired with this device. 
-       Re-pair with VCP. We don't repair with a real device, as this
-       may cause somebody suddenly typing where they shouldn't. 
-     */
-    for (paired = inputInfo.devices; paired; paired = paired->next)
+    /* float attached devices */
+    if (dev->isMaster)
     {
-        if (paired->spriteInfo->paired == dev)
-            PairDevices(NULL, inputInfo.pointer, paired);
+        for (other = inputInfo.devices; other; other = other->next) 
+        {
+            if (other->master == dev)
+                AttachDevice(NULL, dev, NULL);
+        }
     }
 
     ev.type = DevicePresenceNotify;
@@ -313,7 +343,7 @@ ActivateDevice(DeviceIntPtr dev)
     dev->inited = (ret == Success);
 
     /* Initialize memory for sprites. */
-    if (IsPointerDevice(dev))
+    if (dev->isMaster && dev->spriteInfo->spriteOwner)
         pScreen->DeviceCursorInitialize(dev, pScreen);
     
     ev.type = DevicePresenceNotify;
@@ -485,6 +515,7 @@ InitCoreDevices(void)
             FatalError("Couldn't allocate keyboard devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
         dev->master = NULL;
+        dev->isMaster = TRUE;
         (void)ActivateDevice(dev);
 
         inputInfo.keyboard = dev;
@@ -512,6 +543,7 @@ InitCoreDevices(void)
             FatalError("Couldn't allocate pointer devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
         dev->master = NULL;
+        dev->isMaster = TRUE;
         (void)ActivateDevice(dev);
 
         inputInfo.pointer = dev;
@@ -550,10 +582,10 @@ InitAndStartDevices(WindowPtr root)
     }
 
     /* Now enable all devices */
-    if (inputInfo.keyboard->inited && inputInfo.keyboard->startup)
-        EnableDevice(inputInfo.keyboard);
     if (inputInfo.pointer->inited && inputInfo.pointer->startup)
         EnableDevice(inputInfo.pointer);
+    if (inputInfo.keyboard->inited && inputInfo.keyboard->startup)
+        EnableDevice(inputInfo.keyboard);
 
     /* enable real devices */
     for (dev = inputInfo.off_devices; dev; dev = next)
@@ -2367,3 +2399,15 @@ GuessFreePointerDevice()
 
     return (lastRealPtr) ? lastRealPtr : inputInfo.pointer;
 }
+
+DeviceIntPtr
+NextFreePointerDevice()
+{
+    DeviceIntPtr dev;
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+        if (dev->isMaster && 
+                dev->spriteInfo->spriteOwner && 
+                !dev->spriteInfo->paired)
+            return dev;
+    return NULL;
+}
diff --git a/include/input.h b/include/input.h
index 1ef36b8..f41514a 100644
--- a/include/input.h
+++ b/include/input.h
@@ -476,6 +476,7 @@ extern Bool RegisterPairingClient(ClientPtr client);
 extern Bool UnregisterPairingClient(ClientPtr client);
 
 extern DeviceIntPtr GuessFreePointerDevice(void);
+extern DeviceIntPtr NextFreePointerDevice(void);
 
 /* Window/device based access control */
 extern Bool ACRegisterClient(ClientPtr client);
commit 204f2dc89ef662b57400b128c30c15e8cf32f323
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 04:13:06 2007 +0930

    include: add "isMaster" field to DeviceIntRec.
    
    Set to TRUE for master devices.
    
    Also fixing up comment for paired field in spriteInfo, will be set
    bidirectional from now on.

diff --git a/include/inputstr.h b/include/inputstr.h
index 146fbc8..d96e24a 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -357,8 +357,9 @@ typedef struct _SpriteInfoRec {
      * sprite, let sprite point to a paired spriteOwner's sprite. */
     SpritePtr           sprite;      /* sprite information */
     Bool                spriteOwner; /* True if device owns the sprite */
-    DeviceIntPtr        paired;      /* the real owner of the sprite or
-                                        NULL if spriteOwner is TRUE*/
+    DeviceIntPtr        paired;      /* The paired device. Keyboard if
+                                        spriteOwner is TRUE, otherwise the
+                                        pointer that owns the sprite. */ 
 } SpriteInfoRec, *SpriteInfoPtr;
 
 typedef struct _DeviceIntRec {
@@ -373,6 +374,7 @@ typedef struct _DeviceIntRec {
     Bool        enabled;                /* TRUE if ON returns Success */
     Bool        coreEvents;             /* TRUE if device also sends core */
     GrabInfoRec deviceGrab;             /* grab on the device */
+    Bool        isMaster;               /* TRUE if device is master */
     Atom		type;
     char		*name;
     CARD8		id;
commit bd7d5255ce4865b684f7d8bcf80ba9872a1af22d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 16 11:18:31 2007 +0930

    dix: add AttachDevice, needed to attach a slave device to a master device.
    
    For now, we don't allow attaching slaves to other slaves, and we don't allow
    pairing slaves with other slaves.
    Pairing is for master keyboard->master pointer only.
    Attaching is for slave device->master device only.

diff --git a/dix/devices.c b/dix/devices.c
index 9e9fca3..c41fa0c 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -540,11 +540,11 @@ InitAndStartDevices(WindowPtr root)
 	ActivateDevice(dev);
     }
 
-    if (!inputInfo.keyboard) {
+    if (!inputInfo.keyboard) { /* In theory, this cannot happen */
 	ErrorF("[dix] No core keyboard\n");
 	return BadImplementation;
     }
-    if (!inputInfo.pointer) {
+    if (!inputInfo.pointer) { /* In theory, this cannot happen */
 	ErrorF("[dix] No core pointer\n");
 	return BadImplementation;
     }
@@ -555,10 +555,6 @@ InitAndStartDevices(WindowPtr root)
     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)
     {
@@ -569,17 +565,20 @@ InitAndStartDevices(WindowPtr root)
     }
 
     /* All of the devices are started up now. Pair VCK with VCP, then
-     * pair each real keyboard with a real pointer. 
+     * attach each device to the initial master.
      */ 
     PairDevices(NULL, inputInfo.pointer, inputInfo.keyboard);
 
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
         if (!DevHasCursor(dev))
-            PairDevices(NULL, GuessFreePointerDevice(), dev);
+            AttachDevice(NULL, dev, inputInfo.keyboard);
         else
+        {
+            AttachDevice(NULL, dev, inputInfo.pointer);
             /* enter/leave counter on root window */
             ((FocusSemaphoresPtr)root->devPrivates[FocusPrivatesIndex].ptr)->enterleave++;
+        }
     }
 
     return Success;
@@ -2195,7 +2194,7 @@ ProcQueryKeymap(ClientPtr client)
 }
 
 /* Pair the keyboard to the pointer device. Keyboard events will follow the
- * pointer sprite. 
+ * pointer sprite. Only applicable for master devices. 
  * If the client is set, the request to pair comes from some client. In this
  * case, we need to check for access. If the client is NULL, it's from an
  * internal automatic pairing, we must always permit this.
@@ -2206,6 +2205,10 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
     if (!ptr)
         return BadDevice;
 
+    /* Don't allow pairing for slave devices */
+    if (ptr->master || kbd->master)
+        return BadDevice;
+
     if (!pairingClient)
         RegisterPairingClient(client);
     else if (client && pairingClient != client)
@@ -2223,6 +2226,32 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
     return Success;
 }
 
+/**
+ * Attach device 'dev' to device 'master'.
+ * Client is set to the client that issued the request, or NULL if it comes
+ * from some internal automatic pairing.
+ *
+ * We don't allow multi-layer hierarchies right now. You can't attach a slave
+ * to another slave. 
+ */
+int
+AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
+{
+    if (!dev || !master)
+        return BadDevice;
+
+    if (master->master) /* can't attach to slave device */
+        return BadDevice;
+
+    if (!pairingClient)
+        RegisterPairingClient(client);
+    else if (client && pairingClient != client)
+        return BadAccess;
+
+    dev->master = master;
+
+    return Success;
+}
 /* Return the pointer that is paired with the given keyboard. If no pointer is
  * paired, return the virtual core pointer 
  */ 
diff --git a/include/input.h b/include/input.h
index d86a969..1ef36b8 100644
--- a/include/input.h
+++ b/include/input.h
@@ -465,6 +465,9 @@ extern DeviceIntPtr LookupDeviceIntRec(
 extern int PairDevices(ClientPtr client, 
                        DeviceIntPtr pointer, 
                        DeviceIntPtr keyboard);
+extern int AttachDevice(ClientPtr client,
+                        DeviceIntPtr slave,
+                        DeviceIntPtr master);
 
 extern DeviceIntPtr GetPairedPointer(DeviceIntPtr kbd);
 extern DeviceIntPtr GetPairedKeyboard(DeviceIntPtr ptr);
commit be1565f6b8fb09eba9941d6f7c485bf5fb25fe7a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 01:53:54 2007 +0930

    dix: Set core devices to ProcessOtherEvents, set sendCore and XKB.
    
    Even the virtual core devices should send through ProcessOtherEvents.

diff --git a/dix/devices.c b/dix/devices.c
index 37a98a0..9e9fca3 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -469,21 +469,22 @@ InitCoreDevices(void)
             FatalError("Failed to allocate core keyboard");
         dev->name = strdup("Virtual core keyboard");
 #ifdef XKB
-        dev->public.processInputProc = CoreProcessKeyboardEvent;
-        dev->public.realInputProc = CoreProcessKeyboardEvent;
-        /*if (!noXkbExtension)*/
-        /*XkbSetExtension(dev, ProcessKeyboardEvent);*/
+        dev->public.processInputProc = ProcessOtherEvent;
+        dev->public.realInputProc = ProcessOtherEvent;
+        if (!noXkbExtension)
+            XkbSetExtension(dev, ProcessKeyboardEvent);
 #else
         dev->public.processInputProc = ProcessKeyboardEvent;
         dev->public.realInputProc = ProcessKeyboardEvent;
 #endif
         dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
         dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
-        dev->coreEvents = FALSE;
+        dev->coreEvents = TRUE;
         dev->spriteInfo->spriteOwner = FALSE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate keyboard devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
+        dev->master = NULL;
         (void)ActivateDevice(dev);
 
         inputInfo.keyboard = dev;
@@ -495,8 +496,8 @@ InitCoreDevices(void)
             FatalError("Failed to allocate core pointer");
         dev->name = strdup("Virtual core pointer");
 #ifdef XKB
-        dev->public.processInputProc = CoreProcessPointerEvent;
-        dev->public.realInputProc = CoreProcessPointerEvent;
+        dev->public.processInputProc = ProcessOtherEvent;
+        dev->public.realInputProc = ProcessOtherEvent;
         if (!noXkbExtension)
            XkbSetExtension(dev, ProcessPointerEvent);
 #else
@@ -505,11 +506,12 @@ InitCoreDevices(void)
 #endif
         dev->deviceGrab.ActivateGrab = ActivatePointerGrab;
         dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
-        dev->coreEvents = FALSE;
+        dev->coreEvents = TRUE;
         dev->spriteInfo->spriteOwner = TRUE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate pointer devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
+        dev->master = NULL;
         (void)ActivateDevice(dev);
 
         inputInfo.pointer = dev;
commit ce9bf9a19185a36ac2f7ae75acd320ab8d03d247
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Oct 14 01:50:40 2007 +0930

    include: add "master" field to DeviceIntRec.
    
    "master" points to the device this device is attached to. Event sent by the
    device will also be routed through the master.
    master and spriteOwner are mutually exclusive.

diff --git a/include/inputstr.h b/include/inputstr.h
index cbbc4e2..146fbc8 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -398,6 +398,7 @@ typedef struct _DeviceIntRec {
     int			nPrivates;
     DeviceUnwrapProc    unwrapProc;
     SpriteInfoPtr       spriteInfo;
+    DeviceIntPtr        master;       /* master device */
 } DeviceIntRec;
 
 typedef struct {
commit 042e16458b751ad0fcfa1ebbdd74d7d48036b22a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 9 23:07:51 2007 +0930

    dix: change a few inputInfo.keyboard over to PickKeyboard()

diff --git a/dix/devices.c b/dix/devices.c
index 59404e9..37a98a0 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1514,7 +1514,7 @@ int
 ProcGetModifierMapping(ClientPtr client)
 {
     xGetModifierMappingReply rep;
-    KeyClassPtr keyc = inputInfo.keyboard->key;
+    KeyClassPtr keyc = PickKeyboard(client)->key;
 
     REQUEST_SIZE_MATCH(xReq);
     rep.type = X_Reply;
@@ -1537,7 +1537,7 @@ ProcChangeKeyboardMapping(ClientPtr client)
     REQUEST(xChangeKeyboardMappingReq);
     unsigned len;
     KeySymsRec keysyms;
-    KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
+    KeySymsPtr curKeySyms = &PickKeyboard(client)->key->curKeySyms;
     DeviceIntPtr pDev = NULL;
     REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
 
@@ -1940,7 +1940,7 @@ int
 ProcGetKeyboardControl (ClientPtr client)
 {
     int i;
-    KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl;
+    KeybdCtrl *ctrl = &PickKeyboard(client)->kbdfeed->ctrl;
     xGetKeyboardControlReply rep;
 
     REQUEST_SIZE_MATCH(xReq);
@@ -1962,7 +1962,7 @@ ProcGetKeyboardControl (ClientPtr client)
 int
 ProcBell(ClientPtr client)
 {
-    DeviceIntPtr keybd = inputInfo.keyboard;
+    DeviceIntPtr keybd = PickKeyboard(client);
     int base = keybd->kbdfeed->ctrl.bell;
     int newpercent;
     REQUEST(xBellReq);
@@ -2174,7 +2174,7 @@ ProcQueryKeymap(ClientPtr client)
 {
     xQueryKeymapReply rep;
     int i;
-    CARD8 *down = inputInfo.keyboard->key->down;
+    CARD8 *down = PickKeyboard(client)->key->down;
 
     REQUEST_SIZE_MATCH(xReq);
     rep.type = X_Reply;
commit d42909b23a9be64a26aa349c1d6dcd8b228bffa7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Oct 5 13:04:10 2007 +0930

    dix: when disabling a device, make sure all paired devices are re-paired.
    
    We re-pair them with the VCP, not a real device! If we would do otherwise,
    somebody may change our keyboard focus and thus get us typing where we don't
    want to type.

diff --git a/dix/devices.c b/dix/devices.c
index 7cf82ee..59404e9 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -252,7 +252,7 @@ EnableDevice(DeviceIntPtr dev)
 Bool
 DisableDevice(DeviceIntPtr dev)
 {
-    DeviceIntPtr *prev;
+    DeviceIntPtr *prev, paired;
     DeviceIntRec dummyDev;
     devicePresenceNotify ev;
 
@@ -268,6 +268,16 @@ DisableDevice(DeviceIntPtr dev)
     dev->next = inputInfo.off_devices;
     inputInfo.off_devices = dev;
 
+    /* Some other device may have been paired with this device. 
+       Re-pair with VCP. We don't repair with a real device, as this
+       may cause somebody suddenly typing where they shouldn't. 
+     */
+    for (paired = inputInfo.devices; paired; paired = paired->next)
+    {
+        if (paired->spriteInfo->paired == dev)
+            PairDevices(NULL, inputInfo.pointer, paired);
+    }
+
     ev.type = DevicePresenceNotify;
     ev.time = currentTime.milliseconds;
     ev.devchange = DeviceDisabled;
commit ff2351246da30b56a3a8f90654993c41b8eb3921
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Oct 5 12:19:03 2007 +0930

    dix: When pairing, only check for access right if client is set.
    
    If the pairing client is not set, then the pairing is initiated internally
    (e.g. when a new keyboard device is configured). In this case we _must_ pair
    regardless of who is the pairing client.

diff --git a/dix/devices.c b/dix/devices.c
index 24eaa4b..7cf82ee 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2184,6 +2184,9 @@ ProcQueryKeymap(ClientPtr client)
 
 /* Pair the keyboard to the pointer device. Keyboard events will follow the
  * pointer sprite. 
+ * If the client is set, the request to pair comes from some client. In this
+ * case, we need to check for access. If the client is NULL, it's from an
+ * internal automatic pairing, we must always permit this.
  */
 int 
 PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
@@ -2193,7 +2196,7 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
 
     if (!pairingClient)
         RegisterPairingClient(client);
-    else if (pairingClient != client)
+    else if (client && pairingClient != client)
         return BadAccess;
 
     if (kbd->spriteInfo->spriteOwner)
commit ab88cb8d2e7c1410f9ed2be928b38f176b132e11
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 3 18:08:33 2007 +0930

    Xext: add missing geint.h to Makefile.am (un-breaks make dist)

diff --git a/Xext/Makefile.am b/Xext/Makefile.am
index cdfd0dc..e9e2d9c 100644
--- a/Xext/Makefile.am
+++ b/Xext/Makefile.am
@@ -15,7 +15,7 @@ INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod
 AM_CFLAGS = $(DIX_CFLAGS)
 
 if XORG
-sdk_HEADERS = xvdix.h xvmcext.h geext.h
+sdk_HEADERS = xvdix.h xvmcext.h geext.h geint.h
 endif
 
 # Sources always included in libXextbuiltin.la & libXext.la
commit 9f2b493e34e93881101f31e631901d3fe56da4f0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 27 15:35:41 2007 +0930

    xkb: remove some warning comments.
    
    Obsolete with 340911d7243a7f1095d79b5b2dcfa81b145c2474.

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 891b915..dd4d7c1 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -907,10 +907,6 @@ ProcessInputProc backupproc;
 
 	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
 	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
-        /* XXX: Bad! Since the switch to XI devices xkbi->device will be the
-         * XI device. Sending a core event through ProcessOtherEvent will
-         * cause trouble. Somebody should fix this. 
-         */
 	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
 	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
 	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
@@ -953,10 +949,6 @@ ProcessInputProc backupproc;
 
 	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
 	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
-        /* XXX: Bad! Since the switch to XI devices xkbi->device will be the
-         * XI device. Sending a core event through ProcessOtherEvent will
-         * cause trouble. Somebody should fix this. 
-         */
 	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
 	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
 	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
commit 1eebb03a3190947a8102f2ddc73766cf98d34c84
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 3 15:18:17 2007 +0930

    dix: ignore passive grab if the client already has a grab on the device.
    
    In some cases a button press may activate a passive core grab. If the client
    owning the passive grab already has a core grab on another device, don't
    actually activate it. Otherwise the client gets two simultaneous passive
    core grabs, and may never ungrab the device again (only if the other grab uses
    GrabModeSync).
    
    Reproducable: fire up gnome-session, open up gnome-terminal. Click with the
    ClientPointer onto the window decoration, then click with another pointer onto
    an application icon in the panel. Drag the icon out, release the button and
    voila - you just lost your second mouse.

diff --git a/dix/events.c b/dix/events.c
index 6489292..8141a40 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3297,6 +3297,35 @@ CheckPassiveGrabsOnWindow(
                 grab->modifierDevice = GetPairedKeyboard(device);
             }
 
+            /* In some cases a passive core grab may exist, but the client
+             * already has a core grab on some other device. In this case we
+             * must not get the grab, otherwise we may never ungrab the
+             * device.
+             */
+
+            if (grab->coreGrab)
+            {
+                DeviceIntPtr other;
+                BOOL interfering = FALSE;
+                for (other = inputInfo.devices; other; other = other->next)
+                {
+                    GrabPtr othergrab = other->deviceGrab.grab;
+                    if (othergrab && othergrab->coreGrab &&
+                        SameClient(grab, rClient(othergrab)) &&
+                        ((IsPointerDevice(grab->device) &&
+                         IsPointerDevice(othergrab->device)) ||
+                         (IsKeyboardDevice(grab->device) &&
+                          IsKeyboardDevice(othergrab->device))))
+                    {
+                        interfering = TRUE;
+                        break;
+                    }
+                }
+                if (interfering)
+                    continue;
+            }
+
+
 	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
  
 	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
commit 0b485067823620b5dbd9ef2b3e13bd35ad5a4410
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 3 14:22:55 2007 +0930

    dix: send NotifyGrab/NotifyUngrab focus events regardless of semaphore state.
    
    This is just papering over a problem. The whole focus system needs to be
    revised.

diff --git a/dix/events.c b/dix/events.c
index 35abffd..6489292 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4374,7 +4374,7 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
      * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
      * we only send an FocusIn event for the first kbd to set the focus. A
      * FocusOut event is sent for the last kbd to set the focus away from the
-     * window.. 
+     * window.
      *
      * For events with Virtual detail, we send them only to a window that does
      * not have a focus from another keyboard.
@@ -4392,7 +4392,9 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
 
     numFoci =
         &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout;
-    if (detail != NotifyVirtual && 
+    if (mode == NotifyGrab || mode == NotifyUngrab)
+        sendevent = TRUE;
+    else if (detail != NotifyVirtual && 
             detail != NotifyNonlinearVirtual && 
             detail != NotifyPointer &&
             detail != NotifyPointerRoot &&
commit 05106ac9839102c0e4a3ce5d9d83d19abf129f8a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Oct 3 11:33:10 2007 +0930

    dix: change Enter/Leave semaphore handling to accommodate for NotifyGrab.
    
    This is a half-assed attempt at getting rid of some enter-leave problems. When
    a grab is activated, the events didn't get sent before, leading to interesting
    results. This commit papers over it but doesn't actually fix it properly. The
    whole enter/leave (focusin/out) structure needs to be ripped out and changed
    for multiple devices.

diff --git a/dix/events.c b/dix/events.c
index 6eac090..35abffd 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4160,7 +4160,7 @@ EnterLeaveEvent(
      * Sending multiple core enter/leave events to the same window confuse the
      * client.  
      * We can send multiple events that have detail NotifyVirtual or
-     * NotifyNonlinearVirtual however.
+     * NotifyNonlinearVirtual however. For most clients anyway.
      *
      * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
      * we only send an enter event for the first pointer to enter. A leave
@@ -4183,8 +4183,6 @@ EnterLeaveEvent(
     if (event.u.u.detail != NotifyVirtual && 
             event.u.u.detail != NotifyNonlinearVirtual)
     {
-        (type == EnterNotify) ? (*inWindow)++ : (*inWindow)--;
-
         if (((*inWindow) == (LeaveNotify - type)))
             sendevent = TRUE;
     } else
@@ -4289,6 +4287,22 @@ LeaveNotifies(DeviceIntPtr pDev,
     }
 }
 
+#define FOCUS_SEMAPHORE_MODIFY(win, field, mode, val) \
+    { \
+        if (mode != NotifyGrab && mode != NotifyUngrab) \
+        { \
+            FocusSemaphoresPtr sem;\
+            sem = (FocusSemaphoresPtr)win->devPrivates[FocusPrivatesIndex].ptr; \
+            sem->field += val; \
+        } \
+    }
+#define ENTER_LEAVE_SEMAPHORE_UP(win, mode)  \
+        FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode, 1); 
+
+#define ENTER_LEAVE_SEMAPHORE_DOWN(win, mode) \
+        FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode,  -1);
+
+
 /**
  * Figure out if enter/leave events are necessary and send them to the
  * appropriate windows.
@@ -4306,27 +4320,33 @@ DoEnterLeaveEvents(DeviceIntPtr pDev,
 	return;
     if (IsParent(fromWin, toWin))
     {
+        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode); 
         EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin,
                         None); 
         EnterNotifies(pDev, fromWin, toWin, mode,
                       NotifyVirtual);
+        ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
         EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None);
     }
     else if (IsParent(toWin, fromWin))
     {
+        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode); 
 	EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin, 
                         None);
 	LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual);
+        ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
 	EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None);
     }
     else
     { /* neither fromWin nor toWin is descendent of the other */
 	WindowPtr common = CommonAncestor(toWin, fromWin);
 	/* common == NullWindow ==> different screens */
+        ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode); 
         EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin,
                         None); 
         LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual);
 	EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual);
+        ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
         EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin,
                         None); 
     }
commit f965a5f3454a95ddffb2faf9b291feff46305adf
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 2 16:20:27 2007 +0930

    dix: Ignore devices when deleting passive core grabs.

diff --git a/dix/grabs.c b/dix/grabs.c
index f1d0086..d51511c 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -406,7 +406,7 @@ DeletePassiveGrabFromList(GrabPtr pMinuendGrab)
 	 grab = grab->next)
     {
 	if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) ||
-	    !GrabMatchesSecond(grab, pMinuendGrab, FALSE))
+	    !GrabMatchesSecond(grab, pMinuendGrab, (grab->coreGrab)))
 	    continue;
 	if (GrabSupersedesSecond(pMinuendGrab, grab))
 	{
commit 2b075e97ec913ebe19290181e36bb169410b820b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 2 13:28:40 2007 +0930

    mi: switch core keyboard on XI events, not only on core events.
    
    We only get core events through the EQ in exceptional cases, so make sure we
    actually swap the core keymap for XI events as well. Gives us back the ability
    to have multiple keyboard layouts simultaneously.

diff --git a/mi/mieq.c b/mi/mieq.c
index 9e0f5be..f5e119e 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -267,10 +267,12 @@ mieqProcessInputEvents(void)
                 return;
             }
 
-            /* If this is a core event, make sure our keymap, et al, is
-             * changed to suit. */
-            if (e->events->event[0].u.u.type == KeyPress ||
-                e->events->event[0].u.u.type == KeyRelease) {
+            /* Make sure our keymap, et al, is changed to suit. */
+            if ((e->events->event[0].u.u.type == DeviceKeyPress ||
+                e->events->event[0].u.u.type == DeviceKeyRelease ||
+                e->events->event[0].u.u.type == KeyPress ||
+                e->events->event[0].u.u.type == KeyRelease) && 
+                    e->pDev->coreEvents) {
                 SwitchCoreKeyboard(e->pDev);
             }
 
commit 45ec6cd1fb242363c91ad8af1fd4a27a7f02621a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 2 13:19:07 2007 +0930

    xfree86: fix DGA to use the correct devices.
    
    DGAStealXXXEvent modified to take in device argument.
    
    The evdev driver only sends one valuator when only one axis changed. We need
    to check for DGA either way (xf86PostMotionEventP), otherwise we lose purely
    horizontal/vertical movements.
    
    Note that DGA does not do XI events.

diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
index ea8baaf..553679d 100644
--- a/hw/xfree86/common/xf86DGA.c
+++ b/hw/xfree86/common/xf86DGA.c
@@ -916,7 +916,7 @@ DGAVTSwitch(void)
 }
 
 Bool
-DGAStealKeyEvent(int index, int key_code, int is_down)
+DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down)
 {
    DGAScreenPtr pScreenPriv;
    dgaEvent    de;
@@ -932,7 +932,7 @@ DGAStealKeyEvent(int index, int key_code, int is_down)
     de.u.u.type = *XDGAEventBase + (is_down ? KeyPress : KeyRelease);
     de.u.u.detail = key_code;
     de.u.event.time = GetTimeInMillis();
-    mieqEnqueue (inputInfo.keyboard, (xEvent *) &de);
+    mieqEnqueue (dev, (xEvent *) &de);
 
    return TRUE;
 }  
@@ -940,7 +940,7 @@ DGAStealKeyEvent(int index, int key_code, int is_down)
 static int  DGAMouseX, DGAMouseY;
 
 Bool
-DGAStealMotionEvent(int index, int dx, int dy)
+DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy)
 {
    DGAScreenPtr pScreenPriv;
     dgaEvent    de;
@@ -970,12 +970,12 @@ DGAStealMotionEvent(int index, int dx, int dy)
     de.u.event.dy = dy;
     de.u.event.pad1 = DGAMouseX;
     de.u.event.pad2 = DGAMouseY;
-    mieqEnqueue (inputInfo.pointer, (xEvent *) &de);
+    mieqEnqueue (dev, (xEvent *) &de);
     return TRUE;
 }
 
 Bool
-DGAStealButtonEvent(int index, int button, int is_down)
+DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down)
 {
     DGAScreenPtr pScreenPriv;
     dgaEvent de;
@@ -995,7 +995,7 @@ DGAStealButtonEvent(int index, int button, int is_down)
     de.u.event.dy = 0;
     de.u.event.pad1 = DGAMouseX;
     de.u.event.pad2 = DGAMouseY;
-    mieqEnqueue (inputInfo.pointer, (xEvent *) &de);
+    mieqEnqueue (dev, (xEvent *) &de);
 
     return TRUE;
 }
@@ -1038,6 +1038,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
     xEvent	    core;
     KeyClassPtr	    keyc = keybd->key;
     DGAScreenPtr    pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
+    DeviceIntPtr    pointer = GetPairedPointer(keybd);
     
     coreEquiv = de->u.u.type - *XDGAEventBase;
 
@@ -1047,7 +1048,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
     de->u.event.dx = 0;
     de->u.event.dy = 0;
     de->u.event.screen = pScreen->myNum;
-    de->u.event.state = keyc->state | (inputInfo.pointer)->button->state;
+    de->u.event.state = keyc->state | pointer->button->state;
 
     /*
      * Keep the core state in sync by duplicating what
@@ -1060,7 +1061,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
     switch (coreEquiv)
     {
     case KeyPress:
-	inputInfo.pointer->valuator->motionHintWindow = NullWindow;
+        pointer->valuator->motionHintWindow = NullWindow;
 	*kptr |= bit;
 	keyc->prev_state = keyc->state;
 #ifdef XKB
@@ -1081,7 +1082,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
 	}
 	break;
     case KeyRelease:
-	inputInfo.pointer->valuator->motionHintWindow = NullWindow;
+	pointer->valuator->motionHintWindow = NullWindow;
 	*kptr &= ~bit;
 	keyc->prev_state = keyc->state;
 #ifdef XKB
@@ -1197,8 +1198,6 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
 	/* If the pointer is actively grabbed, deliver a grabbed core event */
 	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) */
 	    core.u.u.type		    = coreEquiv;
 	    core.u.u.detail		    = de->u.u.detail;
 	    core.u.keyButtonPointer.time    = de->u.event.time;
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index a458c11..c6df92c 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -539,7 +539,7 @@ xf86PostMotionEventP(DeviceIntPtr	device,
                     int			*valuators)
 {
     int i = 0, nevents = 0;
-    int dx, dy;
+    int dx = 0, dy = 0;
     Bool drag = xf86SendDragEvents(device);
     xEvent *xE = NULL;
     int index;
@@ -551,18 +551,25 @@ xf86PostMotionEventP(DeviceIntPtr	device,
         flags = POINTER_RELATIVE | POINTER_ACCELERATE;
 
 #if XFreeXDGA
-    if (first_valuator == 0 && num_valuators >= 2) {
-        if (miPointerGetScreen(inputInfo.pointer)) {
-            index = miPointerGetScreen(inputInfo.pointer)->myNum;
-            if (is_absolute) {
-                dx = valuators[0] - device->valuator->lastx;
-                dy = valuators[1] - device->valuator->lasty;
-            }
-            else {
+    /* The evdev driver may not always send all axes across. */
+    if (num_valuators >= 1 && first_valuator <= 1) {
+        if (miPointerGetScreen(device)) {
+            index = miPointerGetScreen(device)->myNum;
+            if (first_valuator == 0)
+            {
                 dx = valuators[0];
-                dy = valuators[1];
+                if (is_absolute)
+                    dx -= device->valuator->lastx;
+            }
+
+            if (first_valuator == 1 || num_valuators >= 2)
+            {
+                dy = valuators[1 - first_valuator];
+                if (is_absolute)
+                    dy -= device->valuator->lasty;
             }
-            if (DGAStealMotionEvent(index, dx, dy))
+
+            if (DGAStealMotionEvent(device, index, dx, dy))
                 return;
         }
     }
@@ -633,9 +640,9 @@ xf86PostButtonEvent(DeviceIntPtr	device,
     int index;
 
 #if XFreeXDGA
-    if (miPointerGetScreen(inputInfo.pointer)) {
-        index = miPointerGetScreen(inputInfo.pointer)->myNum;
-        if (DGAStealButtonEvent(index, button, is_down))
+    if (miPointerGetScreen(device)) {
+        index = miPointerGetScreen(device)->myNum;
+        if (DGAStealButtonEvent(device, index, button, is_down))
             return;
     }
 #endif
@@ -716,9 +723,11 @@ xf86PostKeyboardEvent(DeviceIntPtr      device,
     int index;
 
 #if XFreeXDGA
-    if (miPointerGetScreen(inputInfo.pointer)) {
-        index = miPointerGetScreen(inputInfo.pointer)->myNum;
-        if (DGAStealKeyEvent(index, key_code, is_down))
+    DeviceIntPtr pointer = GetPairedPointer(device);
+
+    if (miPointerGetScreen(pointer)) {
+        index = miPointerGetScreen(pointer)->myNum;
+        if (DGAStealKeyEvent(device, index, key_code, is_down))
             return;
     }
 #endif
diff --git a/hw/xfree86/dixmods/extmod/dgaproc.h b/hw/xfree86/dixmods/extmod/dgaproc.h
index aaea4e2..f4d3fe4 100644
--- a/hw/xfree86/dixmods/extmod/dgaproc.h
+++ b/hw/xfree86/dixmods/extmod/dgaproc.h
@@ -120,9 +120,10 @@ int DGAGetOldDGAMode(int Index);
 int DGAGetModeInfo(int Index, XDGAModePtr mode, int num);
 
 Bool DGAVTSwitch(void);
-Bool DGAStealButtonEvent(int Index, int button, int is_down);
-Bool DGAStealMotionEvent(int Index, int dx, int dy);
-Bool DGAStealKeyEvent(int Index, int key_code, int is_down);
+Bool DGAStealButtonEvent(DeviceIntPtr dev, int Index, int button, 
+                         int is_down);
+Bool DGAStealMotionEvent(DeviceIntPtr dev, int Index, int dx, int dy);
+Bool DGAStealKeyEvent(DeviceIntPtr dev, int Index, int key_code, int is_down);
 Bool DGAIsDgaEvent (xEvent *e);
 
 Bool DGADeliverEvent (ScreenPtr pScreen, xEvent *e);
commit 122ae65ed90195c584a770027b4d14ef65f72492
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 2 10:50:59 2007 +0930

    xfree86: xf86DGA: some cleanup to use the correct devices instead of VCP/VCK.

diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
index 074c1c7..ea8baaf 100644
--- a/hw/xfree86/common/xf86DGA.c
+++ b/hw/xfree86/common/xf86DGA.c
@@ -1144,15 +1144,15 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
      * Fill in remaining event state
      */
     de->u.event.screen = pScreen->myNum;
-    de->u.event.state = butc->state | inputInfo.keyboard->key->state;
+    de->u.event.state = butc->state | GetPairedKeyboard(mouse)->key->state;
     /*
      * Keep the core state in sync by duplicating what
      * CoreProcessPointerEvent does
      */
     if (coreEquiv != MotionNotify)
     {
-	register int  key;
-	register BYTE *kptr;
+	int           key;
+	BYTE          *kptr;
 	int           bit;
 	
 	key = de->u.u.detail;
@@ -1295,10 +1295,10 @@ DGAHandleEvent(int screen_num, xEvent *event, DeviceIntPtr device, int nevents)
     switch (coreEquiv) {
     case KeyPress:
     case KeyRelease:
-	DGAProcessKeyboardEvent (pScreen, de, inputInfo.keyboard);
+	DGAProcessKeyboardEvent (pScreen, de, device);
 	break;
     default:
-	DGAProcessPointerEvent (pScreen, de, inputInfo.pointer);
+	DGAProcessPointerEvent (pScreen, de, device);
 	break;
     }
 }
commit 54ce7436b2579bb20728eab7c8d460b531c378af
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Oct 2 10:49:46 2007 +0930

    xfree86: update all pointers when calling xf86SwitchMode
    
    Center the frame around the first pointer found and then update all pointers
    on the same screen to move to the edges (if necessary).
    
    Note: xf86WarpCursor needs to be modified, is using deprecated
    miPointerWarpCursor and will kill the server when called with
    inputInfo.pointer.

diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c
index 38bd38c..d6fa604 100644
--- a/hw/xfree86/common/xf86Cursor.c
+++ b/hw/xfree86/common/xf86Cursor.c
@@ -206,6 +206,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
   ScreenPtr   pCursorScreen;
   Bool        Switched;
   int         px, py;
+  DeviceIntPtr dev, it;
 
   if (!pScr->vtSema || !mode || !pScr->SwitchMode)
     return FALSE;
@@ -221,9 +222,20 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
   if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY)
     return FALSE;
 
-  pCursorScreen = miPointerGetScreen(inputInfo.pointer);
+  /* Let's take an educated guess for which pointer to take here. And about as
+     educated as it gets is to take the first pointer we find.
+   */
+  for (dev = inputInfo.devices; dev; dev = dev->next)
+  {
+      if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
+          break;
+  }
+  if (!dev)
+      dev = inputInfo.pointer;
+
+  pCursorScreen = miPointerGetScreen(dev);
   if (pScreen == pCursorScreen)
-    miPointerGetPosition(inputInfo.pointer, &px, &py);
+    miPointerGetPosition(dev, &px, &py);
 
   xf86EnterServerState(SETUP);
   Switched = (*pScr->SwitchMode)(pScr->scrnIndex, mode, 0);
@@ -232,6 +244,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
 
     /*
      * Adjust frame for new display size.
+     * Frame is centered around cursor position if cursor is on same screen.
      */
     if (pScreen == pCursorScreen)
       pScr->frameX0 = px - (mode->HDisplay / 2) + 1;
@@ -266,8 +279,42 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
   if (pScr->AdjustFrame)
     (*pScr->AdjustFrame)(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0);
 
+  /* The original code centered the frame around the cursor if possible.
+   * Since this is hard to achieve with multiple cursors, we do the following:
+   *   - center around the first pointer
+   *   - move all other pointers to the nearest edge on the screen (or leave
+   *   them unmodified if they are within the boundaries).
+   */
   if (pScreen == pCursorScreen)
-    xf86WarpCursor(inputInfo.pointer, pScreen, px, py);
+  {
+      xf86WarpCursor(dev, pScreen, px, py);
+  }
+
+  for (it = inputInfo.devices; it; it = it->next)
+  {
+      if (it == dev)
+          continue;
+
+      if (IsPointerDevice(it) && it->spriteInfo->spriteOwner)
+      {
+          pCursorScreen = miPointerGetScreen(it);
+          if (pScreen == pCursorScreen)
+          {
+              miPointerGetPosition(it, &px, &py);
+              if (px < pScr->frameX0)
+                  px = pScr->frameX0;
+              else if (px > pScr->frameX1)
+                  px = pScr->frameX1;
+
+              if(py < pScr->frameY0)
+                  py = pScr->frameY0;
+              else if(py > pScr->frameY1)
+                  py = pScr->frameY1;
+
+              xf86WarpCursor(it, pScreen, px, py);
+          }
+      }
+  }
 
   return Switched;
 }
commit 113011221a4fcbd70bc592930b35f20d55809f1e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Oct 1 21:42:01 2007 +0930

    Xi, xfree86: Remove leftovers of the XI wrapper code.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 3566906..1bcc101 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -89,64 +89,12 @@ Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
 static Bool MakeInputMasks(WindowPtr	/* pWin */
     );
 
-static int xiDevPrivateIndex = 0;
-static int _xiServerGeneration = -1;
-
-typedef struct {
-    ProcessInputProc processInputProc;
-    ProcessInputProc realInputProc;
-} xiDevPrivateRec, *xiDevPrivatePtr;
-
-/**************************************************************************
- *
- * Procedures for extension device event routing.
- *
- */
-
-#define WRAP_PROCESS_INPUT_PROC(device, saveprocs, newproc) \
-    saveprocs->processInputProc = \
-    saveprocs->realInputProc = device->public.realInputProc; \
-    device->public.processInputProc = newproc; \
-    device->public.realInputProc = newproc 
-
-#define UNWRAP_PROCESS_INPUT_PROC(device, saveprocs, backupproc) \
-    backupproc = device->public.processInputProc; \
-    device->public.processInputProc = saveprocs->processInputProc; \
-    device->public.realInputProc = saveprocs->realInputProc; 
-
-#define REWRAP_PROCESS_INPUT_PROC(device, saveprocs, newproc) \
-    if (device->public.processInputProc == device->public.realInputProc) \
-        device->public.processInputProc = newproc; \
-    saveprocs->processInputProc = \
-    saveprocs->realInputProc = device->public.realInputProc; \
-    device->public.realInputProc = newproc;
 
 void
 RegisterOtherDevice(DeviceIntPtr device)
 {
-    xiDevPrivatePtr xiPrivPtr;
-
-    if (serverGeneration != _xiServerGeneration)
-    {
-        xiDevPrivateIndex = AllocateDevicePrivateIndex();
-        if (xiDevPrivateIndex == 1)
-        {
-            FatalError("[Xi] Could not allocate private index.\n"); 
-        }
-        _xiServerGeneration = serverGeneration;
-    }
-
-    if (!AllocateDevicePrivate(device, xiDevPrivateIndex))
-        FatalError("[Xi] Dev private allocation failed.\n");
-
-
-    xiPrivPtr = (xiDevPrivatePtr)xcalloc(1, sizeof(xiDevPrivateRec));
-    if (!xiPrivPtr)
-        FatalError("[Xi] Cannot get memory for dev private.\n");
-
-    device->devPrivates[xiDevPrivateIndex].ptr = xiPrivPtr;
-
-    WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent);
+    device->public.processInputProc = ProcessOtherEvent;
+    device->public.realInputProc = ProcessOtherEvent;
 }
 
 /**
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index a43230e..a458c11 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -181,24 +181,10 @@ xf86ActivateDevice(LocalDevicePtr local)
 
         if (DeviceIsPointerType(dev))
         {
-#ifdef XKB
-            dev->public.processInputProc = CoreProcessPointerEvent;
-            dev->public.realInputProc = CoreProcessPointerEvent;
-#else
-            dev->public.processInputProc = ProcessPointerEvent;
-            dev->public.realInputProc = ProcessPointerEvent;
-#endif
             dev->deviceGrab.ActivateGrab = ActivatePointerGrab;
             dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
         } else 
         {
-#ifdef XKB
-            dev->public.processInputProc = CoreProcessKeyboardEvent;
-            dev->public.realInputProc = CoreProcessKeyboardEvent;
-#else
-            dev->public.processInputProc = ProcessKeyboardEvent;
-            dev->public.realInputProc = ProcessKeyboardEvent;
-#endif
             dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
             dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
         }
commit a511c445debbd13e8c48146ecd2d7c97e793f788
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Sep 28 18:46:41 2007 +0930

    Remove generation of core events, long live XI!
    
    Let the drivers only generate XI events and put those into the event queue.
    When processing events, generate core events as needed. This fixes a number of
    problems with XKB and the DIX in general.
    
    The previous approach was to put core events and XI events as separate events
    into the event queue. When being processed, the server had no knowledge of
    them coming from the same device state change. Anything that would then change
    the state of the device accordingly was in danger of changing it twice,
    leading to some funny (i.e. not funny at all) results.
    
    Emulating core events while processing XI events fixes this, there is only one
    path that actually changes the device state now. Although we have to be
    careful when replaying events from synced devices, otherwise we may lose
    events.
    
    Note: XI has precedence over core for passive grabs, but core events are
    delivered to the client first.
    
    This removes the wrapping added in 340911d7243a7f1095d79b5b2dcfa81b145c2474

diff --git a/Xi/exevents.c b/Xi/exevents.c
index d844eef..3566906 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -149,7 +149,15 @@ RegisterOtherDevice(DeviceIntPtr device)
     WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent);
 }
 
- /*ARGSUSED*/ void
+/**
+ * Main device event processing function. 
+ * Called from when processing the events from the event queue. 
+ * Generates core events for XI events as needed.
+ * 
+ * Note that these core events are then delivered first. For passive grabs, XI
+ * events have preference over core.
+ */
+void
 ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 {
     BYTE *kptr;
@@ -163,19 +171,13 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     KeyClassPtr k = device->key;
     ValuatorClassPtr v = device->valuator;
     deviceValuator *xV = (deviceValuator *) xE;
+    BOOL sendCore = FALSE;
+    xEvent core;
+    int coretype = 0;
 
-    /* Handle core events. */
-    if (xE->u.u.type < LASTEvent && xE->u.u.type != GenericEvent)
-    {
-        ProcessInputProc backupproc;
-        xiDevPrivatePtr xiPrivPtr = 
-            (xiDevPrivatePtr)device->devPrivates[xiDevPrivateIndex].ptr;
-        UNWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, backupproc);
-        device->public.processInputProc(xE, device, count);
-        /* only rewraps is the processInputProc hasn't been modified */
-        REWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, backupproc);
-        return;
-    }
+    coretype = XItoCoreType(xE->u.u.type);
+    if (device->coreEvents && coretype)
+        sendCore = TRUE;
 
     CheckMotion(xE, device);
 
@@ -280,7 +282,12 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 		modifiers &= ~mask;
 	    }
 	}
-	if (!grab && CheckDeviceGrabs(device, xE, 0, count)) {
+        /* XI grabs have priority */
+        core = *xE;
+        core.u.u.type = coretype;
+	if (!grab &&
+              (CheckDeviceGrabs(device, xE, 0, count) ||
+                 (sendCore && CheckDeviceGrabs(device, &core, 0, 1)))) {
 	    device->deviceGrab.activatingKey = key;
 	    return;
 	}
@@ -308,7 +315,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	}
 
 	if (device->deviceGrab.fromPassiveGrab && 
-            !device->deviceGrab.grab->coreGrab &&
             (key == device->deviceGrab.activatingKey))
 	    deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == DeviceButtonPress) {
@@ -328,10 +334,17 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
         if (!grab)
-            if (CheckDeviceGrabs(device, xE, 0, count))
+        {
+            core = *xE;
+            core.u.u.type = coretype;
+            if (CheckDeviceGrabs(device, xE, 0, count) ||
+                    (sendCore && CheckDeviceGrabs(device, &core, 0, 1)))
+            {
                 /* if a passive grab was activated, the event has been sent
                  * already */
                 return;
+            }
+        }
 
     } else if (xE->u.u.type == DeviceButtonRelease) {
         if (!b)
@@ -350,21 +363,39 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
         if (!b->state 
-            && device->deviceGrab.fromPassiveGrab
-            && !device->deviceGrab.grab->coreGrab)
+            && device->deviceGrab.fromPassiveGrab)
             deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == ProximityIn)
 	device->valuator->mode &= ~OutOfProximity;
     else if (xE->u.u.type == ProximityOut)
 	device->valuator->mode |= OutOfProximity;
 
+    if (sendCore)
+    {
+        core = *xE;
+        core.u.u.type = coretype;
+    }
+
     if (grab)
-	DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
+    {
+        if (sendCore)                      /* never deactivate from core */
+            DeliverGrabbedEvent(&core, device, FALSE , 1);
+        DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
+    }
     else if (device->focus)
+    {
+        if (sendCore)
+            DeliverFocusedEvent(device, &core, GetSpriteWindow(device), 1);
 	DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
+    }
     else
+    {
+        if (sendCore)
+            DeliverDeviceEvents(GetSpriteWindow(device), &core, NullGrab,
+                                NullWindow, device, 1);
 	DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
 			    device, count);
+    }
 
     if (deactivateDeviceGrab == TRUE)
 	(*device->deviceGrab.DeactivateGrab) (device);
diff --git a/dix/events.c b/dix/events.c
index 45ff943..6eac090 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -294,6 +294,27 @@ static struct {
 static xEvent* swapEvent = NULL;
 static int swapEventLen = 0;
 
+/**
+ * Convert the given event type from an XI event to a core event.
+ * @return The matching core event type or 0 if there is none.
+ */
+_X_EXPORT int
+XItoCoreType(int xitype)
+{
+    int coretype = 0;
+    if (xitype == DeviceMotionNotify)
+        coretype = MotionNotify;
+    else if (xitype == DeviceButtonPress)
+        coretype = ButtonPress;
+    else if (xitype == DeviceButtonRelease)
+        coretype = ButtonRelease;
+    else if (xitype == DeviceKeyPress)
+        coretype = KeyPress;
+    else if (xitype == DeviceKeyRelease)
+        coretype = KeyRelease;
+    return coretype;
+}
+
 /** 
  * True if device owns a cursor, false if device shares a cursor sprite with
  * another device.
@@ -775,9 +796,15 @@ XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 void
 SetMaskForEvent(Mask mask, int event)
 {
+    int coretype;
     if ((event < LASTEvent) || (event >= 128))
 	FatalError("SetMaskForEvent: bogus event number");
     filters[event] = mask;
+
+    /* Need to change the mask for the core events too */
+    coretype = XItoCoreType(event);
+    if (coretype)
+        filters[coretype] = mask;
 }
 
 _X_EXPORT void
@@ -1343,10 +1370,11 @@ ComputeFreezes(void)
     DeviceIntPtr replayDev = syncEvents.replayDev;
     int i;
     WindowPtr w;
-    xEvent *xE;
+    xEvent *xE, core;
     int count;
     GrabPtr grab;
     DeviceIntPtr dev;
+    BOOL sendCore;
 
     for (dev = inputInfo.devices; dev; dev = dev->next)
 	FreezeThaw(dev, dev->deviceGrab.sync.other || 
@@ -1367,11 +1395,38 @@ ComputeFreezes(void)
 		replayDev->spriteInfo->sprite->spriteTrace[i])
 	    {
 		if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
+                    /* There is no other client that gets a passive grab on
+                     * the event anymore. Emulate core event if necessary and
+                     * deliver it too.
+                     * However, we might get here with a core event, in which
+                     * case we mustn't emulate a core event.
+                     * XXX: I think this may break things. If a client has a
+                     * device grab, and another client a core grab on an
+                     * inferior window, we never get the core grab. (whot)
+                     */
+                    sendCore = (replayDev->coreEvents &&
+                        (xE->u.u.type & EXTENSION_EVENT_BASE &&
+                         XItoCoreType(xE->u.u.type)));
+
+                    if (sendCore)
+                    {
+                        core = *xE;
+                        core.u.u.type = XItoCoreType(xE->u.u.type);
+                    }
 		    if (replayDev->focus)
+                    {
+                        if (sendCore)
+                            DeliverFocusedEvent(replayDev, &core, w, 1);
 			DeliverFocusedEvent(replayDev, xE, w, count);
+                    }
 		    else
+                    {
+                        if (sendCore)
+                            DeliverDeviceEvents(w, &core, NullGrab,
+                                                NullWindow, replayDev, 1);
 			DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
 					        replayDev, count);
+                    }
 		}
 		goto playmore;
 	    }
@@ -2089,7 +2144,13 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
             }
         }
     }
-    if ((type == ButtonPress) && deliveries && (!grab))
+    /*
+     * Note that since core events are delivered first, an implicit grab may
+     * be activated on a core grab, stopping the XI events.
+     */
+    if ((type == DeviceButtonPress || type == ButtonPress)
+            && deliveries
+            && (!grab))
     {
 	GrabRec tempGrab;
         OtherInputMasks *inputMasks;
@@ -2104,7 +2165,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 	tempGrab.pointerMode = GrabModeAsync;
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
-        tempGrab.coreGrab = True;
+        tempGrab.coreGrab = (type == ButtonPress);
 
         /* get the XI device mask */
         inputMasks = wOtherInputMasks(pWin);
@@ -2127,9 +2188,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
                 tempGrab.genericMasks->next = NULL;
             }
         }
-	(*inputInfo.pointer->deviceGrab.ActivateGrab)(pDev, &tempGrab,
-					   currentTime, 
-                                           TRUE | ImplicitGrabMask);
+	(*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab,
+                                        currentTime, TRUE | ImplicitGrabMask);
     }
     else if ((type == MotionNotify) && deliveries)
 	pDev->valuator->motionHintWindow = pWin;
@@ -3182,6 +3242,8 @@ CheckPassiveGrabsOnWindow(
 	XkbSrvInfoPtr	xkbi;
 
 	gdev= grab->modifierDevice;
+        if (grab->coreGrab)
+            gdev = GetPairedKeyboard(device);
 	xkbi= gdev->key->xkbInfo;
 #endif
 	tempGrab.modifierDevice = grab->modifierDevice;
diff --git a/dix/getevents.c b/dix/getevents.c
index fda4e27..7457078 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -191,10 +191,10 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
  */
 _X_EXPORT int
 GetMaximumEventsNum(void) {
-    /* Three base events -- raw event, core and device, plus valuator events.
+    /* Three base events -- raw event and device, plus valuator events.
      * Multiply by two if we're doing key repeats. 
      */
-    int ret = 3 + MAX_VALUATOR_EVENTS;
+    int ret = 2 + MAX_VALUATOR_EVENTS;
 
 #ifdef XKB
     if (noXkbExtension)
@@ -366,6 +366,9 @@ GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code)
  * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
  * also with valuator events.  Handles Xi and XKB.
  *
+ * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
+ * event (ProcessOtherEvent).
+ *
  * 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.
@@ -399,10 +402,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
         (pDev->coreEvents && !inputInfo.keyboard->key))
         return 0;
 
-    if (pDev->coreEvents)
-        numEvents = 2;
-    else
-        numEvents = 1;
+    numEvents = 1;
 
     if (num_valuators) {
         if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS)
@@ -469,12 +469,6 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
                                    num_valuators, valuators);
     }
 
-    if (pDev->coreEvents) {
-        events->event->u.keyButtonPointer.time = ms;
-        events->event->u.u.type = type;
-        events->event->u.u.detail = key_code;
-    }
-
     return numEvents;
 }
 
@@ -533,6 +527,9 @@ FreeEventList(EventListPtr list, int num_events)
  * Generate a series of xEvents (filled into the EventList) representing
  * pointer motion, or button presses.  Xi and XKB-aware.
  *
+ * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
+ * event (ProcessOtherEvent).
+ *
  * 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 InitEventList() and GetMaximumEventsNum(), and for freeing it.
@@ -567,10 +564,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     if (!pDev->valuator)
         return 0;
 
-    if (!coreOnly && pDev->coreEvents)
-        num_events = 3;
-    else
-        num_events = 2;
+    num_events = 2;
 
     if (type == MotionNotify && num_valuators <= 0)
         return 0;
@@ -703,24 +697,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         }
     }
 
-    /* for some reason inputInfo.pointer does not have coreEvents set */
-    if (coreOnly || pDev->coreEvents) {
-        events->event->u.u.type = type;
-        events->event->u.keyButtonPointer.time = ms;
-        events->event->u.keyButtonPointer.rootX = x;
-        events->event->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->event->u.u.detail = pDev->button->map[buttons];
-        }
-        else {
-            events->event->u.u.detail = 0;
-        }
-    }
-
     return num_events;
 }
 
diff --git a/include/dix.h b/include/dix.h
index bec19dd..34abb2d 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -689,6 +689,7 @@ typedef struct {
 extern int xstrcasecmp(char *s1, char *s2);
 #endif
 
+extern int XItoCoreType(int xi_type);
 extern Bool DevHasCursor(DeviceIntPtr pDev);
 
 extern Bool IsPointerDevice( DeviceIntPtr dev);
diff --git a/mi/mieq.c b/mi/mieq.c
index 78e57ad..9e0f5be 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -300,7 +300,8 @@ mieqProcessInputEvents(void)
         }
 
         /* Update the sprite now. Next event may be from different device. */
-        if (e->events->event[0].u.u.type == MotionNotify && e->pDev->coreEvents)
+        if (e->events->event[0].u.u.type == DeviceMotionNotify 
+                && e->pDev->coreEvents)
         {
             miPointerUpdateSprite(e->pDev);
         }
commit be466d8df808c4e4067a7963617bc3f506768f2d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 27 22:23:05 2007 +0930

    dix: GetPairedKeyboard() always returns a valid keyboard (VCK if necessary).
    
    We need it unconditionally in a few places, and the rest checked for NULL and
    then set it to VCK anyway. So, fixing up all callers to appreciate the defined
    return value.

diff --git a/dix/devices.c b/dix/devices.c
index 63d7ea4..24eaa4b 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2229,15 +2229,16 @@ GetPairedPointer(DeviceIntPtr kbd)
 }
 
 /* Find the keyboard device that is paired with the given pointer. If none is
- * found, return NULL.
- * We also check if the paired device is a keyboard. If not (e.g. evdev brain)
- * we don't return it. This probably needs to be fixed.
+ * found, return the VCK.
  */
 _X_EXPORT DeviceIntPtr
 GetPairedKeyboard(DeviceIntPtr ptr)
 {
     DeviceIntPtr dev = inputInfo.devices;
 
+    if (IsKeyboardDevice(ptr))
+        return ptr;
+
     while(dev)
     {
         if (ptr != dev && 
@@ -2246,7 +2247,7 @@ GetPairedKeyboard(DeviceIntPtr ptr)
             return dev;
         dev = dev->next;
     }
-    return dev;
+    return (dev) ? dev : inputInfo.keyboard;
 }
 
 /*
diff --git a/dix/events.c b/dix/events.c
index a803550..45ff943 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3233,8 +3233,6 @@ CheckPassiveGrabsOnWindow(
             {
                 grab->device = device; 
                 grab->modifierDevice = GetPairedKeyboard(device);
-                if (!grab->modifierDevice)
-                    grab->modifierDevice = inputInfo.keyboard;
             }
 
 	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
@@ -4052,8 +4050,7 @@ EnterLeaveEvent(
     int                 mskidx;
     OtherInputMasks     *inputMasks;
 
-    if (!(keybd = GetPairedKeyboard(mouse)))
-        keybd = inputInfo.keyboard;
+    keybd = GetPairedKeyboard(mouse);
 
     if ((pWin == mouse->valuator->motionHintWindow) &&
 	(detail != NotifyInferior))
@@ -4572,11 +4569,7 @@ SetInputFocus(
     if (IsKeyboardDevice(dev))
         keybd = dev;
     else
-    {
         keybd = GetPairedKeyboard(dev);
-        if (!keybd) 
-            keybd = inputInfo.keyboard;
-    }
 
     if ((focusID == None) || (focusID == PointerRoot))
 	focusWin = (WindowPtr)(long)focusID;
@@ -5592,8 +5585,6 @@ ProcGrabButton(ClientPtr client)
 
     pointer = PickPointer(client);
     modifierDevice = GetPairedKeyboard(pointer);
-    if (!modifierDevice)
-        modifierDevice = inputInfo.keyboard;
 
     grab = CreateGrab(client->index, pointer, pWin, 
         (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
commit 53434edc3d306137d019d95189ecdf0dbff75205
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 27 22:14:09 2007 +0930

    dix: take paired keyboard instead of VCK (CoreProcessPointerEvents)

diff --git a/dix/events.c b/dix/events.c
index b396b65..a803550 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3707,7 +3707,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
     SpritePtr           pSprite = mouse->spriteInfo->sprite;
 
 #ifdef XKB
-    XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
+    XkbSrvInfoPtr xkbi= GetPairedKeyboard(mouse)->key->xkbInfo;
 #endif
 #ifdef XEVIE
     if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState &&
commit de06a47d4ad9c845b098438d9492a5f42483a2ad
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 27 11:45:03 2007 +0930

    dix: GetMaximumEventsNum() needs to return 3 + MAX_VALUATOR_EVENTS.
    
    Raw events can be generated for pointer events, so 2 + MVE isn't enough.

diff --git a/dix/getevents.c b/dix/getevents.c
index df1dc6a..fda4e27 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -191,9 +191,10 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
  */
 _X_EXPORT int
 GetMaximumEventsNum(void) {
-    /* Two base events -- core and device, plus valuator events.  Multiply
-     * by two if we're doing key repeats. */
-    int ret = 2 + MAX_VALUATOR_EVENTS;
+    /* Three base events -- raw event, core and device, plus valuator events.
+     * Multiply by two if we're doing key repeats. 
+     */
+    int ret = 3 + MAX_VALUATOR_EVENTS;
 
 #ifdef XKB
     if (noXkbExtension)
commit 32d0440c7f6e604807cb14dd32349df6f22c903b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 27 11:44:03 2007 +0930

    xkb: xkbHandleActions: let wrapping take care of event delivery.
    
    This is hopefully better than hardcodey calling CoreProcessPointerEvent.

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index cc707bd..891b915 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1148,7 +1148,6 @@ XkbAction	act;
 XkbFilterPtr	filter;
 Bool		keyEvent;
 Bool		pressEvent;
-Bool		xiEvent;
 ProcessInputProc backupproc;
     
 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
@@ -1173,9 +1172,6 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 		(xE->u.u.type==KeyRelease)||(xE->u.u.type==DeviceKeyRelease));
     pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)||
 		 (xE->u.u.type==ButtonPress)||(xE->u.u.type==DeviceButtonPress);
-    xiEvent= (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease)||
-	     (xE->u.u.type==DeviceButtonPress)||
-	     (xE->u.u.type==DeviceButtonRelease);
 
     if (pressEvent) {
 	if (keyEvent)	
@@ -1279,23 +1275,21 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
     }
 
     if (sendEvent) {
+        DeviceIntPtr tmpdev;
 	if (keyEvent) {
 	    realMods = keyc->modifierMap[key];
 	    keyc->modifierMap[key] = 0;
-	    UNWRAP_PROCESS_INPUT_PROC(dev,xkbPrivPtr, backupproc);
-	    dev->public.processInputProc(xE,dev,count);
-	    COND_WRAP_PROCESS_INPUT_PROC(dev, xkbPrivPtr,
-					 backupproc,xkbUnwrapProc);
+            tmpdev = dev;
+        } else
+            tmpdev = GetPairedPointer(dev);
+
+
+        UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
+        dev->public.processInputProc(xE,tmpdev,count);
+        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
+                                     backupproc,xkbUnwrapProc);
+        if (keyEvent)
 	    keyc->modifierMap[key] = realMods;
-	}
-	else 
-        {
-            if (xE->u.u.type & EXTENSION_EVENT_BASE)
-                ProcessOtherEvent(xE, dev, count);
-            else
-                CoreProcessPointerEvent(xE,dev,count);
-            
-        }
     }
     else if (keyEvent)
 	FixKeyState(xE,dev);
commit 8f9bf927e1beecf9b9ec8877131ec12c765e4d84
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 18:04:59 2007 +0930

    xkb: Unwrap properly in ProcessPointerEvent.
    
    Instead of hardcoding CoreProcessPointerEvent, actually try to unwrap properly
    and then call the unwrapped processInputProc. Seems to be a better idea,
    especially since it makes stuff actually work...

diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index 8e897c8..063c844 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -684,6 +684,8 @@ Bool		ignoreKeyEvent = FALSE;
 /* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/
 /*									*/
 /************************************************************************/
+extern int xkbDevicePrivateIndex;
+extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer);
 void
 ProcessPointerEvent(	register xEvent  *	xE, 
 			register DeviceIntPtr	mouse, 
@@ -692,6 +694,8 @@ ProcessPointerEvent(	register xEvent  *	xE,
 DeviceIntPtr	dev = (DeviceIntPtr)LookupKeyboardDevice();
 XkbSrvInfoPtr	xkbi = dev->key->xkbInfo;
 unsigned 	changed = 0;
+ProcessInputProc backupproc;
+xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse);
 
     xkbi->shiftKeyCount = 0;
     xkbi->lastPtrEventTime= xE->u.keyButtonPointer.time;
@@ -703,7 +707,26 @@ unsigned 	changed = 0;
 	xkbi->lockedPtrButtons&= ~(1<<(xE->u.u.detail&0x7));
 	changed |= XkbPointerButtonMask;
     }
-    CoreProcessPointerEvent(xE,mouse,count);
+
+    /* Guesswork. mostly. 
+     * xkb actuall goes through some effort to transparently wrap the
+     * processInputProcs (see XkbSetExtension). But we all love fun, so the
+     * previous XKB implementation just hardcoded the CPPE call here instead
+     * of unwrapping like anybody with any sense of decency would do. 
+     * I got no clue what the correct thing to do is, but my guess is that
+     * it's not hardcoding. I may be wrong. whatever it is, don't come whining
+     * to me. I just work here. 
+     *
+     * Anyway. here's the old call, if you don't like the wrapping, revert it.
+     *
+     * CoreProcessPointerEvent(xE,mouse,count);
+     *
+     *          see. it's still steaming. told you. (whot)
+     */
+    UNWRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc);
+    mouse->public.processInputProc(xE, mouse, count);
+    COND_WRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr,
+				     backupproc, xkbUnwrapProc);
 
     xkbi->state.ptr_buttons = mouse->button->state;
     
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index e51b0cc..cc707bd 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -42,9 +42,9 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #define EXTENSION_EVENT_BASE 64
 
 static unsigned int _xkbServerGeneration;
-static int xkbDevicePrivateIndex = -1;
+int xkbDevicePrivateIndex = -1;
 
-static void
+void
 xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
                    pointer data)
 {
commit 3342b5ad47be25c6838321c0aafc28c329c308b5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 18:03:21 2007 +0930

    Xi: fix the wrapper code for processInputProc wrapping.
    
    Followup to [1].
    If a core grab causes the device to freeze, it overwrites the processInputProc
    of the device. [1] would then overwrite this while unwrapping, the device
    does not thaw anymore.
    Changing this to only re-wrap if the processInputProc hasn't been changed
    during the event handling.
    
    [1] 340911d7243a7f1095d79b5b2dcfa81b145c2474

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 2baaa58..d844eef 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -104,15 +104,23 @@ typedef struct {
  */
 
 #define WRAP_PROCESS_INPUT_PROC(device, saveprocs, newproc) \
-    saveprocs->processInputProc = device->public.processInputProc; \
+    saveprocs->processInputProc = \
     saveprocs->realInputProc = device->public.realInputProc; \
     device->public.processInputProc = newproc; \
-    device->public.realInputProc = newproc;
+    device->public.realInputProc = newproc 
 
-#define UNWRAP_PROCESS_INPUT_PROC(device, saveprocs) \
+#define UNWRAP_PROCESS_INPUT_PROC(device, saveprocs, backupproc) \
+    backupproc = device->public.processInputProc; \
     device->public.processInputProc = saveprocs->processInputProc; \
     device->public.realInputProc = saveprocs->realInputProc; 
 
+#define REWRAP_PROCESS_INPUT_PROC(device, saveprocs, newproc) \
+    if (device->public.processInputProc == device->public.realInputProc) \
+        device->public.processInputProc = newproc; \
+    saveprocs->processInputProc = \
+    saveprocs->realInputProc = device->public.realInputProc; \
+    device->public.realInputProc = newproc;
+
 void
 RegisterOtherDevice(DeviceIntPtr device)
 {
@@ -159,11 +167,13 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     /* Handle core events. */
     if (xE->u.u.type < LASTEvent && xE->u.u.type != GenericEvent)
     {
+        ProcessInputProc backupproc;
         xiDevPrivatePtr xiPrivPtr = 
             (xiDevPrivatePtr)device->devPrivates[xiDevPrivateIndex].ptr;
-        UNWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr);
+        UNWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, backupproc);
         device->public.processInputProc(xE, device, count);
-        WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent);
+        /* only rewraps is the processInputProc hasn't been modified */
+        REWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, backupproc);
         return;
     }
 
commit e2cb8515661b1f7826981931d82dee6e05529f04
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 18:01:17 2007 +0930

    xfree86: pass in the XKB event processing proc instead of the XI one.
    
    We need to pass ProcessPointerEvent or ProcessKeyboardEvent to
    XkbSetExtension, otherwise we lose the xkb layer.

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 31c3008..a43230e 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -205,7 +205,7 @@ xf86ActivateDevice(LocalDevicePtr local)
 
         RegisterOtherDevice(dev);
         if (!noXkbExtension)
-            XkbSetExtension(dev, ProcessOtherEvent);
+            XkbSetExtension(dev, (DeviceIsPointerType(dev)) ? ProcessPointerEvent : ProcessKeyboardEvent);
 
         if (serverGeneration == 1) 
             xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n",
commit 27bc1a8fef2bfd3d62fb44f7c7eb0d463ed08632
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 15:24:41 2007 +0930

    xkb: XkbFilterEvents: Remove unused variable compiler warning.

diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c
index 64cddd0..37d850d 100644
--- a/xkb/xkbEvents.c
+++ b/xkb/xkbEvents.c
@@ -809,7 +809,6 @@ XkbFilterEvents(ClientPtr pClient,int nEvents,xEvent *xE)
 int	i, button_mask;
 DeviceIntPtr pXDev = (DeviceIntPtr)LookupKeyboardDevice();
 XkbSrvInfoPtr	xkbi;
-GrabInfoPtr grabinfo;
 
     xkbi= pXDev->key->xkbInfo;
     if ( pClient->xkbClientFlags & _XkbClientInitialized ) {
commit bfc89c035542a10594f5f0cbde1c7e28b7d024a7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 15:23:37 2007 +0930

    xkb: unify ErrorFs. Prefix all with [xkb].
    
    Output for XkbUseMsg intentionally skipped.

diff --git a/xkb/ddxBeep.c b/xkb/ddxBeep.c
index 331357d..2fab4ed 100644
--- a/xkb/ddxBeep.c
+++ b/xkb/ddxBeep.c
@@ -141,12 +141,12 @@ Atom		name;
     duration= oldDuration= ctrl->bell_duration;
 #ifdef DEBUG
     if (xkbDebugFlags>1)
-	ErrorF("beep: %d (count= %d)\n",xkbInfo->beepType,xkbInfo->beepCount);
+	ErrorF("[xkb] beep: %d (count= %d)\n",xkbInfo->beepType,xkbInfo->beepCount);
 #endif
     name= None;
     switch (xkbInfo->beepType) {
 	default:
-	    ErrorF("Unknown beep type %d\n",xkbInfo->beepType);
+	    ErrorF("[xkb] Unknown beep type %d\n",xkbInfo->beepType);
 	case _BEEP_NONE:
 	    duration= 0;
 	    break;
diff --git a/xkb/ddxCtrls.c b/xkb/ddxCtrls.c
index 0f7f918..73a5e03 100644
--- a/xkb/ddxCtrls.c
+++ b/xkb/ddxCtrls.c
@@ -49,7 +49,7 @@ int realRepeat;
 	ctrl->autoRepeat= 0;
 #ifdef DEBUG
 if (xkbDebugFlags&0x4) {
-    ErrorF("XkbDDXKeybdCtrlProc: setting repeat to %d (real repeat is %d)\n",
+    ErrorF("[xkb] XkbDDXKeybdCtrlProc: setting repeat to %d (real repeat is %d)\n",
 					ctrl->autoRepeat,realRepeat);
 }
 #endif
diff --git a/xkb/ddxKeyClick.c b/xkb/ddxKeyClick.c
index f48296d..10f3f38 100644
--- a/xkb/ddxKeyClick.c
+++ b/xkb/ddxKeyClick.c
@@ -44,7 +44,7 @@ XkbDDXKeyClick(DeviceIntPtr pXDev,int keycode,int synthetic)
 {
 #ifdef DEBUG
     if (xkbDebugFlags)
-	ErrorF("Click.\n");
+	ErrorF("[xkb] Click.\n");
 #endif
     return;
 }
diff --git a/xkb/ddxList.c b/xkb/ddxList.c
index a91a9ba..2baf652 100644
--- a/xkb/ddxList.c
+++ b/xkb/ddxList.c
@@ -200,10 +200,10 @@ char	tmpname[PATH_MAX];
 	in= Popen(buf,"r");
 #else
 #ifdef DEBUG_CMD
-	ErrorF("xkb executes: %s\n",buf);
+	ErrorF("[xkb] xkb executes: %s\n",buf);
 #endif
 	if (System(buf) < 0)
-	    ErrorF("Could not invoke keymap compiler\n");
+	    ErrorF("[xkb] Could not invoke keymap compiler\n");
 	else
 	    in= fopen(tmpname, "r");
 #endif
@@ -271,7 +271,7 @@ char	tmpname[PATH_MAX];
 	fclose(in);
     else if ((rval=Pclose(in))!=0) {
 	if (xkbDebugFlags)
-	    ErrorF("xkbcomp returned exit code %d\n",rval);
+	    ErrorF("[xkb] xkbcomp returned exit code %d\n",rval);
     }
 #else
     fclose(in);
diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c
index d79ae7a..a0fa606 100644
--- a/xkb/ddxLoad.c
+++ b/xkb/ddxLoad.c
@@ -134,11 +134,11 @@ Win32System(const char *cmdline)
 		    0,
 		    NULL ))
 	{
-	    ErrorF("Starting '%s' failed!\n", cmdline); 
+	    ErrorF("[xkb] Starting '%s' failed!\n", cmdline); 
 	}
 	else
 	{
-	    ErrorF("Starting '%s' failed: %s", cmdline, (char *)buffer); 
+	    ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *)buffer); 
 	    LocalFree(buffer);
 	}
 
@@ -258,12 +258,12 @@ char 	*cmd = NULL,file[PATH_MAX],xkm_output_dir[PATH_MAX],*map,*outFile;
     }
 #ifdef DEBUG
     if (xkbDebugFlags) {
-	ErrorF("XkbDDXCompileNamedKeymap compiling keymap using:\n");
-	ErrorF("    \"cmd\"\n");
+	ErrorF("[xkb] XkbDDXCompileNamedKeymap compiling keymap using:\n");
+	ErrorF("[xkb]     \"cmd\"\n");
     }
 #endif
 #ifdef DEBUG_CMD
-    ErrorF("xkb executes: %s\n",cmd);
+    ErrorF("[xkb] xkb executes: %s\n",cmd);
 #endif
     if (System(cmd)==0) {
 	if (nameRtrn) {
@@ -277,7 +277,7 @@ char 	*cmd = NULL,file[PATH_MAX],xkm_output_dir[PATH_MAX],*map,*outFile;
 	return True;
     } 
 #ifdef DEBUG
-    ErrorF("Error compiling keymap (%s)\n",names->keymap);
+    ErrorF("[xkb] Error compiling keymap (%s)\n",names->keymap);
 #endif
     if (outFile!=NULL)
 	_XkbFree(outFile);
@@ -305,7 +305,7 @@ char tmpname[PATH_MAX];
     }
     else {
 	if (strlen(names->keymap) > PATH_MAX - 1) {
-	    ErrorF("name of keymap (%s) exceeds max length\n", names->keymap);
+	    ErrorF("[xkb] name of keymap (%s) exceeds max length\n", names->keymap);
 	    return False;
 	}
 	strcpy(keymap,names->keymap);
@@ -360,7 +360,7 @@ char tmpname[PATH_MAX];
     if (out!=NULL) {
 #ifdef DEBUG
     if (xkbDebugFlags) {
-       ErrorF("XkbDDXCompileKeymapByNames compiling keymap:\n");
+       ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
        XkbWriteXKBKeymapForNames(stderr,names,NULL,xkb,want,need);
     }
 #endif
@@ -372,10 +372,10 @@ char tmpname[PATH_MAX];
 #endif
 	{
 #ifdef DEBUG_CMD
-	    ErrorF("xkb executes: %s\n",buf);
-	    ErrorF("xkbcomp input:\n");
+	    ErrorF("[xkb] xkb executes: %s\n",buf);
+	    ErrorF("[xkb] xkbcomp input:\n");
 	    XkbWriteXKBKeymapForNames(stderr,names,NULL,xkb,want,need);
-	    ErrorF("end xkbcomp input\n");
+	    ErrorF("[xkb] end xkbcomp input\n");
 #endif
 	    if (nameRtrn) {
 		strncpy(nameRtrn,keymap,nameRtrnLen);
@@ -387,7 +387,7 @@ char tmpname[PATH_MAX];
 	}
 #ifdef DEBUG
 	else
-	    ErrorF("Error compiling keymap (%s)\n",keymap);
+	    ErrorF("[xkb] Error compiling keymap (%s)\n",keymap);
 #endif
 #ifdef WIN32
         /* remove the temporary file */
@@ -397,9 +397,9 @@ char tmpname[PATH_MAX];
 #ifdef DEBUG
     else {
 #ifndef WIN32
-	ErrorF("Could not invoke keymap compiler\n");
+	ErrorF("[xkb] Could not invoke keymap compiler\n");
 #else
-	ErrorF("Could not open file %s\n", tmpname);
+	ErrorF("[xkb] Could not open file %s\n", tmpname);
 #endif
     }
 #endif
@@ -478,7 +478,7 @@ unsigned	missing;
 	}
 	else if (!XkbDDXCompileNamedKeymap(xkb,names,nameRtrn,nameRtrnLen)) {
 #ifdef NOISY
-	    ErrorF("Couldn't compile keymap file\n");
+	    ErrorF("[xkb] Couldn't compile keymap file\n");
 #endif
 	    return 0;
 	}
@@ -486,7 +486,7 @@ unsigned	missing;
     else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need,
 						nameRtrn,nameRtrnLen)){
 #ifdef NOISY
-	ErrorF("Couldn't compile keymap file\n");
+	ErrorF("[xkb] Couldn't compile keymap file\n");
 #endif
 	return 0;
     }
@@ -504,7 +504,7 @@ unsigned	missing;
     }
 #ifdef DEBUG
     else if (xkbDebugFlags) {
-	ErrorF("Loaded %s, defined=0x%x\n",fileName,finfoRtrn->defined);
+	ErrorF("[xkb] Loaded %s, defined=0x%x\n",fileName,finfoRtrn->defined);
     }
 #endif
     fclose(file);
diff --git a/xkb/xkb.c b/xkb/xkb.c
index cf42430..4f0677a 100644
--- a/xkb/xkb.c
+++ b/xkb/xkb.c
@@ -170,7 +170,7 @@ ProcXkbUseExtension(ClientPtr client)
 	client->vMinor= stuff->wantedMinor;
     }
     else if (xkbDebugFlags&0x1) {
-	ErrorF("Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
+	ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
 					client->index,
 					(long)client->clientAsMask,
 					stuff->wantedMajor,stuff->wantedMinor,
@@ -334,7 +334,7 @@ ProcXkbSelectEvents(ClientPtr client)
 	    }
 	}
 	if (dataLeft>2) {
-	    ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft);
+	    ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft);
 	    return BadLength;
 	}
 	return client->noClientException;
@@ -1339,7 +1339,7 @@ char		*desc,*start;
     if ( rep->totalVModMapKeys>0 )
 	desc= XkbWriteVirtualModMap(xkb,rep,desc,client);
     if ((desc-start)!=(len)) {
-	ErrorF("BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
+	ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
 					len, (unsigned long)(desc-start));
     }
     if (client->swapped) {
@@ -2374,7 +2374,7 @@ ProcXkbSetMap(ClientPtr client)
 	return BadValue;
     }
     if (((tmp-((char *)stuff))/4)!=stuff->length) {
-	ErrorF("Internal error! Bad length in XkbSetMap (after check)\n");
+	ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
 	client->errorValue = tmp-((char *)&stuff[1]);
 	return BadLength;
     }
@@ -2425,7 +2425,7 @@ ProcXkbSetMap(ClientPtr client)
     if (stuff->present&XkbVirtualModMapMask)
 	tmp= SetVirtualModMap(xkbi,stuff,(xkbVModMapWireDesc *)tmp,&change);
     if (((tmp-((char *)stuff))/4)!=stuff->length) {
-	ErrorF("Internal error! Bad length in XkbSetMap (after set)\n");
+	ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
 	client->errorValue = tmp-((char *)&stuff[1]);
 	return BadLength;
     }
@@ -2701,7 +2701,7 @@ ProcXkbSetCompatMap(ClientPtr client)
     }
     i= XkbPaddedSize((data-((char *)stuff)));
     if ((i/4)!=stuff->length) {
-	ErrorF("Internal length error on read in ProcXkbSetCompatMap\n");
+	ErrorF("[xkb] Internal length error on read in ProcXkbSetCompatMap\n");
 	return BadLength;
     }
     
@@ -3411,7 +3411,7 @@ register int            n;
     }
 
     if ((desc-start)!=(length)) {
-	ErrorF("BOGUS LENGTH in write names, expected %d, got %ld\n",
+	ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
 					length, (unsigned long)(desc-start));
     }
     WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep);
@@ -4102,9 +4102,9 @@ xkbDoodadWireDesc *	doodadWire;
 		wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap);
 		break;
 	    default:
-		ErrorF("Unknown doodad type %d in XkbWriteGeomDoodads\n",
+		ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
 			doodad->any.type);
-		ErrorF("Ignored\n");
+		ErrorF("[xkb] Ignored\n");
 		break;
 	}
     }
@@ -4332,7 +4332,7 @@ XkbSendGeometry(	ClientPtr		client,
 	if ( rep->nKeyAliases>0 )
 	    desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped);
 	if ((desc-start)!=(len)) {
-	    ErrorF("BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
+	    ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
 			len, (unsigned long)(desc-start));
 	}
     }
@@ -5781,8 +5781,8 @@ char *			str;
     }
     else if (length!=0)  {
 #ifdef DEBUG
-	ErrorF("Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
-	ErrorF("                 Wrote %d fewer bytes than expected\n",length);
+	ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
+	ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",length);
 #endif
 	return BadLength;
     }
@@ -6078,25 +6078,25 @@ xkbSetDebuggingFlagsReply 	rep;
     newCtrls=  xkbDebugCtrls&(~stuff->affectCtrls);
     newCtrls|= (stuff->ctrls&stuff->affectCtrls);
     if (xkbDebugFlags || newFlags || stuff->msgLength) {
-	ErrorF("XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
+	ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags);
 	if (newCtrls!=xkbDebugCtrls)
-	    ErrorF("XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
+	    ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls);
     }
     extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq;
     if (stuff->msgLength>0) {
 	char *msg;
 	if (extraLength<XkbPaddedSize(stuff->msgLength)) {
-	    ErrorF("XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
+	    ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
 			stuff->msgLength,(long)extraLength,
 			XkbPaddedSize(stuff->msgLength));
 	    return BadLength;
 	}
 	msg= (char *)&stuff[1];
 	if (msg[stuff->msgLength-1]!='\0') {
-	    ErrorF("XkbDebug: message not null-terminated\n");
+	    ErrorF("[xkb] XkbDebug: message not null-terminated\n");
 	    return BadValue;
 	}
-	ErrorF("XkbDebug: %s\n",msg);
+	ErrorF("[xkb] XkbDebug: %s\n",msg);
     }
     xkbDebugFlags = newFlags;
     xkbDebugCtrls = newCtrls;
@@ -6193,7 +6193,7 @@ XkbClientGone(pointer data,XID id)
     DevicePtr	pXDev = (DevicePtr)data;
 
     if (!XkbRemoveResourceClient(pXDev,id)) {
-	ErrorF("Internal Error! bad RemoveResourceClient in XkbClientGone\n");
+	ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
     }
     return 1;
 }
diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index 2954a0c..8e897c8 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -132,7 +132,7 @@ xEvent		xE;
     xE.u.keyButtonPointer.time = GetTimeInMillis();	    
 #ifdef DEBUG
     if (xkbDebugFlags&0x8) {
-	ErrorF("AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up"));
+	ErrorF("[xkb] AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up"));
     }
 #endif
 
@@ -530,7 +530,7 @@ KeySym *	sym = XkbKeySymsPtr(xkbi->desc,key);
 	    if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) {
 #ifdef DEBUG
 		if (xkbDebugFlags&0x10)
-		    ErrorF("Starting software autorepeat...\n");
+		    ErrorF("[xkb] Starting software autorepeat...\n");
 #endif	    
 		xkbi->repeatKey = key;
 		xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer,
diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c
index b387a8c..64cddd0 100644
--- a/xkb/xkbEvents.c
+++ b/xkb/xkbEvents.c
@@ -818,15 +818,15 @@ GrabInfoPtr grabinfo;
 		((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
                  (xE[0].u.u.type==DeviceKeyPress)||
                  (xE[0].u.u.type == DeviceKeyRelease))) {
-	    ErrorF("XKbFilterWriteEvents:\n");
-	    ErrorF("   Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
-	    ErrorF("   XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
+	    ErrorF("[xkb] XKbFilterWriteEvents:\n");
+	    ErrorF("[xkb]    Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
+	    ErrorF("[xkb]    XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
 			XkbLastRepeatEvent,xE,
 			((XkbLastRepeatEvent!=(pointer)xE)?"True":"False"));
-	    ErrorF("   (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n",
+	    ErrorF("[xkb]    (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n",
 		pClient->xkbClientFlags,
 		(_XkbWantsDetectableAutoRepeat(pClient)?"True":"False"));
-	    ErrorF("   !IsRelease(%d) %s\n",xE[0].u.u.type,
+	    ErrorF("[xkb]    !IsRelease(%d) %s\n",xE[0].u.u.type,
 			(!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False");
 	}
 #endif /* DEBUG */
@@ -872,7 +872,7 @@ GrabInfoPtr grabinfo;
 	     * when the mouse is released, the server does not behave properly.
 	     * Faking a release of the button here solves the problem.
 	     */
-	    ErrorF("Faking release of button %d\n", xE[0].u.u.detail);
+	    ErrorF("[xkb] Faking release of button %d\n", xE[0].u.u.detail);
 #endif
 	    XkbDDXFakePointerButton(ButtonRelease, xE[0].u.u.detail);
         }
@@ -888,11 +888,11 @@ GrabInfoPtr grabinfo;
                  (xE[i].u.u.type==DeviceKeyPress)||
                  (xE[i].u.u.type == DeviceKeyRelease))) {
 		XkbStatePtr s= &xkbi->state;
-		ErrorF("XKbFilterWriteEvents (non-XKB):\n");
-		ErrorF("event= 0x%04x\n",xE[i].u.keyButtonPointer.state);
-		ErrorF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods,
+		ErrorF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
+		ErrorF("[xkb] event= 0x%04x\n",xE[i].u.keyButtonPointer.state);
+		ErrorF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods,
 							s->grab_mods);
-		ErrorF("compat lookup= 0x%02x, grab= 0x%02x\n",
+		ErrorF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
 							s->compat_lookup_mods,
 							s->compat_grab_mods);
 	    }
@@ -930,14 +930,14 @@ GrabInfoPtr grabinfo;
 		((xE[i].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
 		(xkbi->lockedPtrButtons & button_mask) == button_mask) {
 #ifdef DEBUG
-		ErrorF("Faking release of button %d\n", xE[i].u.u.detail);
+		ErrorF("[xkb] Faking release of button %d\n", xE[i].u.u.detail);
 #endif
 		XkbDDXFakePointerButton(ButtonRelease, xE[i].u.u.detail);
 	    } else if (type == DeviceButtonPress &&
                     ((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask &&
                     (xkbi->lockedPtrButtons & button_mask) == button_mask) {
 #ifdef DEBUG
-		ErrorF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
+		ErrorF("[xkb] Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
 #endif
 		XkbDDXFakePointerButton(DeviceButtonRelease, ((deviceKeyButtonPointer*)&xE[i])->state);
             }
diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index c0867ad..bcfd149 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -179,12 +179,12 @@ char *			pval;
 
     name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1);
     if (name==None) {
-	ErrorF("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
+	ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM);
 	return True;
     }
     pval= (char*) ALLOCATE_LOCAL(len);
     if (!pval) {
-	ErrorF("Allocation error: %s proprerty not created\n",
+	ErrorF("[xkb] Allocation error: %s proprerty not created\n",
 						_XKB_RF_NAMES_PROP_ATOM);
 	return True;
     }
@@ -218,7 +218,7 @@ char *			pval;
     }
     pval[out++]= '\0';
     if (out!=len) {
-	ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
+	ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n",
 								out,len);
     }
     ChangeWindowProperty(WindowTable[0],name,XA_STRING,8,PropModeReplace,
@@ -511,7 +511,7 @@ XkbEventCauseRec	cause;
 	    /*                 the other here, but for now just complain */
 	    /*                 can't just update the core range without */
 	    /*                 reallocating the KeySymsRec (pain)       */
-	    ErrorF("Internal Error!! XKB and core keymap have different range\n");
+	    ErrorF("[xkb] Internal Error!! XKB and core keymap have different range\n");
 	}
 	if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success)
 	    FatalError("Couldn't allocate client map in XkbInitDevice\n");
@@ -772,7 +772,7 @@ XkbSrvLedInfoPtr	sli;
     if (sli && xkbi)
 	XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask);
 #ifdef DEBUG
-    else ErrorF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
+    else ErrorF("[xkb] No indicator feedback in XkbFinishInit (shouldn't happen)!\n");
 #endif
     return softRepeat;
 }
diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c
index ba3fcc0..212ee94 100644
--- a/xkb/xkbPrKeyEv.c
+++ b/xkb/xkbPrKeyEv.c
@@ -58,7 +58,7 @@ int             xiEvent;
     xiEvent= (xE->u.u.type & EXTENSION_EVENT_BASE);
 #ifdef DEBUG
     if (xkbDebugFlags&0x8) {
-	ErrorF("XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
+	ErrorF("[xkb] XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
     }
 #endif
 
@@ -162,7 +162,7 @@ int             xiEvent;
 		    }
 		    rg->currentDown= key;
 		}
-		else ErrorF("InternalError! Illegal radio group %d\n",ndx);
+		else ErrorF("[xkb] InternalError! Illegal radio group %d\n",ndx);
 		break;
 	    case XkbKB_Overlay1: case XkbKB_Overlay2:
 		{
@@ -182,7 +182,7 @@ int             xiEvent;
 		}
 		break;
 	    default:
-		ErrorF("unknown key behavior 0x%04x\n",behavior.type);
+		ErrorF("[xkb] unknown key behavior 0x%04x\n",behavior.type);
 		break;
 	}
     }
@@ -201,7 +201,7 @@ XkbSrvInfoPtr	xkbi;
 #ifdef DEBUG
     if (xkbDebugFlags&0x8) {
 	int key= xE->u.u.detail;
-	ErrorF("PKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
+	ErrorF("[xkb] PKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
     }
 #endif
     if ((xkbi->desc->ctrls->enabled_ctrls&XkbAllFilteredEventsMask)==0)
diff --git a/xkb/xkbSwap.c b/xkb/xkbSwap.c
index da4c905..bbb2a91 100644
--- a/xkb/xkbSwap.c
+++ b/xkb/xkbSwap.c
@@ -129,7 +129,7 @@ register int n;
 	    dataLeft-= (size*2);
 	}
 	if (dataLeft>2) {
-	    ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft);
+	    ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft);
 	    return BadLength;
 	}
     }
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index c7f9a26..e87064a 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -2010,7 +2010,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
 
     if (sendNotifies) {
         if (!pDev) {
-            ErrorF("XkbCopyKeymap: asked for notifies, but can't find device!\n");
+            ErrorF("[xkb] XkbCopyKeymap: asked for notifies, but can't find device!\n");
         }
         else {
             /* send NewKeyboardNotify if the keycode range changed, else
commit 8b508f5d6bd0d3995294d5ff300a856754442999
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 15:19:53 2007 +0930

    dix: unify ErrorFs. prepend all with [dix].

diff --git a/dix/access.c b/dix/access.c
index 2015716..e7d39b4 100644
--- a/dix/access.c
+++ b/dix/access.c
@@ -143,7 +143,7 @@ ACChangeWindowAccess(ClientPtr client,
 
     if (!win->optional && !MakeWindowOptional(win))
     {
-        ErrorF("ACChangeWindowAcccess: Failed to make window optional.\n");
+        ErrorF("[dix] ACChangeWindowAcccess: Failed to make window optional.\n");
         return BadImplementation;
     }
 
@@ -183,7 +183,7 @@ acReplaceList(DeviceIntPtr** list,
             xalloc(ndevices * sizeof(DeviceIntPtr*));
         if (!*list)
         {
-            ErrorF("ACChangeWindowAccess: out of memory\n");
+            ErrorF("[dix] ACChangeWindowAccess: out of memory\n");
             return;
         }
         memcpy(*list,
@@ -223,7 +223,7 @@ ACQueryWindowAccess(WindowPtr win,
         *perm = (DeviceIntPtr*)xalloc(*nperm * sizeof(DeviceIntPtr));
         if (!*perm)
         {
-            ErrorF("ACQuerywinAccess: xalloc failure\n");
+            ErrorF("[dix] ACQuerywinAccess: xalloc failure\n");
             return;
         }
         memcpy(*perm, 
@@ -237,7 +237,7 @@ ACQueryWindowAccess(WindowPtr win,
         *deny = (DeviceIntPtr*)xalloc(*ndeny * sizeof(DeviceIntPtr));
         if (!*deny)
         {
-            ErrorF("ACQuerywinAccess: xalloc failure\n");
+            ErrorF("[dix] ACQuerywinAccess: xalloc failure\n");
             return;
         }
         memcpy(*deny, 
diff --git a/dix/devices.c b/dix/devices.c
index 3ce045c..63d7ea4 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -220,7 +220,7 @@ EnableDevice(DeviceIntPtr dev)
 
     if ((*prev != dev) || !dev->inited ||
 	((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
-        ErrorF("couldn't enable device %d\n", dev->id);
+        ErrorF("[dix] couldn't enable device %d\n", dev->id);
 	return FALSE;
     }
     dev->enabled = TRUE;
@@ -357,13 +357,13 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
                                          keySyms.minKeyCode + 1) *
                                         keySyms.mapWidth);
         if (!keySyms.map) {
-            ErrorF("Couldn't allocate core keymap\n");
+            ErrorF("[dix] Couldn't allocate core keymap\n");
             return BadAlloc;
         }
 
         modMap = (CARD8 *)xalloc(MAP_LENGTH);
         if (!modMap) {
-            ErrorF("Couldn't allocate core modifier map\n");
+            ErrorF("[dix] Couldn't allocate core modifier map\n");
             return BadAlloc;
         }
         bzero((char *)modMap, MAP_LENGTH);
@@ -529,11 +529,11 @@ InitAndStartDevices(WindowPtr root)
     }
 
     if (!inputInfo.keyboard) {
-	ErrorF("No core keyboard\n");
+	ErrorF("[dix] No core keyboard\n");
 	return BadImplementation;
     }
     if (!inputInfo.pointer) {
-	ErrorF("No core pointer\n");
+	ErrorF("[dix] No core pointer\n");
 	return BadImplementation;
     }
 
diff --git a/dix/dixfonts.c b/dix/dixfonts.c
index c21b3ec..9d3bf08 100644
--- a/dix/dixfonts.c
+++ b/dix/dixfonts.c
@@ -378,7 +378,7 @@ OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontna
     f = (char *)xalloc(lenfname + 1);
     memmove(f, pfontname, lenfname);
     f[lenfname] = '\0';
-    ErrorF("OpenFont: fontname is \"%s\"\n", f);
+    ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f);
     xfree(f);
 #endif
     if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
@@ -1628,7 +1628,7 @@ FreeFontPath(FontPathElementPtr *list, int n, Bool force)
 		    found++;
 	    }
 	    if (list[i]->refcount != found) {
-		ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n",
+		ErrorF("[dix] FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n",
 		       list[i]->name_length, list[i]->name,
 		       list[i]->refcount, found);
 		list[i]->refcount = found; /* ensure it will get freed */
@@ -1680,7 +1680,7 @@ SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
 	if (len == 0) 
 	{
 	    if (persist)
-		ErrorF ("Removing empty element from the valid list of fontpaths\n");
+		ErrorF("[dix] Removing empty element from the valid list of fontpaths\n");
 	    err = BadValue;
 	}
 	else
@@ -1732,7 +1732,7 @@ SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
 		{
 		    if (persist)
 		    {
-			ErrorF("Could not init font path element %s, removing from list!\n",
+			ErrorF("[dix] Could not init font path element %s, removing from list!\n",
 			       fpe->name);
 		    }
 		    xfree (fpe->name);
diff --git a/dix/dixutils.c b/dix/dixutils.c
index c1e30ff..dc4e08c 100644
--- a/dix/dixutils.c
+++ b/dix/dixutils.c
@@ -288,7 +288,7 @@ SecurityLookupWindow(XID id, ClientPtr client, Mask access_mode)
     int i = dixLookupWindow(&pWin, id, client, access_mode);
     static int warn = 1;
     if (warn-- > 0)
-	ErrorF("Warning: LookupWindow()/SecurityLookupWindow() "
+	ErrorF("[dix] Warning: LookupWindow()/SecurityLookupWindow() "
 	       "are deprecated.  Please convert your driver/module "
 	       "to use dixLookupWindow().\n");
     return (i == Success) ? pWin : NULL;
@@ -307,7 +307,7 @@ SecurityLookupDrawable(XID id, ClientPtr client, Mask access_mode)
     int i = dixLookupDrawable(&pDraw, id, client, M_DRAWABLE, access_mode);
     static int warn = 1;
     if (warn-- > 0)
-	ErrorF("Warning: LookupDrawable()/SecurityLookupDrawable() "
+	ErrorF("[dix] Warning: LookupDrawable()/SecurityLookupDrawable() "
 	       "are deprecated.  Please convert your driver/module "
 	       "to use dixLookupDrawable().\n");
     return (i == Success) ? pDraw : NULL;
@@ -326,7 +326,7 @@ LookupClient(XID id, ClientPtr client)
     int i = dixLookupClient(&pClient, id, client, DixUnknownAccess);
     static int warn = 1;
     if (warn-- > 0)
-	ErrorF("Warning: LookupClient() is deprecated.  Please convert your "
+	ErrorF("[dix] Warning: LookupClient() is deprecated.  Please convert your "
 	       "driver/module to use dixLookupClient().\n");
     return (i == Success) ? pClient : NULL;
 }
diff --git a/dix/events.c b/dix/events.c
index 7d69ca5..b396b65 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1887,7 +1887,7 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
     int type;
 
 #ifdef DEBUG_EVENTS
-    ErrorF("Event([%d, %d], mask=0x%x), client=%d",
+    ErrorF("[dix] Event([%d, %d], mask=0x%x), client=%d",
 	pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
 #endif
     if ((client) && (client != serverClient) && (!client->clientGone) &&
@@ -1904,8 +1904,8 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
 		    pEvents->u.keyButtonPointer.event)
 		{
 #ifdef DEBUG_EVENTS
-		    ErrorF("\n");
-	    ErrorF("motionHintWindow == keyButtonPointer.event\n");
+		    ErrorF("[dix] \n");
+	    ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
 #endif
 		    return 1; /* don't send, but pretend we did */
 		}
@@ -1944,14 +1944,14 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
 
 	WriteEventsToClient(client, count, pEvents);
 #ifdef DEBUG_EVENTS
-	ErrorF(  " delivered\n");
+	ErrorF("[dix]  delivered\n");
 #endif
 	return 1;
     }
     else
     {
 #ifdef DEBUG_EVENTS
-	ErrorF("\n");
+	ErrorF("[dix] \n");
 #endif
 	return 0;
     }
@@ -2031,7 +2031,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
             /* 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");
+                ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
                 return 0;
             }
 
@@ -2355,7 +2355,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
 
             if (count > 1)
             {
-                ErrorF("Do not send more than one GenericEvent at a time!\n");
+                ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
                 return 0;
             }
             filter = generic_filters[GEEXTIDX(xE)][ge->evtype];
@@ -5942,7 +5942,7 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
     {
         if (events[i].u.u.type == GenericEvent)
         {
-            ErrorF("TryClientEvents: Only one GenericEvent at a time.");
+            ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
             return; 
         }
     }
@@ -6028,7 +6028,7 @@ PickPointer(ClientPtr client)
 
         if (!it)
         {
-            ErrorF("Picking VCP\n");
+            ErrorF("[dix] Picking VCP\n");
             return inputInfo.pointer;
         }
     }
diff --git a/dix/main.c b/dix/main.c
index 5d24922..d78d7e8 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -402,7 +402,7 @@ main(int argc, char *argv[], char *envp[])
 	}
         else {
 	    if (SetDefaultFontPath(defaultFontPath) != Success)
-		ErrorF("failed to set default font path '%s'",
+		ErrorF("[dix] failed to set default font path '%s'",
 			defaultFontPath);
 	}
 	if (!SetDefaultFont(defaultTextFont)) {
diff --git a/dix/property.c b/dix/property.c
index e281dd7..6768100 100644
--- a/dix/property.c
+++ b/dix/property.c
@@ -81,11 +81,11 @@ PrintPropertys(WindowPtr pWin)
     pProp = pWin->userProps;
     while (pProp)
     {
-        ErrorF(  "%x %x\n", pProp->propertyName, pProp->type);
-        ErrorF("property format: %d\n", pProp->format);
-        ErrorF("property data: \n");
+        ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type);
+        ErrorF("[dix] property format: %d\n", pProp->format);
+        ErrorF("[dix] property data: \n");
         for (j=0; j<(pProp->format/8)*pProp->size; j++)
-           ErrorF("%c\n", pProp->data[j]);
+           ErrorF("[dix] %c\n", pProp->data[j]);
         pProp = pProp->next;
     }
 }
diff --git a/dix/resource.c b/dix/resource.c
index e83c529..e5bc900 100644
--- a/dix/resource.c
+++ b/dix/resource.c
@@ -468,7 +468,7 @@ AddResource(XID id, RESTYPE type, pointer value)
     rrec = &clientTable[client];
     if (!rrec->buckets)
     {
-	ErrorF("AddResource(%lx, %lx, %lx), client=%d \n",
+	ErrorF("[dix] AddResource(%lx, %lx, %lx), client=%d \n",
 		(unsigned long)id, type, (unsigned long)value, client);
         FatalError("client not in use\n");
     }
@@ -589,7 +589,7 @@ FreeResource(XID id, RESTYPE skipDeleteFuncType)
 	}
     }
     if (!gotOne)
-	ErrorF("Freeing resource id=%lX which isn't there.\n",
+	ErrorF("[dix] Freeing resource id=%lX which isn't there.\n",
 		   (unsigned long)id);
 }
 
diff --git a/dix/window.c b/dix/window.c
index 3247446..f296d34 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -206,8 +206,9 @@ PrintChildren(WindowPtr p1, int indent)
     while (p1)
     {
 	p2 = p1->firstChild;
-	for (i=0; i<indent; i++) ErrorF( " ");
-	ErrorF( "%lx\n", p1->drawable.id);
+        ErrorF("[dix] ");
+	for (i=0; i<indent; i++) ErrorF(" ");
+	ErrorF("%lx\n", p1->drawable.id);
 	miPrintRegion(&p1->clipList);
 	PrintChildren(p2, indent+4);
 	p1 = p1->nextSib;
@@ -222,7 +223,7 @@ PrintWindowTree(void)
 
     for (i=0; i<screenInfo.numScreens; i++)
     {
-	ErrorF( "WINDOW %d\n", i);
+	ErrorF("[dix] WINDOW %d\n", i);
 	pWin = WindowTable[i];
 	miPrintRegion(&pWin->clipList);
 	p1 = pWin->firstChild;
@@ -2232,7 +2233,7 @@ WhereDoIGoInTheStack(
 	    return pWin->nextSib;
       default:
       {
-	ErrorF("Internal error in ConfigureWindow, smode == %d\n",smode );
+	ErrorF("[dix] Internal error in ConfigureWindow, smode == %d\n",smode );
 	return pWin->nextSib;
       }
     }
commit 394f3c1dbee7270a1d930846d49278424c3072d4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 15:19:37 2007 +0930

    dix: GetPointerEvents: remove unused variable compiler warning.

diff --git a/dix/getevents.c b/dix/getevents.c
index 12ddc82..df1dc6a 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -550,7 +550,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     /* Thanks to a broken lib, we _always_ have to chase DeviceMotionNotifies
      * with DeviceValuators. */
     Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
-    DeviceIntPtr pointer = NULL;
     int x = 0, y = 0;
     /* The core pointer must not send Xi events. */
     Bool coreOnly = (pDev == inputInfo.pointer);
commit 55fd50273ea67eb99a0c8a830349851931298387
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 15:15:34 2007 +0930

    Xi: unify ErrorFs. Prefix all with [Xi].

diff --git a/Xi/chaccess.c b/Xi/chaccess.c
index f099206..2a0e5fa 100644
--- a/Xi/chaccess.c
+++ b/Xi/chaccess.c
@@ -110,7 +110,7 @@ ProcXChangeWindowAccess(ClientPtr client)
             (DeviceIntPtr*)xalloc(stuff->npermit * sizeof(DeviceIntPtr));
         if (!perm_devices)
         {
-            ErrorF("ProcXChangeWindowAccess: alloc failure.\n");
+            ErrorF("[Xi] ProcXChangeWindowAccess: alloc failure.\n");
             SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, 
                     BadImplementation);
             return Success;
@@ -136,7 +136,7 @@ ProcXChangeWindowAccess(ClientPtr client)
             (DeviceIntPtr*)xalloc(stuff->ndeny * sizeof(DeviceIntPtr));
         if (!deny_devices)
         {
-            ErrorF("ProcXChangeWindowAccecss: alloc failure.\n");
+            ErrorF("[Xi] ProcXChangeWindowAccecss: alloc failure.\n");
             SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, 
                     BadImplementation);
 
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 1d23809..c1b6eed 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -891,7 +891,7 @@ FixExtensionEvents(ExtensionEntry * extEntry)
     {
         /* This should never happen, but if it does, hide under the
          * bed and cry for help. */
-        ErrorF("DeviceButtonMotionMask != ButtonMotionMask. Trouble!\n");
+        ErrorF("[Xi] DeviceButtonMotionMask != ButtonMotionMask. Trouble!\n");
     }
 
     DeviceFocusChangeMask = GetNextExtEventMask();
diff --git a/Xi/qryacces.c b/Xi/qryacces.c
index b596969..95f2dd0 100644
--- a/Xi/qryacces.c
+++ b/Xi/qryacces.c
@@ -99,7 +99,7 @@ ProcXQueryWindowAccess(ClientPtr client)
         deviceids = (XID*)xalloc((nperm + ndeny) * sizeof(XID));
         if (!deviceids)
         {
-            ErrorF("ProcXQueryWindowAccess: xalloc failure.\n");
+            ErrorF("[Xi] ProcXQueryWindowAccess: xalloc failure.\n");
             SendErrorToClient(client, IReqCode, X_QueryWindowAccess, 
                     0, BadImplementation); 
             return Success;
commit 340911d7243a7f1095d79b5b2dcfa81b145c2474
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 15:12:49 2007 +0930

    Wrap core event handling through ProcessOtherEvents.
    
    When processing events from the EQ, _always_ call the processInputProc of the
    matching device. For XI devices, this proc is wrapped in three layers.
    Core event handling is wrapped by XI event handling, which is wrapped by XKB.
    A core event now passes through XKB -> XI -> DIX.
    
    This gets rid of a sync'd grab problem: with the previous code, core events
    did disappear during a sync'd device grab on account of mieqProcessInputEvents
    calling the processInputProc of the VCP/VCK instead of the actual device. This
    lead to the event being processed as normal instead of being enqueued for
    later replaying.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index aa2b4c9..2baaa58 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -89,26 +89,56 @@ Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
 static Bool MakeInputMasks(WindowPtr	/* pWin */
     );
 
+static int xiDevPrivateIndex = 0;
+static int _xiServerGeneration = -1;
+
+typedef struct {
+    ProcessInputProc processInputProc;
+    ProcessInputProc realInputProc;
+} xiDevPrivateRec, *xiDevPrivatePtr;
+
 /**************************************************************************
  *
  * Procedures for extension device event routing.
  *
  */
 
+#define WRAP_PROCESS_INPUT_PROC(device, saveprocs, newproc) \
+    saveprocs->processInputProc = device->public.processInputProc; \
+    saveprocs->realInputProc = device->public.realInputProc; \
+    device->public.processInputProc = newproc; \
+    device->public.realInputProc = newproc;
+
+#define UNWRAP_PROCESS_INPUT_PROC(device, saveprocs) \
+    device->public.processInputProc = saveprocs->processInputProc; \
+    device->public.realInputProc = saveprocs->realInputProc; 
+
 void
 RegisterOtherDevice(DeviceIntPtr device)
 {
-    device->public.processInputProc = ProcessOtherEvent;
-    device->public.realInputProc = ProcessOtherEvent;
-    if (DeviceIsPointerType(device))
-    {
-        (device)->deviceGrab.ActivateGrab = ActivatePointerGrab;
-        (device)->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
-    } else 
+    xiDevPrivatePtr xiPrivPtr;
+
+    if (serverGeneration != _xiServerGeneration)
     {
-        (device)->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
-        (device)->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
+        xiDevPrivateIndex = AllocateDevicePrivateIndex();
+        if (xiDevPrivateIndex == 1)
+        {
+            FatalError("[Xi] Could not allocate private index.\n"); 
+        }
+        _xiServerGeneration = serverGeneration;
     }
+
+    if (!AllocateDevicePrivate(device, xiDevPrivateIndex))
+        FatalError("[Xi] Dev private allocation failed.\n");
+
+
+    xiPrivPtr = (xiDevPrivatePtr)xcalloc(1, sizeof(xiDevPrivateRec));
+    if (!xiPrivPtr)
+        FatalError("[Xi] Cannot get memory for dev private.\n");
+
+    device->devPrivates[xiDevPrivateIndex].ptr = xiPrivPtr;
+
+    WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent);
 }
 
  /*ARGSUSED*/ void
@@ -126,6 +156,17 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     ValuatorClassPtr v = device->valuator;
     deviceValuator *xV = (deviceValuator *) xE;
 
+    /* Handle core events. */
+    if (xE->u.u.type < LASTEvent && xE->u.u.type != GenericEvent)
+    {
+        xiDevPrivatePtr xiPrivPtr = 
+            (xiDevPrivatePtr)device->devPrivates[xiDevPrivateIndex].ptr;
+        UNWRAP_PROCESS_INPUT_PROC(device, xiPrivPtr);
+        device->public.processInputProc(xE, device, count);
+        WRAP_PROCESS_INPUT_PROC(device, xiPrivPtr, ProcessOtherEvent);
+        return;
+    }
+
     CheckMotion(xE, device);
 
     if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 2436231..31c3008 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -179,15 +179,33 @@ xf86ActivateDevice(LocalDevicePtr local)
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE; 
         dev->spriteInfo->spriteOwner = !(local->flags & XI86_SHARED_POINTER);
 
-        RegisterOtherDevice(dev);
-
+        if (DeviceIsPointerType(dev))
+        {
 #ifdef XKB
-        if (!DeviceIsPointerType(dev) && !noXkbExtension)
+            dev->public.processInputProc = CoreProcessPointerEvent;
+            dev->public.realInputProc = CoreProcessPointerEvent;
+#else
+            dev->public.processInputProc = ProcessPointerEvent;
+            dev->public.realInputProc = ProcessPointerEvent;
+#endif
+            dev->deviceGrab.ActivateGrab = ActivatePointerGrab;
+            dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
+        } else 
         {
-            XkbSetExtension(dev, ProcessKeyboardEvent);
-        }
+#ifdef XKB
+            dev->public.processInputProc = CoreProcessKeyboardEvent;
+            dev->public.realInputProc = CoreProcessKeyboardEvent;
+#else
+            dev->public.processInputProc = ProcessKeyboardEvent;
+            dev->public.realInputProc = ProcessKeyboardEvent;
 #endif
+            dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
+            dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
+        }
 
+        RegisterOtherDevice(dev);
+        if (!noXkbExtension)
+            XkbSetExtension(dev, ProcessOtherEvent);
 
         if (serverGeneration == 1) 
             xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n",
diff --git a/mi/mieq.c b/mi/mieq.c
index c3f63fb..78e57ad 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -232,7 +232,6 @@ mieqProcessInputEvents(void)
 {
     EventRec *e = NULL;
     int x = 0, y = 0;
-    DeviceIntPtr dev = NULL;
     xEvent* event;
 
     while (miEventQueue.head != miEventQueue.tail) {
@@ -262,7 +261,8 @@ mieqProcessInputEvents(void)
             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->events->event,
+                                                      e->pDev,
                                                       e->nevents);
                 return;
             }
@@ -272,17 +272,7 @@ mieqProcessInputEvents(void)
             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->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
@@ -303,11 +293,7 @@ mieqProcessInputEvents(void)
                 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(event, e->pDev, e->nevents);
+            e->pDev->public.processInputProc(event, e->pDev, e->nevents);
 
             if (e->nevents > 1)
                 xfree(event);
commit b2a4883bd89d406713d4f808e72721ecc1456d67
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 26 09:20:11 2007 +0930

    dix: add comments to PlayReleasedEvents()
    
    Also stick another warning in, more changes needed for XGE if panoramix is
    active.

diff --git a/dix/events.c b/dix/events.c
index f5b0f00..7d69ca5 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1241,6 +1241,15 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
     *syncEvents.pendtail = qe;
 }
 
+/**
+ * Run through the list of events queued up in syncEvents.
+ * For each event do: 
+ * If the device for this event is not frozen anymore, take it and process it
+ * as usually. 
+ * After that, check if there's any devices in the list that are not frozen.
+ * If there is none, we're done. If there is at least one device that is not
+ * frozen, then re-run from the beginning of the event queue.
+ */
 static void
 PlayReleasedEvents(void)
 {
@@ -1276,6 +1285,7 @@ PlayReleasedEvents(void)
 	   /* Translate back to the sprite screen since processInputProc
 	      will translate from sprite screen to screen 0 upon reentry
 	      to the DIX layer */
+            /* XXX: we can't do that for generic events */
 	    if(!noPanoramiXExtension) {
 		qe->event->u.keyButtonPointer.rootX += 
 			panoramiXdataPtr[0].x - 
commit 275dc77c2972147407584323b866b8acc1654ea0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Sep 25 21:40:08 2007 +0930

    dix: add comments to ComputeFreezes() and syncEvents struct.

diff --git a/dix/events.c b/dix/events.c
index aab5352..f5b0f00 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -263,6 +263,24 @@ static int DontPropagateRefCnts[DNPMCOUNT];
  */
 _X_EXPORT InputInfo inputInfo;
 
+/**
+ * syncEvents is the global structure for queued events.
+ * Devices can be frozen through GrabModeSync pointer grabs. If this is the
+ * case, events from these devices are added to "pending" instead of being
+ * processed normally. When the device is unfrozen, events in "pending" are
+ * replayed and processed as if they would come from the device directly.
+ *
+ * pending ... list of queued events
+ * pendtail ... last event in list
+ * replayDev ... The device to replay events for. Only set in AllowEvents, in
+ *               which case it is set to the device specified in the request.
+ * replayWin ... the window the events are supposed to be replayed on. This
+ *               window may be set to the grab's window (but only when
+ *               Replay{Pointer|Keyboard} is given in the XAllowEvents
+ *               request.
+ * playingEvents ... flag to indicate whether we're in the process of
+ *                   replaying events. Only set in ComputeFreezes().
+ */
 static struct {
     QdEventPtr		pending, *pendtail;
     DeviceIntPtr	replayDev;	/* kludgy rock to put flag for */
@@ -1430,6 +1448,9 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
 	     CLIENT_BITS(grab->resource)))
 	    thisDev->deviceGrab.sync.other = NullGrab;
     }
+    /* XXX: other should only work on the paired keyboard, not on all other
+       devices 
+     */
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
 	if (dev != thisDev)
commit 5d9f6cf51becdeb1d2be9bdeec4bb5d0c4dd0e8b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 13 23:33:07 2007 +0930

    dix: cosmetic change. Remove "pointer" variable, might as well use pDev.

diff --git a/dix/getevents.c b/dix/getevents.c
index e88c56c..12ddc82 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -619,7 +619,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         *valptr = valuators[i];
 
     events++;
-    pointer = pDev;
 
     /* Set x and y based on whether this is absolute or relative, and
      * accelerate if we need to. */
@@ -628,14 +627,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
             x = valuators[0];
         }
         else {
-            x = pointer->valuator->lastx;
+            x = pDev->valuator->lastx;
         }
 
         if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
             y = valuators[1 - first_valuator];
         }
         else {
-            y = pointer->valuator->lasty;
+            y = pDev->valuator->lasty;
         }
     }
     else {
@@ -644,14 +643,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
                               valuators);
 
         if (first_valuator == 0 && num_valuators >= 1)
-            x = pointer->valuator->lastx + valuators[0];
+            x = pDev->valuator->lastx + valuators[0];
         else
-            x = pointer->valuator->lastx;
+            x = pDev->valuator->lastx;
 
         if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-            y = pointer->valuator->lasty + valuators[1 - first_valuator];
+            y = pDev->valuator->lasty + valuators[1 - first_valuator];
         else
-            y = pointer->valuator->lasty;
+            y = pDev->valuator->lasty;
     }
 
     /* Clip both x and y to the defined limits (usually co-ord space limit). */
commit c4db4d1fcf7fa2ba802a208beee6b3adc83921f5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 13 23:27:07 2007 +0930

    include: remove register keywords.

diff --git a/include/cursor.h b/include/cursor.h
index e51394c..ef81afc 100644
--- a/include/cursor.h
+++ b/include/cursor.h
@@ -119,7 +119,7 @@ extern CursorPtr CreateRootCursor(
 extern int ServerBitsFromGlyph(
     FontPtr /*pfont*/,
     unsigned int /*ch*/,
-    register CursorMetricPtr /*cm*/,
+    CursorMetricPtr /*cm*/,
     unsigned char ** /*ppbits*/);
 
 extern Bool CursorMetricsFromGlyph(
diff --git a/include/dix.h b/include/dix.h
index 5caa6e2..bec19dd 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -61,7 +61,7 @@ SOFTWARE.
 
 #define NullClient ((ClientPtr) 0)
 #define REQUEST(type) \
-	register type *stuff = (type *)client->requestBuffer
+	type *stuff = (type *)client->requestBuffer
 
 
 #define REQUEST_SIZE_MATCH(req)\
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index e220f0a..a4f15f0 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -737,14 +737,14 @@ extern void AccessXInit(
 );
 
 extern Bool AccessXFilterPressEvent(
-    register struct _xEvent *	/* xE */,
-    register DeviceIntPtr	/* keybd */,
+    struct _xEvent *	/* xE */,
+    DeviceIntPtr	/* keybd */,
     int				/* count */
 );
 
 extern Bool AccessXFilterReleaseEvent(
-    register struct _xEvent *	/* xE */,
-    register DeviceIntPtr	/* keybd */,
+    struct _xEvent *	/* xE */,
+    DeviceIntPtr	/* keybd */,
     int				/* count */
 );
 
commit 1c25c46f3d5f98be8dbf36684aad4302b220e163
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 13 23:22:27 2007 +0930

    dix: fix compiler warnings about unused variables.

diff --git a/dix/events.c b/dix/events.c
index 3d833ef..aab5352 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -777,8 +777,9 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
     BoxRec box;
     int x = *px, y = *py;
     int incx = 1, incy = 1;
-    SpritePtr pSprite = pDev->spriteInfo->sprite;
+    SpritePtr pSprite; 
 
+    pSprite = pDev->spriteInfo->sprite;
     if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box))
 	return;
     box = *REGION_EXTENTS(pSprite->hot.pScreen, shape);
@@ -3488,16 +3489,14 @@ ProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
 #endif
 {
     int             key, bit;
-    BYTE   *kptr;
-    int    i;
-    CARD8  modifiers;
-    CARD16 mask;
+    BYTE            *kptr;
+    CARD8           modifiers;
     GrabPtr         grab;
     GrabInfoPtr     grabinfo;
     Bool            deactivateGrab = FALSE;
-    KeyClassPtr keyc = keybd->key;
+    KeyClassPtr     keyc = keybd->key;
 #ifdef XEVIE
-    static Window           rootWin = 0;
+    static Window   rootWin = 0;
 
     if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] &&
           (xevieMask & xevieFilters[xE->u.u.type])) {
commit 68e0c4988e359e3c9da933946bc703cf8530bdbc
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 12 20:48:48 2007 +0930

    dix: fix "possible use of uninitialized variable" warning.
    
    The device passed through to UnrealizeCursor isn't used anyway, so setting it
    to NULL is enough.

diff --git a/dix/cursor.c b/dix/cursor.c
index 917dc69..5f48c83 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -115,7 +115,7 @@ FreeCursor(pointer value, XID cid)
     CursorPtr 	pCurs = (CursorPtr)value;
 
     ScreenPtr	pscr;
-    DeviceIntPtr pDev; 
+    DeviceIntPtr pDev = NULL; /* unused anyway */
 
     if ( --pCurs->refcnt != 0)
 	return(Success);
commit b484451eab261a919fe94c0c0f56877f7571fc9e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 12 18:34:51 2007 +0930

    dix: don't try to access "time" field for GenericEvents in PlayReleasedEvent.
    
    GenericEvents can't be parsed to keyButtonPointer, and there's no guarantee
    that it has a time field anyway. PlayReleasedEvent needs to store the millis
    when we know it (core events, XI event) and just re-use them for GenericEvents.
    
    Yes, this is a hack. But it looks like the time has zero significance anyway.

diff --git a/dix/events.c b/dix/events.c
index f13d542..3d833ef 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1228,6 +1228,7 @@ PlayReleasedEvents(void)
     QdEventPtr *prev, qe;
     DeviceIntPtr dev;
     DeviceIntPtr pDev;
+    static CARD32 lastKnownMillis = 0; /* Hack, see comment below */
 
     prev = &syncEvents.pending;
     while ( (qe = *prev) )
@@ -1241,7 +1242,17 @@ PlayReleasedEvents(void)
 	    if (qe->event->u.u.type == MotionNotify)
 		CheckVirtualMotion(pDev, qe, NullWindow);
 	    syncEvents.time.months = qe->months;
-	    syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
+            /* XXX: Hack! We can't reliably get the time from GenericEvents,
+               since we don't know which struct it may be. So we store the time
+               when we know it, and re-use it when we can't get it. */
+            if (qe->event->u.u.type == GenericEvent)
+            {
+                syncEvents.time.milliseconds = lastKnownMillis;
+            } else
+            {
+                syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
+                lastKnownMillis = syncEvents.time.milliseconds;
+            }
 #ifdef PANORAMIX
 	   /* Translate back to the sprite screen since processInputProc
 	      will translate from sprite screen to screen 0 upon reentry
commit 1c38eac442a3ab9e8469e944f382251957996c5a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 12 18:09:57 2007 +0930

    dix: fix comment for DeliverDeviceEvents.
    
    DDE is not always called, grabbed or focused devices go through
    Deliver{Grabbed|Focus}Event first.
    
    Thanks to Eamon Walsh for spotting it.

diff --git a/dix/events.c b/dix/events.c
index 8dfea6a..f13d542 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2246,9 +2246,14 @@ FixUpEventFromWindow(
 }
 
 /**
- * Deliver events caused by input devices. Called for all core input events
- * and XI events. No filtering of events happens before DeliverDeviceEvents(),
- * it will be called for any event that comes out of the event queue.
+ * Deliver events caused by input devices. Called for both core input events
+ * and XI events. 
+ * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
+ * called directly from the processInputProc.
+ * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
+ * DeliverDeviceEvents.
+ * For focused events, DeliverFocusedEvent is called first, and _may_ call
+ * DeliverDeviceEvents.
  *
  * @param pWin Window to deliver event to.
  * @param xE Events to deliver.
@@ -2257,6 +2262,8 @@ FixUpEventFromWindow(
  * @param dev The device that is responsible for the event.
  * @param count number of events in xE.
  *
+ * @see DeliverGrabbedEvent
+ * @see DeliverFocusedEvent
  */
 int
 DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, 
commit 06188ce90d2a8146140773f9367f23404b464282
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 12 18:00:03 2007 +0930

    dix: Make EnqueueEvent aware of GenericEvents.
    
    GenericEvents can be > sizeof(xEvents), so we need to make sure we're
    allocating and copying enough memory for the event.

diff --git a/dix/events.c b/dix/events.c
index 87cf7b0..8dfea6a 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1125,13 +1125,19 @@ NoticeEventTime(xEvent *xE)
  *            The following procedures deal with synchronous events       *
  **************************************************************************/
 
+/**
+ * EnqueueEvent is a device's processInputProc if a device is frozen. 
+ * Instead of delivering the events to the client, the event is tacked onto a
+ * linked list for later delivery.
+ */
 void
 EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 {
-    QdEventPtr tail = *syncEvents.pendtail;
-    QdEventPtr qe;
-    xEvent		*qxE;
-    SpritePtr pSprite = device->spriteInfo->sprite;
+    QdEventPtr 	tail = *syncEvents.pendtail;
+    QdEventPtr 	qe;
+    SpritePtr 	pSprite = device->spriteInfo->sprite;
+    int		eventlen;
+
 
     NoticeTime(xE);
 
@@ -1186,7 +1192,12 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 	    return;
 	}
     }
-    qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent)));
+
+    eventlen = count * sizeof(xEvent);
+    if (xE->u.u.type == GenericEvent) /* count is 1 for GenericEvents */
+	eventlen += ((xGenericEvent*)xE)->length * 4;
+
+    qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + eventlen);
     if (!qe)
 	return;
     qe->next = (QdEventPtr)NULL;
@@ -1195,8 +1206,17 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
     qe->months = currentTime.months;
     qe->event = (xEvent *)(qe + 1);
     qe->evcount = count;
-    for (qxE = qe->event; --count >= 0; qxE++, xE++)
-	*qxE = *xE;
+    if (xE->u.u.type == GenericEvent)
+    {
+	memcpy(qe->event, xE, eventlen);
+    } else
+    {
+	xEvent	*qxE;
+	for (qxE = qe->event; --count >= 0; qxE++, xE++)
+	{
+	    *qxE = *xE;
+	}
+    }
     if (tail)
 	syncEvents.pendtail = &tail->next;
     *syncEvents.pendtail = qe;
commit 8840829ab93c4eb62eb58753c015da5307133fe5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 12 17:40:11 2007 +0930

    dix: don't compress motion events from different devices (EventEnqueue)

diff --git a/dix/events.c b/dix/events.c
index ad9ec1c..87cf7b0 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1173,9 +1173,10 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 #endif
 	pSprite->hotPhys.x = XE_KBPTR.rootX;
 	pSprite->hotPhys.y = XE_KBPTR.rootY;
-	/* do motion compression */
+	/* do motion compression, but not if from different devices */
 	if (tail &&
 	    (tail->event->u.u.type == MotionNotify) &&
+            (tail->device == device) &&
 	    (tail->pScreen == pSprite->hotPhys.pScreen))
 	{
 	    tail->event->u.keyButtonPointer.rootX = pSprite->hotPhys.x;
commit 12a18cc8903fac53c3c77b23dd8093187594a4f3
Author: David Nolden <david.nolden.git at art-master.de>
Date:   Fri Sep 14 22:42:19 2007 +0200

    compilation-fix in debug mode

diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c
index 22ca2d6..b387a8c 100644
--- a/xkb/xkbEvents.c
+++ b/xkb/xkbEvents.c
@@ -937,7 +937,7 @@ GrabInfoPtr grabinfo;
                     ((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask &&
                     (xkbi->lockedPtrButtons & button_mask) == button_mask) {
 #ifdef DEBUG
-		ErrorF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state)
+		ErrorF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
 #endif
 		XkbDDXFakePointerButton(DeviceButtonRelease, ((deviceKeyButtonPointer*)&xE[i])->state);
             }
commit 72b347e681f5667b68257822e7cec02ab4c9cb6d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Sep 7 14:31:19 2007 +0930

    dix: Enabling devices must not overwrite existing sprites/pairing.
    
    EnableDevices is (amongst others )called after a VT switch. We must not create
    a new sprite or re-pair the device, otherwise we lose the input device setup
    that we had before the VT switch.
    
    This requires the devices to be in exactly the same order as before
    the VT switch. Removing a device while on a different VT is probably a bad
    idea.

diff --git a/dix/devices.c b/dix/devices.c
index e606016..3ce045c 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -210,10 +210,13 @@ EnableDevice(DeviceIntPtr dev)
     /* Sprites pop up on the first root window, so we can supply it directly
      * here. 
      */
-    if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
-        InitializeSprite(dev, WindowTable[0]);
-    else
-        PairDevices(NULL, inputInfo.pointer, dev);
+    if (!dev->spriteInfo->sprite)
+    {
+        if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
+            InitializeSprite(dev, WindowTable[0]);
+        else
+            PairDevices(NULL, inputInfo.pointer, dev);
+    }
 
     if ((*prev != dev) || !dev->inited ||
 	((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
commit d627061b48ae06d27b37be209d67a3f4f2388dd3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 6 18:57:00 2007 +0930

    xfree86: wrap keyboard devices for XKB.
    
    Call ProcessOtherEvents first, then for all keyboard devices let them be
    wrapped by XKB. This way all XI events will go through XKB.
    
    Note that the VCK is still not wrapped, so core events will bypass XKB.

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 4c9de1f..2436231 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -179,20 +179,15 @@ xf86ActivateDevice(LocalDevicePtr local)
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE; 
         dev->spriteInfo->spriteOwner = !(local->flags & XI86_SHARED_POINTER);
 
+        RegisterOtherDevice(dev);
+
 #ifdef XKB
-        if (!DeviceIsPointerType(dev))
+        if (!DeviceIsPointerType(dev) && !noXkbExtension)
         {
-        /* FIXME: that's not the nice way to do it. XKB wraps the previously
-         * set procs, so if we don't have them here, our event will disappear
-         * in a black hole.*/
-            dev->public.processInputProc = CoreProcessKeyboardEvent;
-            dev->public.realInputProc = CoreProcessKeyboardEvent;
-            if (!noXkbExtension)
-                XkbSetExtension(dev, ProcessKeyboardEvent);
+            XkbSetExtension(dev, ProcessKeyboardEvent);
         }
 #endif
 
-        RegisterOtherDevice(dev);
 
         if (serverGeneration == 1) 
             xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n",
commit 5ee409794ee604fcf84886f70429fc2d6b1ff4f1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 6 18:52:02 2007 +0930

    dix: add XI event support to FixKeyState.
    
    FixKeyState needs to be able to handle XI events, otherwise we get "impossible
    keyboard events" on server zaps and other special key combos.

diff --git a/dix/events.c b/dix/events.c
index 07a191f..ad9ec1c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3584,7 +3584,7 @@ drawable.id:0;
 #ifdef XKB
 /* This function is used to set the key pressed or key released state -
    this is only used when the pressing of keys does not cause 
-   CoreProcessKeyEvent to be called, as in for example Mouse Keys.
+   the device's processInputProc to be called, as in for example Mouse Keys.
 */
 void
 FixKeyState (xEvent *xE, DeviceIntPtr keybd)
@@ -3597,22 +3597,19 @@ FixKeyState (xEvent *xE, DeviceIntPtr keybd)
     kptr = &keyc->down[key >> 3];
     bit = 1 << (key & 7);
 
-    if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) {
+    if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease)||
+         (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease))
+            ) {
 	DebugF("FixKeyState: Key %d %s\n",key,
-			(xE->u.u.type==KeyPress?"down":"up"));
+               (((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress))?"down":"up"));
     }
 
-    switch (xE->u.u.type)
-    {
-	case KeyPress: 
+    if (xE->u.u.type == KeyPress || xE->u.u.type == DeviceKeyPress)
 	    *kptr |= bit;
-	    break;
-	case KeyRelease: 
+    else if (xE->u.u.type == KeyRelease || xE->u.u.type == DeviceKeyRelease)
 	    *kptr &= ~bit;
-	    break;
-	default: 
-	    FatalError("Impossible keyboard event");
-    }
+    else
+        FatalError("Impossible keyboard event");
 }
 #endif
 
commit 6334d4e7be18de5f237c12a6dc20f75aa23477d0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 6 18:49:57 2007 +0930

    xkb: enable XI event processing for xkb.
    
    XI events can now take the same processing paths as core events, and should do
    the correct state changes etc.
    
    There's some cases where XKB will use KeyPress as type for an event to be
    delivered to the client. Stuck warnings in, not sure what the correct solution
    is yet.

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index be2cff6..e220f0a 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -311,8 +311,9 @@ extern CARD32	xkbDebugFlags;
 #define	_XkbErrCode3(a,b,c)	_XkbErrCode2(a,(((unsigned int)(b))<<16)|(c))
 #define	_XkbErrCode4(a,b,c,d) _XkbErrCode3(a,b,((((unsigned int)(c))<<8)|(d)))
 
-extern	int	DeviceKeyPress,DeviceKeyRelease;
+extern	int	DeviceKeyPress,DeviceKeyRelease,DeviceMotionNotify;
 extern	int	DeviceButtonPress,DeviceButtonRelease;
+extern	int	DeviceEnterNotify,DeviceLeaveNotify;
 
 #ifdef XINPUT
 #define	_XkbIsPressEvent(t)	(((t)==KeyPress)||((t)==DeviceKeyPress))
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 762b6e5..e51b0cc 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -39,6 +39,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <xkbsrv.h>
 #include "xkb.h"
 #include <ctype.h>
+#define EXTENSION_EVENT_BASE 64
 
 static unsigned int _xkbServerGeneration;
 static int xkbDevicePrivateIndex = -1;
@@ -83,13 +84,11 @@ XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
 			    proc,xkbUnwrapProc);
 }
 
-#ifdef XINPUT
 extern	void	ProcessOtherEvent(
     xEvent *		/* xE */,
     DeviceIntPtr 	/* dev */,
     int 		/* count */
 );
-#endif
 
 /***====================================================================***/
 
@@ -673,6 +672,7 @@ _XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
 						&old,xkbi->desc->ctrls,
 						&cn,False)) {
 			cn.keycode = keycode;
+                        /* XXX: what about DeviceKeyPress? */
 			cn.eventType = KeyPress;
 			cn.requestMajor = 0;
 			cn.requestMinor = 0;
@@ -737,6 +737,7 @@ XkbEventCauseRec	cause;
 	    ctrls->enabled_ctrls|= change;
 	    if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
 		cn.keycode = keycode;
+                /* XXX: what about DeviceKeyPress? */
 		cn.eventType = KeyPress;
 		cn.requestMajor = 0;
 		cn.requestMinor = 0;
@@ -878,6 +879,7 @@ ProcessInputProc backupproc;
 	filter->filter = _XkbFilterRedirectKey;
 	filter->upAction = *pAction;
 
+        /* XXX: what about DeviceKeyPress */
 	ev.u.u.type = KeyPress;
 	ev.u.u.detail = pAction->redirect.new_key;
 
@@ -905,6 +907,10 @@ ProcessInputProc backupproc;
 
 	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
 	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
+        /* XXX: Bad! Since the switch to XI devices xkbi->device will be the
+         * XI device. Sending a core event through ProcessOtherEvent will
+         * cause trouble. Somebody should fix this. 
+         */
 	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
 	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
 	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
@@ -919,6 +925,7 @@ ProcessInputProc backupproc;
     }
     else if (filter->keycode==keycode) {
 
+        /* XXX: what about DeviceKeyRelease */
 	ev.u.u.type = KeyRelease;
 	ev.u.u.detail = filter->upAction.redirect.new_key;
 
@@ -946,6 +953,10 @@ ProcessInputProc backupproc;
 
 	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
 	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
+        /* XXX: Bad! Since the switch to XI devices xkbi->device will be the
+         * XI device. Sending a core event through ProcessOtherEvent will
+         * cause trouble. Somebody should fix this. 
+         */
 	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
 	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
 	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
@@ -1009,7 +1020,6 @@ _XkbFilterXF86Private(	XkbSrvInfoPtr	xkbi,
     return 1;
 }
 
-#ifdef XINPUT
 
 static int
 _XkbFilterDeviceBtn(	XkbSrvInfoPtr	xkbi,
@@ -1081,7 +1091,6 @@ int		button;
     }
     return 0;
 }
-#endif
 
 static XkbFilterPtr
 _XkbNextFreeFilter(
@@ -1139,9 +1148,7 @@ XkbAction	act;
 XkbFilterPtr	filter;
 Bool		keyEvent;
 Bool		pressEvent;
-#ifdef XINPUT
 Bool		xiEvent;
-#endif
 ProcessInputProc backupproc;
     
 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
@@ -1162,7 +1169,6 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
     xkbi->groupChange = 0;
 
     sendEvent = 1;
-#ifdef XINPUT
     keyEvent= ((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)||
 		(xE->u.u.type==KeyRelease)||(xE->u.u.type==DeviceKeyRelease));
     pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)||
@@ -1170,10 +1176,6 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
     xiEvent= (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease)||
 	     (xE->u.u.type==DeviceButtonPress)||
 	     (xE->u.u.type==DeviceButtonRelease);
-#else
-    keyEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease);
-    pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==ButtonPress);
-#endif
 
     if (pressEvent) {
 	if (keyEvent)	
@@ -1234,13 +1236,11 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
 		    break;
-#ifdef XINPUT
 		case XkbSA_DeviceBtn:
 		case XkbSA_LockDeviceBtn:
 		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act);
 		    break;
-#endif
 		case XkbSA_XFree86Private:
 		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act);
@@ -1279,11 +1279,6 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
     }
 
     if (sendEvent) {
-#ifdef XINPUT
-	if (xiEvent)
-	    ProcessOtherEvent(xE,dev,count);
-	else 
-#endif
 	if (keyEvent) {
 	    realMods = keyc->modifierMap[key];
 	    keyc->modifierMap[key] = 0;
@@ -1293,7 +1288,14 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 					 backupproc,xkbUnwrapProc);
 	    keyc->modifierMap[key] = realMods;
 	}
-	else CoreProcessPointerEvent(xE,dev,count);
+	else 
+        {
+            if (xE->u.u.type & EXTENSION_EVENT_BASE)
+                ProcessOtherEvent(xE, dev, count);
+            else
+                CoreProcessPointerEvent(xE,dev,count);
+            
+        }
     }
     else if (keyEvent)
 	FixKeyState(xE,dev);
diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c
index 973e1ad..22ca2d6 100644
--- a/xkb/xkbEvents.c
+++ b/xkb/xkbEvents.c
@@ -34,6 +34,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <X11/Xproto.h>
 #include <X11/keysym.h>
 #include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
 #include "inputstr.h"
 #include "windowstr.h"
 #include <xkbsrv.h>
@@ -814,7 +815,9 @@ GrabInfoPtr grabinfo;
     if ( pClient->xkbClientFlags & _XkbClientInitialized ) {
 #ifdef DEBUG
 	if ((xkbDebugFlags&0x10)&&
-		((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) {
+		((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
+                 (xE[0].u.u.type==DeviceKeyPress)||
+                 (xE[0].u.u.type == DeviceKeyRelease))) {
 	    ErrorF("XKbFilterWriteEvents:\n");
 	    ErrorF("   Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
 	    ErrorF("   XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
@@ -834,7 +837,9 @@ GrabInfoPtr grabinfo;
 	}
 	if ((pXDev->deviceGrab.grab != NullGrab) 
                 && pXDev->deviceGrab.fromPassiveGrab &&
-	    ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) {
+	    ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
+             (xE[0].u.u.type==DeviceKeyPress)||
+             (xE[0].u.u.type == DeviceKeyRelease))) {
 	    register unsigned state,flags;
 
 	    flags= pClient->xkbClientFlags;
@@ -879,10 +884,12 @@ GrabInfoPtr grabinfo;
 	    type= xE[i].u.u.type;
 #ifdef DEBUG
 	    if ((xkbDebugFlags&0x4)&&
-		((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) {
+		((xE[i].u.u.type==KeyPress)||(xE[i].u.u.type==KeyRelease)||
+                 (xE[i].u.u.type==DeviceKeyPress)||
+                 (xE[i].u.u.type == DeviceKeyRelease))) {
 		XkbStatePtr s= &xkbi->state;
 		ErrorF("XKbFilterWriteEvents (non-XKB):\n");
-		ErrorF("event= 0x%04x\n",xE[0].u.keyButtonPointer.state);
+		ErrorF("event= 0x%04x\n",xE[i].u.keyButtonPointer.state);
 		ErrorF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods,
 							s->grab_mods);
 		ErrorF("compat lookup= 0x%02x, grab= 0x%02x\n",
@@ -902,9 +909,22 @@ GrabInfoPtr grabinfo;
 		xE[i].u.keyButtonPointer.state= new;
 	    }
 	    else if ((type==EnterNotify)||(type==LeaveNotify)) {
-		xE->u.enterLeave.state&= 0x1F00;
-		xE->u.enterLeave.state|= xkbi->state.compat_grab_mods;
-	    }
+		xE[i].u.enterLeave.state&= 0x1F00;
+		xE[i].u.enterLeave.state|= xkbi->state.compat_grab_mods;
+	    } else if ((type>=DeviceKeyPress)&&(type<=DeviceMotionNotify)) {
+                CARD16  old, new;
+                deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*)&xE[i];
+                old= kbp->state&(~0x1F00);
+                new= kbp->state&0x1F00;
+		if (old==XkbStateFieldFromRec(&xkbi->state))
+		     new|= xkbi->state.compat_lookup_mods;
+		else new|= xkbi->state.compat_grab_mods;
+                kbp->state= new;
+            } else if ((type==DeviceEnterNotify)||(type==DeviceLeaveNotify)) {
+                deviceEnterNotify *del = (deviceEnterNotify*)&xE[i];
+                del->state&=0x1F00;
+                del->state|= xkbi->state.compat_grab_mods;
+            }
 	    button_mask = 1 << xE[i].u.u.detail;
 	    if (type == ButtonPress &&
 		((xE[i].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
@@ -913,7 +933,14 @@ GrabInfoPtr grabinfo;
 		ErrorF("Faking release of button %d\n", xE[i].u.u.detail);
 #endif
 		XkbDDXFakePointerButton(ButtonRelease, xE[i].u.u.detail);
-	    }
+	    } else if (type == DeviceButtonPress &&
+                    ((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask &&
+                    (xkbi->lockedPtrButtons & button_mask) == button_mask) {
+#ifdef DEBUG
+		ErrorF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state)
+#endif
+		XkbDDXFakePointerButton(DeviceButtonRelease, ((deviceKeyButtonPointer*)&xE[i])->state);
+            }
 	}
     }
     return True;
diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c
index 02f3c35..ba3fcc0 100644
--- a/xkb/xkbPrKeyEv.c
+++ b/xkb/xkbPrKeyEv.c
@@ -38,6 +38,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include "inputstr.h"
 #include <xkbsrv.h>
 #include <ctype.h>
+#define EXTENSION_EVENT_BASE 64
 
 
 /***====================================================================***/
@@ -50,9 +51,11 @@ XkbSrvInfoPtr	xkbi;
 int		key;
 XkbBehavior	behavior;
 unsigned        ndx;
+int             xiEvent;
 
     xkbi= keyc->xkbInfo;
     key= xE->u.u.detail;
+    xiEvent= (xE->u.u.type & EXTENSION_EVENT_BASE);
 #ifdef DEBUG
     if (xkbDebugFlags&0x8) {
 	ErrorF("XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up"));
@@ -70,51 +73,68 @@ unsigned        ndx;
     /* do anything to implement the behavior, but it *does* report that */
     /* key is hardwired */
 
-    /* FIXME: this is bad. The down mask is set during ProcessOtherEvent. When
-     * we start processing the core event (and eventually arrive here), the
-     * down mask is already set and Xkb thinks it's a repeat event. We just
-     * silently ignore it for now.
-     */
-#if 0
     if ((behavior.type&XkbKB_Permanent)==0) {
 	switch (behavior.type) {
 	    case XkbKB_Default:
-		if (( xE->u.u.type == KeyPress ) && 
+		if (( xE->u.u.type == KeyPress || 
+                            xE->u.u.type == DeviceKeyPress) && 
 		    (keyc->down[key>>3] & (1<<(key&7)))) {
 		    XkbLastRepeatEvent=	(pointer)xE;
-		    xE->u.u.type = KeyRelease;
+
+                    if (xiEvent)
+                        xE->u.u.type = DeviceKeyRelease;
+                    else
+                        xE->u.u.type = KeyRelease;
 		    XkbHandleActions(keybd,keybd,xE,count);
-		    xE->u.u.type = KeyPress;
+
+                    if (xiEvent)
+                        xE->u.u.type = DeviceKeyPress;
+                    else
+                        xE->u.u.type = KeyPress;
 		    XkbHandleActions(keybd,keybd,xE,count);
 		    XkbLastRepeatEvent= NULL;
 		    return;
 		}
-		else if ((xE->u.u.type==KeyRelease) &&
+		else if ((xE->u.u.type==KeyRelease || 
+                            xE->u.u.type == DeviceKeyRelease) &&
 			(!(keyc->down[key>>3]&(1<<(key&7))))) {
 		    XkbLastRepeatEvent=	(pointer)&xE;
-		    xE->u.u.type = KeyPress;
+                    if (xiEvent)
+                        xE->u.u.type = DeviceKeyPress;
+                    else
+                        xE->u.u.type = KeyPress;
 		    XkbHandleActions(keybd,keybd,xE,count);
-		    xE->u.u.type = KeyRelease;
+                    if (xiEvent)
+                        xE->u.u.type = DeviceKeyRelease;
+                    else
+                        xE->u.u.type = KeyRelease;
 		    XkbHandleActions(keybd,keybd,xE,count);
 		    XkbLastRepeatEvent= NULL;
 		    return;
 		}
 		break;
 	    case XkbKB_Lock:
-		if ( xE->u.u.type == KeyRelease )
+		if ( xE->u.u.type == KeyRelease || 
+                        xE->u.u.type == DeviceKeyRelease)
 		    return;
 		else {
 		    int	bit= 1<<(key&7);
 		    if ( keyc->down[key>>3]&bit )
-			xE->u.u.type= KeyRelease;
-		}
+                    {
+                        if (xiEvent)
+                            xE->u.u.type = DeviceKeyRelease;
+                        else
+                            xE->u.u.type= KeyRelease;
+                    }
+                }
 		break;
 	    case XkbKB_RadioGroup:
 		ndx= (behavior.data&(~XkbKB_RGAllowNone));
 		if ( ndx<xkbi->nRadioGroups ) {
 		    XkbRadioGroupPtr	rg;
 
-		    if ( xE->u.u.type == KeyRelease )
+		    if ( xE->u.u.type == KeyRelease ||
+                            xE->u.u.type == DeviceKeyRelease)
 		        return;
 
 		    rg = &xkbi->radioGroups[ndx];
@@ -128,10 +148,16 @@ unsigned        ndx;
 		    }
 		    if ( rg->currentDown!=0 ) {
 			int key = xE->u.u.detail;
-			xE->u.u.type= KeyRelease;
+                        if (xiEvent)
+                            xE->u.u.type = DeviceKeyRelease;
+                        else
+                            xE->u.u.type= KeyRelease;
 			xE->u.u.detail= rg->currentDown;
 		        XkbHandleActions(keybd,keybd,xE,count);
-		        xE->u.u.type= KeyPress;
+                        if (xiEvent)
+                            xE->u.u.type = DeviceKeyPress;
+                        else
+                            xE->u.u.type= KeyPress;
 		        xE->u.u.detail= key;
 		    }
 		    rg->currentDown= key;
@@ -160,7 +186,6 @@ unsigned        ndx;
 		break;
 	}
     }
-#endif
     XkbHandleActions(keybd,keybd,xE,count);
     return;
 }
@@ -181,9 +206,9 @@ XkbSrvInfoPtr	xkbi;
 #endif
     if ((xkbi->desc->ctrls->enabled_ctrls&XkbAllFilteredEventsMask)==0)
 	XkbProcessKeyboardEvent(xE,keybd,count);
-    else if (xE->u.u.type==KeyPress)
+    else if (xE->u.u.type==KeyPress || xE->u.u.type==DeviceKeyPress)
 	AccessXFilterPressEvent(xE,keybd,count);
-    else if (xE->u.u.type==KeyRelease)
+    else if (xE->u.u.type==KeyRelease || xE->u.u.type==DeviceKeyRelease)
 	AccessXFilterReleaseEvent(xE,keybd,count);
     return;
 }
commit 49dbe9a757a3d7a0b9ab318242c6cc0cbd4dd1f0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 6 17:27:28 2007 +0930

    dix: close virtual core devices after other devices.
    
    If a device is paired with the VCP, deleting the VCP before the device will
    segfault the server when the sprite should get updated.

diff --git a/dix/devices.c b/dix/devices.c
index fbb6cba..e606016 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -712,9 +712,6 @@ CloseDownDevices(void)
 {
     DeviceIntPtr dev, next;
 
-    CloseDevice(inputInfo.keyboard);
-    CloseDevice(inputInfo.pointer);
-
     for (dev = inputInfo.devices; dev; dev = next)
     {
 	next = dev->next;
@@ -725,6 +722,10 @@ CloseDownDevices(void)
 	next = dev->next;
 	CloseDevice(dev);
     }
+
+    CloseDevice(inputInfo.keyboard);
+    CloseDevice(inputInfo.pointer);
+
     inputInfo.devices = NULL;
     inputInfo.off_devices = NULL;
     inputInfo.keyboard = NULL;
commit 03680a384aa423ece75b658f00b96db2628c39fa
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Sep 6 15:43:47 2007 +0930

    dix: don't change the device struct while processing core events.
    
    The device state needs to be changed while processing the XI event. Core
    events are always processed after XI, so by then the device is already set up
    properly. However, we now rely on DeviceButtonMotionMask to be equal to
    ButtonMotionMask. It already is, but stick a big fat warning in so nobody
    attempts to change it.
    
    This commit disables XKB for the VCK, thus essentially for all devices.
    Temporarily anyway.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 8f60561..aa2b4c9 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -126,9 +126,6 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     ValuatorClassPtr v = device->valuator;
     deviceValuator *xV = (deviceValuator *) xE;
 
-    if (grab && grab->coreGrab && !device->deviceGrab.fromPassiveGrab)
-        return;
-
     CheckMotion(xE, device);
 
     if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 70253fe..1d23809 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -879,8 +879,20 @@ FixExtensionEvents(ExtensionEntry * extEntry)
     SetEventInfo(GetNextExtEventMask(), _deviceButton3Motion);
     SetEventInfo(GetNextExtEventMask(), _deviceButton4Motion);
     SetEventInfo(GetNextExtEventMask(), _deviceButton5Motion);
+
+    /* If DeviceButtonMotionMask is != ButtonMotionMask, event delivery
+     * breaks down. The device needs the dev->button->motionMask. If DBMM is
+     * the same as BMM, we can ensure that both core and device events can be
+     * delivered, without the need for extra structures in the DeviceIntRec.
+     */
     DeviceButtonMotionMask = GetNextExtEventMask();
     SetEventInfo(DeviceButtonMotionMask, _deviceButtonMotion);
+    if (DeviceButtonMotionMask != ButtonMotionMask)
+    {
+        /* This should never happen, but if it does, hide under the
+         * bed and cry for help. */
+        ErrorF("DeviceButtonMotionMask != ButtonMotionMask. Trouble!\n");
+    }
 
     DeviceFocusChangeMask = GetNextExtEventMask();
     SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusIn);
diff --git a/dix/devices.c b/dix/devices.c
index 60825c1..fbb6cba 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -458,8 +458,8 @@ InitCoreDevices(void)
 #ifdef XKB
         dev->public.processInputProc = CoreProcessKeyboardEvent;
         dev->public.realInputProc = CoreProcessKeyboardEvent;
-        if (!noXkbExtension)
-           XkbSetExtension(dev, ProcessKeyboardEvent);
+        /*if (!noXkbExtension)*/
+        /*XkbSetExtension(dev, ProcessKeyboardEvent);*/
 #else
         dev->public.processInputProc = ProcessKeyboardEvent;
         dev->public.realInputProc = ProcessKeyboardEvent;
diff --git a/dix/events.c b/dix/events.c
index 0f413a6..07a191f 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3524,7 +3524,9 @@ drawable.id:0;
 #endif
     )))
 #endif
-    XE_KBPTR.state = (keyc->state | GetPairedPointer(keybd)->button->state);
+    /* ProcessOtherEvent already updated the keyboard's state, so we need to
+     * access prev_state here! */
+    XE_KBPTR.state = (keyc->prev_state | GetPairedPointer(keybd)->button->state);
     XE_KBPTR.rootX = keybd->spriteInfo->sprite->hot.x;
     XE_KBPTR.rootY = keybd->spriteInfo->sprite->hot.y;
     key = xE->u.u.detail;
@@ -3545,31 +3547,14 @@ drawable.id:0;
     switch (xE->u.u.type)
     {
 	case KeyPress: 
-	    if (*kptr & bit) /* allow ddx to generate multiple downs */
-	    {   
-		if (!modifiers)
-		{
-		    xE->u.u.type = KeyRelease;
-		    (*keybd->public.processInputProc)(xE, keybd, count);
-		    xE->u.u.type = KeyPress;
-		    /* release can have side effects, don't fall through */
-		    (*keybd->public.processInputProc)(xE, keybd, count);
-		}
-		return;
-	    }
-	    GetPairedPointer(keybd)->valuator->motionHintWindow = NullWindow;
-	    *kptr |= bit;
-	    keyc->prev_state = keyc->state;
-	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
-	    {
-		if (mask & modifiers)
-		{
-		    /* This key affects modifier "i" */
-		    keyc->modifierKeyCount[i]++;
-		    keyc->state |= mask;
-		    modifiers &= ~mask;
-		}
-	    }
+            /* We MUST NOT change the device itself here.  All device state
+             * changes must be performed in ProcessOtherEvents. We're dealing
+             * with the same device struct, so if we change it in POE and
+             * here, we've just screwed up the state by setting it twice. 
+             *
+             * Devices may not send core events but always send XI events, so
+             * the state must be changed in POE, not here.
+             */
 	    if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
 	    {
 		grabinfo->activatingKey = key;
@@ -3579,20 +3564,7 @@ drawable.id:0;
 	case KeyRelease: 
 	    if (!(*kptr & bit)) /* guard against duplicates */
 		return;
-	    GetPairedPointer(keybd)->valuator->motionHintWindow = NullWindow;
-	    *kptr &= ~bit;
-	    keyc->prev_state = keyc->state;
-	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
-	    {
-		if (mask & modifiers) {
-		    /* This key affects modifier "i" */
-		    if (--keyc->modifierKeyCount[i] <= 0) {
-			keyc->state &= ~mask;
-			keyc->modifierKeyCount[i] = 0;
-		    }
-		    modifiers &= ~mask;
-		}
-	    }
+            /* No device state changes, see comment for KeyPress */
 	    if (grabinfo->fromPassiveGrab && (key == grabinfo->activatingKey))
 		deactivateGrab = TRUE;
 	    break;
@@ -3729,31 +3701,21 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 	switch (xE->u.u.type)
 	{
 	case ButtonPress: 
-	    mouse->valuator->motionHintWindow = NullWindow;
-	    if (!(*kptr & bit))
-		butc->buttonsDown++;
-	    butc->motionMask = ButtonMotionMask;
-	    *kptr |= bit;
+            /*
+             * We rely on the fact that ButtonMotionMask is the same as
+             * DeviceButtonMotionMask, so setting the motionMask
+             * to this value ensures correctness for both XI and core events.
+             */
 	    if (xE->u.u.detail == 0)
 		return;
-	    if (xE->u.u.detail <= 5)
-		butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
 	    filters[MotionNotify] = Motion_Filter(butc);
 	    if (!grab)
 		if (CheckDeviceGrabs(mouse, xE, 0, count))
 		    return;
 	    break;
 	case ButtonRelease: 
-	    mouse->valuator->motionHintWindow = NullWindow;
-	    if (*kptr & bit)
-		--butc->buttonsDown;
-	    if (!butc->buttonsDown)
-		butc->motionMask = 0;
-	    *kptr &= ~bit;
 	    if (xE->u.u.detail == 0)
 		return;
-	    if (xE->u.u.detail <= 5)
-		butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	    filters[MotionNotify] = Motion_Filter(butc);
 	    if (!butc->state && mouse->deviceGrab.fromPassiveGrab)
 		deactivateGrab = TRUE;
commit c4fff050836feeef8390b7197f1de39af2997811
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Sep 5 16:19:45 2007 +0930

    Revert "Input: Fix stuck modifiers (bug #11683)"
    
    This reverts commit 6b055e5d9751e3679ff98065e43225ec8a960053.
    
    MPX relies on the XI event being delivered before the core event. Device grabs
    break, amongst other things. I guess stuck modifiers need to be fixed some
    other way.
    
    Conflicts:
    
            dix/getevents.c

diff --git a/dix/getevents.c b/dix/getevents.c
index bcbc00b..e88c56c 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -451,14 +451,6 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
 
     ms = GetTimeInMillis();
 
-    if (pDev->coreEvents) {
-        xEvent* evt = events->event;
-        evt->u.keyButtonPointer.time = ms;
-        evt->u.u.type = type;
-        evt->u.u.detail = key_code;
-        events++;
-    }
-
     kbp = (deviceKeyButtonPointer *) events->event;
     kbp->time = ms;
     kbp->deviceid = pDev->id;
@@ -476,6 +468,12 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
                                    num_valuators, valuators);
     }
 
+    if (pDev->coreEvents) {
+        events->event->u.keyButtonPointer.time = ms;
+        events->event->u.u.type = type;
+        events->event->u.u.detail = key_code;
+    }
+
     return numEvents;
 }
 
@@ -677,28 +675,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     pDev->valuator->lastx = x;
     pDev->valuator->lasty = y;
 
-    /* for some reason inputInfo.pointer does not have coreEvents set */
-    if (coreOnly || pDev->coreEvents) {
-        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. */
-            evt->u.u.detail = pDev->button->map[buttons];
-        }
-        else {
-            evt->u.u.detail = 0;
-        }
-
-        events++;
-    }
-
-    if (!coreOnly) {
+    if (!coreOnly)
+    {
         kbp = (deviceKeyButtonPointer *) events->event;
         kbp->time = ms;
         kbp->deviceid = pDev->id;
@@ -726,6 +704,24 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         }
     }
 
+    /* for some reason inputInfo.pointer does not have coreEvents set */
+    if (coreOnly || pDev->coreEvents) {
+        events->event->u.u.type = type;
+        events->event->u.keyButtonPointer.time = ms;
+        events->event->u.keyButtonPointer.rootX = x;
+        events->event->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->event->u.u.detail = pDev->button->map[buttons];
+        }
+        else {
+            events->event->u.u.detail = 0;
+        }
+    }
+
     return num_events;
 }
 
commit bfe6b4d2d9952a80f8dbc63eec974ef894e5c226
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Sep 4 17:44:51 2007 +0930

    xkb: Store the action filters per device in the XkbSrvInfoRec.
    
    Using a global array for action filters is bad. If two keyboard hit a modifier
    at the same time, releaseing the first one will deactivate the filter and
    thus the second keyboard can never release the modifier again.

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index e018749..be2cff6 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -126,6 +126,24 @@ typedef struct	_XkbEventCause {
 #define	_BEEP_LED_CHANGE	14
 #define	_BEEP_BOUNCE_REJECT	15
 
+struct _XkbSrvInfo; /* definition see below */
+
+typedef struct _XkbFilter {
+	CARD16			  keycode;
+	CARD8			  what;
+	CARD8			  active;
+	CARD8			  filterOthers;
+	CARD32			  priv;
+	XkbAction		  upAction;
+	int			(*filter)(
+					struct _XkbSrvInfo* 	/* xkbi */,
+					struct _XkbFilter *	/* filter */,
+					unsigned		/* keycode */,
+					XkbAction *		/* action */
+				  );
+	struct _XkbFilter	 *next;
+} XkbFilterRec,*XkbFilterPtr;
+
 typedef struct _XkbSrvInfo {
 	XkbStateRec	 prev_state;
 	XkbStateRec	 state;
@@ -169,6 +187,9 @@ typedef struct _XkbSrvInfo {
 	OsTimerPtr	 bounceKeysTimer;
 	OsTimerPtr	 repeatKeyTimer;
 	OsTimerPtr	 krgTimer;
+
+	int		 szFilters;
+	XkbFilterPtr	 filters;
 } XkbSrvInfoRec, *XkbSrvInfoPtr;
 
 #define	XkbSLI_IsDefault	(1L<<0)
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 252c653..762b6e5 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -73,7 +73,7 @@ XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
     if (!AllocateDevicePrivate(device, xkbDevicePrivateIndex))
 	return;
 
-    xkbPrivPtr = (xkbDeviceInfoPtr) xalloc(sizeof(xkbDeviceInfoRec));
+    xkbPrivPtr = (xkbDeviceInfoPtr) xcalloc(1, sizeof(xkbDeviceInfoRec));
     if (!xkbPrivPtr)
 	return;
     xkbPrivPtr->unwrapProc = NULL;
@@ -237,22 +237,6 @@ XkbAction fake;
 #define	SYNTHETIC_KEYCODE	1
 #define	BTN_ACT_FLAG		0x100
 
-typedef struct _XkbFilter {
-	CARD16			  keycode;
-	CARD8			  what;
-	CARD8			  active;
-	CARD8			  filterOthers;
-	CARD32			  priv;
-	XkbAction		  upAction;
-	int			(*filter)(
-					XkbSrvInfoPtr 		/* xkbi */,
-					struct _XkbFilter *	/* filter */,
-					unsigned		/* keycode */,
-					XkbAction *		/* action */
-				  );
-	struct _XkbFilter	 *next;
-} XkbFilterRec,*XkbFilterPtr;
-
 static int
 _XkbFilterSetState(	XkbSrvInfoPtr	xkbi,
 			XkbFilterPtr	filter,
@@ -1099,32 +1083,32 @@ int		button;
 }
 #endif
 
-static	int		szFilters = 0;
-static	XkbFilterPtr	filters = NULL;
-
 static XkbFilterPtr
 _XkbNextFreeFilter(
-	void
+	XkbSrvInfoPtr xkbi
 )
 {
 register int	i;
 
-    if (szFilters==0) {
-	szFilters = 4;
-	filters = _XkbTypedCalloc(szFilters,XkbFilterRec);
+    if (xkbi->szFilters==0) {
+	xkbi->szFilters = 4;
+	xkbi->filters = _XkbTypedCalloc(xkbi->szFilters,XkbFilterRec);
 	/* 6/21/93 (ef) -- XXX! deal with allocation failure */
     }
-    for (i=0;i<szFilters;i++) {
-	if (!filters[i].active) {
-	    filters[i].keycode = 0;
-	    return &filters[i];
+    for (i=0;i<xkbi->szFilters;i++) {
+	if (!xkbi->filters[i].active) {
+	    xkbi->filters[i].keycode = 0;
+	    return &xkbi->filters[i];
 	}
     }
-    szFilters*=2;
-    filters= _XkbTypedRealloc(filters,szFilters,XkbFilterRec);
+    xkbi->szFilters*=2;
+    xkbi->filters= _XkbTypedRealloc(xkbi->filters,
+                                    xkbi->szFilters,
+                                    XkbFilterRec);
     /* 6/21/93 (ef) -- XXX! deal with allocation failure */
-    bzero(&filters[szFilters/2],(szFilters/2)*sizeof(XkbFilterRec));
-    return &filters[szFilters/2];
+    bzero(&xkbi->filters[xkbi->szFilters/2],
+            (xkbi->szFilters/2)*sizeof(XkbFilterRec));
+    return &xkbi->filters[xkbi->szFilters/2];
 }
 
 static int
@@ -1133,9 +1117,10 @@ _XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction)
 register int	i,send;
 
     send= 1;
-    for (i=0;i<szFilters;i++) {
-	if ((filters[i].active)&&(filters[i].filter))
-	    send= ((*filters[i].filter)(xkbi,&filters[i],kc,pAction)&&send);
+    for (i=0;i<xkbi->szFilters;i++) {
+	if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter))
+	    send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction) 
+                    && send);
     }
     return send;
 }
@@ -1164,6 +1149,8 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
     keyc= kbd->key;
     xkbi= keyc->xkbInfo;
     key= xE->u.u.detail;
+    /* The state may change, so if we're not in the middle of sending a state
+     * notify, prepare for it */
     if ((xkbi->flags&_XkbStateNotifyInProgress)==0) {
 	oldState= xkbi->state;
 	xkbi->flags|= _XkbStateNotifyInProgress;
@@ -1200,62 +1187,62 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 	    switch (act.type) {
 		case XkbSA_SetMods:
 		case XkbSA_SetGroup:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent = _XkbFilterSetState(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_LatchMods:
 		case XkbSA_LatchGroup:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_LockMods:
 		case XkbSA_LockGroup:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_ISOLock:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_MovePtr:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_PtrBtn:
 		case XkbSA_LockPtrBtn:
 		case XkbSA_SetPtrDflt:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_Terminate:
 		    sendEvent= XkbDDXTerminateServer(dev,key,&act);
 		    break;
 		case XkbSA_SwitchScreen:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_SetControls:
 		case XkbSA_LockControls:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent=_XkbFilterControls(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_ActionMessage:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_RedirectKey:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
 		    break;
 #ifdef XINPUT
 		case XkbSA_DeviceBtn:
 		case XkbSA_LockDeviceBtn:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act);
 		    break;
 #endif
 		case XkbSA_XFree86Private:
-		    filter = _XkbNextFreeFilter();
+		    filter = _XkbNextFreeFilter(xkbi);
 		    sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act);
 		    break;
 	    }
@@ -1355,7 +1342,7 @@ unsigned	clear;
 	act.type = XkbSA_LatchMods;
 	act.mods.flags = 0;
 	act.mods.mask  = mask&latches;
-	filter = _XkbNextFreeFilter();
+	filter = _XkbNextFreeFilter(xkbi);
 	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
 	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
 	return Success;
@@ -1375,7 +1362,7 @@ XkbAction	act;
 	act.type = XkbSA_LatchGroup;
 	act.group.flags = 0;
 	XkbSASetGroup(&act.group,group);
-	filter = _XkbNextFreeFilter();
+	filter = _XkbNextFreeFilter(xkbi);
 	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
 	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
 	return Success;
commit cc5c926267be099d793e6dfec17916f21c73c64d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Aug 30 15:51:22 2007 +0930

    randr: RRPointerScreenConfigured needs to move all pointers.
    
    Previous version only moved the VCP, causing "bogus pointer events" lateron.
    Now we run through the device list, updating each pointer separately if
    necessary.
    
    Also stick a big warning into RRPointerMoved, not sure what device we need to
    work on here.

diff --git a/randr/rrpointer.c b/randr/rrpointer.c
index 722b22c..e3b8b03 100644
--- a/randr/rrpointer.c
+++ b/randr/rrpointer.c
@@ -52,7 +52,7 @@ RRCrtcContainsPosition (RRCrtcPtr crtc, int x, int y)
  * Find the CRTC nearest the specified position, ignoring 'skip'
  */
 static void
-RRPointerToNearestCrtc (ScreenPtr pScreen, int x, int y, RRCrtcPtr skip)
+RRPointerToNearestCrtc (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, RRCrtcPtr skip)
 {
     rrScrPriv (pScreen);
     int		c;
@@ -96,7 +96,7 @@ RRPointerToNearestCrtc (ScreenPtr pScreen, int x, int y, RRCrtcPtr skip)
 	}
     }
     if (best_dx || best_dy)
-	(*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, x + best_dx, y + best_dy, TRUE);
+	(*pScreen->SetCursorPosition) (pDev, pScreen, x + best_dx, y + best_dy, TRUE);
     pScrPriv->pointerCrtc = nearest;
 }
 
@@ -125,28 +125,37 @@ RRPointerMoved (ScreenPtr pScreen, int x, int y)
     }
 
     /* None contain pointer, find nearest */
-    RRPointerToNearestCrtc (pScreen, x, y, pointerCrtc);
+    ErrorF("RRPointerMoved: Untested, may cause \"bogus pointer event\"\n");
+    RRPointerToNearestCrtc (inputInfo.pointer, pScreen, x, y, pointerCrtc);
 }
 
 /*
- * When the screen is reconfigured, move the pointer to the nearest
+ * When the screen is reconfigured, move all pointers to the nearest
  * CRTC
  */
 void
 RRPointerScreenConfigured (ScreenPtr pScreen)
 {
-    WindowPtr	pRoot = GetCurrentRootWindow (inputInfo.pointer);
-    ScreenPtr	pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL;
+    WindowPtr	pRoot; 
+    ScreenPtr	pCurrentScreen;
     int		x, y;
-
-    /* XXX: GetCurrentRootWindow revices an argument, It is inputInfo.pointer,
-     * but I really think this is wrong...  What do we do here? This was made so
-     * that it can compile, but I don't think randr should assume there is just
-     * one pointer. There might be more than one pointer on the screen! So, what
-     * to do? What happens? */
+    DeviceIntPtr pDev;
 
     if (pScreen != pCurrentScreen)
 	return;
-    GetSpritePosition(inputInfo.pointer, &x, &y);
-    RRPointerToNearestCrtc (pScreen, x, y, NULL);
+
+    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+    {
+        if (IsPointerDevice(pDev))
+        {
+            pRoot = GetCurrentRootWindow(pDev);
+            pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL;
+
+            if (pScreen == pCurrentScreen)
+            {
+                GetSpritePosition(pDev, &x, &y);
+                RRPointerToNearestCrtc (pDev, pScreen, x, y, NULL);
+            }
+        }
+    }
 }
commit 88a9828ef906bba973debc191e35ea669b7ec271
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Aug 23 18:02:10 2007 +0930

    dix: Only check device events for possible ACLs.
    
    We shouldn't be able to restrict events like Expose, etc. with device based
    ACLs. So we just ignore all non-input events when checking for permissions.

diff --git a/dix/access.c b/dix/access.c
index 970d7c4..2015716 100644
--- a/dix/access.c
+++ b/dix/access.c
@@ -36,6 +36,7 @@ from the author.
 
 #include <X11/Xlib.h>
 #include <X11/extensions/XI.h>
+#include "exglobals.h"
 
 #include "input.h"
 #include "inputstr.h"
@@ -257,15 +258,41 @@ ACQueryWindowAccess(WindowPtr win,
  * If no rule could be found, allow.
  */
 Bool
-ACDeviceAllowed(WindowPtr win, DeviceIntPtr dev)
+ACDeviceAllowed(WindowPtr win, DeviceIntPtr dev, xEvent* xE)
 {
     int i;
 
     if (!win) /* happens for parent of RootWindow */
         return True;
 
+    /* there's a number of events we don't care about */
+    switch (xE->u.u.type)
+    {
+        case ButtonPress:
+        case ButtonRelease:
+        case MotionNotify:
+        case EnterNotify:
+        case LeaveNotify:
+        case KeyPress:
+        case KeyRelease:
+            break;
+        default:
+            if (xE->u.u.type == DeviceMotionNotify ||
+                    xE->u.u.type == DeviceButtonPress ||
+                    xE->u.u.type == DeviceButtonRelease ||
+                    xE->u.u.type == DeviceKeyPress ||
+                    xE->u.u.type == DeviceKeyRelease ||
+                    xE->u.u.type == DeviceEnterNotify ||
+                    xE->u.u.type == DeviceLeaveNotify)
+            {
+                break;
+            }
+            return True;
+    }
+
+
     if (!win->optional) /* no list, check parent */
-        return ACDeviceAllowed(win->parent, dev);
+        return ACDeviceAllowed(win->parent, dev, xE);
 
     for (i = 0; i < win->optional->access.nperm; i++)
     {
@@ -282,6 +309,6 @@ ACDeviceAllowed(WindowPtr win, DeviceIntPtr dev)
             return False;
     }
 
-    return ACDeviceAllowed(win->parent, dev);
+    return ACDeviceAllowed(win->parent, dev, xE);
 }
 
diff --git a/dix/events.c b/dix/events.c
index 4c9ca3b..0f413a6 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1928,8 +1928,10 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
     
     /* if a  is denied, we return 0. This could cause the caller to
      * traverse the parent. May be bad! (whot) */
-    if (!ACDeviceAllowed(pWin, pDev))
+    if (!ACDeviceAllowed(pWin, pDev, pEvents))
+    {
         return 0;
+    }
 
     /* CantBeFiltered means only window owner gets the event */
     if ((filter == CantBeFiltered) || 
@@ -3348,7 +3350,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
     }
     if (!deliveries)
     {
-        if (ACDeviceAllowed(grab->window, thisDev))
+        if (ACDeviceAllowed(grab->window, thisDev, xE))
         {
             if (xE->u.u.type == GenericEvent)
             {
diff --git a/include/input.h b/include/input.h
index 6443a58..d86a969 100644
--- a/include/input.h
+++ b/include/input.h
@@ -495,7 +495,8 @@ extern void ACQueryWindowAccess(WindowPtr win,
                                 int* ndeny);
 
 extern Bool ACDeviceAllowed(WindowPtr win, 
-                            DeviceIntPtr dev);
+                            DeviceIntPtr dev,
+                            xEvent* xE);
 
 /* Implemented by the DDX. */
 extern int NewInputDeviceRequest(
commit 2c1431a76e7219e3bd14fd7f7888a8bc4fea0f58
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Aug 20 10:06:13 2007 +0930

    dix: ProcChangeActivePointerGrab: make sure variable is initialised.
    
    Thanks to Ben Close for spotting it.

diff --git a/dix/events.c b/dix/events.c
index 76894ca..4c9ca3b 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4808,7 +4808,7 @@ int
 ProcChangeActivePointerGrab(ClientPtr client)
 {
     DeviceIntPtr device, grabbed;
-    GrabPtr      grab = device->deviceGrab.grab;
+    GrabPtr      grab;
     CursorPtr newCursor, oldCursor;
     REQUEST(xChangeActivePointerGrabReq);
     TimeStamp time;
@@ -4831,7 +4831,11 @@ ProcChangeActivePointerGrab(ClientPtr client)
 	    return BadCursor;
 	}
     }
-    if (!grab && !SameClient(grab, client))
+
+    device = PickPointer(client);
+    grab = device->deviceGrab.grab;
+
+    if (!grab || !SameClient(grab, client))
     {
         /* no grab on ClientPointer, or some other client has a grab on our
          * ClientPointer, let's check if we have a pointer grab on some other
commit 14d0397cded699378fa3c19f4e61dbab7d3a9b2c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Aug 15 22:12:29 2007 +0930

    dix: ProcUngrabKeyboard: make sure grab is initialized.
    
    This should fix the random segfaults with ProcUngrabKeyboard.
    
    Thanks to David Nolden for spotting it.

diff --git a/dix/events.c b/dix/events.c
index 4cfdab7..76894ca 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5139,6 +5139,8 @@ ProcUngrabKeyboard(ClientPtr client)
     REQUEST_SIZE_MATCH(xResourceReq);
     UpdateCurrentTime();
 
+    grab = device->deviceGrab.grab;
+
     if (!grab || !grab->coreGrab || !SameClient(grab, client))
     {
 	for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
commit f367285fd5825e0adc271982a529c9904ad65c89
Merge: b1272ee... ff4bd3a...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Aug 12 15:31:10 2007 +0930

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	Xi/exevents.c
    	dix/devices.c
    	dix/getevents.c
    	include/dix.h
    	mi/mieq.c

diff --cc dix/devices.c
index 09e64eb,923bc0d..60825c1
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -83,12 -87,13 +87,16 @@@ SOFTWARE
  int CoreDevicePrivatesIndex = 0;
  static int CoreDevicePrivatesGeneration = -1;
  
 +/* The client that is allowed to change pointer-keyboard pairings. */
 +static ClientPtr pairingClient = NULL;
 +
- /** 
-  * Alloc memory for new sprite, reset to default values 
-  */ 
+ /**
+  * Create a new input device and init it to sane values. The device is added
+  * to the server's off_devices list.
+  *
+  * @param deviceProc Callback for device control function (switch dev on/off).
+  * @return The newly created device.
+  */
  DeviceIntPtr
  AddInputDevice(DeviceProc deviceProc, Bool autoStart)
  {
@@@ -175,10 -166,13 +184,15 @@@
  }
  
  /**
-  * Enable the device through the driver, initialize the DIX sprite or pair the
-  * device, add the device to the device list.
++ * Enable the device through the driver, add the device to the device list.
+  * Switch device ON through the driver and push it onto the global device
 - * list. All clients are notified about the device being enabled.
++ * list. Initialize the DIX sprite or pair the device. All clients are
++ * notified about the device being enabled.
   *
-  * After calling EnableDevice(), a device can and will send events.
+  * A device will send events once enabled.
+  *
+  * @param The device to be enabled.
+  * @return TRUE on success or FALSE otherwise.
   */
  Bool
  EnableDevice(DeviceIntPtr dev)
@@@ -259,10 -248,12 +277,13 @@@ DisableDevice(DeviceIntPtr dev
  }
  
  /**
-  * Initialize device through driver, allocate memory for cursor sprite (if
-  * applicable) and send a PresenceNotify event to all clients.
-  *
+  * Initialise a new device through the driver and tell all clients about the
+  * new device.
+  * 
 + * Must be called before EnableDevice.
+  * The device will NOT send events until it is enabled!
+  *
+  * @return Success or an error code on failure.
   */
  int
  ActivateDevice(DeviceIntPtr dev)
@@@ -398,12 -394,10 +429,16 @@@ CorePointerProc(DeviceIntPtr pDev, int 
  }
  
  /**
-  * Initialize a virtual core keyboard and a virtual core pointer. 
-  *
+  * Initialise the two core devices, VCP and VCK (see events.c).
 + * Both devices are not tied to physical devices, but guarantee that there is
 + * always a keyboard and a pointer present and keep the protocol semantics.
 + * Both core devices are NOT part of the device list and act only as a
 + * fallback if no physical device is available.
++ *
+  * The devices are activated but not enabled.
++ *
+  * Note that the server MUST have two core devices at all times, even if there
+  * is no physical device connected.
   */
  void
  InitCoreDevices(void)
@@@ -469,14 -459,15 +504,19 @@@
  }
  
  /**
-  * Activate and enable all devices. 
+  * Activate all switched-off devices and then enable all those devices.
+  * 
+  * Will return an error if no core keyboard or core pointer is present.
+  * In theory this should never happen if you call InitCoreDevices() first.
 + *
 + * InitAndStartDevices needs to be called AFTER the windows are initialized.
 + * Devices will start sending events after InitAndStartDevices() has
 + * completed.
+  * 
+  * @return Success or error code on failure.
   */
  int
 -InitAndStartDevices(void)
 +InitAndStartDevices(WindowPtr root)
  {
      DeviceIntPtr dev, next;
  
@@@ -684,21 -635,11 +732,27 @@@ CloseDownDevices(void
  }
  
  /**
 + * Remove the cursor sprite for all devices. This needs to be done before any
 + * resources are freed or any device is deleted.
 + */
 +void 
 +UndisplayDevices()
 +{
 +    DeviceIntPtr dev;
 +    ScreenPtr screen = screenInfo.screens[0];
 +
 +    for (dev = inputInfo.devices; dev; dev = dev->next)
 +    {
 +        screen->UndisplayCursor(dev, screen);
 +    }
 +}
 +
++/**
+  * Remove a device from the device list, closes it and thus frees all
+  * resources. 
+  * Removes both enabled and disabled devices and notifies all devices about
+  * the removal of the device.
+  */
  int
  RemoveDevice(DeviceIntPtr dev)
  {
diff --cc dix/getevents.c
index 6988b8b,2a10038..bcbc00b
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -449,7 -445,14 +451,15 @@@ GetKeyboardValuatorEvents(EventList *ev
  
      ms = GetTimeInMillis();
  
+     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;
+         events++;
+     }
+ 
 -    kbp = (deviceKeyButtonPointer *) events;
 +    kbp = (deviceKeyButtonPointer *) events->event;
      kbp->time = ms;
      kbp->deviceid = pDev->id;
      kbp->detail = key_code;
@@@ -561,14 -502,18 +564,18 @@@ GetPointerEvents(EventList *events, Dev
      if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
          return 0;
  
-     if (!coreOnly && (pDev->coreEvents))
+     /* FIXME: I guess it should, in theory, be possible to post button events
+      *        from devices without valuators. */
+     if (!pDev->valuator)
+         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) {
+     if (type == MotionNotify && num_valuators <= 0)
          return 0;
-     }
  
      /* Do we need to send a DeviceValuator event? */
      if (!coreOnly && sendValuators) {
@@@ -670,10 -603,32 +677,29 @@@
 -    if (pDev->coreEvents) {
 -        cp->valuator->lastx = x;
 -        cp->valuator->lasty = y;
 -    }
      pDev->valuator->lastx = x;
      pDev->valuator->lasty = y;
  
-     /* create Xi event */
-     if (!coreOnly)
-     {
+     /* for some reason inputInfo.pointer does not have coreEvents set */
+     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;
+         }
+ 
+         events++;
+     }
+ 
+     if (!coreOnly) {
 -        kbp = (deviceKeyButtonPointer *) events;
 +        kbp = (deviceKeyButtonPointer *) events->event;
          kbp->time = ms;
          kbp->deviceid = pDev->id;
  
diff --cc dix/main.c
index 595ed15,9fe822b..5d24922
--- a/dix/main.c
+++ b/dix/main.c
@@@ -397,16 -393,16 +395,12 @@@ 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
-         defaultFontPath = "built-ins";
- #else
  	if (loadableFonts) {
  	    SetFontPath(0, 0, (unsigned char *)defaultFontPath, &error);
- 	} else 
- #endif
-         {
+ 	}
+         else {
  	    if (SetDefaultFontPath(defaultFontPath) != Success)
  		ErrorF("failed to set default font path '%s'",
  			defaultFontPath);
diff --cc dix/window.c
index 193f1aa,be4ea2c..3247446
--- a/dix/window.c
+++ b/dix/window.c
@@@ -310,14 -298,8 +310,14 @@@ SetWindowToDefaults(WindowPtr pWin
      pWin->dontPropagate = 0;
      pWin->forcedBS = FALSE;
  #ifdef COMPOSITE
-     pWin->redirectDraw = 0;
+     pWin->redirectDraw = RedirectDrawNone;
  #endif
 +
 +    ((FocusSemaphoresPtr)
 +     pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave = 0;
 +    ((FocusSemaphoresPtr)
 +     pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout = 0;
 +
  }
  
  static void
diff --cc hw/xfree86/common/xf86Xinput.c
index 3bc8542,e45d44c..4c9de1f
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@@ -45,17 -45,7 +45,16 @@@
   * the sale, use or other dealings in this Software without prior written
   * authorization from the copyright holder(s) and author(s).
   */
- /* $XConsortium: xf86Xinput.c /main/14 1996/10/27 11:05:25 kaleb $ */
  
 + /* 
 +  * MPX additions:
 +  * Copyright © 2006 Peter Hutterer
 +  * License see above.
 +  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
 +  *
 +  */
 +
 +
  #ifdef HAVE_XORG_CONFIG_H
  #include <xorg-config.h>
  #endif
@@@ -447,15 -408,12 +447,18 @@@ NewInputDeviceRequest (InputOption *opt
  
      dev = pInfo->dev;
      ActivateDevice(dev);
-     if (dev->inited && dev->startup && xf86Screens[0]->vtSema)
+     /* Enable it if it's properly initialised, we're currently in the VT, and
+      * either it's a manual request, or we're automatically enabling devices. */
+     if (dev->inited && dev->startup && xf86Screens[0]->vtSema &&
+         (!is_auto || xf86Info.autoEnableDevices))
          EnableDevice(dev);
  
 +    if (!IsPointerDevice(dev))
 +        PairDevices(NULL, GuessFreePointerDevice(), dev);
 +
 +    /* send enter/leave event, update sprite window */
 +    CheckMotion(NULL, dev);
 +
      *pdev = dev;
      return Success;
  
diff --cc include/dix.h
index 2fc6254,c1d609a..5caa6e2
--- a/include/dix.h
+++ b/include/dix.h
@@@ -689,30 -640,4 +689,27 @@@ typedef struct 
  extern int xstrcasecmp(char *s1, char *s2);
  #endif
  
- /* ffs.c */
- extern int ffs(int i);
- 
 +extern Bool DevHasCursor(DeviceIntPtr pDev);
 +
 +extern Bool IsPointerDevice( DeviceIntPtr dev);
 +extern Bool IsKeyboardDevice(DeviceIntPtr dev);
 +
 +
 +/* GE stuff */
 +extern void SetGenericFilter(int extension, Mask* filters);
 +
 +extern int ExtGrabDevice(ClientPtr client,
 +                         DeviceIntPtr dev,
 +                         int device_mode,
 +                         WindowPtr grabWindow,
 +                         WindowPtr confineTo,
 +                         TimeStamp ctime,
 +                         Bool ownerEvents,
 +                         CursorPtr cursor, 
 +                         Mask xi_mask,
 +                         GenericMaskPtr ge_masks);
 +
 +extern int ExtUngrabDevice(ClientPtr client,
 +                         DeviceIntPtr dev);
 +
  #endif /* DIX_H */
commit b1272eefd9a3e340d65c14903f337747ec82d021
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Aug 8 15:00:02 2007 +0930

    Fix typo from last commit. Oh well.

diff --git a/dix/events.c b/dix/events.c
index 7627f4e..6727a17 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3157,7 +3157,7 @@ CheckPassiveGrabsOnWindow(
                This essentially requires a client to re-create all
                passiveGrabs when the pairing changes... oh well.
              */ 
-            if (xE->u.u.type < LASTEVENT)
+            if (xE->u.u.type < LASTEvent)
             {
                 grab->device = device; 
                 grab->modifierDevice = GetPairedKeyboard(device);
commit c02128532e910e813fba94983733942d30c2d5cb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Aug 8 13:10:00 2007 +0930

    dix: Allow flexible devices for passive core grabs.
    
    A passive core grab doesn't specify the device, and is thus created with the
    ClientPointer as device.  When this grab is activated later, don't actually
    activate the grab on the grab device, but rather change the device to the one
    that caused the grab to activate. Same procedure for keyboards.
    
    Makes core apps _A LOT_ more useable and reduces the need to set the
    ClientPointer.
    
    Only applies to core grabs!

diff --git a/dix/events.c b/dix/events.c
index faf8eed..7627f4e 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1685,17 +1685,45 @@ AllowSome(ClientPtr client,
  * Server-side protocol handling for AllowEvents request.
  *
  * Release some events from a frozen device. 
+ * 
+ * In some cases, the grab the client has is not on the ClientPointer but on
+ * some other device (see ProcGrabPointer comments). To cover this case, we
+ * need to run through all devices to ensure we don't forget the device we
+ * actually have a grab on.
  */
 int
 ProcAllowEvents(ClientPtr client)
 {
     TimeStamp		time;
-    DeviceIntPtr	mouse = PickPointer(client);
-    DeviceIntPtr	keybd = PickKeyboard(client);
+    DeviceIntPtr	mouse = NULL,
+			grabbed;
+    DeviceIntPtr	keybd = NULL;
+    GrabPtr		grab;
     REQUEST(xAllowEventsReq);
 
     REQUEST_SIZE_MATCH(xAllowEventsReq);
     time = ClientTimeToServerTime(stuff->time);
+
+    for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
+    {
+        grab = grabbed->deviceGrab.grab;
+        if (grab && grab->coreGrab && SameClient(grab, client))
+        {
+            if (IsPointerDevice(grabbed))
+                mouse = grabbed;
+            else if (IsKeyboardDevice(grabbed))
+                keybd = grabbed;
+
+	    if (mouse && keybd) 
+		break;
+        }
+    }
+
+    if (!mouse)
+        mouse = PickPointer(client);
+    if (!keybd)
+        keybd = PickKeyboard(client);
+
     switch (stuff->mode)
     {
 	case ReplayPointer:
@@ -3104,7 +3132,8 @@ CheckPassiveGrabsOnWindow(
 #else
 		grab->modifierDevice->key->state;
 #endif
-	if (GrabMatchesSecond(&tempGrab, grab) &&
+            /* ignore the device for core events when comparing grabs */
+	if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) &&
 	    (!grab->confineTo ||
 	     (grab->confineTo->realized && 
 				BorderSizeNotEmpty(device, grab->confineTo))))
@@ -3119,6 +3148,23 @@ CheckPassiveGrabsOnWindow(
 	    }
 #endif
             grabinfo = &device->deviceGrab;
+            /* A passive grab may have been created for a different device
+               than it is assigned to at this point in time.
+               Update the grab's device and modifier device to reflect the
+               current state.
+               XXX: Since XGrabDeviceButton requires to specify the
+               modifierDevice explicitly, we don't override this choice.
+               This essentially requires a client to re-create all
+               passiveGrabs when the pairing changes... oh well.
+             */ 
+            if (xE->u.u.type < LASTEVENT)
+            {
+                grab->device = device; 
+                grab->modifierDevice = GetPairedKeyboard(device);
+                if (!grab->modifierDevice)
+                    grab->modifierDevice = inputInfo.keyboard;
+            }
+
 	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
  
 	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
@@ -4607,10 +4653,16 @@ ProcGetInputFocus(ClientPtr client)
 }
 
 /**
- * Server-side protocol handling for Grabpointer request.
+ * Server-side protocol handling for GrabPointer request.
  *
  * Sets an active grab on the client's ClientPointer and returns success
  * status to client.
+ *
+ * A special case of GrabPointer is when there is already a grab on some
+ * device (by the same client). In this case, this grab is overwritten, and
+ * the device stays as it is. This case can happen when a client has a passive
+ * grab and then grabs the pointer, or when the client already has an active
+ * grab and the ClientPointer was changed since.
  */
 int
 ProcGrabPointer(ClientPtr client)
@@ -4623,6 +4675,7 @@ ProcGrabPointer(ClientPtr client)
     REQUEST(xGrabPointerReq);
     TimeStamp time;
     int rc;
+    DeviceIntPtr grabbed = NULL;
 
     REQUEST_SIZE_MATCH(xGrabPointerReq);
     UpdateCurrentTime();
@@ -4677,6 +4730,21 @@ ProcGrabPointer(ClientPtr client)
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
     rep.length = 0;
+
+    /* Check if a the client already has a grab on a device */
+    for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
+    {
+        if (IsPointerDevice(grabbed))
+        {
+            grab = grabbed->deviceGrab.grab;
+            if (grab && grab->coreGrab && SameClient(grab, client))
+            {
+                device = grabbed;
+                break;
+            }
+        }
+    }
+
     grab = device->deviceGrab.grab;
     if ((grab) && !SameClient(grab, client))
 	rep.status = AlreadyGrabbed;
@@ -4720,6 +4788,7 @@ ProcGrabPointer(ClientPtr client)
 	    FreeCursor (oldCursor, (Cursor)0);
 	rep.status = GrabSuccess;
 
+        /* guarantee only one core pointer grab at a time by this client */
         RemoveOtherCoreGrabs(client, device);
     }
     WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
@@ -4732,12 +4801,14 @@ ProcGrabPointer(ClientPtr client)
  * Changes properties of the grab hold by the client. If the client does not
  * hold an active grab on the device, nothing happens. 
  *
- * Works on the client's ClientPointer.
+ * Works on the client's ClientPointer, but in some cases the client may have
+ * a grab on a device that isn't the ClientPointer (see ProcGrabPointer
+ * comments). 
  */
 int
 ProcChangeActivePointerGrab(ClientPtr client)
 {
-    DeviceIntPtr device = PickPointer(client);
+    DeviceIntPtr device, grabbed;
     GrabPtr      grab = device->deviceGrab.grab;
     CursorPtr newCursor, oldCursor;
     REQUEST(xChangeActivePointerGrabReq);
@@ -4761,6 +4832,31 @@ ProcChangeActivePointerGrab(ClientPtr client)
 	    return BadCursor;
 	}
     }
+    if (!grab && !SameClient(grab, client))
+    {
+        /* no grab on ClientPointer, or some other client has a grab on our
+         * ClientPointer, let's check if we have a pointer grab on some other
+         * device. */
+        for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
+        {
+            if (IsPointerDevice(grabbed))
+            {
+                grab = grabbed->deviceGrab.grab;
+                if (grab && grab->coreGrab && SameClient(grab, client))
+                {
+                    device = grabbed;
+                    break;
+                }
+            }
+        }
+        /* nope. no grab on any actual device */
+        if (!grabbed)
+        {
+            device = inputInfo.pointer;
+            grab = inputInfo.pointer->deviceGrab.grab;
+        }
+    }
+
     if (!grab)
 	return Success;
     if (!SameClient(grab, client))
@@ -4783,12 +4879,17 @@ ProcChangeActivePointerGrab(ClientPtr client)
 /**
  * Server-side protocol handling for UngrabPointer request.
  *
- * Deletes the pointer grab on the client's ClientPointer device.
+ * Deletes a pointer grab on a device the client has grabbed. This should be
+ * the ClientPointer, but may not be. So we search the device list for a
+ * device we have a pointer grab on and then ungrab this device. (see
+ * ProcGrabPointer comments). We are guaranteed that the client doesn't have
+ * more than one core pointer grab at a time.
  */
 int
 ProcUngrabPointer(ClientPtr client)
 {
-    DeviceIntPtr device = PickPointer(client);
+    DeviceIntPtr device = PickPointer(client),
+                 grabbed;
     GrabPtr grab;
     TimeStamp time;
     REQUEST(xResourceReq);
@@ -4796,6 +4897,31 @@ ProcUngrabPointer(ClientPtr client)
     REQUEST_SIZE_MATCH(xResourceReq);
     UpdateCurrentTime();
     grab = device->deviceGrab.grab;
+
+    if (!grab || !grab->coreGrab || !SameClient(grab, client))
+    {
+        /* No pointer grab on ClientPointer. May be a pointer grab on some
+         * other device */
+        for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
+        {
+            if (IsPointerDevice(grabbed))
+            {
+                grab = grabbed->deviceGrab.grab;
+                if (grab && grab->coreGrab && SameClient(grab, client))
+                {
+                    device = grabbed;
+                    break;
+                }
+            }
+        }
+        /* nope. no grab on any actual device */
+        if (!grabbed)
+        {
+            device = inputInfo.pointer;
+            grab = inputInfo.pointer->deviceGrab.grab;
+        }
+    }
+
     time = ClientTimeToServerTime(stuff->id);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
 	    (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
@@ -4935,6 +5061,15 @@ RemoveOtherCoreGrabs(ClientPtr client, DeviceIntPtr dev)
  * Server-side protocol handling for GrabKeyboard request.
  *
  * Grabs the client's keyboard and returns success status to client.
+ *
+ * In some special cases the client may already have a grab on a keyboard that
+ * is not the one that is paired with the ClientPointer. This can happen when
+ * the client alreay has a passive grab on some keyboard device, or when the
+ * client actively grabbed the keyboard and the ClientPointer or keyboard
+ * pairing was changed since.
+ * Therefore, we need to run through all the keyboards available and check if
+ * there's already a grab on it from our client. The client will only ever
+ * have one core keyboard grab at a time.
  */
 int
 ProcGrabKeyboard(ClientPtr client)
@@ -4942,16 +5077,32 @@ ProcGrabKeyboard(ClientPtr client)
     xGrabKeyboardReply rep;
     REQUEST(xGrabKeyboardReq);
     int result;
-    DeviceIntPtr keyboard = PickKeyboard(client);
+    DeviceIntPtr keyboard = PickKeyboard(client),
+                 grabbed;
+    GrabPtr      grab;
 
     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
 
+    for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
+    {
+	if (IsKeyboardDevice(grabbed))
+	{
+	    grab = grabbed->deviceGrab.grab;
+	    if (grab && grab->coreGrab && SameClient(grab, client))
+	    {
+		keyboard = grabbed;
+		break;
+	    }
+	}
+    }
+
     if (XaceHook(XACE_DEVICE_ACCESS, client, keyboard, TRUE))
     {
 	result = GrabDevice(client, keyboard, stuff->keyboardMode,
 			    stuff->pointerMode, stuff->grabWindow,
 			    stuff->ownerEvents, stuff->time,
 			    KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
+        /* ensure only one core keyboard grab by this client */
         RemoveOtherCoreGrabs(client, keyboard);
     }
     else {
@@ -4972,18 +5123,40 @@ ProcGrabKeyboard(ClientPtr client)
  * Server-side protocol handling for UngrabKeyboard request.
  *
  * Deletes a possible grab on the client's keyboard.
+ *
+ * We may have a grab on a keyboard that isn't the ClientPointer's keyboard.
+ * Thus we need to check all keyboar devices for a grab. (see ProcGrabKeyboard
+ * comments)
  */
 int
 ProcUngrabKeyboard(ClientPtr client)
 {
-    DeviceIntPtr device = PickKeyboard(client);
+    DeviceIntPtr device = PickKeyboard(client),
+		 grabbed;
     GrabPtr grab;
     TimeStamp time;
     REQUEST(xResourceReq);
 
     REQUEST_SIZE_MATCH(xResourceReq);
     UpdateCurrentTime();
+
+    if (!grab || !grab->coreGrab || !SameClient(grab, client))
+    {
+	for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next)
+	{
+	    if (IsKeyboardDevice(grabbed))
+	    {
+		grab = device->deviceGrab.grab;
+		if (grab && grab->coreGrab && SameClient(grab, client))
+		{
+		    device = grabbed;
+		    break;
+		}
+	    }
+	}
+    }
     grab = device->deviceGrab.grab;
+
     time = ClientTimeToServerTime(stuff->id);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
 	(CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
diff --git a/dix/grabs.c b/dix/grabs.c
index 9150c3c..01f4b64 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -240,12 +240,28 @@ GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
     return FALSE;
 }
 
+/**
+ * Compares two grabs and returns TRUE if the first grab matches the second
+ * grab. 
+ * 
+ * A match is when 
+ *  - the devices set for the grab are equal (this is optional).
+ *  - the event types for both grabs are equal.
+ *  - XXX
+ *
+ * @param ignoreDevice TRUE if the device settings on the grabs are to be
+ * ignored.
+ * @return TRUE if the grabs match or FALSE otherwise.
+ */
 Bool
-GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
+GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab, Bool ignoreDevice)
 {
-    if ((pFirstGrab->device != pSecondGrab->device) ||
-	(pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) ||
-	(pFirstGrab->type != pSecondGrab->type))
+    if (!ignoreDevice &&
+            ((pFirstGrab->device != pSecondGrab->device) ||
+             (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice)))
+            return FALSE;
+
+    if (pFirstGrab->type != pSecondGrab->type)
 	return FALSE;
 
     if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
@@ -278,7 +294,7 @@ AddPassiveGrabToList(GrabPtr pGrab)
 
     for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
     {
-	if (GrabMatchesSecond(pGrab, grab))
+	if (GrabMatchesSecond(pGrab, grab, FALSE))
 	{
 	    if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource))
 	    {
@@ -343,7 +359,7 @@ DeletePassiveGrabFromList(GrabPtr pMinuendGrab)
 	 grab = grab->next)
     {
 	if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) ||
-	    !GrabMatchesSecond(grab, pMinuendGrab))
+	    !GrabMatchesSecond(grab, pMinuendGrab, FALSE))
 	    continue;
 	if (GrabSupersedesSecond(pMinuendGrab, grab))
 	{
diff --git a/include/dixgrabs.h b/include/dixgrabs.h
index 2d66d6b..b237ab3 100644
--- a/include/dixgrabs.h
+++ b/include/dixgrabs.h
@@ -47,7 +47,8 @@ extern int DeletePassiveGrab(
 
 extern Bool GrabMatchesSecond(
 	GrabPtr /* pFirstGrab */,
-	GrabPtr /* pSecondGrab */);
+	GrabPtr /* pSecondGrab */,
+	Bool /*ignoreDevice*/);
 
 extern int AddPassiveGrabToList(
 	GrabPtr /* pGrab */);
commit b8abeaf74ee8296d4bc3164a5a253624f984a6d4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Aug 7 12:32:46 2007 +0930

    dix: get the paired keyboard for a passive grab (ProcGrabButton).
    
    Taking the VCK is only correct if no physical device is connected, and even
    then it's not really a good idea.

diff --git a/dix/events.c b/dix/events.c
index 7de8d2e..faf8eed 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5326,6 +5326,7 @@ ProcGrabButton(ClientPtr client)
     REQUEST(xGrabButtonReq);
     CursorPtr cursor;
     GrabPtr grab;
+    DeviceIntPtr pointer, modifierDevice;
     int rc;
 
     REQUEST_SIZE_MATCH(xGrabButtonReq);
@@ -5381,11 +5382,15 @@ ProcGrabButton(ClientPtr client)
 	}
     }
 
+    pointer = PickPointer(client);
+    modifierDevice = GetPairedKeyboard(pointer);
+    if (!modifierDevice)
+        modifierDevice = inputInfo.keyboard;
 
-    grab = CreateGrab(client->index, PickPointer(client), pWin, 
+    grab = CreateGrab(client->index, pointer, pWin, 
         (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
         (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode,
-        inputInfo.keyboard, stuff->modifiers, ButtonPress,
+        modifierDevice, stuff->modifiers, ButtonPress,
         stuff->button, confineTo, cursor);
     if (!grab)
 	return BadAlloc;
commit a0b87f87fb8753955505958bf3d438eef191302d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Aug 7 10:49:33 2007 +0930

    dix: check for core event to determine if grab is a core grab (CreateGrab).
    
    Checking for VCP/VCK is simply not a safe way to check if a grab is a core grab.

diff --git a/dix/grabs.c b/dix/grabs.c
index af471eb..9150c3c 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -87,8 +87,7 @@ CreateGrab(
 	return (GrabPtr)NULL;
     grab->resource = FakeClientID(client);
     grab->device = device;
-    grab->coreGrab = ((device == inputInfo.keyboard) ||
-		      (device == inputInfo.pointer));
+    grab->coreGrab = (type < LASTEvent);
     grab->window = window;
     grab->eventMask = eventMask;
     grab->deviceMask = 0;
commit 9eddede039f6cbcc323b7e3e4e841c43d3ed4f43
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jul 16 18:01:00 2007 +0930

    mieqEnqueue: Don't try to update the time for GenericEvents.
    
    Doing so may overwrite the event's length field and cause havoc. Also check if
    realloc'd memory did actually return valid pointer.

diff --git a/mi/mieq.c b/mi/mieq.c
index 4b29950..c3f63fb 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -184,6 +184,11 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
     {
         evt->evlen = evlen;
         evt->event = xrealloc(evt->event, evt->evlen);
+        if (!evt->event)
+        {
+            ErrorF("Running out of memory. Tossing event.\n");
+            return;
+        }
     }
 
     memcpy(evt->event, e, evlen);
@@ -191,8 +196,9 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 
     /* 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)
+    if (e->u.u.type != GenericEvent &&
+        e->u.keyButtonPointer.time < miEventQueue.lastEventTime &&
+            miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
         evt->event->u.keyButtonPointer.time = miEventQueue.lastEventTime;
 
     miEventQueue.lastEventTime = evt->event->u.keyButtonPointer.time;
@@ -293,7 +299,9 @@ mieqProcessInputEvents(void)
                     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
commit ffdf8f3e452638e6b050fccabee465d6c0300f45
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jul 10 13:56:38 2007 +0930

    DeliverEventsToWindow: ensure that genericMask has a defined value.

diff --git a/autogen.sh b/autogen.sh
index 66acd28..54e9f33 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -9,4 +9,4 @@ cd $srcdir
 autoreconf -v --install || exit 1
 cd $ORIGDIR || exit $?
 
-$srcdir/configure --enable-maintainer-mode --disable-dmx --enable-kdrive "$@"
+$srcdir/configure --enable-maintainer-mode --disable-dmx --enable-dri --enable-kdrive "$@"
diff --git a/dix/events.c b/dix/events.c
index 097ebba..7de8d2e 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2020,9 +2020,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
         /* get the XGE event mask. 
          * FIXME: needs to be freed somewhere too.
          */
-        if (!pWin->optional || !pWin->optional->geMasks)
-            tempGrab.genericMasks = NULL;
-        else
+        tempGrab.genericMasks = NULL;
+        if (pWin->optional && pWin->optional->geMasks)
         {
             GenericClientMasksPtr gemasks = pWin->optional->geMasks;
             GenericMaskPtr geclient = gemasks->geClients;
commit 583e988b9f7cfb9293144c8309023c0dd1766715
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jul 10 09:19:02 2007 +0930

    Install geext.h, otherwise drivers won't build.

diff --git a/Xext/Makefile.am b/Xext/Makefile.am
index 2fcac89..cdfd0dc 100644
--- a/Xext/Makefile.am
+++ b/Xext/Makefile.am
@@ -15,7 +15,7 @@ INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod
 AM_CFLAGS = $(DIX_CFLAGS)
 
 if XORG
-sdk_HEADERS = xvdix.h xvmcext.h
+sdk_HEADERS = xvdix.h xvmcext.h geext.h
 endif
 
 # Sources always included in libXextbuiltin.la & libXext.la
commit 9809715afaafee9baf2aef348c1ebda7e8b3f076
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jul 9 10:42:03 2007 +0930

    Change CheckMotion to ignore non-pointer events but acknowledge XI events.
    
    Call CheckMotion from ProcessOtherEvents() to make sure absolute XI events
    update the sprite before an event is sent.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index c13b747..8f60561 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -129,6 +129,8 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     if (grab && grab->coreGrab && !device->deviceGrab.fromPassiveGrab)
         return;
 
+    CheckMotion(xE, device);
+
     if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
         DeviceIntPtr mouse = NULL, kbd = NULL;
 	GetSpritePosition(device, &rootX, &rootY);
diff --git a/dix/events.c b/dix/events.c
index 8fcbec7..097ebba 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2449,10 +2449,16 @@ XYToWindow(DeviceIntPtr pDev, int x, int y)
  * position, then update the event with the new coordinates that may have been
  * changed. If the window underneath the sprite has changed, change to new
  * cursor and send enter/leave events.
+ *
+ * CheckMotion() will not do anything and return FALSE if the event is not a
+ * pointer event.
+ *
+ * @return TRUE if the sprite has moved or FALSE otherwise. 
  */
 Bool
 CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
+    INT16     *rootX, *rootY;
     WindowPtr prevSpriteWin;
     SpritePtr pSprite = pDev->spriteInfo->sprite;
         
@@ -2465,21 +2471,44 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 
     if (xE && !syncEvents.playingEvents)
     {
-	if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
-	{
-	    pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
-	    RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
-	}
-	pSprite->hot.x = XE_KBPTR.rootX;
-	pSprite->hot.y = XE_KBPTR.rootY;
-	if (pSprite->hot.x < pSprite->physLimits.x1)
-	    pSprite->hot.x = pSprite->physLimits.x1;
-	else if (pSprite->hot.x >= pSprite->physLimits.x2)
-	    pSprite->hot.x = pSprite->physLimits.x2 - 1;
-	if (pSprite->hot.y < pSprite->physLimits.y1)
-	    pSprite->hot.y = pSprite->physLimits.y1;
-	else if (pSprite->hot.y >= pSprite->physLimits.y2)
-	    pSprite->hot.y = pSprite->physLimits.y2 - 1;
+        /* GetPointerEvents() guarantees that pointer events have the correct
+           rootX/Y set already. */
+        switch(xE->u.u.type)
+        {
+            case ButtonPress:
+            case ButtonRelease:
+            case MotionNotify:
+                rootX = &XE_KBPTR.rootX;
+                rootY = &XE_KBPTR.rootY;
+                break;
+            default:
+                if (xE->u.u.type == DeviceButtonPress ||
+                        xE->u.u.type == DeviceButtonRelease ||
+                        xE->u.u.type == DeviceMotionNotify)
+                {
+                    rootX = &((deviceKeyButtonPointer*)xE)->root_x;
+                    rootY = &((deviceKeyButtonPointer*)xE)->root_y;
+                    break;
+                }
+                /* all other events return FALSE */
+                return FALSE;
+        }
+
+        if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
+        {
+            pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
+            RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
+        }
+        pSprite->hot.x = *rootX;
+        pSprite->hot.y = *rootY;
+        if (pSprite->hot.x < pSprite->physLimits.x1)
+            pSprite->hot.x = pSprite->physLimits.x1;
+        else if (pSprite->hot.x >= pSprite->physLimits.x2)
+            pSprite->hot.x = pSprite->physLimits.x2 - 1;
+        if (pSprite->hot.y < pSprite->physLimits.y1)
+            pSprite->hot.y = pSprite->physLimits.y1;
+        else if (pSprite->hot.y >= pSprite->physLimits.y2)
+            pSprite->hot.y = pSprite->physLimits.y2 - 1;
 #ifdef SHAPE
 	if (pSprite->hotShape)
 	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
@@ -2490,16 +2519,16 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 #endif
 	pSprite->hotPhys = pSprite->hot;
 
-	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
-	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
+	if ((pSprite->hotPhys.x != *rootX) ||
+	    (pSprite->hotPhys.y != *rootY))
 	{
 	    (*pSprite->hotPhys.pScreen->SetCursorPosition)(
                 pDev, pSprite->hotPhys.pScreen,
 		pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
 	}
 
-	XE_KBPTR.rootX = pSprite->hot.x;
-	XE_KBPTR.rootY = pSprite->hot.y;
+	*rootX = pSprite->hot.x;
+	*rootY = pSprite->hot.y;
     }
 
 #ifdef XEVIE
@@ -3635,9 +3664,8 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 	}
     }
     /* We need to call CheckMotion for each event. It doesn't really give us
-       any benefit for relative devices, but absolute devices won't send
-       button events to the right position. 
-     */
+       any benefit for relative devices, but absolute devices may not send
+       button events to the right position otherwise. */
     if (!CheckMotion(xE, mouse) && xE->u.u.type == MotionNotify)
             return;
     if (xE->u.u.type != MotionNotify)
commit 62efc3951a96648cf975302aa6651cb67b87fa64
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jul 6 17:00:20 2007 +0930

    DeliverGrabbedEvent: stop segfault when gemask == NULL.

diff --git a/dix/events.c b/dix/events.c
index 9a6ab33..8fcbec7 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3283,7 +3283,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                 xGenericEvent* ge = ((xGenericEvent*)xE);
                 GenericMaskPtr    gemask = grab->genericMasks;
 
-                if (!gemask->eventMask[GEEXTIDX(ge)])
+                if (!gemask || !gemask->eventMask[GEEXTIDX(ge)])
                     return;
 
                 if (GEEventFill(xE))
commit 3312e4dd5e055b2cb445b5d5c617aa7a611eedc1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jul 6 16:41:52 2007 +0930

    Call CheckMotion for all core events.
    
    We need to do this to update the sprites x/y coordinate before we assemble a
    button event. Absolute devices may send a buttonEvent with valuators attached.
    If we don't update the sprite before assembling the event, the valuators are
    lost and the button press is delivered to the previous position of the device.
    Doesn't have any effect on relative devices.

diff --git a/dix/events.c b/dix/events.c
index 1bec4fc..9a6ab33 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3634,6 +3634,12 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 	    CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
 	}
     }
+    /* We need to call CheckMotion for each event. It doesn't really give us
+       any benefit for relative devices, but absolute devices won't send
+       button events to the right position. 
+     */
+    if (!CheckMotion(xE, mouse) && xE->u.u.type == MotionNotify)
+            return;
     if (xE->u.u.type != MotionNotify)
     {
 	int  key;
@@ -3682,8 +3688,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
 	    FatalError("bogus pointer event from ddx");
 	}
     }
-    else if (!CheckMotion(xE, mouse))
-	return;
+
     if (grab)
 	DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
     else
commit c1a6841a64576b7e688e9ca0d3e0db8acf52d4ae
Author: Paulo Ricardo Zanoni <prz05 at c3sl.ufpr.br>
Date:   Tue Jul 10 10:08:44 2007 +0930

    ProcX{Change|Query}WindowAccess: change device list from char* to XID*.

diff --git a/Xi/chaccess.c b/Xi/chaccess.c
index 5005e94..f099206 100644
--- a/Xi/chaccess.c
+++ b/Xi/chaccess.c
@@ -65,7 +65,7 @@ int
 ProcXChangeWindowAccess(ClientPtr client)
 {
     int padding, err, i;
-    CARD8* deviceids = NULL;
+    XID* deviceids = NULL;
     WindowPtr win;
     DeviceIntPtr* perm_devices = NULL;
     DeviceIntPtr* deny_devices = NULL;
@@ -73,10 +73,10 @@ ProcXChangeWindowAccess(ClientPtr client)
     REQUEST_AT_LEAST_SIZE(xChangeWindowAccessReq);
     
 
-    padding = (4 - ((stuff->npermit + stuff->ndeny) % 4)) % 4;
+    padding = (4 - (((stuff->npermit + stuff->ndeny) * sizeof(XID)) % 4)) % 4;
 
     if (stuff->length != ((sizeof(xChangeWindowAccessReq)  + 
-            (stuff->npermit + stuff->ndeny + padding)) >> 2))
+            (((stuff->npermit + stuff->ndeny) * sizeof(XID)) + padding)) >> 2))
     {
         SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
                 0, BadLength);
@@ -102,7 +102,7 @@ ProcXChangeWindowAccess(ClientPtr client)
     }
 
     if (stuff->npermit || stuff->ndeny)
-        deviceids = (CARD8*)&stuff[1];
+        deviceids = (XID*)&stuff[1];
 
     if (stuff->npermit)
     {
diff --git a/Xi/qryacces.c b/Xi/qryacces.c
index 817bec8..b596969 100644
--- a/Xi/qryacces.c
+++ b/Xi/qryacces.c
@@ -69,7 +69,7 @@ ProcXQueryWindowAccess(ClientPtr client)
     DeviceIntPtr *perm, *deny;
     int nperm, ndeny, i;
     int defaultRule;
-    CARD8* deviceids;
+    XID* deviceids;
     xQueryWindowAccessReply rep;
 
     REQUEST(xQueryWindowAccessReq);
@@ -88,7 +88,7 @@ ProcXQueryWindowAccess(ClientPtr client)
     rep.repType = X_Reply;
     rep.RepType = X_QueryWindowAccess;
     rep.sequenceNumber = client->sequence;
-    rep.length = (nperm + ndeny + 3) >> 2;
+    rep.length = ((nperm + ndeny) * sizeof(XID) + 3) >> 2;
     rep.defaultRule = defaultRule;
     rep.npermit = nperm;
     rep.ndeny = ndeny;
@@ -96,7 +96,7 @@ ProcXQueryWindowAccess(ClientPtr client)
 
     if (nperm + ndeny)
     {
-        deviceids = (CARD8*)xalloc((nperm + ndeny) * sizeof(CARD8));
+        deviceids = (XID*)xalloc((nperm + ndeny) * sizeof(XID));
         if (!deviceids)
         {
             ErrorF("ProcXQueryWindowAccess: xalloc failure.\n");
@@ -110,7 +110,7 @@ ProcXQueryWindowAccess(ClientPtr client)
         for (i = 0; i < ndeny; i++)
             deviceids[i + nperm] = deny[i]->id;
 
-        WriteToClient(client, nperm + ndeny, (char*)deviceids);
+        WriteToClient(client, (nperm + ndeny) * sizeof(XID), (char*)deviceids);
         xfree(deviceids);
     }
     return Success;
commit 5ccc09b18244f91a06b3bea20b02a97280d1a229
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jul 6 15:43:08 2007 +0930

    Use the same struct for generic event masks throughout the code.
    Renaming those structs too.
    
    Previously grabs were using a different struct than windows, which was
    reasonably stupid.

diff --git a/Xext/geext.c b/Xext/geext.c
index 0add5e1..0c5fcab 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -207,7 +207,7 @@ GEExtensionInit(void)
 
     GEClientPrivateIndex = AllocateClientPrivateIndex(); 
     if (!AllocateClientPrivate(GEClientPrivateIndex, 
-                               sizeof(GEClientRec)))
+                               sizeof(GenericMaskRec)))
     {
         FatalError("GEExtensionInit: Alloc client private failed.\n");
     }
@@ -277,8 +277,8 @@ static void
 GERecalculateWinMask(WindowPtr pWin)
 {
     int i;
-    GEClientPtr it;
-    GEEventMasksPtr evmasks;
+    GenericMaskPtr it;
+    GenericClientMasksPtr evmasks;
 
     if (!pWin->optional)
         return;
@@ -304,7 +304,7 @@ GERecalculateWinMask(WindowPtr pWin)
 /* Set generic event mask for given window. */
 void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask)
 {
-    GEClientPtr cli;
+    GenericMaskPtr cli;
 
     extension = (extension & 0x7F);
 
@@ -322,7 +322,7 @@ void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask
 
     if (mask)
     {
-        GEEventMasksPtr evmasks = pWin->optional->geMasks;
+        GenericClientMasksPtr evmasks = pWin->optional->geMasks;
 
         /* check for existing client */
         cli = evmasks->geClients;
@@ -335,7 +335,7 @@ void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask
         if (!cli)
         {
             /* new client */
-            cli  = (GEClientPtr)xcalloc(1, sizeof(GEClientRec));
+            cli  = (GenericMaskPtr)xcalloc(1, sizeof(GenericMaskRec));
             if (!cli)
             {
                 ErrorF("GE: Insufficient memory to alloc client.\n");
@@ -356,7 +356,7 @@ void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask
             xfree(cli);
         } else 
         { 
-            GEClientPtr prev = cli;
+            GenericMaskPtr prev = cli;
             cli = cli->next;
 
             while(cli)
diff --git a/Xext/geext.h b/Xext/geext.h
index bac4726..f3352c2 100644
--- a/Xext/geext.h
+++ b/Xext/geext.h
@@ -34,6 +34,21 @@ from the author.
 #define _GEEXT_H_
 #include <X11/extensions/geproto.h>
 
+
+/**
+ * This struct is used both in the window and by grabs to determine the event
+ * mask for a client.
+ * A window will have a linked list of these structs, with one entry per
+ * client, null-terminated.
+ * A grab has only one instance of this struct.
+ */
+typedef struct _GenericMaskRec {
+    ClientPtr   client;                   /* client who set the event mask */
+    Mask        eventMask[MAXEXTENSIONS]; /* one mask per extension */
+    struct _GenericMaskRec* next;            
+} GenericMaskRec, *GenericMaskPtr;
+
+
 /* Struct to keep information about registered extensions
  *
  * evswap ... use to swap event fields for different byte ordered clients.
@@ -48,6 +63,7 @@ typedef struct _GEExtension {
                     );
 } GEExtension, *GEExtensionPtr;
 
+
 /* All registered extensions and their handling functions. */
 extern GEExtension GEExtensions[MAXEXTENSIONS];
 
diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
index 8ae2053..c4011f5 100644
--- a/Xi/extgrbdev.c
+++ b/Xi/extgrbdev.c
@@ -194,19 +194,13 @@ ProcXExtendedGrabDevice(ClientPtr client)
             (XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
 
         gemasks = xcalloc(1, sizeof(GenericMaskRec));
-        gemasks->extension = xgeMask->extension;
-        gemasks->mask = xgeMask->evmask;
+        gemasks->client = client;
         gemasks->next = NULL;
-        xgeMask++;
+        gemasks->eventMask[xgeMask->extension & 0x7F] = xgeMask->evmask;
 
+        xgeMask++;
         for (i = 1; i < stuff->generic_event_count; i++, xgeMask++)
-        {
-            gemasks->next = xcalloc(1, sizeof(GenericMaskRec));
-            gemasks = gemasks->next;
-            gemasks->extension = xgeMask->extension;
-            gemasks->mask = xgeMask->evmask;
-            gemasks->next = NULL;
-        }
+            gemasks->eventMask[xgeMask->extension & 0x7F]= xgeMask->evmask;
     }
 
     ExtGrabDevice(client, dev, stuff->device_mode, 
@@ -221,12 +215,8 @@ ProcXExtendedGrabDevice(ClientPtr client)
     
 cleanup:
 
-    while(gemasks)
-    {
-        GenericMaskPtr prev = gemasks;
-        gemasks = gemasks->next;
-        xfree(prev);
-    }
+    if (gemasks)
+        xfree(gemasks);
 
     if (err == Success)
     {
diff --git a/dix/events.c b/dix/events.c
index d4af307..1bec4fc 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1934,7 +1934,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
         /* Handle generic events */
         if (type == GenericEvent)
         {
-            GEClientPtr pClient;
+            GenericMaskPtr pClient;
             /* We don't do more than one GenericEvent at a time. */
             if (count > 1)
             {
@@ -2017,7 +2017,24 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
         inputMasks = wOtherInputMasks(pWin);
         tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
 
-        tempGrab.genericMasks = NULL;
+        /* get the XGE event mask. 
+         * FIXME: needs to be freed somewhere too.
+         */
+        if (!pWin->optional || !pWin->optional->geMasks)
+            tempGrab.genericMasks = NULL;
+        else
+        {
+            GenericClientMasksPtr gemasks = pWin->optional->geMasks;
+            GenericMaskPtr geclient = gemasks->geClients;
+            while(geclient && geclient->client != client)
+                geclient = geclient->next;
+            if (geclient)
+            {
+                tempGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec));
+                *tempGrab.genericMasks = *geclient;
+                tempGrab.genericMasks->next = NULL;
+            }
+        }
 	(*inputInfo.pointer->deviceGrab.ActivateGrab)(pDev, &tempGrab,
 					   currentTime, 
                                            TRUE | ImplicitGrabMask);
@@ -3264,21 +3281,15 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
             {
                 /* 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;
-                }
+                GenericMaskPtr    gemask = grab->genericMasks;
 
-                if (!gemask)
+                if (!gemask->eventMask[GEEXTIDX(ge)])
                     return;
 
                 if (GEEventFill(xE))
                     GEEventFill(xE)(ge, thisDev, grab->window, grab);
                 deliveries = TryClientEvents(rClient(grab), xE, count, 
-                        gemask->mask,
+                        gemask->eventMask[GEEXTIDX(ge)],
                         generic_filters[GEEXTIDX(ge)][ge->evtype],
                         grab);
             } else 
@@ -4161,7 +4172,6 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
     xEvent event;
     int* numFoci; /* no of foci the window has already */
     Bool sendevent = FALSE;
-    FocusSemaphoresPtr focus;
 
     if (dev != inputInfo.keyboard)
 	DeviceFocusEvent(dev, type, mode, detail, pWin);
@@ -5914,21 +5924,9 @@ ExtGrabDevice(ClientPtr client,
 
     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;
-            last->next = NULL;
-            ge_masks = ge_masks->next;
-        }
     }
 
     if (IsPointerDevice(dev))
diff --git a/dix/window.c b/dix/window.c
index b49abdf..193f1aa 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -3751,7 +3751,8 @@ MakeWindowOptional (WindowPtr pWin)
 #endif
     optional->deviceCursors = NULL;
 
-    optional->geMasks = (GEEventMasksPtr)xalloc(sizeof(GEEventMasksRec));
+    optional->geMasks = 
+        (GenericClientMasksPtr)xalloc(sizeof(GenericClientMasksRec));
     if (!optional->geMasks)
     {
         xfree(optional);
diff --git a/include/dix.h b/include/dix.h
index be1cb95..2fc6254 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -52,6 +52,7 @@ SOFTWARE.
 #include "window.h"
 #include "input.h"
 #include "cursor.h"
+#include "geext.h"
 #include <X11/extensions/XI.h>
 
 #define EARLIER -1
diff --git a/include/inputstr.h b/include/inputstr.h
index d9128cc..6c65aa4 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -53,6 +53,7 @@ SOFTWARE.
 #include "window.h"
 #include "dixstruct.h"
 #include "cursorstr.h"
+#include "geext.h"
 
 #define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7)))
 
@@ -102,12 +103,6 @@ typedef struct _DetailRec {		/* Grab details may be bit masks */
     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
@@ -139,7 +134,7 @@ typedef struct _GrabRec {
     CursorPtr		cursor;		/* always NULL for keyboards */
     Mask		eventMask;
     Mask                deviceMask;     
-    GenericMaskPtr      genericMasks;   /* null terminated list */
+    GenericMaskPtr      genericMasks;
 } GrabRec;
 
 typedef struct _KeyClassRec {
diff --git a/include/misc.h b/include/misc.h
index 14c848d..e6a5e9e 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -243,7 +243,6 @@ typedef struct pixman_box16 *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 --git a/include/windowstr.h b/include/windowstr.h
index a1d501d..959ea0e 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -77,17 +77,15 @@ 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;
+/* Mask structure for GE extension as stored on the window.
+ * Allows one mask per extension.
+ *   .eventMask - Summary mask for all clients, used for quick checking.
+ *   .geClients - list of clients with their specific mask.
+ */
+typedef struct _GenericClientMasks {
+    Mask                eventMasks[MAXEXTENSIONS];
+    GenericMaskPtr      geClients;
+} GenericClientMasksRec, *GenericClientMasksPtr;
 
 typedef struct _WindowAccessRec {
     int                  defaultRule;      /* WindowAccessDenyAll */
@@ -117,7 +115,7 @@ typedef struct _WindowOpt {
     struct _OtherInputMasks *inputMasks;   /* default: NULL */
 #endif
     DevCursorList       deviceCursors;     /* default: NULL */
-    struct _GEEventMasks* geMasks;         /* default: NULL */
+    struct _GenericClientMasks *geMasks;/* default: NULL */
     WindowAccessRec     access;
 } WindowOptRec, *WindowOptPtr;
 
commit c1a16bdcfe7aa907fe78f27dc606a8e5a2699952
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Jun 27 18:08:03 2007 +0930

    Add 'evfill' field to GEExtensions.
    We need this to allow extensions to fill in extra data for an event before it
    is sent to the client. This is probably to be used like
    FillUpEventsFromWindow().

diff --git a/Xext/geext.c b/Xext/geext.c
index f0801cb..0add5e1 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -41,15 +41,8 @@ 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];
+GEExtension GEExtensions[MAXEXTENSIONS];
 
 /* Major available requests */
 static const int version_requests[] = {
@@ -249,11 +242,15 @@ GEExtensionInit(void)
 /* 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.  
+ * @param ev_swap The event swap function.  
+ * @param ev_fill Called for an event before delivery. The extension now has
+ * the chance to fill in necessary fields for the event.
  */
 void GERegisterExtension(
         int extension, 
-        void (*ev_swap)(xGenericEvent* from, xGenericEvent* to)
+        void (*ev_swap)(xGenericEvent* from, xGenericEvent* to),
+        void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev, 
+                        WindowPtr pWin, GrabPtr pGrab)
         )
 {
     if ((extension & 0x7F) >=  MAXEXTENSIONS)
@@ -261,6 +258,7 @@ void GERegisterExtension(
 
     /* extension opcodes are > 128, might as well save some space here */
     GEExtensions[extension & 0x7f].evswap = ev_swap;
+    GEExtensions[extension & 0x7f].evfill = ev_fill;
 }
 
 
diff --git a/Xext/geext.h b/Xext/geext.h
index 7a73e81..bac4726 100644
--- a/Xext/geext.h
+++ b/Xext/geext.h
@@ -34,6 +34,23 @@ from the author.
 #define _GEEXT_H_
 #include <X11/extensions/geproto.h>
 
+/* Struct to keep information about registered extensions
+ *
+ * evswap ... use to swap event fields for different byte ordered clients.
+ * evfill ... use to fill various event fields from the given parameters.
+ */
+typedef struct _GEExtension {
+    void (*evswap)(xGenericEvent* from, xGenericEvent* to);
+    void (*evfill)(xGenericEvent* ev, 
+                    DeviceIntPtr pDev,  /* device */
+                    WindowPtr pWin,     /* event window */
+                    GrabPtr pGrab       /* current grab, may be NULL */
+                    );
+} GEExtension, *GEExtensionPtr;
+
+/* All registered extensions and their handling functions. */
+extern GEExtension GEExtensions[MAXEXTENSIONS];
+
 /* Returns the extension offset from the event */
 #define GEEXT(ev) (((xGenericEvent*)(ev))->extension)
 
@@ -50,11 +67,19 @@ from the author.
 #define GECLIENT(pWin) \
     (((pWin)->optional) ? (pWin)->optional->geMasks->geClients : NULL)
 
+/* Returns the event_fill for the given event */
+#define GEEventFill(ev) \
+    GEExtensions[GEEXTIDX(xE)].evfill
+
 /* Interface for other extensions */
 void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask);
 void GERegisterExtension(
         int extension,
-        void (*ev_dispatch)(xGenericEvent* from, xGenericEvent* to));
+        void (*ev_dispatch)(xGenericEvent* from, xGenericEvent* to),
+        void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev, 
+                        WindowPtr pWin, GrabPtr pGrab)
+        );
+
 void GEInitEvent(xGenericEvent* ev, int extension);
 
 
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 99518e1..70253fe 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -1151,6 +1151,16 @@ XIGEEventSwap(xGenericEvent* from, xGenericEvent* to)
     }
 }
 
+/**
+ * EventFill to fill various fields for events before they are delivered to
+ * the client.
+ */
+static void 
+XIGEEventFill(xGenericEvent* ev, DeviceIntPtr pDev, 
+              WindowPtr pWin, GrabPtr grab)
+{
+}
+
 /**********************************************************************
  *
  * IExtensionInit - initialize the input extension.
@@ -1195,7 +1205,7 @@ XInputExtensionInit(void)
 	EventSwapVector[DeviceLeaveNotify] = SEventIDispatch;
 
         /* init GE events */
-        GERegisterExtension(IReqCode, XIGEEventSwap);
+        GERegisterExtension(IReqCode, XIGEEventSwap, XIGEEventFill);
         SetGenericFilter(IReqCode, xi_filters);
     } else {
 	FatalError("IExtensionInit: AddExtensions failed\n");
diff --git a/dix/events.c b/dix/events.c
index 77d6275..d4af307 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2129,6 +2129,9 @@ FixUpEventFromWindow(
 {
     SpritePtr pSprite = pDev->spriteInfo->sprite;
 
+    if (xE->u.u.type == GenericEvent) /* just a safety barrier */
+        return;
+
     if (calcChild)
     {
         WindowPtr w= pSprite->spriteTrace[pSprite->spriteTraceGood-1];
@@ -2245,6 +2248,8 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
             {
                 if (GEMaskIsSet(pWin, GEEXT(xE), filter))
                 {
+                    if (GEExtensions[GEEXTIDX(xE)].evfill)
+                        GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, pWin, grab);
                     deliveries = DeliverEventsToWindow(dev, pWin, xE, count, 
                                                         filter, grab, 0);
                     if (deliveries > 0)
@@ -3270,6 +3275,8 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                 if (!gemask)
                     return;
 
+                if (GEEventFill(xE))
+                    GEEventFill(xE)(ge, thisDev, grab->window, grab);
                 deliveries = TryClientEvents(rClient(grab), xE, count, 
                         gemask->mask,
                         generic_filters[GEEXTIDX(ge)][ge->evtype],
commit 08779c62ba2f4cbfa47e3cf738daf8abd74b60cf
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Jun 27 11:16:55 2007 +0930

    Reset grab->next to NULL when we're creating a grab.
    
    This is definitely necessary in CheckDeviceGrabAndHintWindow (thanks to Paulo
    Zanoni for spotting it). We're resetting it everywhere else too, just to be
    save.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 719e9db..c13b747 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1170,6 +1170,7 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
         tempGrab.genericMasks = NULL;
+        tempGrab.next = NULL;
 	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
     }
 }
diff --git a/dix/events.c b/dix/events.c
index 51bd2d8..77d6275 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2001,6 +2001,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 	GrabRec tempGrab;
         OtherInputMasks *inputMasks;
 
+        tempGrab.next = NULL;
 	tempGrab.device = pDev;
 	tempGrab.resource = client->clientAsMask;
 	tempGrab.window = pWin;
@@ -3023,6 +3024,7 @@ CheckPassiveGrabsOnWindow(
     tempGrab.detail.exact = xE->u.u.detail;
     tempGrab.detail.pMask = NULL;
     tempGrab.modifiersDetail.pMask = NULL;
+    tempGrab.next = NULL;
     for (; grab; grab = grab->next)
     {
 #ifdef XKB
@@ -4652,6 +4654,7 @@ ProcGrabPointer(ClientPtr client)
 		ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE);
 	    oldCursor = grab->cursor;
 	}
+        tempGrab.next = NULL;
 	tempGrab.cursor = cursor;
 	tempGrab.resource = client->clientAsMask;
 	tempGrab.ownerEvents = stuff->ownerEvents;
@@ -4820,6 +4823,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
         /* Otherwise segfaults happen on grabbed MPX devices */
         memset(&tempGrab, 0, sizeof(GrabRec));
 
+        tempGrab.next = NULL;
 	tempGrab.window = pWin;
 	tempGrab.resource = client->clientAsMask;
 	tempGrab.ownerEvents = ownerEvents;
@@ -5192,6 +5196,7 @@ ProcUngrabKey(ClientPtr client)
     tempGrab.type = KeyPress;
     tempGrab.detail.exact = stuff->key;
     tempGrab.detail.pMask = NULL;
+    tempGrab.next = NULL;
 
     if (!DeletePassiveGrabFromList(&tempGrab))
 	return(BadAlloc);
@@ -5370,6 +5375,7 @@ ProcUngrabButton(ClientPtr client)
     tempGrab.type = ButtonPress;
     tempGrab.detail.exact = stuff->button;
     tempGrab.detail.pMask = NULL;
+    tempGrab.next = NULL;
 
     if (!DeletePassiveGrabFromList(&tempGrab))
 	return(BadAlloc);
@@ -5897,6 +5903,7 @@ ExtGrabDevice(ClientPtr client,
     newGrab.confineTo      = confineTo;
     newGrab.eventMask      = xi_mask;
     newGrab.genericMasks   = NULL;
+    newGrab.next           = NULL;
 
     if (ge_masks)
     {
diff --git a/dix/grabs.c b/dix/grabs.c
index e1dd6c5..af471eb 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -106,6 +106,7 @@ CreateGrab(
     grab->confineTo = confineTo;
     grab->cursor = cursor;
     grab->genericMasks = NULL;
+    grab->next = NULL;
     if (cursor)
 	cursor->refcnt++;
     return grab;
commit 49136d3e9fe2d065090ee90c18a49f65fb027c9f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jun 26 19:43:54 2007 +0930

    mieqEnqueue: use modulo for queue tail wrapping.
    
    This was previously committed by Michael Daenzer, but was lost during a pull.

diff --git a/mi/mieq.c b/mi/mieq.c
index ff20003..4b29950 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -119,7 +119,7 @@ mieqInit(void)
 void
 mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 {
-    HWEventQueueType       oldtail = miEventQueue.tail, newtail;
+    unsigned int           oldtail = miEventQueue.tail, newtail;
     EventListPtr           evt;
     int                    isMotion = 0;
     int                    evlen;
@@ -138,7 +138,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
         EventPtr               laste;
         deviceKeyButtonPointer *lastkbp;
 
-        laste = &miEventQueue.events[(oldtail ? oldtail : QUEUE_SIZE) - 1];
+        laste = &miEventQueue.events[(oldtail - 1) % QUEUE_SIZE];
         lastkbp = (deviceKeyButtonPointer *) laste->events->event;
 
         if (laste->nevents > 6) {
@@ -161,9 +161,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 
     if (isMotion && isMotion == miEventQueue.lastMotion &&
         oldtail != miEventQueue.head) {
-	if (oldtail == 0)
-	    oldtail = QUEUE_SIZE;
-	oldtail = oldtail - 1;
+	oldtail = (oldtail - 1) % QUEUE_SIZE;
     }
     else {
     	newtail = (oldtail + 1) % QUEUE_SIZE;
commit 8396bf7c8b4eb6b8f2d1e1ef19887064c69591da
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jun 26 12:58:37 2007 +0930

    Init genericMasks to 0, make sure list is NULL terminated.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 622e8cc..719e9db 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1169,6 +1169,7 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
 	tempGrab.pointerMode = GrabModeAsync;
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
+        tempGrab.genericMasks = NULL;
 	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
     }
 }
diff --git a/dix/events.c b/dix/events.c
index 58d9ed4..51bd2d8 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5912,6 +5912,7 @@ ExtGrabDevice(ClientPtr client,
             last->next = xcalloc(1, sizeof(GenericMaskRec));
             last = last->next;
             *last = *ge_masks;
+            last->next = NULL;
             ge_masks = ge_masks->next;
         }
     }
commit c4e850a781e3b85631cb386d24efcca2a835d4c9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jun 25 13:38:25 2007 +0930

    Quickfix to stop core key events from doubling up.

diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c
index 81124bc..02f3c35 100644
--- a/xkb/xkbPrKeyEv.c
+++ b/xkb/xkbPrKeyEv.c
@@ -69,6 +69,13 @@ unsigned        ndx;
     /* below XKB, such as a key that physically locks.   XKB does not   */
     /* do anything to implement the behavior, but it *does* report that */
     /* key is hardwired */
+
+    /* FIXME: this is bad. The down mask is set during ProcessOtherEvent. When
+     * we start processing the core event (and eventually arrive here), the
+     * down mask is already set and Xkb thinks it's a repeat event. We just
+     * silently ignore it for now.
+     */
+#if 0
     if ((behavior.type&XkbKB_Permanent)==0) {
 	switch (behavior.type) {
 	    case XkbKB_Default:
@@ -153,6 +160,7 @@ unsigned        ndx;
 		break;
 	}
     }
+#endif
     XkbHandleActions(keybd,keybd,xE,count);
     return;
 }
commit 4d5df14f2c4a3108a8c8adfcf4766c0d1a9daad2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jun 21 18:24:30 2007 +0930

    Save processInputProc before wrapping it and restore it later, instead of
    using a hardcoded ProcessKeyboardEvent. Otherwise we lose the ability to
    process DeviceKeyEvents after the first key press.
    
    This should be the correct fix now.

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 5edee53..e018749 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -241,7 +241,8 @@ typedef struct
 	oldprocs->unwrapProc = device->unwrapProc; \
 	device->unwrapProc = unwrapproc;
 
-#define UNWRAP_PROCESS_INPUT_PROC(device, oldprocs) \
+#define UNWRAP_PROCESS_INPUT_PROC(device, oldprocs, backupproc) \
+        backupproc = device->public.processInputProc; \
 	device->public.processInputProc = oldprocs->processInputProc; \
 	device->public.realInputProc = oldprocs->realInputProc; \
 	device->unwrapProc = oldprocs->unwrapProc;
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 4c3efe2..252c653 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -49,10 +49,11 @@ xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
 {
     xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
     ProcessInputProc tmp = device->public.processInputProc;
+    ProcessInputProc dummy; /* unused, but neede for macro */
     if(xkbPrivPtr->unwrapProc)
 	xkbPrivPtr->unwrapProc = NULL;
 
-    UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr);
+    UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, dummy);
     proc(device,data);
     WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr,
 			    tmp,xkbUnwrapProc);
@@ -867,6 +868,7 @@ int		x,y;
 XkbStateRec	old;
 unsigned	mods,mask,oldCoreState = 0,oldCorePrevState = 0;
 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
+ProcessInputProc backupproc;
 
     /* never actually used uninitialised, but gcc isn't smart enough
      * to work that out. */
@@ -919,10 +921,10 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
 
 	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
 	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
-	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr);
+	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
 	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
 	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
-				     ProcessKeyboardEvent,xkbUnwrapProc);
+				     backupproc,xkbUnwrapProc);
 	xkbi->device->key->modifierMap[ev.u.u.detail] = realMods;
 	
 	if ( mask || mods ) {
@@ -960,10 +962,10 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
 
 	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
 	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
-	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr);
+	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
 	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
 	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
-				     ProcessKeyboardEvent,xkbUnwrapProc);
+				     backupproc,xkbUnwrapProc);
 	xkbi->device->key->modifierMap[ev.u.u.detail] = realMods;
 
 	if ( mask || mods ) {
@@ -1155,6 +1157,7 @@ Bool		pressEvent;
 #ifdef XINPUT
 Bool		xiEvent;
 #endif
+ProcessInputProc backupproc;
     
 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 
@@ -1297,10 +1300,10 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 	if (keyEvent) {
 	    realMods = keyc->modifierMap[key];
 	    keyc->modifierMap[key] = 0;
-	    UNWRAP_PROCESS_INPUT_PROC(dev,xkbPrivPtr);
+	    UNWRAP_PROCESS_INPUT_PROC(dev,xkbPrivPtr, backupproc);
 	    dev->public.processInputProc(xE,dev,count);
 	    COND_WRAP_PROCESS_INPUT_PROC(dev, xkbPrivPtr,
-					 ProcessKeyboardEvent,xkbUnwrapProc);
+					 backupproc,xkbUnwrapProc);
 	    keyc->modifierMap[key] = realMods;
 	}
 	else CoreProcessPointerEvent(xE,dev,count);
commit f6f3322fc7562dbfccaf798b05d42ea222860ba8
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jun 21 18:16:21 2007 +0930

    Revert "Save processInputProc before wrapping it and restore it later, instead of"
    Mixed up source trees, this was a very bad fix.
    
    This reverts commit 8431f6083076cf1e701366767d8f8d32a628200f.

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 156fb26..4c3efe2 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1300,8 +1300,7 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 	    UNWRAP_PROCESS_INPUT_PROC(dev,xkbPrivPtr);
 	    dev->public.processInputProc(xE,dev,count);
 	    COND_WRAP_PROCESS_INPUT_PROC(dev, xkbPrivPtr,
-                (dev == inputInfo.keyboard) ?  ProcessKeyboardEvent : ProcessOtherEvent, 
-                xkbUnwrapProc);
+					 ProcessKeyboardEvent,xkbUnwrapProc);
 	    keyc->modifierMap[key] = realMods;
 	}
 	else CoreProcessPointerEvent(xE,dev,count);
commit 8431f6083076cf1e701366767d8f8d32a628200f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jun 21 17:00:41 2007 +0930

    Save processInputProc before wrapping it and restore it later, instead of
    using a hardcoded ProcessKeyboardEvent. Otherwise we lose the ability to
    process DeviceKeyEvents after the first key press.

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 4c3efe2..156fb26 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1300,7 +1300,8 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 	    UNWRAP_PROCESS_INPUT_PROC(dev,xkbPrivPtr);
 	    dev->public.processInputProc(xE,dev,count);
 	    COND_WRAP_PROCESS_INPUT_PROC(dev, xkbPrivPtr,
-					 ProcessKeyboardEvent,xkbUnwrapProc);
+                (dev == inputInfo.keyboard) ?  ProcessKeyboardEvent : ProcessOtherEvent, 
+                xkbUnwrapProc);
 	    keyc->modifierMap[key] = realMods;
 	}
 	else CoreProcessPointerEvent(xE,dev,count);
commit 0c33dc152e372cdc8ae59d9a5696b0774bcd03b7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jun 21 15:47:48 2007 +0930

    Set the detail field for DeviceKeyEvents to the keycode.

diff --git a/dix/getevents.c b/dix/getevents.c
index 4d1fbb7..6988b8b 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -452,6 +452,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
     kbp = (deviceKeyButtonPointer *) events->event;
     kbp->time = ms;
     kbp->deviceid = pDev->id;
+    kbp->detail = key_code;
     if (type == KeyPress)
         kbp->type = DeviceKeyPress;
     else if (type == KeyRelease)
commit 1f97a7647606226cde61d6ad7a94f2b0b571a06c
Merge: 5dee64f... 2e7fef7...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jun 19 17:20:52 2007 +0930

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	dix/devices.c
    	hw/xfree86/common/xf86Xinput.c
    	hw/xfree86/loader/xf86sym.c
    	mi/mieq.c

diff --cc hw/xfree86/common/xf86Config.c
index 4ace24e,8e58bef..6c03377
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@@ -2463,6 -2509,14 +2509,12 @@@ xf86HandleConfigFile(Bool autoconfig
               return CONFIG_PARSE_ERROR;
      }
  
+     configFiles(xf86configptr->conf_files);
+     configExtensions(xf86configptr->conf_extensions);
+ #ifdef XF86DRI
+     configDRI(xf86configptr->conf_dri);
+ #endif
+ 
 -    checkInput(&xf86ConfigLayout);
 -
      /*
       * Handle some command line options that can override some of the
       * ServerFlags settings.
diff --cc hw/xfree86/common/xf86Xinput.c
index 1cce136,c08b15f..3bc8542
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@@ -445,15 -408,9 +447,15 @@@ NewInputDeviceRequest (InputOption *opt
  
      dev = pInfo->dev;
      ActivateDevice(dev);
-     if (dev->inited && dev->startup)
+     if (dev->inited && dev->startup && xf86Screens[0]->vtSema)
          EnableDevice(dev);
  
 +    if (!IsPointerDevice(dev))
 +        PairDevices(NULL, GuessFreePointerDevice(), dev);
 +
 +    /* send enter/leave event, update sprite window */
 +    CheckMotion(NULL, dev);
 +
      *pdev = dev;
      return Success;
  
@@@ -557,12 -535,9 +580,9 @@@ xf86PostMotionEventP(DeviceIntPtr	devic
          /* 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);
          }
      }
- 
- out:
-     xfree(valuators);
  }
  
  _X_EXPORT void
diff --cc hw/xfree86/loader/xf86sym.c
index ca32d6e,b4ae42f..9ae7957
--- a/hw/xfree86/loader/xf86sym.c
+++ b/hw/xfree86/loader/xf86sym.c
@@@ -96,10 -96,12 +96,15 @@@
  #endif
  #include "xf86DDC.h"
  #include "edid.h"
+ #include "xf86Cursor.h"
+ #include "xf86RamDac.h"
+ #include "BT.h"
+ #include "IBM.h"
+ #include "TI.h"
  
 +#include "xf86RamDac.h"
 +#include "BT.h"
 +
  #ifndef HAS_GLIBC_SIGSETJMP
  #if defined(setjmp) && defined(__GNU_LIBRARY__) && \
      (!defined(__GLIBC__) || (__GLIBC__ < 2) || \
diff --cc mi/mieq.c
index 06fdffc,f64e540..ff20003
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@@ -120,26 -106,21 +120,27 @@@ voi
  mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
  {
      HWEventQueueType       oldtail = miEventQueue.tail, newtail;
 +    EventListPtr           evt;
      int                    isMotion = 0;
-     int evlen;
 -    deviceValuator         *v = (deviceValuator *) e;
 -    EventPtr               laste = &miEventQueue.events[(oldtail - 1) %
 -							QUEUE_SIZE];
 -    deviceKeyButtonPointer *lastkbp = (deviceKeyButtonPointer *)
 -                                      &laste->event[0];
++    int                    evlen;
++
  
 +    /* avoid merging events from different devices */
      if (e->u.u.type == MotionNotify)
 -        isMotion = inputInfo.pointer->id;
 -    else if (e->u.u.type == DeviceMotionNotify)
          isMotion = pDev->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];
++        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;
@@@ -160,14 -140,10 +161,12 @@@
  
      if (isMotion && isMotion == miEventQueue.lastMotion &&
          oldtail != miEventQueue.head) {
 -	oldtail = (oldtail - 1) % QUEUE_SIZE;
 +	if (oldtail == 0)
 +	    oldtail = QUEUE_SIZE;
 +	oldtail = oldtail - 1;
      }
      else {
-     	newtail = oldtail + 1;
-     	if (newtail == QUEUE_SIZE)
- 	    newtail = 0;
+     	newtail = (oldtail + 1) % QUEUE_SIZE;
      	/* Toss events which come in late.  Usually this means your server's
           * stuck in an infinite loop somewhere, but SIGIO is still getting
           * handled. */
@@@ -245,29 -211,21 +244,22 @@@ mieqProcessInputEvents(void
  
          e = &miEventQueue.events[miEventQueue.head];
          /* Assumption - screen switching can only occur on motion events. */
+         miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
+ 
 -        if (e->pScreen != miEventQueue.pDequeueScreen) {
 -            miEventQueue.pDequeueScreen = e->pScreen;
 -            x = e->event[0].u.keyButtonPointer.rootX;
 -            y = e->event[0].u.keyButtonPointer.rootY;
 -            NewCurrentScreen (miEventQueue.pDequeueScreen, x, y);
 +        if (e->pScreen != DequeueScreen(e->pDev)) {
 +            DequeueScreen(e->pDev) = e->pScreen;
 +            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
-                 ++miEventQueue.head;
 +            NewCurrentScreen (e->pDev, DequeueScreen(e->pDev), x, y);
          }
          else {
-             if (miEventQueue.head == QUEUE_SIZE - 1)
-                 miEventQueue.head = 0;
-             else
-                 ++miEventQueue.head;
- 
              /* 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](miEventQueue.pDequeueScreen->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;
              }
  
commit 5dee64fc99f34e091abce65d47c4b6f026ab4849
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jun 19 11:31:22 2007 +0930

    Add a few comments to ProcXGrabDevice.

diff --git a/Xi/grabdev.c b/Xi/grabdev.c
index f3349ba..f2227bc 100644
--- a/Xi/grabdev.c
+++ b/Xi/grabdev.c
@@ -160,8 +160,19 @@ ProcXGrabDevice(ClientPtr client)
  * 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. 
+ * If an error occurs, it is sent to the client. Errors are generated if 
+ *  - if the device given in the event classs is invalid
+ *  - if the device in the class list is not the device given as parameter (no
+ *  error if parameter is NULL)
  *
  * mask has to be size EMASKSIZE and pre-allocated.
+ *
+ * @param client The client to send the error to (if one occurs)
+ * @param list List of event classes as sent from the client.
+ * @param count Number of elements in list.
+ * @param mask Preallocated mask (size EMASKSIZE).
+ * @param dev The device we're creating masks for.
+ * @param req The request we're processing. Used to fill in error fields.
  */
 
 int
@@ -179,7 +190,7 @@ CreateMaskFromList(ClientPtr client, XEventClass * list, int count,
 
     for (i = 0; i < count; i++, list++) {
 	device = *list >> 8;
-	if (device > 255) {
+	if (device > 255) { /* FIXME: we only use 7 bit for devices? */
 	    SendErrorToClient(client, IReqCode, req, 0, BadClass);
 	    return BadClass;
 	}
commit 9e257029c760883c4ea0715d4fd06476f3fe8053
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jun 19 11:28:07 2007 +0930

    Add implicitGrab field to GrabInfoRec.
    Is set when passive grab is implicit as result of a ButtonPress event. If this
    is the case, we need to store the XI mask as well as the core mask to ensure
    delivery of XI events during the grab's lifetime.
    
    Remove all core grabs on other devices when client issues a GrabPointer or
    GrabKeyboard request. Let's assume that the client really only wants one
    device to interact, so this seems like a reasonable solution.

diff --git a/dix/devices.c b/dix/devices.c
index 4672b2a..b56423a 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -135,6 +135,7 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
     dev->deviceGrab.grab = NullGrab;
     dev->deviceGrab.grabTime = currentTime;
     dev->deviceGrab.fromPassiveGrab = FALSE;
+    dev->deviceGrab.implicitGrab = FALSE;
 
     dev->key = (KeyClassPtr)NULL;
     dev->valuator = (ValuatorClassPtr)NULL;
diff --git a/dix/events.c b/dix/events.c
index 4c5f5b9..f6e9021 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -209,6 +209,12 @@ static xEvent *xeviexE;
 	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
 	Mod3Mask | Mod4Mask | Mod5Mask )
 #define AllEventMasks (lastEventMask|(lastEventMask-1))
+
+/**
+ * Used to indicate a implicit passive grab created by a ButtonPress event.
+ * See DeliverEventsToWindow().
+ */
+#define ImplicitGrabMask (1 << 7)
 /*
  * The following relies on the fact that the Button<n>MotionMasks are equal
  * to the corresponding Button<n>Masks from the current modifier/button state.
@@ -1238,6 +1244,14 @@ PlayReleasedEvents(void)
     } 
 }
 
+/**
+ * Freeze or thaw the given devices. The device's processing proc is
+ * switched to either the real processing proc (in case of thawing) or an
+ * enqueuing processing proc (usually EnqueueEvent()).
+ *
+ * @param dev The device to freeze/thaw
+ * @param frozen True to freeze or false to thaw.
+ */
 static void
 FreezeThaw(DeviceIntPtr dev, Bool frozen)
 {
@@ -1248,6 +1262,14 @@ FreezeThaw(DeviceIntPtr dev, Bool frozen)
 	dev->public.processInputProc = dev->public.realInputProc;
 }
 
+/**
+ * Unfreeze devices and replay all events to the respective clients.
+ *
+ * ComputeFreezes takes the first event in the device's frozen event queue. It
+ * runs up the sprite tree (spriteTrace) and searches for the window to replay
+ * the events from. If it is found, it checks for passive grabs one down from
+ * the window or delivers the events.
+ */
 void
 ComputeFreezes(void)
 {
@@ -1394,7 +1416,8 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
  * on, but core events will be sent to other clients.
  * Can cause the cursor to change if a grab cursor is set.
  * 
- * Extension devices are set up for ActivateKeyboardGrab().
+ * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
+ * is an implicit grab caused by a ButtonPress event.
  * 
  * @param mouse The device to grab.
  * @param grab The grab structure, needs to be setup.
@@ -1428,7 +1451,8 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
 	grab->cursor->refcnt++;
     grabinfo->activeGrab = *grab;
     grabinfo->grab = &grabinfo->activeGrab;
-    grabinfo->fromPassiveGrab = autoGrab;
+    grabinfo->fromPassiveGrab = autoGrab & ~ImplicitGrabMask;
+    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
     PostNewCursor(mouse);
     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
 }
@@ -1987,7 +2011,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 
         tempGrab.genericMasks = NULL;
 	(*inputInfo.pointer->deviceGrab.ActivateGrab)(pDev, &tempGrab,
-					   currentTime, TRUE);
+					   currentTime, 
+                                           TRUE | ImplicitGrabMask);
     }
     else if ((type == MotionNotify) && deliveries)
 	pDev->valuator->motionHintWindow = pWin;
@@ -3243,13 +3268,19 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
             } else 
             {
                 Mask mask = grab->eventMask;
-                if (grabinfo->fromPassiveGrab && (xE->u.u.type &
-                            EXTENSION_EVENT_BASE))
+                if (grabinfo->fromPassiveGrab  &&
+                        grabinfo->implicitGrab && 
+                        (xE->u.u.type & EXTENSION_EVENT_BASE))
                     mask = grab->deviceMask;
 
                 FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
-                deliveries = TryClientEvents(rClient(grab), xE, count,
-                        mask, filters[xE->u.u.type], grab);
+
+                if (!(!(xE->u.u.type & EXTENSION_EVENT_BASE) &&
+                        IsInterferingGrab(rClient(grab), thisDev, xE)))
+                {
+                    deliveries = TryClientEvents(rClient(grab), xE, count,
+                            mask, filters[xE->u.u.type], grab);
+                }
             }
             if (deliveries && (xE->u.u.type == MotionNotify
 #ifdef XINPUT
@@ -4629,6 +4660,8 @@ ProcGrabPointer(ClientPtr client)
 	if (oldCursor)
 	    FreeCursor (oldCursor, (Cursor)0);
 	rep.status = GrabSuccess;
+
+        RemoveOtherCoreGrabs(client, device);
     }
     WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
     return Success;
@@ -4798,6 +4831,47 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
 }
 
 /**
+ * Deactivate any core grabs on the given client except the given device.
+ *
+ * This fixes race conditions where clients deal with implicit passive grabs
+ * on one device, but then actively grab their client pointer, which is
+ * another device.
+ *
+ * Grabs are only removed if the other device matches the type of device. If
+ * dev is a pointer device, only other pointer grabs are removed. Likewise, if
+ * dev is a keyboard device, only keyboard grabs are removed.
+ * 
+ * If dev doesn't have a grab, do nothing and go for a beer.
+ *
+ * @param client The client that is to be limited.
+ * @param dev The only device allowed to have a grab on the client.
+ */
+
+_X_EXPORT void
+RemoveOtherCoreGrabs(ClientPtr client, DeviceIntPtr dev)
+{
+    if (!dev || !dev->deviceGrab.grab)
+        return;
+
+    DeviceIntPtr it = inputInfo.devices;
+    for (; it; it = it->next)
+    {
+        if (it == dev)
+            continue;
+        /* check for IsPointer Device */
+
+        if (it->deviceGrab.grab &&
+                it->deviceGrab.grab->coreGrab &&
+                SameClient(it->deviceGrab.grab, client))
+        {
+            if ((IsPointerDevice(dev) && IsPointerDevice(it)) ||
+                    (IsKeyboardDevice(dev) && IsKeyboardDevice(it)))
+                (*it->deviceGrab.DeactivateGrab)(it);
+        }
+    }
+}
+
+/**
  * Server-side protocol handling for GrabKeyboard request.
  *
  * Grabs the client's keyboard and returns success status to client.
@@ -4813,10 +4887,13 @@ ProcGrabKeyboard(ClientPtr client)
     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
 
     if (XaceHook(XACE_DEVICE_ACCESS, client, keyboard, TRUE))
+    {
 	result = GrabDevice(client, keyboard, stuff->keyboardMode,
 			    stuff->pointerMode, stuff->grabWindow,
 			    stuff->ownerEvents, stuff->time,
 			    KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
+        RemoveOtherCoreGrabs(client, keyboard);
+    }
     else {
 	result = Success;
 	rep.status = AlreadyGrabbed;
@@ -5857,3 +5934,4 @@ ExtUngrabDevice(ClientPtr client, DeviceIntPtr dev)
 }
 
 
+
diff --git a/include/dix.h b/include/dix.h
index f0e2f2a..be1cb95 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -494,6 +494,10 @@ extern int GrabDevice(
     CARD8 * /* status */,
     Bool /* coreGrab */);
 
+extern void RemoveOtherCoreGrabs(
+    ClientPtr /* client */,
+    DeviceIntPtr /* dev */);
+
 extern void InitEvents(void);
 extern void InitSprite(
         DeviceIntPtr /* pDev */, 
diff --git a/include/inputstr.h b/include/inputstr.h
index 986232c..d9128cc 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -333,9 +333,11 @@ typedef struct {
 #define FROZEN_NO_EVENT		5
 #define FROZEN_WITH_EVENT	6
 #define THAW_OTHERS		7
+
 typedef struct _GrabInfoRec {
-    TimeStamp	    grabTime;
-    Bool            fromPassiveGrab;
+    TimeStamp	    grabTime;           
+    Bool            fromPassiveGrab;    /* true if from passive grab */
+    Bool            implicitGrab;       /* implicit from ButtonPress */
     GrabRec         activeGrab;
     GrabPtr         grab;
     CARD8           activatingKey;
commit 3e894974cdd6a75683d4601f71622d1da7ec4395
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jun 15 17:16:16 2007 +0930

    Only decrement buttonsDown when the button count is greater than 0.
    Device drivers flush their buttons on device init and cause a button down
    event to be generated. If we unconditionally decrease the buttons, we won't be
    able to ever get a passive device grab.
    
    Format documentation for CheckDeviceGrabs to make it readable.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 2e9e826..622e8cc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -279,6 +279,8 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
         if (!grab)
             if (CheckDeviceGrabs(device, xE, 0, count))
+                /* if a passive grab was activated, the event has been sent
+                 * already */
                 return;
 
     } else if (xE->u.u.type == DeviceButtonRelease) {
@@ -289,7 +291,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 	*kptr &= ~bit;
 	if (device->valuator)
 	    device->valuator->motionHintWindow = NullWindow;
-	if (!--b->buttonsDown)
+        if (b->buttonsDown >= 1 && !--b->buttonsDown)
 	    b->motionMask = 0;
 	xE->u.u.detail = b->map[key];
 	if (xE->u.u.detail == 0)
diff --git a/dix/events.c b/dix/events.c
index ba1463a..4c5f5b9 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2963,6 +2963,7 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
 /** 
  * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
  * passive grab set on the window to be activated. 
+ * If a passive grab is activated, the event will be delivered to the client.
  * 
  * @param pWin The window that may be subject to a passive grab.
  * @param device Device that caused the event.
@@ -3064,16 +3065,26 @@ CheckPassiveGrabsOnWindow(
 }
 
 /**
-"CheckDeviceGrabs" handles both keyboard and pointer events that may cause
-a passive grab to be activated.  If the event is a keyboard event, the
-ancestors of the focus window are traced down and tried to see if they have
-any passive grabs to be activated.  If the focus window itself is reached and
-it's descendants contain they pointer, the ancestors of the window that the
-pointer is in are then traced down starting at the focus window, otherwise no
-grabs are activated.  If the event is a pointer event, the ancestors of the
-window that the pointer is in are traced down starting at the root until
-CheckPassiveGrabs causes a passive grab to activate or all the windows are
-tried. PRH
+ * CheckDeviceGrabs handles both keyboard and pointer events that may cause
+ * a passive grab to be activated.  
+ *
+ * If the event is a keyboard event, the ancestors of the focus window are
+ * traced down and tried to see if they have any passive grabs to be
+ * activated.  If the focus window itself is reached and it's descendants
+ * contain the pointer, the ancestors of the window that the pointer is in
+ * are then traced down starting at the focus window, otherwise no grabs are
+ * activated.  
+ * If the event is a pointer event, the ancestors of the window that the
+ * pointer is in are traced down starting at the root until CheckPassiveGrabs
+ * causes a passive grab to activate or all the windows are
+ * tried. PRH
+ *
+ * If a grab is activated, the event has been sent to the client already!
+ *
+ * @param device The device that caused the event.
+ * @param xE The event to handle (most likely {Device}ButtonPress).
+ * @param count Number of events in list.
+ * @return TRUE if a grab has been activated or false otherwise.
 */
 
 Bool
commit 0aaf51546666f71e8d1711978bc7988ec2ecc7d9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Jun 12 16:55:26 2007 +0930

    Zero deviceMask and genericMask when creating a grab via CreateGrab().

diff --git a/dix/grabs.c b/dix/grabs.c
index 714fea3..e1dd6c5 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -91,6 +91,7 @@ CreateGrab(
 		      (device == inputInfo.pointer));
     grab->window = window;
     grab->eventMask = eventMask;
+    grab->deviceMask = 0;
     grab->ownerEvents = ownerEvents;
     grab->keyboardMode = keyboardMode;
     grab->pointerMode = pointerMode;
@@ -104,6 +105,7 @@ CreateGrab(
     grab->detail.pMask = NULL;
     grab->confineTo = confineTo;
     grab->cursor = cursor;
+    grab->genericMasks = NULL;
     if (cursor)
 	cursor->refcnt++;
     return grab;
commit 26b21157cf934ae387b15faa9ebb060120e6a0d6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu May 31 17:05:14 2007 +0930

    Add a deviceMask to the GrabRec and don't interfere with passiveGrabs.
    
    This quickfixes event delivery problems with XI events when a grab was on.
    deviceMask is only used when the grab was from a ButtonPress to preserve
    potential XI event masks.
    
    This is not an ideal solution but it works until I have time to work on
    PassiveGrabs.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 98c2885..2e9e826 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -126,6 +126,9 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
     ValuatorClassPtr v = device->valuator;
     deviceValuator *xV = (deviceValuator *) xE;
 
+    if (grab && grab->coreGrab && !device->deviceGrab.fromPassiveGrab)
+        return;
+
     if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
         DeviceIntPtr mouse = NULL, kbd = NULL;
 	GetSpritePosition(device, &rootX, &rootY);
diff --git a/dix/events.c b/dix/events.c
index 9dddf2c..ba1463a 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1839,6 +1839,10 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
  * Deliver events to a window. At this point, we do not yet know if the event
  * actually needs to be delivered. May activate a grab if the event is a
  * button press.
+ * 
+ * Core events are always delivered to the window owner. If the filter is
+ * something other than CantBeFiltered, the event is also delivered to other
+ * clients with the matching mask on the window.
  *
  * More than one event may be delivered at a time. This is the case with
  * DeviceMotionNotifies which may be followed by DeviceValuator events.
@@ -1964,6 +1968,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
     if ((type == ButtonPress) && deliveries && (!grab))
     {
 	GrabRec tempGrab;
+        OtherInputMasks *inputMasks;
 
 	tempGrab.device = pDev;
 	tempGrab.resource = client->clientAsMask;
@@ -1975,6 +1980,11 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
         tempGrab.coreGrab = True;
+
+        /* get the XI device mask */
+        inputMasks = wOtherInputMasks(pWin);
+        tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
+
         tempGrab.genericMasks = NULL;
 	(*inputInfo.pointer->deviceGrab.ActivateGrab)(pDev, &tempGrab,
 					   currentTime, TRUE);
@@ -3221,10 +3231,14 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
                         grab);
             } else 
             {
+                Mask mask = grab->eventMask;
+                if (grabinfo->fromPassiveGrab && (xE->u.u.type &
+                            EXTENSION_EVENT_BASE))
+                    mask = grab->deviceMask;
+
                 FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
                 deliveries = TryClientEvents(rClient(grab), xE, count,
-                        (Mask)grab->eventMask,
-                        filters[xE->u.u.type], grab);
+                        mask, filters[xE->u.u.type], grab);
             }
             if (deliveries && (xE->u.u.type == MotionNotify
 #ifdef XINPUT
@@ -5716,7 +5730,8 @@ IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
     {
         if (it != dev)
         {
-            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client))
+            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
+                        && !it->deviceGrab.fromPassiveGrab)
             {
                 return TRUE;
             }
diff --git a/include/inputstr.h b/include/inputstr.h
index a535884..986232c 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -117,6 +117,9 @@ typedef struct _GenericMaskRec {
  * 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).
+ *
+ * If the grab is a result of a ButtonPress, then eventMask is the core mask
+ * and deviceMask is set to the XI event mask for the grab.
  */
 typedef struct _GrabRec {
     GrabPtr		next;		/* for chain of passive grabs */
@@ -135,6 +138,7 @@ typedef struct _GrabRec {
     WindowPtr		confineTo;	/* always NULL for keyboards */
     CursorPtr		cursor;		/* always NULL for keyboards */
     Mask		eventMask;
+    Mask                deviceMask;     
     GenericMaskPtr      genericMasks;   /* null terminated list */
 } GrabRec;
 
commit 182ab3a3d5b28daa86e6d6155e76ce759687ae6d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed May 30 17:44:31 2007 +0930

    Fix up comments for event.c

diff --git a/dix/events.c b/dix/events.c
index 402e3b3..9dddf2c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -237,22 +237,24 @@ static int DontPropagateRefCnts[DNPMCOUNT];
  *     inputInfo.pointer 
  *     is the core pointer. Referred to as "virtual core pointer", "VCP",
  *     "core pointer" or inputInfo.pointer. There is exactly one core pointer,
- *     but multiple devices may send core events. If a device generates core
- *     events, those events will appear to originate from the core pointer.
+ *     but multiple devices may send core events. The VCP is only used if no
+ *     physical device is connected and does not have a visible cursor. 
+ *     Before the integration of MPX, any core request would operate on the
+ *     VCP/VCK. Core events would always come from one of those two. Now both
+ *     are only fallback devices if no physical devices are available.
  * 
  *     inputInfo.keyboard
  *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
  *     See inputInfo.pointer.
  * 
  *     inputInfo.devices
- *     linked list containing all devices including VCK and VCP. The VCK will
- *     always be the first entry, the VCP the second entry in the device list.
+ *     linked list containing all devices BUT NOT INCLUDING VCK and VCP. 
  *
  *     inputInfo.off_devices
  *     Devices that have not been initialized and are thus turned off.
  *
  *     inputInfo.numDevices
- *     Total number of devices.
+ *     Total number of devices (not counting VCP and VCK).
  */
 _X_EXPORT InputInfo inputInfo;
 
@@ -1387,11 +1389,12 @@ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
 
 /**
  * Activate a pointer grab on the given device. A pointer grab will cause all
- * core pointer events to be delivered to the grabbing client only. Can cause
- * the cursor to change if a grab cursor is set.
+ * core pointer events of this device to be delivered to the grabbing client only. 
+ * No other device will send core events to the grab client while the grab is
+ * on, but core events will be sent to other clients.
+ * Can cause the cursor to change if a grab cursor is set.
  * 
- * As a pointer grab can only be issued on the core devices, mouse is always
- * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
+ * Extension devices are set up for ActivateKeyboardGrab().
  * 
  * @param mouse The device to grab.
  * @param grab The grab structure, needs to be setup.
@@ -1433,8 +1436,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
 /**
  * Delete grab on given device, update the sprite.
  *
- * As a pointer grab can only be issued on the core devices, mouse is always
- * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
+ * Extension devices are set up for ActivateKeyboardGrab().
  */
 void
 DeactivatePointerGrab(DeviceIntPtr mouse)
@@ -1651,7 +1653,7 @@ AllowSome(ClientPtr client,
 /**
  * Server-side protocol handling for AllowEvents request.
  *
- * Release some events from a frozen device. Only applicable for core devices.
+ * Release some events from a frozen device. 
  */
 int
 ProcAllowEvents(ClientPtr client)
@@ -2135,9 +2137,6 @@ FixUpEventFromWindow(
  * Deliver events caused by input devices. Called for all core input events
  * and XI events. No filtering of events happens before DeliverDeviceEvents(),
  * it will be called for any event that comes out of the event queue.
- * 
- * For all core events, dev is either inputInfo.pointer or inputInfo.keyboard.
- * For all extension events, dev is the device that caused the event.
  *
  * @param pWin Window to deliver event to.
  * @param xE Events to deliver.
@@ -2535,8 +2534,8 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
 #endif
 
 /**
- * Set the given window to sane values, display the cursor in the center of
- * the screen. Called from main() with the root window on the first screen.
+ * Called from main() with the root window on the first screen. Used to do a
+ * lot more when MPX wasn't around yet. Things change.
  */
 void
 DefineInitialRootWindow(WindowPtr win)
@@ -2547,6 +2546,21 @@ DefineInitialRootWindow(WindowPtr win)
 
 }
 
+/**
+ * Initialize a sprite for the given device and set it to some sane values. If
+ * the device already has a sprite alloc'd, don't realloc but just reset to
+ * default values.
+ * If a window is supplied, the sprite will be initialized with the window's
+ * cursor and positioned in the center of the window's screen. The root window
+ * is a good choice to pass in here.
+ *
+ * It's a good idea to call it only for pointer devices, unless you have a
+ * really talented keyboard.
+ *
+ * @param pDev The device to initialize.
+ * @param pWin The window where to generate the sprite in.
+ * 
+ */
 void 
 InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
 {
@@ -3824,7 +3838,7 @@ CommonAncestor(
 
 /**
  * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 
- * The core devices are used to fill in the event fields.
+ * Uses the paired keyboard to get some additional information.
  */
 static void
 EnterLeaveEvent(
@@ -4453,7 +4467,7 @@ ProcSetInputFocus(client)
 /**
  * Server-side protocol handling for GetInputFocus request.
  * 
- * Sends the current input focus for the virtual core keyboard back to the
+ * Sends the current input focus for the client's keyboard back to the
  * client.
  */
 int
@@ -4481,8 +4495,8 @@ ProcGetInputFocus(ClientPtr client)
 /**
  * Server-side protocol handling for Grabpointer request.
  *
- * Sets an active grab on the inputInfo.pointer and returns success status to
- * client.
+ * Sets an active grab on the client's ClientPointer and returns success
+ * status to client.
  */
 int
 ProcGrabPointer(ClientPtr client)
@@ -4601,7 +4615,7 @@ ProcGrabPointer(ClientPtr client)
  * Changes properties of the grab hold by the client. If the client does not
  * hold an active grab on the device, nothing happens. 
  *
- * Works on the core pointer only.
+ * Works on the client's ClientPointer.
  */
 int
 ProcChangeActivePointerGrab(ClientPtr client)
@@ -4652,7 +4666,7 @@ ProcChangeActivePointerGrab(ClientPtr client)
 /**
  * Server-side protocol handling for UngrabPointer request.
  *
- * Deletes the pointer grab on the core pointer device.
+ * Deletes the pointer grab on the client's ClientPointer device.
  */
 int
 ProcUngrabPointer(ClientPtr client)
@@ -4676,7 +4690,7 @@ ProcUngrabPointer(ClientPtr client)
 /**
  * Sets a grab on the given device.
  * 
- * Called from ProcGrabKeyboard to work on the inputInfo.keyboard.
+ * Called from ProcGrabKeyboard to work on the client's keyboard.
  * Called from ProcXGrabDevice to work on the device specified by the client.
  * 
  * The parameters this_mode and other_mode represent the keyboard_mode and
@@ -4761,7 +4775,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
 /**
  * Server-side protocol handling for GrabKeyboard request.
  *
- * Grabs the inputInfo.keyboad and returns success status to client.
+ * Grabs the client's keyboard and returns success status to client.
  */
 int
 ProcGrabKeyboard(ClientPtr client)
@@ -4795,7 +4809,7 @@ ProcGrabKeyboard(ClientPtr client)
 /**
  * Server-side protocol handling for UngrabKeyboard request.
  *
- * Deletes a possible grab on the inputInfo.keyboard.
+ * Deletes a possible grab on the client's keyboard.
  */
 int
 ProcUngrabKeyboard(ClientPtr client)
@@ -4819,7 +4833,8 @@ ProcUngrabKeyboard(ClientPtr client)
 /**
  * Server-side protocol handling for QueryPointer request.
  *
- * Returns the current state and position of the core pointer to the client. 
+ * Returns the current state and position of the client's ClientPointer to the
+ * client. 
  */
 int
 ProcQueryPointer(ClientPtr client)
@@ -5029,8 +5044,8 @@ ProcSendEvent(ClientPtr client)
 /**
  * Server-side protocol handling for UngrabKey request.
  *
- * Deletes a passive grab for the given key. Only works on the
- * inputInfo.keyboard.
+ * Deletes a passive grab for the given key. Works on the
+ * client's keyboard.
  */
 int
 ProcUngrabKey(ClientPtr client)
@@ -5077,8 +5092,8 @@ ProcUngrabKey(ClientPtr client)
 /**
  * Server-side protocol handling for GrabKey request.
  *
- * Creates a grab for the inputInfo.keyboard and adds it to the list of
- * passive grabs. 
+ * Creates a grab for the client's keyboard and adds it to the list of passive
+ * grabs. 
  */
 int
 ProcGrabKey(ClientPtr client)
@@ -5138,8 +5153,8 @@ ProcGrabKey(ClientPtr client)
 /**
  * Server-side protocol handling for GrabButton request.
  *
- * Creates a grab for the inputInfo.pointer and adds it as a passive grab to
- * the list.
+ * Creates a grab for the client's ClientPointer and adds it as a passive grab
+ * to the list.
  */
 int
 ProcGrabButton(ClientPtr client)
@@ -5217,7 +5232,7 @@ ProcGrabButton(ClientPtr client)
 /**
  * Server-side protocol handling for UngrabButton request.
  *
- * Deletes a passive grab on the inputInfo.pointer from the list.
+ * Deletes a passive grab on the client's ClientPointer from the list.
  */
 int
 ProcUngrabButton(ClientPtr client)
@@ -5597,6 +5612,12 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
 /*
  * Set the client pointer for the given client. Second parameter setter could
  * be used in the future to determine access rights. Unused for now.
+ *
+ * A client can have exactly one ClientPointer. Each time a
+ * request/reply/event is processed and the choice of devices is ambiguous
+ * (e.g. QueryPointer request), the server will pick the ClientPointer (see
+ * PickPointer()). 
+ * If a keyboard is needed, the first keyboard paired with the CP is used.
  */
 _X_EXPORT Bool
 SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device)
commit b5db863945fa8045995b3bf742c44e40f2650f04
Author: Paulo Ricardo Zanoni <prz05 at c3sl.ufpr.br>
Date:   Wed May 30 16:15:15 2007 +0930

    Allow value None for windows when setting ClientPointer.
    
    We need this for clients that need to set the ClientPointer but don't have a
    window on display yet. If used, it will set the device as the ClientPointer
    for the requesting client.

diff --git a/Xi/setcptr.c b/Xi/setcptr.c
index 25874f0..66c8981 100644
--- a/Xi/setcptr.c
+++ b/Xi/setcptr.c
@@ -70,6 +70,7 @@ ProcXSetClientPointer(ClientPtr client)
 {
     DeviceIntPtr pDev;
     WindowPtr pWin;
+    ClientPtr targetClient;
     int err;
 
     REQUEST(xSetClientPointerReq);
@@ -93,9 +94,11 @@ ProcXSetClientPointer(ClientPtr client)
                     stuff->win, err);
             return Success;
         }
-    }
+        targetClient= wClient(pWin);
+    } else
+        targetClient = client;
     
-    if (!SetClientPointer(wClient(pWin), client, pDev))
+    if (!SetClientPointer(targetClient, client, pDev))
     {
         SendErrorToClient(client, IReqCode, X_SetClientPointer, 
                 stuff->win, BadAccess);
commit d0e8f474099dea40bbea555427772724ccb787d1
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, DeviceIntPtr dev,
 	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);
commit 167e1773de0fb566559d4362ff929eedcdb6d055
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"
commit 0b4db74922299df785e6273fdb1bf65c38d36070
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);
commit 333bab4b235801efd2b2de5b60df5b0c44048d3e
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 * extEntry)
     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 keybd)
     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, WindowPtr pWin, xEvent
         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, DeviceIntPtr dev,
     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, DeviceIntPtr dev,
 	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, DeviceIntPtr pDev, int type, int buttons,
     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;
commit bc334286b060bc8d0c829b18acebadf24fbdaf19
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(DeviceIntPtr dev, int numAxes,
         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;
commit a8c56372ba8aa36bac09877c478ff53ea5358df7
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, WindowPtr pWin, xEvent
 	    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, WindowPtr pWin, xEvent
             {
                 /* 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, WindowPtr win, DeviceIntPtr dev, xEvent* eve
             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 */);
 
commit 81fc6a128b64ad412064405ed45db0175398e3f0
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 client)
     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 client)
 	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, DeviceIntPtr thisDev,
     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* filters)
 
 
 /**
- * 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;
-
-        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)
+        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)
         {
-            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 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);
 
+extern int ExtUngrabDevice(ClientPtr client,
+                         DeviceIntPtr dev);
+
 #endif /* DIX_H */
commit 5c680e94938c16e04a4349715cf11796b80400db
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, Bool autoStart)
     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, GrabPtr grab,
 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, GrabPtr grab, TimeStamp time, Bool pass
 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 keybd)
 	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, WindowPtr pWin, xEvent
 	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 win, int xoff, int yoff)
                 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, DeviceIntPtr thisDev,
     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, DeviceIntPtr mouse, int count)
 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, DeviceIntPtr mouse, int count)
 	    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, DeviceIntPtr mouse, int count)
 	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 client)
 	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, DeviceIntPtr dev,
 	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, Bool freeResources)
 
     /* 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, Bool freeResources)
 
                 /* 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, WindowPtr win, DeviceIntPtr dev, xEvent* eve
     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, WindowPtr win, DeviceIntPtr dev, xEvent* eve
     {
         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, WindowPtr win, DeviceIntPtr dev, xEvent* eve
                 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* filters)
 
 
 /**
- * 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 pScreen, dgaEvent *de, DeviceIntPtr keybd)
     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 pScreen, dgaEvent *de, DeviceIntPtr mouse)
     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 action, void *arg)
 	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 action, void *arg)
 	  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;
 
commit 4dc973f08c54294e06bc831bd2839fd3aa24ecfb
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 len, xGrabDeviceReply * rep)
         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, GrabPtr grab,
     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, GrabPtr grab, TimeStamp time, Bool pass
 	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 keybd)
     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, DeviceIntPtr thisDev,
     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, DeviceIntPtr thisDev,
     {
         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, DeviceIntPtr dev,
 	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* filters)
 {
     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(DeviceIntPtr dev);
 
 
 /* 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 details may be bit masks */
     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
commit cb22bdbe678a9948eda75d464d6701a729664ef0
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)
 };
commit c03d9a7217f9895feed8cfed3ede4752faf6187c
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 @@ SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify *from,
 
     *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_Present,
     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 (deviceLeaveNotify *from, deviceLeaveNotify *to)
     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 * to)
     }
 }
 
+/****************************************************************
+ *
+ * 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");
commit e6fd4a24ebd205013b41e44aacbbfb847709d2fd
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 */
commit af25720598bb35d9d953ac8d9a07528289ebfb4a
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 */
+
commit 58c0fd29272fb6c2f193cff82fb0b0573c607eec
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, DeviceIntPtr device, int count)
     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, xEvent *xE, GrabPtr grab,
     }
     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, WindowPtr win, DeviceIntPtr dev, xEvent* eve
     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 first_valuator, int num_valuators,
  *        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, DeviceIntPtr pDev, int first_valuator,
  * 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, DeviceIntPtr pDev, int type, int key_code) {
  * 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, DeviceIntPtr pDev, int type,
 
     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, DeviceIntPtr pDev, int type,
     }
 
     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, DeviceIntPtr pDev, int type, int buttons,
         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, DeviceIntPtr pDev, int type, int buttons,
 
     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, DeviceIntPtr pDev, int type, int buttons,
     /* 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, DeviceIntPtr pDev, int type, int buttons,
     }
 
     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, DeviceIntPtr pDev, int type, int buttons,
  * 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	device,
     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	device,
                                  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      device,
 #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      device,
                                 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 pDev);
 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 *OtherClientsPtr;
 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 authorization from The Open Group.
 # 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 authorization from The Open Group.
 #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(DeviceIntPtr pDev, ScreenPtr pScreen);
 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, ScreenPtr pScreen, int x, int y, unsigned long
 
     if (!events)
     {
-        events = (xEvent*)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+        events = InitEventList(GetMaximumEventsNum());
 
         if (!events)
         {
@@ -635,6 +635,8 @@ miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, unsigned long
 
     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();
 }
commit 0214d0b96a9b900a8cf5c7f2183add3a411441f3
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 win, int xoff, int yoff)
 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);
 
commit 11d0e2109b699714055e263e8963f2c39eded28b
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;
     }
commit 8b42ba64e169a35df2a90528dcb0cd06be0f67a1
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(ClientPtr client)
 {
     DeviceIntPtr pPointer, pKeyboard;
     int ret;
+    pairingChangedNotify ev; 
 
     REQUEST(xChangePointerKeyboardPairingReq);
     REQUEST_SIZE_MATCH(xChangePointerKeyboardPairingReq);
@@ -105,6 +109,27 @@ ProcXChangePointerKeyboardPairing(ClientPtr 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(ClientPtr	/* client */
 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_Present,
     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 (deviceLeaveNotify *from, deviceLeaveNotify *to)
     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 * extEntry)
     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 * extEntry)
     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 * to)
         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");
     }
commit 325380adb20ec2b82e176d75599fd4bc97a3b918
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, DeviceIntPtr ptr, DeviceIntPtr kbd)
     }
 
     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, WindowPtr pWin)
 
     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;
commit b043a184509cfe5c4c4691ecde1a4a065e53d575
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, Bool autoStart)
 
     /* 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)
commit 5e439109292e54b5c4d1a7bc7b6ac0e42ee285f7
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, WindowPtr pWin, xEvent
         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, WindowPtr pWin, xEvent
     }
     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, int count, xEvent *events)
 #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, int count, xEvent *events)
 	}
     }
 #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>
 
commit f28eea0647f007c2e2415ecc6fceef46201faad4
Merge: 339b73e... ae04f2c...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 27 16:34:36 2007 +0930

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	dix/devices.c
    	dix/events.c

diff --cc dix/devices.c
index cf6090d,e227617..a6e1415
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -693,15 -569,16 +715,19 @@@ RemoveDevice(DeviceIntPtr dev
      int ret = BadMatch;
      devicePresenceNotify ev;
      DeviceIntRec dummyDev;
 +    ScreenPtr screen = screenInfo.screens[0];
+     int deviceid;
  
      DebugF("(dix) removing device %d\n", dev->id);
  
      if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
          return BadImplementation;
  
 +    screen->UndisplayCursor(dev, screen);
 +
+     deviceid = dev->id;
+     DisableDevice(dev);
+ 
      prev = NULL;
      for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
  	next = tmp->next;
diff --cc dix/events.c
index da3f6aa,bc6b6ae..deb2da1
--- a/dix/events.c
+++ b/dix/events.c
@@@ -107,12 -107,10 +107,16 @@@ of the copyright holder
  
  ******************************************************************/
  
 +/* 
 + * MPX additions
 + * Copyright 2006 by Peter Hutterer
 + * Author: Peter Hutterer <peter at cs.unisa.edu.au>
 + */
 +
+ /** @file
+  * This file handles event delivery and a big part of the server-side protocol
+  * handling (the parts for input devices).
+  */
  
  #ifdef HAVE_DIX_CONFIG_H
  #include <dix-config.h>
@@@ -230,39 -252,43 +258,38 @@@ static struct 
      TimeStamp		time;
  } syncEvents;
  
 +#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
 +
 +/** 
 + * True if device owns a cursor, false if device shares a cursor sprite with
 + * another device.
 + */
 +_X_EXPORT Bool
 +DevHasCursor(DeviceIntPtr pDev) 
 +{
 +    return (pDev != inputInfo.pointer && pDev->spriteInfo->spriteOwner);
 +}
 +
  /*
 - * The window trace information is used to avoid having to compute all the
 - * windows between the root and the current pointer window each time a button
 - * or key goes down. The grabs on each of those windows must be checked.
 - * 
 - * @see XYToWindow() for a documentation on how the array is set up.
 + * Return true if a device is a pointer, check is the same as used by XI to
 + * fill the 'use' field.
   */
 -static WindowPtr *spriteTrace = (WindowPtr *)NULL;
 -#define ROOT spriteTrace[0]
 -static int spriteTraceSize = 0;
 -static int spriteTraceGood;
 +_X_EXPORT Bool
 +IsPointerDevice(DeviceIntPtr dev)
 +{
 +    return ((dev->valuator && dev->button) || dev == inputInfo.pointer);
 +}
  
 -/**
 - * DIX sprite information. This is the sprite as seen from the DIX. It does
 - * not represent the actual sprite rendered to the screen.
 - * 
 +/*
 + * Return true if a device is a keyboard, check is the same as used by XI to
 + * fill the 'use' field.
   */
 -static  struct {
 -    CursorPtr	current;
 -    BoxRec	hotLimits;	/* logical constraints of hot spot */
 -    Bool	confined;	/* confined to screen */
 -#if defined(SHAPE) || defined(PANORAMIX)
 -    RegionPtr	hotShape;	/* additional logical shape constraint */
 -#endif
 -    BoxRec	physLimits;	/* physical constraints of hot spot */
 -    WindowPtr	win;		/* window of logical position */
 -    HotSpot	hot;		/* logical pointer position */
 -    HotSpot	hotPhys;	/* physical pointer position */
 -#ifdef PANORAMIX
 -    ScreenPtr	screen;		/* all others are in Screen 0 coordinates */
 -    RegionRec   Reg1;	        /* Region 1 for confining motion */
 -    RegionRec   Reg2;		/* Region 2 for confining virtual motion */
 -    WindowPtr   windows[MAXSCREENS];
 -    WindowPtr	confineWin;	/* confine window */ 
 -#endif
 -} sprite;			/* info about the cursor sprite */
 +_X_EXPORT Bool
 +IsKeyboardDevice(DeviceIntPtr dev)
 +{
 +    return ((dev->key && dev->kbdfeed) || dev == inputInfo.keyboard);
 +}
  
- 
  #ifdef XEVIE
  _X_EXPORT WindowPtr xeviewin;
  _X_EXPORT HotSpot xeviehot;
@@@ -885,19 -882,24 +915,26 @@@ ConfineCursorToWindow(DeviceIntPtr pDev
  }
  
  _X_EXPORT Bool
 -PointerConfinedToScreen(void)
 +PointerConfinedToScreen(DeviceIntPtr pDev)
  {
 -    return sprite.confined;
 +    return pDev->spriteInfo->sprite->confined;
  }
  
+ /**
+  * Update the sprite cursor to the given cursor.
+  *
+  * ChangeToCursor() will display the new cursor and free the old cursor (if
+  * applicable). If the provided cursor is already the updated cursor, nothing
+  * happens.
+  */
  static void
 -ChangeToCursor(CursorPtr cursor)
 +ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
  {
 +    SpritePtr pSprite = pDev->spriteInfo->sprite;
 +
  #ifdef PANORAMIX
      if(!noPanoramiXExtension) {
 -	XineramaChangeToCursor(cursor);
 +	XineramaChangeToCursor(pDev, cursor);
  	return;
      }
  #endif
@@@ -926,13 -929,16 +965,18 @@@ IsParent(WindowPtr a, WindowPtr b
      return FALSE;
  }
  
+ /**
+  * Update the cursor displayed on the screen.
+  *
+  * Called whenever a cursor may have changed shape or position.  
+  */
  static void
 -PostNewCursor(void)
 +PostNewCursor(DeviceIntPtr pDev)
  {
      WindowPtr win;
 -    GrabPtr grab = inputInfo.pointer->grab;
 +    GrabPtr grab = pDev->coreGrab.grab;
 +    SpritePtr   pSprite = pDev->spriteInfo->sprite;
 +    CursorPtr   pCursor;
  
      if (syncEvents.playingEvents)
  	return;
@@@ -949,52 -955,50 +993,61 @@@
  	    win = grab->window;
      }
      else
 -	win = sprite.win;
 +	win = pSprite->win;
      for (; win; win = win->parent)
 -	if (win->optional && win->optional->cursor != NullCursor)
 -	{
 -	    ChangeToCursor(win->optional->cursor);
 -	    return;
 +    {
 +	if (win->optional) 
 +        {
 +            pCursor = WindowGetDeviceCursor(win, pDev);
 +            if (!pCursor && win->optional->cursor != NullCursor)
 +                pCursor = win->optional->cursor;
 +            if (pCursor)
 +            {
 +                ChangeToCursor(pDev, pCursor);
 +                return;
 +            }
  	}
 +    }
  }
  
 +
  /**
 - * @return root window of current active screen.
 + * @param dev device which you want to know its current root window
 + * @return root window where dev's sprite is located
   */
  _X_EXPORT WindowPtr
 -GetCurrentRootWindow(void)
 +GetCurrentRootWindow(DeviceIntPtr dev)
  {
 -    return ROOT;
 +    return RootWindow(dev);
  }
  
+ /**
+  * @return window underneath the cursor sprite.
+  */
  _X_EXPORT WindowPtr
 -GetSpriteWindow(void)
 +GetSpriteWindow(DeviceIntPtr pDev)
  {
 -    return sprite.win;
 +    return pDev->spriteInfo->sprite->win;
  }
  
+ /**
+  * @return current sprite cursor.
+  */
  _X_EXPORT CursorPtr
 -GetSpriteCursor(void)
 +GetSpriteCursor(DeviceIntPtr pDev)
  {
 -    return sprite.current;
 +    return pDev->spriteInfo->sprite->current;
  }
  
+ /**
+  * Set x/y current sprite position in screen coordinates.
+  */
  _X_EXPORT void
 -GetSpritePosition(int *px, int *py)
 +GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
  {
 -    *px = sprite.hotPhys.x;
 -    *py = sprite.hotPhys.y;
 +    SpritePtr pSprite = pDev->spriteInfo->sprite;
 +    *px = pSprite->hotPhys.x;
 +    *py = pSprite->hotPhys.y;
  }
  
  #ifdef PANORAMIX
@@@ -1703,9 -1711,26 +1815,26 @@@ TryClientEvents (ClientPtr client, xEve
      }
  }
  
+ /**
+  * Deliver events to a window. At this point, we do not yet know if the event
+  * actually needs to be delivered. May activate a grab if the event is a
+  * button press.
+  *
+  * More than one event may be delivered at a time. This is the case with
+  * DeviceMotionNotifies which may be followed by DeviceValuator events.
+  * 
+  * @param pWin The window that would get the event.
+  * @param pEvents The events to be delivered.
+  * @param count Number of elements in pEvents.
+  * @param filter Mask based on event type.
+  * @param grab Possible grab on the device that caused the event. 
+  * @param mskidx Mask index, depending on device that caused event.
+  *
+  * @return Number of events delivered to various clients.
+  */
  int
 -DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, 
 -                      Mask filter, GrabPtr grab, int mskidx)
 +DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 +        *pEvents, int count, Mask filter, GrabPtr grab, int mskidx)
  {
      int deliveries = 0, nondeliveries = 0;
      int attempt;
@@@ -1875,9 -1893,16 +2013,17 @@@ MaybeDeliverEventsToClient(WindowPtr pW
      return 2;
  }
  
+ /**
+  * Adjust event fields to comply with the window properties.
+  *
+  * @param xE Event to be modified in place
+  * @param pWin The window to get the information from.
+  * @param child Child window setting for event (if applicable)
+  * @param calcChild If True, calculate the child window.
+  */
  static void
  FixUpEventFromWindow(
 +    DeviceIntPtr pDev,
      xEvent *xE,
      WindowPtr pWin,
      Window child,
@@@ -2062,8 -2111,19 +2236,19 @@@ PointInBorderSize(WindowPtr pWin, int x
      return FALSE;
  }
  
+ /**
+  * Traversed from the root window to the window at the position x/y. While
+  * traversing, it sets up the traversal history in the spriteTrace array.
+  * After completing, the spriteTrace history is set in the following way:
+  *   spriteTrace[0] ... root window
+  *   spriteTrace[1] ... top level window that encloses x/y
+  *       ...
+  *   spriteTrace[spriteTraceGood - 1] ... window at x/y
+  *
+  * @returns the window at the given coordinates.
+  */
  static WindowPtr 
 -XYToWindow(int x, int y)
 +XYToWindow(DeviceIntPtr pDev, int x, int y)
  {
      WindowPtr  pWin;
      BoxRec		box;
@@@ -2110,16 -2167,19 +2295,22 @@@
  	else
  	    pWin = pWin->nextSib;
      }
 -    return spriteTrace[spriteTraceGood-1];
 +    return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
  }
  
+ /**
+  * Update the sprite coordinates based on the event. Update the cursor
+  * position, then update the event with the new coordinates that may have been
+  * changed. If the window underneath the sprite has changed, change to new
+  * cursor and send enter/leave events.
+  */
 -static Bool
 -CheckMotion(xEvent *xE)
 +Bool
 +CheckMotion(xEvent *xE, DeviceIntPtr pDev)
  {
 -    WindowPtr prevSpriteWin = sprite.win;
 +    WindowPtr prevSpriteWin;
 +    SpritePtr pSprite = pDev->spriteInfo->sprite;
 +        
 +    prevSpriteWin = pSprite->win;
  
  #ifdef PANORAMIX
      if(!noPanoramiXExtension)
@@@ -3456,9 -3458,12 +3721,13 @@@ CommonAncestor
      return NullWindow;
  }
  
+ /**
+  * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 
+  * The core devices are used to fill in the event fields.
+  */
  static void
  EnterLeaveEvent(
 +    DeviceIntPtr mouse,
      int type,
      int mode,
      int detail,
@@@ -3610,27 -3544,28 +3879,36 @@@
      }
  }
  
+ /**
+  * Send enter notifies to all parent windows up to ancestor.
+  * This function recurses.
+  */
  static void
 -EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail)
 +EnterNotifies(DeviceIntPtr pDev, 
 +              WindowPtr ancestor, 
 +              WindowPtr child, 
 +              int mode, 
 +              int detail) 
  {
      WindowPtr	parent = child->parent;
  
      if (ancestor == parent)
  	return;
 -    EnterNotifies(ancestor, parent, mode, detail);
 -    EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id);
 -}
 +    EnterNotifies(pDev, ancestor, parent, mode, detail);
 +    EnterLeaveEvent(pDev, EnterNotify, mode, detail, parent,
 +                    child->drawable.id); }
  
+ 
+ /**
+  * Send leave notifies to all parent windows up to ancestor.
+  * This function recurses.
+  */
  static void
 -LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
 +LeaveNotifies(DeviceIntPtr pDev, 
 +              WindowPtr child, 
 +              WindowPtr ancestor, 
 +              int mode, 
 +              int detail)
  {
      WindowPtr  pWin;
  
@@@ -3644,11 -3578,15 +3922,18 @@@
      }
  }
  
+ /**
+  * Figure out if enter/leave events are necessary and send them to the
+  * appropriate windows.
+  * 
+  * @param fromWin Window the sprite moved out of.
+  * @param toWin Window the sprite moved into.
+  */
  static void
 -DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode)
 +DoEnterLeaveEvents(DeviceIntPtr pDev, 
 +        WindowPtr fromWin, 
 +        WindowPtr toWin, 
 +        int mode) 
  {
      if (fromWin == toWin)
  	return;
@@@ -4447,16 -4402,19 +4816,21 @@@ InitEvents(void
      }
  }
  
 -void
 +/**
 + * This function is deprecated! It shouldn't be used anymore. It used to free
 + * the spriteTraces, but now they are freed when the SpriteRec is freed.
 + */
 +_X_DEPRECATED void
  CloseDownEvents(void)
  {
 -  xfree(spriteTrace);
 -  spriteTrace = NULL;
 -  spriteTraceSize = 0;
 +
  }
  
+ /**
+  * Server-side protocol handling for SendEvent request.
+  *
+  * Locates the window to send the event to and forwards the event. 
+  */
  int
  ProcSendEvent(ClientPtr client)
  {
commit 339b73e710a0920608a3fbcb20b406f0f6c4e0f6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 27 13:24:27 2007 +0930

    Allow events to grabWindows event if the device is not grabbed.
    
    This kinda makes popup windows useable if the WM doesn't set the
    ClientPointer. Kinda.

diff --git a/dix/events.c b/dix/events.c
index a751e3c..da3f6aa 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1729,7 +1729,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 	    return 0;
         
         if (!(type & EXTENSION_EVENT_BASE) && 
-            IsInterferingGrab(wClient(pWin), pDev, pEvents))
+            IsInterferingGrab(wClient(pWin), pWin, pDev, pEvents))
                 return 0;
 
 	if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
@@ -1762,7 +1762,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 	{
             /* core event? check for grab interference */
             if (!(type & EXTENSION_EVENT_BASE) &&
-                    IsInterferingGrab(rClient(other), pDev, pEvents))
+                    IsInterferingGrab(rClient(other), pWin, pDev, pEvents))
                 continue;
 
 	    if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
@@ -5097,15 +5097,19 @@ 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, DeviceIntPtr dev, xEvent* event)
+IsInterferingGrab(ClientPtr client, WindowPtr win, DeviceIntPtr dev, xEvent* event)
 {
-    DeviceIntPtr it = inputInfo.devices;
+    DeviceIntPtr it;
+    Bool mayInterfere = FALSE;
 
     if (dev->coreGrab.grab && SameClient(dev->coreGrab.grab, client))
         return FALSE;
@@ -5124,19 +5128,30 @@ IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
             return FALSE;
     }
 
+    it = inputInfo.devices;
     while(it)
     {
         if (it != dev)
         {
             if (it->coreGrab.grab && SameClient(it->coreGrab.grab, client))
             {
-                return TRUE;
+                /* 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->coreGrab.grab->window == parent)
+                        return FALSE;
+                    parent = parent->parent;
+                }
 
+                mayInterfere = TRUE;
             }
         }
         it = it->next;
     }
 
-    return FALSE;
+    return mayInterfere;
 }
 
diff --git a/include/dix.h b/include/dix.h
index 9da265d..93472e8 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -550,6 +550,7 @@ extern DeviceIntPtr PickKeyboard(
 
 extern Bool IsInterferingGrab(
         ClientPtr /* client */,
+        WindowPtr /* win */,
         DeviceIntPtr /* dev */,
         xEvent* /* events */);
 
commit cfc01115af4136b2dad8218ba6b389513a356a2e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 26 22:18:35 2007 +0930

    Fix cursor rendering for multi-head.
    
    Before putting anything on the screen, check if the GC was made for the
    ScreenRec we want to render to. If not, toss the GC and create a new one. This
    is not the best solution but it does the job for now. Same thing for ARGB
    cursors except that it's even uglier.
    
    Also remember the screen the cursor was rendered to and check for the right
    screen in the BlockHandler, SourceValidate and a few others. Only remove or
    restore the cursor if we are rendering to the same screen, otherwise we get
    artefacts that are both funky and really annoying.

diff --git a/mi/midispcur.c b/mi/midispcur.c
index d4471f9..d7a8964 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -488,6 +488,15 @@ miDCPutUpCursor (pDev, pScreen, pCursor, x, y, source, mask)
 #ifdef ARGB_CURSOR
     if (pPriv->pPicture)
     {
+        /* see comment in miDCPutUpCursor */
+        if (pBuffer->pRootPicture && 
+                pBuffer->pRootPicture->pDrawable &&
+                pBuffer->pRootPicture->pDrawable->pScreen != pScreen)
+        {
+            tossPict(pBuffer->pRootPicture);
+            pBuffer->pRootPicture = NULL;
+        }
+
 	if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
 	    return FALSE;
 	CompositePicture (PictOpOver,
@@ -502,6 +511,25 @@ miDCPutUpCursor (pDev, pScreen, pCursor, x, y, source, mask)
     else
 #endif
     {
+        /**
+         * XXX: Before MPX, the sourceGC and maskGC were attached to the
+         * screen, and would switch as the screen switches.  With mpx we have
+         * the GC's attached to the device now, so each time we switch screen
+         * we need to make sure the GC's are allocated on the new screen.
+         * This is ... not optimal. (whot)
+         */
+        if (pBuffer->pSourceGC && pScreen != pBuffer->pSourceGC->pScreen)
+        {
+            tossGC(pBuffer->pSourceGC);
+            pBuffer->pSourceGC = NULL;
+        }
+
+        if (pBuffer->pMaskGC && pScreen != pBuffer->pMaskGC->pScreen)
+        {
+            tossGC(pBuffer->pMaskGC);
+            pBuffer->pMaskGC = NULL;
+        }
+
 	if (!EnsureGC(pBuffer->pSourceGC, pWin))
 	    return FALSE;
 	if (!EnsureGC(pBuffer->pMaskGC, pWin))
@@ -544,6 +572,12 @@ miDCSaveUnderCursor (pDev, pScreen, x, y, w, h)
 	if (!pSave)
 	    return FALSE;
     }
+    /* see comment in miDCPutUpCursor */
+    if (pBuffer->pSaveGC && pBuffer->pSaveGC->pScreen != pScreen)
+    {
+        tossGC(pBuffer->pSaveGC);
+        pBuffer->pSaveGC = NULL;
+    }
     if (!EnsureGC(pBuffer->pSaveGC, pWin))
 	return FALSE;
     pGC = pBuffer->pSaveGC;
@@ -573,6 +607,12 @@ miDCRestoreUnderCursor (pDev, pScreen, x, y, w, h)
     pWin = WindowTable[pScreen->myNum];
     if (!pSave)
 	return FALSE;
+    /* see comment in miDCPutUpCursor */
+    if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen)
+    {
+        tossGC(pBuffer->pRestoreGC);
+        pBuffer->pRestoreGC = NULL;
+    }
     if (!EnsureGC(pBuffer->pRestoreGC, pWin))
 	return FALSE;
     pGC = pBuffer->pRestoreGC;
@@ -606,6 +646,12 @@ miDCChangeSave (pDev, pScreen, x, y, w, h, dx, dy)
      */
     if (!pSave)
 	return FALSE;
+    /* see comment in miDCPutUpCursor */
+    if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen)
+    {
+        tossGC(pBuffer->pRestoreGC);
+        pBuffer->pRestoreGC = NULL;
+    }
     if (!EnsureGC(pBuffer->pRestoreGC, pWin))
 	return FALSE;
     pGC = pBuffer->pRestoreGC;
@@ -646,6 +692,12 @@ miDCChangeSave (pDev, pScreen, x, y, w, h, dx, dy)
 	(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
 			       0, sourcey, -dx, copyh, x + dx, desty);
     }
+    /* see comment in miDCPutUpCursor */
+    if (pBuffer->pSaveGC && pBuffer->pSaveGC->pScreen != pScreen)
+    {
+        tossGC(pBuffer->pSaveGC);
+        pBuffer->pSaveGC = NULL;
+    }
     if (!EnsureGC(pBuffer->pSaveGC, pWin))
 	return FALSE;
     pGC = pBuffer->pSaveGC;
@@ -788,6 +840,15 @@ miDCMoveCursor (pDev, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
 #ifdef ARGB_CURSOR
     if (pPriv->pPicture)
     {
+        /* see comment in miDCPutUpCursor */
+        if (pBuffer->pTempPicture && 
+                pBuffer->pTempPicture->pDrawable &&
+                pBuffer->pTempPicture->pDrawable->pScreen != pScreen)
+        {
+            tossPict(pBuffer->pTempPicture);
+            pBuffer->pTempPicture = NULL;
+        }
+
 	if (!EnsurePicture(pBuffer->pTempPicture, &pTemp->drawable, pWin))
 	    return FALSE;
 	CompositePicture (PictOpOver,
@@ -822,6 +883,12 @@ miDCMoveCursor (pDev, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
 		     source, mask);
     }
 
+    /* see comment in miDCPutUpCursor */
+    if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen)
+    {
+        tossGC(pBuffer->pRestoreGC);
+        pBuffer->pRestoreGC = NULL;
+    }
     /*
      * copy the temporary pixmap onto the screen
      */
diff --git a/mi/misprite.c b/mi/misprite.c
index 60774b5..6e42152 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -79,6 +79,7 @@ static int miSpriteDevPrivatesIndex;
        (miCursorInfoPtr) dev->devPrivates[miSpriteDevPrivatesIndex].ptr : \
        (miCursorInfoPtr) inputInfo.pointer->devPrivates[miSpriteDevPrivatesIndex].ptr)
 
+
 /*
  * screen wrappers
  */
@@ -175,6 +176,7 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
             pCursorInfo = MISPRITE(pDev);
 
             if (pCursorInfo->isUp &&
+                pCursorInfo->pScreen == pScreen && 
                 RECT_IN_REGION (pScreen, pRegion, &pCursorInfo->saved) 
                          != rgnOUT) 
             {
@@ -277,7 +279,6 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     damageRegister = 0;
     miSpriteDevPrivatesIndex = AllocateDevicePrivateIndex();
 
-
     return TRUE;
 }
 
@@ -340,6 +341,7 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
              pCursorInfo = MISPRITE(pDev);
              if (pDrawable->type == DRAWABLE_WINDOW &&
                      pCursorInfo->isUp &&
+                     pCursorInfo->pScreen == pScreen &&
                      ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, 
                          sx, sy, w, h)) 
              {
@@ -379,7 +381,9 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
         {
             pCursorInfo = MISPRITE(pDev);
 
-            if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp)
+            if (pDrawable->type == DRAWABLE_WINDOW && 
+                    pCursorInfo->isUp && 
+                    pCursorInfo->pScreen == pScreen)
             {
                 DDXPointPtr    pts;
                 int    	       *widths;
@@ -431,6 +435,7 @@ miSpriteSourceValidate (pDrawable, x, y, width, height)
         {
             pCursorInfo = MISPRITE(pDev);
             if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp &&
+                    pCursorInfo->pScreen == pScreen && 
                     ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
                         x, y, width, height))
             {
@@ -466,7 +471,7 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
             /*
              * Damage will take care of destination check
              */
-            if (pCursorInfo->isUp &&
+            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
                     RECT_IN_REGION (pScreen, prgnSrc, &pCursorInfo->saved) != rgnOUT)
             {
                 SPRITE_DEBUG (("CopyWindow remove\n"));
@@ -504,7 +509,9 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
         if (DevHasCursor(pDev))
         {
             pCursorInfo = MISPRITE(pDev);
-            if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
+            if (!pCursorInfo->isUp 
+                    && pCursorInfo->pScreen == pScreen 
+                    && pCursorInfo->shouldBeUp)
             {
                 SPRITE_DEBUG (("BlockHandler restore\n"));
                 miSpriteSaveUnderCursor (pDev, pScreen);
@@ -516,7 +523,9 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
         if (DevHasCursor(pDev))
         {
             pCursorInfo = MISPRITE(pDev);
-            if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
+            if (!pCursorInfo->isUp && 
+                    pCursorInfo->pScreen == pScreen && 
+                    pCursorInfo->shouldBeUp)
             {
                 SPRITE_DEBUG (("BlockHandler restore\n"));
                 miSpriteRestoreCursor (pDev, pScreen);
@@ -552,7 +561,7 @@ miSpriteInstallColormap (pMap)
             {
                 pCursorInfo = MISPRITE(pDev);
                 pCursorInfo->checkPixels = TRUE;
-                if (pCursorInfo->isUp)
+                if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
                     miSpriteRemoveCursor(pDev, pScreen);
             }
         }
@@ -639,7 +648,7 @@ miSpriteStoreColors (pMap, ndef, pdef)
                 {
                     pCursorInfo = MISPRITE(pDev);
                     pCursorInfo->checkPixels = TRUE;
-                    if (pCursorInfo->isUp)
+                    if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
                         miSpriteRemoveCursor (pDev, pScreen);
                 }
             }
@@ -711,7 +720,7 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
         if(DevHasCursor(pDev))
         {
             pCursorInfo = MISPRITE(pDev);
-            if (pCursorInfo->isUp)
+            if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
             {
                 cursorBox = pCursorInfo->saved;
 
@@ -930,6 +939,7 @@ miSpriteDeviceCursorInitialize(pDev, pScreen)
     pCursorInfo->pCacheWin = NullWindow;
     pCursorInfo->isInCacheWin = FALSE;
     pCursorInfo->checkPixels = TRUE;
+    pCursorInfo->pScreen = FALSE;
 
     ret = (*pScreenPriv->funcs->DeviceCursorInitialize)(pDev, pScreen);
     if (!ret)
@@ -1075,6 +1085,7 @@ miSpriteRestoreCursor (pDev, pScreen)
                 pScreenPriv->colors[MASK_COLOR].pixel))
     {
         miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
+        pCursorInfo->pScreen = pScreen;
     }
     miSpriteEnableDamage(pScreen, pScreenPriv);
     DamageDrawInternal (pScreen, FALSE);
diff --git a/mi/mispritest.h b/mi/mispritest.h
index f4155b5..81efa44 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -53,6 +53,7 @@ typedef struct {
     WindowPtr	    pCacheWin;		/* window the cursor last seen in */
     Bool	    isInCacheWin;
     Bool	    checkPixels;	/* check colormap collision */
+    ScreenPtr       pScreen;
 } miCursorInfoRec, *miCursorInfoPtr;
 
 /*
commit 82f97e1c0cc15b050edc82a8f3b9a423d6cf5fe7
Author: Paulo Ricardo Zanoni <prz05 at c3sl.ufpr.br>
Date:   Thu Apr 26 15:58:50 2007 +0930

    Enable event delivery for multiple heads.
    
    Requires moving the spriteTrace into the DeviceIntRec and adjusting a few
    functions to take in device argument, most notably XYToWindow().
    
    Cursor rendering on the second screen is busted.

diff --git a/XTrap/xtrapdi.c b/XTrap/xtrapdi.c
index bc15bbd..0b70d7b 100644
--- a/XTrap/xtrapdi.c
+++ b/XTrap/xtrapdi.c
@@ -102,7 +102,7 @@ globalref int_function XETrapProcVector[256L]; /* The "shadowed" ProcVector */
 #ifndef VECTORED_EVENTS
 globalref int_function EventProcVector[XETrapCoreEvents];
 #else
-extern WindowPtr GetCurrentRootWindow();
+extern WindowPtr GetCurrentRootWindow(DeviceIntPtr);
 globalref int_function EventProcVector[128L];
 #endif
 static int_function keybd_process_inp = NULL;  /* Used for VECTORED_EVENTS */
@@ -1620,7 +1620,9 @@ int XETrapEventVector(ClientPtr client, xEvent *x_event)
                 (x_event->u.u.type <= MotionNotify) && 
                 (!x_event->u.keyButtonPointer.sameScreen)))
             {   /* we've moved/warped to another screen */
-                WindowPtr root_win = GetCurrentRootWindow();
+		/* XXX: we're getting the client's pointer root window.
+		 * is this correct?  Should it be the client's keyboard? */
+                WindowPtr root_win = GetCurrentRootWindow(PickPointer(client));
                 current_screen = root_win->drawable.pScreen->myNum;
             }
             data.hdr.screen = current_screen;
diff --git a/Xext/xevie.c b/Xext/xevie.c
index 7922913..0feb4d7 100644
--- a/Xext/xevie.c
+++ b/Xext/xevie.c
@@ -463,7 +463,7 @@ XevieKbdProcessInputProc(xEvent *xE, DeviceIntPtr dev, int count)
             xevieModifiersOn = TRUE;
 
         xE->u.keyButtonPointer.event = xeviewin->drawable.id;
-        xE->u.keyButtonPointer.root = GetCurrentRootWindow()->drawable.id;
+        xE->u.keyButtonPointer.root = GetCurrentRootWindow(dev)->drawable.id;
         xE->u.keyButtonPointer.child = (xeviewin->firstChild)
             ? xeviewin->firstChild->drawable.id:0;
         xE->u.keyButtonPointer.rootX = xeviehot.x;
diff --git a/Xext/xtest.c b/Xext/xtest.c
index 93e88c4..963029c 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -363,7 +363,7 @@ ProcXTestFakeInput(client)
         if (!dev)
             dev = PickPointer(client);
 	if (ev->u.keyButtonPointer.root == None)
-	    root = GetCurrentRootWindow();
+	    root = GetCurrentRootWindow(dev);
 	else
 	{
 	    rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client,
@@ -428,10 +428,10 @@ ProcXTestFakeInput(client)
 	if ((!noPanoramiXExtension
 	     && root->drawable.pScreen->myNum 
                 != XineramaGetCursorScreen(dev))
-	    || (noPanoramiXExtension && root != GetCurrentRootWindow()))
+	    || (noPanoramiXExtension && root != GetCurrentRootWindow(dev)))
 
 #else
-	if (root != GetCurrentRootWindow())
+	if (root != GetCurrentRootWindow(dev))
 #endif
 	{
 	    NewCurrentScreen(dev, root->drawable.pScreen,
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 26f3640..d00dc29 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -835,7 +835,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
 	/* If the input focus is PointerRootWin, send the event to where
 	 * the pointer is if possible, then perhaps propogate up to root. */
 	if (inputFocus == PointerRootWin)
-	    inputFocus = GetCurrentRootWindow();
+	    inputFocus = GetCurrentRootWindow(d);
 
 	if (IsParent(inputFocus, spriteWin)) {
 	    effectiveFocus = inputFocus;
diff --git a/Xi/querydp.c b/Xi/querydp.c
index d2ed0b8..6224f13 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -107,7 +107,7 @@ ProcXQueryDevicePointer(ClientPtr client)
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
     rep.mask = pDev->button->state | inputInfo.keyboard->key->state;
-    rep.root = (GetCurrentRootWindow())->drawable.id;
+    rep.root = (GetCurrentRootWindow(pDev))->drawable.id;
     rep.rootX = pSprite->hot.x;
     rep.rootY = pSprite->hot.y;
     rep.child = None;
diff --git a/dix/devices.c b/dix/devices.c
index 9e48c0b..cf6090d 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -194,6 +194,14 @@ EnableDevice(DeviceIntPtr dev)
 	 *prev && (*prev != dev);
 	 prev = &(*prev)->next)
 	;
+
+    /* Sprites will be initialized with their 'windows' just when inside the
+     * DefineInitialRootWindow function! */
+    if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
+        InitializeSprite(dev, NullWindow);
+    else
+        PairDevices(NULL, inputInfo.pointer, dev);
+
     if ((*prev != dev) || !dev->inited ||
 	((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
         ErrorF("couldn't enable device %d\n", dev->id);
@@ -202,11 +210,6 @@ EnableDevice(DeviceIntPtr dev)
     dev->enabled = TRUE;
     *prev = dev->next;
 
-    if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
-        InitializeSprite(dev, GetCurrentRootWindow());
-    else
-        PairDevices(NULL, inputInfo.pointer, dev);
-
     for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next)
         ;
     *prev = dev;
@@ -272,6 +275,11 @@ ActivateDevice(DeviceIntPtr dev)
     return ret;
 }
 
+int
+DeactivateDevice(DeviceIntPtr dev)
+{
+}
+
 static void
 CoreKeyboardBell(int volume, DeviceIntPtr pDev, pointer arg, int something)
 {
@@ -614,8 +622,10 @@ CloseDevice(DeviceIntPtr dev)
 	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
 #endif
     
-    if (DevHasCursor(dev))
-        xfree((pointer)dev->spriteInfo->sprite);
+    if (DevHasCursor(dev)) {
+        xfree(dev->spriteInfo->sprite->spriteTrace);
+        xfree(dev->spriteInfo->sprite);
+    }
 
     /* a client may have the device set as client pointer */
     for (j = 0; j < currentMaxClients; j++)
diff --git a/dix/events.c b/dix/events.c
index 1733e2d..a751e3c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -230,15 +230,7 @@ static struct {
     TimeStamp		time;
 } syncEvents;
 
-/*
- * The window trace information is used to avoid having to compute all the
- * windows between the root and the current pointer window each time a button
- * or key goes down. The grabs on each of those windows must be checked.
- */
-static WindowPtr *spriteTrace = (WindowPtr *)NULL;
-#define ROOT spriteTrace[0]
-static int spriteTraceSize = 0;
-static int spriteTraceGood;
+#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
 
 /** 
  * True if device owns a cursor, false if device shares a cursor sprite with
@@ -284,6 +276,7 @@ static void DoEnterLeaveEvents(
 ); 
 
 static WindowPtr XYToWindow(
+    DeviceIntPtr pDev,
     int x,
     int y
 );
@@ -607,7 +600,7 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
     xeviehot.y = pSprite->hot.y;
     xeviewin =
 #endif
-    pSprite->win = XYToWindow(pSprite->hot.x, pSprite->hot.y);
+    pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y);
 
     if (pSprite->win != prevSpriteWin)
     {
@@ -858,7 +851,7 @@ CheckVirtualMotion(
     xeviehot.x = pSprite->hot.x;
     xeviehot.y = pSprite->hot.y;
 #endif
-    ROOT = WindowTable[pSprite->hot.pScreen->myNum];
+    RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
 }
 
 static void
@@ -973,10 +966,15 @@ PostNewCursor(DeviceIntPtr pDev)
     }
 }
 
+
+/**
+ * @param dev device which you want to know its current root window
+ * @return root window where dev's sprite is located
+ */
 _X_EXPORT WindowPtr
-GetCurrentRootWindow(void)
+GetCurrentRootWindow(DeviceIntPtr dev)
 {
-    return ROOT;
+    return RootWindow(dev);
 }
 
 _X_EXPORT WindowPtr
@@ -1201,10 +1199,11 @@ ComputeFreezes(void)
 	count = replayDev->coreGrab.sync.evcount;
 	syncEvents.replayDev = (DeviceIntPtr)NULL;
 
-        w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY);
-	for (i = 0; i < spriteTraceGood; i++)
+        w = XYToWindow(replayDev, XE_KBPTR.rootX, XE_KBPTR.rootY);
+	for (i = 0; i < replayDev->spriteInfo->sprite->spriteTraceGood; i++)
 	{
-	    if (syncEvents.replayWin == spriteTrace[i])
+	    if (syncEvents.replayWin ==
+		replayDev->spriteInfo->sprite->spriteTrace[i])
 	    {
 		if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
 		    if (replayDev->focus)
@@ -1365,7 +1364,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
     DoEnterLeaveEvents(mouse, grab->window, 
                        mouse->spriteInfo->sprite->win, NotifyUngrab);
     if (grab->confineTo)
-	ConfineCursorToWindow(mouse, ROOT, FALSE, FALSE);
+	ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE);
     PostNewCursor(mouse);
     if (grab->cursor)
 	FreeCursor(grab->cursor, (Cursor)0);
@@ -1888,7 +1887,7 @@ FixUpEventFromWindow(
 
     if (calcChild)
     {
-        WindowPtr w=spriteTrace[spriteTraceGood-1];
+        WindowPtr w= pSprite->spriteTrace[pSprite->spriteTraceGood-1];
 	/* If the search ends up past the root should the child field be 
 	 	set to none or should the value in the argument be passed 
 		through. It probably doesn't matter since everyone calls 
@@ -1913,7 +1912,7 @@ FixUpEventFromWindow(
  	    w = w->parent;
         } 	    
     }
-    XE_KBPTR.root = ROOT->drawable.id;
+    XE_KBPTR.root = RootWindow(pDev)->drawable.id;
     XE_KBPTR.event = pWin->drawable.id;
     if (pSprite->hot.pScreen == pWin->drawable.pScreen)
     {
@@ -2064,13 +2063,15 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
 }
 
 static WindowPtr 
-XYToWindow(int x, int y)
+XYToWindow(DeviceIntPtr pDev, int x, int y)
 {
     WindowPtr  pWin;
     BoxRec		box;
+    SpritePtr pSprite;
 
-    spriteTraceGood = 1;	/* root window still there */
-    pWin = ROOT->firstChild;
+    pSprite = pDev->spriteInfo->sprite;
+    pSprite->spriteTraceGood = 1;	/* root window still there */
+    pWin = RootWindow(pDev)->firstChild;
     while (pWin)
     {
 	if ((pWin->mapped) &&
@@ -2094,21 +2095,22 @@ XYToWindow(int x, int y)
 #endif
 	    )
 	{
-	    if (spriteTraceGood >= spriteTraceSize)
+	    if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
 	    {
-		spriteTraceSize += 10;
+		pSprite->spriteTraceSize += 10;
 		Must_have_memory = TRUE; /* XXX */
-		spriteTrace = (WindowPtr *)xrealloc(
-		    spriteTrace, spriteTraceSize*sizeof(WindowPtr));
+		pSprite->spriteTrace = (WindowPtr *)xrealloc(
+		                    pSprite->spriteTrace,
+		                    pSprite->spriteTraceSize*sizeof(WindowPtr));
 		Must_have_memory = FALSE; /* XXX */
 	    }
-	    spriteTrace[spriteTraceGood++] = pWin;
+	    pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
 	    pWin = pWin->firstChild;
 	}
 	else
 	    pWin = pWin->nextSib;
     }
-    return spriteTrace[spriteTraceGood-1];
+    return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
 }
 
 Bool
@@ -2129,7 +2131,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
 	{
 	    pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
-	    ROOT = WindowTable[pSprite->hot.pScreen->myNum];
+	    RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
 	}
 	pSprite->hot.x = XE_KBPTR.rootX;
 	pSprite->hot.y = XE_KBPTR.rootY;
@@ -2166,7 +2168,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 #ifdef XEVIE
     xeviewin =
 #endif
-    pSprite->win = XYToWindow(pSprite->hot.x, pSprite->hot.y);
+    pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y);
 #ifdef notyet
     if (!(pSprite->win->deliverableEvents &
 	  Motion_Filter(pDev->button))
@@ -2263,7 +2265,6 @@ DefineInitialRootWindow(WindowPtr win)
 #ifdef XEVIE
     xeviewin = win;
 #endif
-    ROOT = win;
 
     InitializeSprite(inputInfo.pointer, win);
 
@@ -2312,8 +2313,25 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
     {
         pSprite->current = wCursor(pWin);
         pSprite->current->refcnt++;
-    } else
+ 	pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr));
+	if (!pSprite->spriteTrace)
+	    FatalError("Failed to allocate spriteTrace");
+	pSprite->spriteTraceSize = 32;
+
+	RootWindow(pDev) = pWin;
+	pSprite->spriteTraceGood = 1;
+
+	pSprite->pEnqueueScreen = pScreen;
+	pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
+
+    } else {
         pSprite->current = NullCursor;
+	pSprite->spriteTrace = NULL;
+	pSprite->spriteTraceSize = 0;
+	pSprite->spriteTraceGood = 0;
+	pSprite->pEnqueueScreen = screenInfo.screens[0];
+	pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
+    }
 
     if (pScreen)
     {
@@ -2768,14 +2786,15 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
 	}
   
 	if ((focus->win == NoneWin) ||
-	    (i >= spriteTraceGood) ||
-	    ((i > checkFirst) && (pWin != spriteTrace[i-1])))
+	    (i >= device->spriteInfo->sprite->spriteTraceGood) ||
+	    ((i > checkFirst) &&
+             (pWin != device->spriteInfo->sprite->spriteTrace[i-1])))
 	    return FALSE;
     }
 
-    for (; i < spriteTraceGood; i++)
+    for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
     {
-	pWin = spriteTrace[i];
+	pWin = device->spriteInfo->sprite->spriteTrace[i];
 	if (pWin->optional &&
 	    CheckPassiveGrabsOnWindow(pWin, device, xE, count))
 	    return TRUE;
@@ -2946,7 +2965,7 @@ ProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
         {
           xeviekb = keybd;
           if(!rootWin) {
-	      rootWin = GetCurrentRootWindow()->drawable.id;
+	      rootWin = GetCurrentRootWindow(keybd)->drawable.id;
           }
           xE->u.keyButtonPointer.event = xeviewin->drawable.id;
           xE->u.keyButtonPointer.root = rootWin;
@@ -3806,8 +3825,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
    	{
 	    if (fromWin == PointerRootWin)
-                FocusOutEvents(dev, pSprite->win, ROOT, mode,
-                        NotifyPointer, TRUE);
+                FocusOutEvents(dev, pSprite->win, RootWindow(dev), mode,
+                               NotifyPointer, TRUE);
 	    /* Notify all the roots */
 #ifdef PANORAMIX
  	    if ( !noPanoramiXExtension )
@@ -3836,16 +3855,16 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	    for (i=0; i<screenInfo.numScreens; i++)
 	        FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
 	if (toWin == PointerRootWin)
-	    (void)FocusInEvents(dev, ROOT, pSprite->win, NullWindow, mode,
-				NotifyPointer, TRUE);
+	    (void)FocusInEvents(dev, RootWindow(dev), pSprite->win,
+				NullWindow, mode, NotifyPointer, TRUE);
     }
     else
     {
 	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
 	{
 	    if (fromWin == PointerRootWin)
-		FocusOutEvents(dev, pSprite->win, ROOT, mode, NotifyPointer,
-			       TRUE);
+		FocusOutEvents(dev, pSprite->win, RootWindow(dev), mode,
+			       NotifyPointer, TRUE);
 #ifdef PANORAMIX
  	    if ( !noPanoramiXExtension )
 	        FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
@@ -3854,7 +3873,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	        for (i=0; i<screenInfo.numScreens; i++)
 	            FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
 	    if (toWin->parent != NullWindow)
-	      (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
+	      (void)FocusInEvents(dev, RootWindow(dev), toWin, toWin, mode,
 				  NotifyNonlinearVirtual, TRUE);
 	    FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
 	    if (IsParent(toWin, pSprite->win))
@@ -4130,7 +4149,7 @@ ProcGrabPointer(ClientPtr client)
 	if (grab)
  	{
 	    if (grab->confineTo && !confineTo)
-		ConfineCursorToWindow(device, ROOT, FALSE, FALSE);
+		ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE);
 	    oldCursor = grab->cursor;
 	}
 	tempGrab.cursor = cursor;
@@ -4351,7 +4370,7 @@ ProcQueryPointer(ClientPtr client)
     rep.sequenceNumber = client->sequence;
     rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
     rep.length = 0;
-    rep.root = (ROOT)->drawable.id;
+    rep.root = (RootWindow(mouse))->drawable.id;
     rep.rootX = pSprite->hot.x;
     rep.rootY = pSprite->hot.y;
     rep.child = None;
@@ -4400,19 +4419,6 @@ InitEvents(void)
     inputInfo.off_devices = (DeviceIntPtr)NULL;
     inputInfo.keyboard = (DeviceIntPtr)NULL;
     inputInfo.pointer = (DeviceIntPtr)NULL;
-    if (spriteTraceSize == 0)
-    {
-	spriteTraceSize = 32;
-	spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr));
-        /* FIXME: spriteTrace[0] needs to be NULL, otherwise
-         * GetCurrentRootWindow() in EnableDevice() may return a invalid
-         * value. (whot)
-         */
-        memset(spriteTrace, 0, 32 * sizeof(WindowPtr));
-	if (!spriteTrace)
-	    FatalError("failed to allocate spriteTrace");
-    }
-    spriteTraceGood = 0;
     lastEventMask = OwnerGrabButtonMask;
     filters[MotionNotify] = PointerMotionMask;
 #ifdef XEVIE
@@ -4441,13 +4447,14 @@ InitEvents(void)
     }
 }
 
-
-void
+/**
+ * This function is deprecated! It shouldn't be used anymore. It used to free
+ * the spriteTraces, but now they are freed when the SpriteRec is freed.
+ */
+_X_DEPRECATED void
 CloseDownEvents(void)
 {
-  xfree(spriteTrace);
-  spriteTrace = NULL;
-  spriteTraceSize = 0;
+
 }
 
 int
@@ -4497,7 +4504,7 @@ ProcSendEvent(ClientPtr client)
 	/* If the input focus is PointerRootWin, send the event to where
 	the pointer is if possible, then perhaps propogate up to root. */
    	if (inputFocus == PointerRootWin)
-	    inputFocus = ROOT;
+	    inputFocus = pSprite->spriteTrace[0]; /* Root window! */
 
 	if (IsParent(inputFocus, pSprite->win))
 	{
diff --git a/dix/main.c b/dix/main.c
index f5b89ba..2f064a9 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -498,7 +498,6 @@ main(int argc, char *argv[], char *envp[])
 	    FreeScreen(screenInfo.screens[i]);
 	    screenInfo.numScreens = i;
 	}
-  	CloseDownEvents();
 	xfree(WindowTable);
 	WindowTable = NULL;
 	FreeFonts();
diff --git a/hw/xwin/winwin32rootlesswndproc.c b/hw/xwin/winwin32rootlesswndproc.c
index ffa8493..54df889 100755
--- a/hw/xwin/winwin32rootlesswndproc.c
+++ b/hw/xwin/winwin32rootlesswndproc.c
@@ -299,7 +299,9 @@ IsRaiseOnClick (WindowPtr pWin)
 
   struct _Window	*pwin;
   struct _Property	*prop;  
-  WindowPtr		pRoot = GetCurrentRootWindow ();
+  /* XXX We're getting inputInfo.poniter here, but this might be really wrong.
+   * Which pointer's current window do we want? */
+  WindowPtr		pRoot = GetCurrentRootWindow (inputInfo.pointer);
 
   if (!pWin)
     {
@@ -352,7 +354,9 @@ IsMouseActive (WindowPtr pWin)
 
   struct _Window	*pwin;
   struct _Property	*prop;
-  WindowPtr		pRoot = GetCurrentRootWindow ();
+  /* XXX We're getting inputInfo.poniter here, but this might be really wrong.
+   * Which pointer's current window do we want? */
+  WindowPtr		pRoot = GetCurrentRootWindow (inputInfo.pointer);
 
   if (!pWin)
     {
diff --git a/include/dix.h b/include/dix.h
index 385f56c..9da265d 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -357,7 +357,7 @@ extern Bool IsParent(
     WindowPtr /* maybeparent */,
     WindowPtr /* child */);
 
-extern WindowPtr GetCurrentRootWindow(void);
+extern WindowPtr GetCurrentRootWindow(DeviceIntPtr pDev);
 
 extern WindowPtr GetSpriteWindow(DeviceIntPtr pDev);
 
diff --git a/include/inputstr.h b/include/inputstr.h
index bdb7518..4924cb1 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -287,6 +287,18 @@ typedef struct {
     WindowPtr   windows[MAXSCREENS];
     WindowPtr	confineWin;	/* confine window */ 
 #endif
+    /* The window trace information is used at dix/events.c to avoid having
+     * to compute all the windows between the root and the current pointer
+     * window each time a button or key goes down. The grabs on each of those
+     * windows must be checked.
+     * spriteTraces should only be used at dix/events.c! */
+    WindowPtr *spriteTrace;
+    int spriteTraceSize;
+    int spriteTraceGood;
+
+    ScreenPtr pEnqueueScreen; /* screen events are being delivered to */
+    ScreenPtr pDequeueScreen; /* screen events are being dispatched to */
+
 } SpriteRec, *SpritePtr;
 
 /* states for devices */
diff --git a/mi/mi.h b/mi/mi.h
index fad2d19..f83c42b 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -158,6 +158,7 @@ extern void mieqEnqueue(
 );
 
 extern void mieqSwitchScreen(
+    DeviceIntPtr /* pDev */,
     ScreenPtr /*pScreen*/,
     Bool /*fromDIX*/
 );
diff --git a/mi/mieq.c b/mi/mieq.c
index 143a94f..2eeb21e 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -67,6 +67,9 @@ in this Software without prior written authorization from The Open Group.
 
 #define QUEUE_SIZE  512
 
+#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
+#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
+
 typedef struct _Event {
     xEvent          event[7];
     int             nevents;
@@ -79,8 +82,6 @@ typedef struct _EventQueue {
     CARD32           lastEventTime;      /* to avoid time running backwards */
     int              lastMotion;         /* device ID if last event motion? */
     EventRec         events[QUEUE_SIZE]; /* static allocation for signals */
-    ScreenPtr        pEnqueueScreen;     /* screen events are being delivered to */
-    ScreenPtr        pDequeueScreen;     /* screen events are being dispatched to */
     mieqHandler      handlers[128];      /* custom event handler */
 } EventQueueRec, *EventQueuePtr;
 
@@ -94,8 +95,6 @@ mieqInit(void)
     miEventQueue.head = miEventQueue.tail = 0;
     miEventQueue.lastEventTime = GetTimeInMillis ();
     miEventQueue.lastMotion = FALSE;
-    miEventQueue.pEnqueueScreen = screenInfo.screens[0];
-    miEventQueue.pDequeueScreen = miEventQueue.pEnqueueScreen;
     for (i = 0; i < 128; i++)
         miEventQueue.handlers[i] = NULL;
     SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
@@ -179,18 +178,18 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 
     miEventQueue.lastEventTime =
 	miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time;
-    miEventQueue.events[oldtail].pScreen = miEventQueue.pEnqueueScreen;
+    miEventQueue.events[oldtail].pScreen = EnqueueScreen(pDev);
     miEventQueue.events[oldtail].pDev = pDev;
 
     miEventQueue.lastMotion = isMotion;
 }
 
 void
-mieqSwitchScreen(ScreenPtr pScreen, Bool fromDIX)
+mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
 {
-    miEventQueue.pEnqueueScreen = pScreen;
+    EnqueueScreen(pDev) = pScreen;
     if (fromDIX)
-	miEventQueue.pDequeueScreen = pScreen;
+	DequeueScreen(pDev) = pScreen;
 }
 
 void
@@ -224,15 +223,15 @@ mieqProcessInputEvents(void)
 
         e = &miEventQueue.events[miEventQueue.head];
         /* Assumption - screen switching can only occur on motion events. */
-        if (e->pScreen != miEventQueue.pDequeueScreen) {
-            miEventQueue.pDequeueScreen = e->pScreen;
+        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;
             if (miEventQueue.head == QUEUE_SIZE - 1)
                 miEventQueue.head = 0;
             else
                 ++miEventQueue.head;
-            NewCurrentScreen (e->pDev, miEventQueue.pDequeueScreen, x, y);
+            NewCurrentScreen (e->pDev, DequeueScreen(e->pDev), x, y);
         }
         else {
             if (miEventQueue.head == QUEUE_SIZE - 1)
@@ -243,7 +242,8 @@ 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](miEventQueue.pDequeueScreen->myNum,
+                miEventQueue.handlers[e->event->u.u.type](
+						  DequeueScreen(e->pDev)->myNum,
                                                           e->event, dev,
                                                           e->nevents);
                 return;
diff --git a/mi/mipointer.c b/mi/mipointer.c
index b06a0be..b14c2c7 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -351,7 +351,7 @@ miPointerWarpCursor (pDev, pScreen, x, y)
     SetupScreen (pScreen);
 
     if (pPointer->pScreen != pScreen)
-	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
+	(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
 
     if (GenerateEvent)
     {
@@ -492,7 +492,7 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
 
 	pScreen = screenInfo.screens[screen_no];
 	pScreenPriv = GetScreenPrivate (pScreen);
-	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
+	(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
 	NewCurrentScreen (pDev, pScreen, x, y);
 
         pPointer->limits.x2 = pScreen->width;
@@ -570,7 +570,8 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
 	    if (newScreen != pScreen)
 	    {
 		pScreen = newScreen;
-		(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
+		(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
+							     FALSE);
 		pScreenPriv = GetScreenPrivate (pScreen);
 	    	/* Smash the confine to the new screen */
                 pPointer->limits.x2 = pScreen->width;
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 666a6eb..cc9c037 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -88,6 +88,7 @@ typedef struct _miPointerScreenFuncRec {
                     xEventPtr /* event */
                     );
     void	(*NewEventScreen)(
+		    DeviceIntPtr /* pDev */,
                     ScreenPtr /* pScr */,
 		    Bool /* fromDIX */
                     );
diff --git a/randr/rrpointer.c b/randr/rrpointer.c
index fec5d45..722b22c 100644
--- a/randr/rrpointer.c
+++ b/randr/rrpointer.c
@@ -135,10 +135,16 @@ RRPointerMoved (ScreenPtr pScreen, int x, int y)
 void
 RRPointerScreenConfigured (ScreenPtr pScreen)
 {
-    WindowPtr	pRoot = GetCurrentRootWindow ();
+    WindowPtr	pRoot = GetCurrentRootWindow (inputInfo.pointer);
     ScreenPtr	pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL;
     int		x, y;
 
+    /* XXX: GetCurrentRootWindow revices an argument, It is inputInfo.pointer,
+     * but I really think this is wrong...  What do we do here? This was made so
+     * that it can compile, but I don't think randr should assume there is just
+     * one pointer. There might be more than one pointer on the screen! So, what
+     * to do? What happens? */
+
     if (pScreen != pCurrentScreen)
 	return;
     GetSpritePosition(inputInfo.pointer, &x, &y);
commit d61ed6c8a2823a3532439d5cb9f355129c93f523
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 19 18:08:55 2007 +0930

    Check for NULL devices in CloseDevice().

diff --git a/dix/devices.c b/dix/devices.c
index 6edf138..9e48c0b 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -523,6 +523,9 @@ CloseDevice(DeviceIntPtr dev)
     ScreenPtr screen = screenInfo.screens[0];
     int j;
 
+    if (!dev)
+        return;
+
     if (dev->inited)
 	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
 
commit 9c30f7422121a0443c8d612d06181e17d8af9730
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 19 12:00:24 2007 +0930

    config: Return errors as negative numbers, device ids as positive numbers.
    Update dbus-api documentation.

diff --git a/config/config.c b/config/config.c
index 4861d9e..9b38faf 100644
--- a/config/config.c
+++ b/config/config.c
@@ -308,12 +308,15 @@ configMessage(DBusConnection *connection, DBusMessage *message, void *closure)
 
         if (ret != BadDrawable && ret != BadAlloc) {
             if (!strlen(dbus_message_get_signature(reply)))
+            {
+                ret = -ret; /* return errors as negative numbers */
                 if (!dbus_message_iter_append_basic(&r_iter, DBUS_TYPE_INT32, &ret)) {
                     ErrorF("[config] couldn't append to iterator\n");
                     dbus_message_unref(reply);
                     dbus_error_free(&error);
                     return DBUS_HANDLER_RESULT_HANDLED;
                 }
+            }
 
             if (!dbus_connection_send(bus, reply, NULL))
                 ErrorF("[config] failed to send reply\n");
diff --git a/config/dbus-api b/config/dbus-api
index cada792..654c22b 100644
--- a/config/dbus-api
+++ b/config/dbus-api
@@ -15,25 +15,23 @@ org.x.config.input:
         Option names beginning with _ are not allowed; they are reserved
         for internal use.
 
-        Returns one int32, which is an X Status, as defined in X.h.  If
-        everything is successful, Success will be returned.  BadMatch will
-        be returned if the options given do not match any device.  BadValue
-        is returned for a malformed message.
+        Returns one signed int32, which is the device id of the new device.
+        If the return value is a negative number, it represents the X
+        Status, as defined in X.h. BadMatch will be returned if the options
+        given do not match any device.  BadValue is returned for a malformed
+        message.  (Example: 8 is new device id 8. -8 is BadMatch.)
 
         Notably, BadAlloc is never returned: the server internally signals
         to D-BUS that the attempt failed for lack of memory.
 
-        The return does not notify the client of which devices were created
-        or modified as a result of this request: clients are encouraged to
-        listen for the XInput DevicePresenceNotify event to monitor changes
-        in the device list.
-
     org.x.config.input.remove:
         Takes one int32 argument, which is the device ID to remove, i.e.:
          i
         is the signature.
-        Same return values as org.x.config.input.add.
+
+        Returns one signed int32 which represents an X status as defined in
+        X.h. See org.x.config.input.add. Error codes are negative numbers.
 
     org.x.config.input.listDevices:
-        Lists the currently active devices.
+        Lists the currently active devices. No argument. 
         Return value is sequence of <id> <name> <id> <name> ...
commit ae75afcb1b5419102c5be10b8826ceed50d2ef5d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 18 12:10:05 2007 +0930

    Change dbus 'listDevices' call to not require an argument.
    Update dbus-api documentation, plug memory leak on dbus reply error.

diff --git a/config/config.c b/config/config.c
index 9828091..4861d9e 100644
--- a/config/config.c
+++ b/config/config.c
@@ -280,11 +280,6 @@ configMessage(DBusConnection *connection, DBusMessage *message, void *closure)
 
     if (strcmp(dbus_message_get_interface(message),
                "org.x.config.input") == 0) {
-        if (!dbus_message_iter_init(message, &iter)) {
-            ErrorF("[config] failed to init iterator\n");
-            dbus_error_free(&error);
-            return DBUS_HANDLER_RESULT_NEED_MEMORY; /* ?? */
-        }
 
         if (!(reply = dbus_message_new_method_return(message))) {
             ErrorF("[config] failed to create the reply message\n");
@@ -292,18 +287,30 @@ configMessage(DBusConnection *connection, DBusMessage *message, void *closure)
             return DBUS_HANDLER_RESULT_NEED_MEMORY;
         }
         dbus_message_iter_init_append(reply, &r_iter);
-        
-        if (strcmp(dbus_message_get_member(message), "add") == 0)
-            ret = configAddDevice(message, &iter, reply, &r_iter, &error);
-        else if (strcmp(dbus_message_get_member(message), "remove") == 0)
-            ret = configRemoveDevice(message, &iter, &error);
-        else if (strcmp(dbus_message_get_member(message), "listDevices") == 0)
-            ret = configListDevices(message, &iter, reply, &r_iter, &error);
-        if (ret != BadDrawable && ret != BadAlloc) {
 
+        /* listDevices doesn't take any arguments */
+        if (strcmp(dbus_message_get_member(message), "listDevices") == 0)
+            ret = configListDevices(message, NULL, reply, &r_iter, &error);
+        else 
+        {
+            if (!dbus_message_iter_init(message, &iter)) {
+                ErrorF("[config] failed to init iterator\n");
+                dbus_message_unref(reply);
+                dbus_error_free(&error);
+                return DBUS_HANDLER_RESULT_NEED_MEMORY; /* ?? */
+            }
+
+            if (strcmp(dbus_message_get_member(message), "add") == 0)
+                ret = configAddDevice(message, &iter, reply, &r_iter, &error);
+            else if (strcmp(dbus_message_get_member(message), "remove") == 0)
+                ret = configRemoveDevice(message, &iter, &error);
+        }
+
+        if (ret != BadDrawable && ret != BadAlloc) {
             if (!strlen(dbus_message_get_signature(reply)))
                 if (!dbus_message_iter_append_basic(&r_iter, DBUS_TYPE_INT32, &ret)) {
                     ErrorF("[config] couldn't append to iterator\n");
+                    dbus_message_unref(reply);
                     dbus_error_free(&error);
                     return DBUS_HANDLER_RESULT_HANDLED;
                 }
diff --git a/config/dbus-api b/config/dbus-api
index 53bb3e4..cada792 100644
--- a/config/dbus-api
+++ b/config/dbus-api
@@ -33,3 +33,7 @@ org.x.config.input:
          i
         is the signature.
         Same return values as org.x.config.input.add.
+
+    org.x.config.input.listDevices:
+        Lists the currently active devices.
+        Return value is sequence of <id> <name> <id> <name> ...
commit b6aec7f6f906a18d13586d63afabf1ee4fbb11c3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 17 16:51:16 2007 +0930

    Change FocusIn/Out semantics to match Enter/Leave semantics.

diff --git a/dix/events.c b/dix/events.c
index def209e..1733e2d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2272,7 +2272,7 @@ DefineInitialRootWindow(WindowPtr win)
         if (DevHasCursor(pDev))
         {
             InitializeSprite(pDev, win);
-            win->devPrivates[EnterLeavePrivatesIndex].val++;
+            win->devPrivates[FocusPrivatesIndex].val++;
         }
         pDev = pDev->next;
     }
@@ -3452,7 +3452,7 @@ EnterLeaveEvent(
     GrabPtr	        grab = mouse->coreGrab.grab;
     GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
-    long*               inWindow; /* no of sprites inside pWin */
+    int*                inWindow; /* no of sprites inside pWin */
     Bool                sendevent = FALSE;        
 
     deviceEnterNotify   *devEnterLeave;
@@ -3502,7 +3502,7 @@ EnterLeaveEvent(
              IsParent(focus, pWin)))
         event.u.enterLeave.flags |= ELFlagFocus;
 
-    inWindow = &pWin->devPrivates[EnterLeavePrivatesIndex].val;
+    inWindow = &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave;
 
     /*
      * Sending multiple core enter/leave events to the same window confuse the
@@ -3665,28 +3665,80 @@ static void
 FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
 {
     xEvent event;
+    int* numFoci; /* no of foci the window has already */
+    Bool sendevent = FALSE;
+    FocusSemaphoresPtr focus;
 
     if (dev != inputInfo.keyboard)
 	DeviceFocusEvent(dev, type, mode, detail, pWin);
-    event.u.focus.mode = mode;
-    event.u.u.type = type;
-    event.u.u.detail = detail;
-    event.u.focus.window = pWin->drawable.id;
-    (void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab,
-                                0);
-    if ((type == FocusIn) &&
-	((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
+
+    /*
+     * Same procedure as for Enter/Leave events.
+     *
+     * Sending multiple core FocusIn/Out events to the same window may confuse
+     * the client.  
+     * We can send multiple events that have detail NotifyVirtual,
+     * NotifyNonlinearVirtual, NotifyPointerRoot, NotifyDetailNone or
+     * NotifyPointer however.
+     *
+     * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
+     * we only send an FocusIn event for the first kbd to set the focus. A
+     * FocusOut event is sent for the last kbd to set the focus away from the
+     * window.. 
+     *
+     * For events with Virtual detail, we send them only to a window that does
+     * not have a focus from another keyboard.
+     *
+     * For a window tree in the form of 
+     *
+     * A -> Bf -> C -> D 
+     *  \               (where B and E have focus)
+     *    -> Ef         
+     *    
+     * If the focus changes from E into D, a FocusOut is sent to E, a
+     * FocusIn is sent to D, a FocusIn with detail
+     * NotifyNonlinearVirtual to C and nothing to B.
+     */
+
+    numFoci =
+        &((FocusSemaphoresPtr)pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout;
+    if (detail != NotifyVirtual && 
+            detail != NotifyNonlinearVirtual && 
+            detail != NotifyPointer &&
+            detail != NotifyPointerRoot &&
+            detail != NotifyDetailNone)
     {
-	xKeymapEvent ke;
-	ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
-	if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
-	    memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
-	else
-	    bzero((char *)&ke.map[0], 31);
+        (type == FocusIn) ? (*numFoci)++ : (*numFoci)--;
+        if (((*numFoci) == (FocusOut - type)))
+            sendevent = TRUE;
+    } else
+    {
+        if (!(*numFoci))
+            sendevent = TRUE;
+    }
 
-	ke.type = KeymapNotify;
-	(void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
-				    KeymapStateMask, NullGrab, 0);
+    if (sendevent)
+    {
+        event.u.focus.mode = mode;
+        event.u.u.type = type;
+        event.u.u.detail = detail;
+        event.u.focus.window = pWin->drawable.id;
+        (void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab,
+                                    0);
+        if ((type == FocusIn) &&
+                ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
+        {
+            xKeymapEvent ke;
+            ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
+            if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
+                memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
+            else
+                bzero((char *)&ke.map[0], 31);
+
+            ke.type = KeymapNotify;
+            (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
+                                        KeymapStateMask, NullGrab, 0);
+        }
     }
 }
 
diff --git a/dix/window.c b/dix/window.c
index 5a03642..4846939 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -155,7 +155,7 @@ _X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF;
 
 _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
 
-_X_EXPORT int EnterLeavePrivatesIndex = -1;
+_X_EXPORT int FocusPrivatesIndex = -1;
 
 #if 0
 extern void DeleteWindowFromAnyEvents();
@@ -312,6 +312,12 @@ SetWindowToDefaults(WindowPtr pWin)
 #ifdef COMPOSITE
     pWin->redirectDraw = 0;
 #endif
+
+    ((FocusSemaphoresPtr)
+     pWin->devPrivates[FocusPrivatesIndex].ptr)->enterleave = 0;
+    ((FocusSemaphoresPtr)
+     pWin->devPrivates[FocusPrivatesIndex].ptr)->focusinout = 0;
+
 }
 
 static void
@@ -3981,10 +3987,11 @@ WindowParentHasDeviceCursor(WindowPtr pWin,
 _X_EXPORT Bool
 InitWindowPrivates(ScreenPtr screen)
 {
-    if (EnterLeavePrivatesIndex == -1)
-        EnterLeavePrivatesIndex = AllocateWindowPrivateIndex();
+    if (FocusPrivatesIndex == -1)
+        FocusPrivatesIndex = AllocateWindowPrivateIndex();
 
-    return AllocateWindowPrivate(screen, EnterLeavePrivatesIndex, 0);
+    return AllocateWindowPrivate(screen, FocusPrivatesIndex, 
+            sizeof(FocusSemaphoresRec));
 }
 
 #ifndef NOLOGOHACK
diff --git a/include/inputstr.h b/include/inputstr.h
index d8d12d7..bdb7518 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -391,5 +391,4 @@ typedef struct _QdEvent {
     int			evcount;
 } QdEventRec;    
 
-#define MPXDBG(...) ErrorF("MPX: " __VA_ARGS__ )
 #endif /* INPUTSTRUCT_H */
diff --git a/include/windowstr.h b/include/windowstr.h
index 4683abe..87158b2 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -216,7 +216,15 @@ typedef struct _ScreenSaverStuff {
 
 extern int screenIsSaved;
 extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
-extern int EnterLeavePrivatesIndex;
+extern int FocusPrivatesIndex;
+
+/* Used to maintain semantics of core protocol for Enter/LeaveNotifies and
+ * FocusIn/Out events for multiple pointers/keyboards. 
+ */ 
+typedef struct _FocusSemaphores {
+    int                 enterleave;
+    int                 focusinout;
+} FocusSemaphoresRec, *FocusSemaphoresPtr;
 
 /*
  * this is the configuration parameter "NO_BACK_SAVE"
commit 451d5464b4e8a2516b8a4598b3c4eb14656be90e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 17 11:17:04 2007 +0930

    Change enter/leave semantics for events with detail Notify{Nonlinear}Virtual.
    
    Core enter/leave events with detail Notify{Ancestor|Inferior|Nonlinear} are
    only sent for the first/last pointer to enter/leave. Events with detail
    Notify{Nonlinear}Virtual are sent at all times, but not to those windows that
    currently have one or more pointers inside their boundaries.

diff --git a/dix/events.c b/dix/events.c
index e515f10..def209e 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -281,7 +281,7 @@ static void DoEnterLeaveEvents(
     WindowPtr fromWin,
     WindowPtr toWin,
     int mode
-);
+); 
 
 static WindowPtr XYToWindow(
     int x,
@@ -3453,6 +3453,7 @@ EnterLeaveEvent(
     GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
     long*               inWindow; /* no of sprites inside pWin */
+    Bool                sendevent = FALSE;        
 
     deviceEnterNotify   *devEnterLeave;
     int                 mskidx;
@@ -3503,21 +3504,51 @@ EnterLeaveEvent(
 
     inWindow = &pWin->devPrivates[EnterLeavePrivatesIndex].val;
 
-    (type == EnterNotify) ? (*inWindow)++ : (*inWindow)--;
+    /*
+     * Sending multiple core enter/leave events to the same window confuse the
+     * client.  
+     * We can send multiple events that have detail NotifyVirtual or
+     * NotifyNonlinearVirtual however.
+     *
+     * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear)
+     * we only send an enter event for the first pointer to enter. A leave
+     * event is sent for the last pointer to leave. 
+     *
+     * For events with Virtual detail, we send them only to a window that does
+     * not have a pointer inside.
+     *
+     * For a window tree in the form of 
+     *
+     * A -> Bp -> C -> D 
+     *  \               (where B and E have pointers)
+     *    -> Ep         
+     *    
+     * If the pointer moves from E into D, a LeaveNotify is sent to E, an
+     * EnterNotify is sent to D, an EnterNotify with detail
+     * NotifyNonlinearVirtual to C and nothing to B.
+     */
 
-    if (mask & filters[type])
+    if (event.u.u.detail != NotifyVirtual && 
+            event.u.u.detail != NotifyNonlinearVirtual)
     {
-        /* only send core events for the first device to enter and the last
-           one to leave */
-        if ((*inWindow) == (LeaveNotify - type))
-        {
-            if (grab)
-                (void)TryClientEvents(rClient(grab), &event, 1, mask,
-                                      filters[type], grab);
-            else
-                (void)DeliverEventsToWindow(mouse, pWin, &event, 1, filters[type],
-                                            NullGrab, 0);
-        }
+        (type == EnterNotify) ? (*inWindow)++ : (*inWindow)--;
+
+        if (((*inWindow) == (LeaveNotify - type)))
+            sendevent = TRUE;
+    } else
+    {
+        if (!(*inWindow))
+            sendevent = TRUE;
+    }
+
+    if ((mask & filters[type]) && sendevent)
+    {
+        if (grab)
+            (void)TryClientEvents(rClient(grab), &event, 1, mask,
+                                  filters[type], grab);
+        else
+            (void)DeliverEventsToWindow(mouse, pWin, &event, 1, filters[type],
+                                        NullGrab, 0);
     }
 
     devEnterLeave = (deviceEnterNotify*)&event;
commit ea27b09d3a973d9a4943f205b24940b8624cf405
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Apr 13 17:15:22 2007 +0930

    Deliver FocusIn/FocusOut events for all devices.
    Don't use VCK in SetInputFocus and DeliverFocusedEvent.

diff --git a/dix/events.c b/dix/events.c
index 294aa2f..e515f10 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2787,9 +2787,9 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
 void
 DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
 {
+    DeviceIntPtr pointer;
     WindowPtr focus = keybd->focus->win;
     int mskidx = 0;
-
     if (focus == FollowKeyboardWin)
 	focus = inputInfo.keyboard->focus->win;
     if (!focus)
@@ -2804,8 +2804,11 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
 	if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
 	    return;
     }
+    pointer = GetPairedPointer(keybd);
+    if (!pointer)
+        pointer = inputInfo.pointer;
     /* just deliver it to the focus window */
-    FixUpEventFromWindow(inputInfo.pointer, xE, focus, None, FALSE);
+    FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
     if (xE->u.u.type & EXTENSION_EVENT_BASE)
 	mskidx = keybd->id;
     (void)DeliverEventsToWindow(keybd, focus, xE, count, filters[xE->u.u.type],
@@ -3632,13 +3635,8 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
 {
     xEvent event;
 
-#ifdef XINPUT
     if (dev != inputInfo.keyboard)
-    {
 	DeviceFocusEvent(dev, type, mode, detail, pWin);
-	return;
-    }
-#endif
     event.u.focus.mode = mode;
     event.u.u.type = type;
     event.u.u.detail = detail;
@@ -3846,6 +3844,8 @@ SetInputFocus(
     WindowPtr focusWin;
     int mode, rc;
     TimeStamp time;
+    DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
+
 
     UpdateCurrentTime();
     if ((revertTo != RevertToParent) &&
@@ -3857,10 +3857,22 @@ SetInputFocus(
 	return BadValue;
     }
     time = ClientTimeToServerTime(ctime);
+
+    if (IsKeyboardDevice(dev))
+        keybd = dev;
+    else
+    {
+        keybd = GetPairedKeyboard(dev);
+        if (!keybd) 
+            keybd = inputInfo.keyboard;
+    }
+
     if ((focusID == None) || (focusID == PointerRoot))
 	focusWin = (WindowPtr)(long)focusID;
     else if ((focusID == FollowKeyboard) && followOK)
-	focusWin = inputInfo.keyboard->focus->win;
+    {
+	focusWin = keybd->focus->win;
+    }
     else {
 	rc = dixLookupWindow(&focusWin, focusID, client, DixReadAccess);
 	if (rc != Success)
@@ -3876,7 +3888,7 @@ SetInputFocus(
 	return Success;
     mode = (dev->coreGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
     if (focus->win == FollowKeyboardWin)
-	DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode);
+	DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
     else
 	DoFocusEvents(dev, focus->win, focusWin, mode);
     focus->time = time;
commit 2bb3c81fc1ca98c909309f3af7e9c8ca6b695657
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 12 16:35:43 2007 +0930

    Use paired kbd instead of VCK for EnterLeaveEvents, sanitize variable naming.

diff --git a/dix/events.c b/dix/events.c
index 444c103..294aa2f 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3436,7 +3436,7 @@ CommonAncestor(
 
 static void
 EnterLeaveEvent(
-    DeviceIntPtr pDev,
+    DeviceIntPtr mouse,
     int type,
     int mode,
     int detail,
@@ -3444,9 +3444,8 @@ EnterLeaveEvent(
     Window child)
 {
     xEvent              event;
-    DeviceIntPtr        keybd = inputInfo.keyboard;
     WindowPtr		focus;
-    DeviceIntPtr        mouse = pDev;
+    DeviceIntPtr        keybd;
     GrabPtr	        grab = mouse->coreGrab.grab;
     GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
@@ -3456,6 +3455,9 @@ EnterLeaveEvent(
     int                 mskidx;
     OtherInputMasks     *inputMasks;
 
+    if (!(keybd = GetPairedKeyboard(mouse)))
+        keybd = inputInfo.keyboard;
+
     if ((pWin == mouse->valuator->motionHintWindow) &&
 	(detail != NotifyInferior))
 	mouse->valuator->motionHintWindow = NullWindow;
@@ -3473,8 +3475,8 @@ EnterLeaveEvent(
     event.u.u.type = type;
     event.u.u.detail = detail;
     event.u.enterLeave.time = currentTime.milliseconds;
-    event.u.enterLeave.rootX = pDev->spriteInfo->sprite->hot.x;
-    event.u.enterLeave.rootY = pDev->spriteInfo->sprite->hot.y;
+    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
+    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
     /* Counts on the same initial structure of crossing & button events! */
     FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
     /* Enter/Leave events always set child */
@@ -3510,7 +3512,7 @@ EnterLeaveEvent(
                 (void)TryClientEvents(rClient(grab), &event, 1, mask,
                                       filters[type], grab);
             else
-                (void)DeliverEventsToWindow(pDev, pWin, &event, 1, filters[type],
+                (void)DeliverEventsToWindow(mouse, pWin, &event, 1, filters[type],
                                             NullGrab, 0);
         }
     }
@@ -3520,8 +3522,8 @@ EnterLeaveEvent(
         DeviceLeaveNotify;
     devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify :
         DeviceLeaveNotify;
-    devEnterLeave->deviceid = pDev->id;
-    mskidx = pDev->id;
+    devEnterLeave->deviceid = mouse->id;
+    mskidx = mouse->id;
     inputMasks = wOtherInputMasks(pWin);
     if (inputMasks && 
        (filters[devEnterLeave->type] & inputMasks->deliverableEvents[mskidx]))
@@ -3530,9 +3532,9 @@ EnterLeaveEvent(
             (void)TryClientEvents(rClient(devgrab), (xEvent*)devEnterLeave, 1,
                                 mask, filters[devEnterLeave->type], devgrab);
 	else
-	    (void)DeliverEventsToWindow(pDev, pWin, (xEvent*)devEnterLeave, 
+	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave, 
                                         1, filters[devEnterLeave->type], 
-                                        NullGrab, pDev->id);
+                                        NullGrab, mouse->id);
     }
 
     if ((type == EnterNotify) && (mask & KeymapStateMask))
@@ -3550,7 +3552,7 @@ EnterLeaveEvent(
 	    (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
 				  KeymapStateMask, grab);
 	else
-	    (void)DeliverEventsToWindow(pDev, pWin, (xEvent *)&ke, 1,
+	    (void)DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
 					KeymapStateMask, NullGrab, 0);
     }
 }
commit e7b47b1758ed20e75ee267b3a09e91bf2861f6fd
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 12 16:24:42 2007 +0930

    Change core enter/leave semantics for multiple pointers.
    
    Send EnterNotify when first device enters the window, LeaveNotify when the
    last device leaves the window. Additional devices will not cause additional
    Enter/LeaveNotifies.

diff --git a/dix/events.c b/dix/events.c
index 46905aa..444c103 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2270,7 +2270,10 @@ DefineInitialRootWindow(WindowPtr win)
     while (pDev)
     {
         if (DevHasCursor(pDev))
+        {
             InitializeSprite(pDev, win);
+            win->devPrivates[EnterLeavePrivatesIndex].val++;
+        }
         pDev = pDev->next;
     }
 }
@@ -3447,6 +3450,7 @@ EnterLeaveEvent(
     GrabPtr	        grab = mouse->coreGrab.grab;
     GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
+    long*               inWindow; /* no of sprites inside pWin */
 
     deviceEnterNotify   *devEnterLeave;
     int                 mskidx;
@@ -3492,14 +3496,23 @@ EnterLeaveEvent(
              IsParent(focus, pWin)))
         event.u.enterLeave.flags |= ELFlagFocus;
 
+    inWindow = &pWin->devPrivates[EnterLeavePrivatesIndex].val;
+
+    (type == EnterNotify) ? (*inWindow)++ : (*inWindow)--;
+
     if (mask & filters[type])
     {
-	if (grab)
-	    (void)TryClientEvents(rClient(grab), &event, 1, mask,
-				  filters[type], grab);
-	else
-	    (void)DeliverEventsToWindow(pDev, pWin, &event, 1, filters[type],
-					NullGrab, 0);
+        /* only send core events for the first device to enter and the last
+           one to leave */
+        if ((*inWindow) == (LeaveNotify - type))
+        {
+            if (grab)
+                (void)TryClientEvents(rClient(grab), &event, 1, mask,
+                                      filters[type], grab);
+            else
+                (void)DeliverEventsToWindow(pDev, pWin, &event, 1, filters[type],
+                                            NullGrab, 0);
+        }
     }
 
     devEnterLeave = (deviceEnterNotify*)&event;
diff --git a/dix/main.c b/dix/main.c
index ac3bfad..f5b89ba 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -391,6 +391,8 @@ main(int argc, char *argv[], char *envp[])
 		FatalError("failed to create scratch GCs");
 	    if (!CreateDefaultStipple(i))
 		FatalError("failed to create default stipple");
+            if (!InitWindowPrivates(pScreen))
+                FatalError("Failed to init window privates.");
 	    if (!CreateRootWindow(pScreen))
 		FatalError("failed to create root window");
 	}
diff --git a/dix/window.c b/dix/window.c
index 4e55319..5a03642 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -155,6 +155,8 @@ _X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF;
 
 _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
 
+_X_EXPORT int EnterLeavePrivatesIndex = -1;
+
 #if 0
 extern void DeleteWindowFromAnyEvents();
 extern Mask EventMaskForClient();
@@ -3969,6 +3971,22 @@ WindowParentHasDeviceCursor(WindowPtr pWin,
     return FALSE;
 }
 
+/**
+ * Initialize some mandatory devPrivates for windows. 
+ *
+ * At the moment, this includes only the enter/leave semaphore.
+ *
+ * Returns TRUE on success.
+ */
+_X_EXPORT Bool
+InitWindowPrivates(ScreenPtr screen)
+{
+    if (EnterLeavePrivatesIndex == -1)
+        EnterLeavePrivatesIndex = AllocateWindowPrivateIndex();
+
+    return AllocateWindowPrivate(screen, EnterLeavePrivatesIndex, 0);
+}
+
 #ifndef NOLOGOHACK
 static void
 DrawLogo(WindowPtr pWin)
diff --git a/include/window.h b/include/window.h
index 87118e3..707272a 100644
--- a/include/window.h
+++ b/include/window.h
@@ -268,4 +268,6 @@ extern void DisableMapUnmapEvents(
 extern void EnableMapUnmapEvents(
     WindowPtr /* pWin */ );
 
+Bool InitWindowPrivates(
+    ScreenPtr /* screen */);
 #endif /* WINDOW_H */
diff --git a/include/windowstr.h b/include/windowstr.h
index 95954a7..4683abe 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -216,6 +216,7 @@ typedef struct _ScreenSaverStuff {
 
 extern int screenIsSaved;
 extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
+extern int EnterLeavePrivatesIndex;
 
 /*
  * this is the configuration parameter "NO_BACK_SAVE"
commit 547d720938b3668666d60110d79b150b1e9325c6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 12 11:16:19 2007 +0930

    Remove workaround for a NULL core pointer in ProcessInputEvents.
    
    This workaround is obsolete with 33a5d9605e3e282f6aa1921d7321a2a12ef02c42

diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index f826b3b..8458899 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -247,13 +247,9 @@ ProcessInputEvents ()
 
   mieqProcessInputEvents();
 
-  /* PIE can be called after devices have been shut down. Blame DGA. */
-  if (inputInfo.pointer)
-  {
-      /* FIXME: This is a problem if we have multiple pointers */
-      miPointerGetPosition(inputInfo.pointer, &x, &y);
-      xf86SetViewport(xf86Info.currentScreen, x, y);
-  }
+  /* FIXME: This is a problem if we have multiple pointers */
+  miPointerGetPosition(inputInfo.pointer, &x, &y);
+  xf86SetViewport(xf86Info.currentScreen, x, y);
 }
 
 void
commit d4dad6f84f82a4ade5005c3aa93511c1295875b8
Merge: f1f8b56... 33a5d96...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 12 11:11:03 2007 +0930

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	configure.ac
    	dix/events.c
    	hw/xfree86/common/xf86Xinput.c

diff --cc dix/devices.c
index 0a91997,c2d4f22..6edf138
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -364,16 -325,8 +376,16 @@@ CorePointerProc(DeviceIntPtr pDev, int 
      return Success;
  }
  
 +/**
 + * Initialize a virtual core keyboard and a virtual core pointer. 
 + *
 + * Both devices are not tied to physical devices, but guarantee that there is
 + * always a keyboard and a pointer present and keep the protocol semantics.
 + * Both core devices are NOT part of the device list and act only as a
 + * fallback if no physical device is available.
 + */
  void
- InitCoreDevices()
+ InitCoreDevices(void)
  {
      DeviceIntPtr dev;
  
@@@ -452,15 -384,8 +464,15 @@@
      }
  }
  
 +/**
 + * 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.
 + */
  int
- InitAndStartDevices()
+ InitAndStartDevices(void)
  {
      DeviceIntPtr dev, next;
  
@@@ -716,10 -598,8 +734,10 @@@ RemoveDevice(DeviceIntPtr dev
  }
  
  int
- NumMotionEvents()
+ NumMotionEvents(void)
  {
 +    /* only called to fill data in initial connection reply. 
 +     * VCP is ok here, it is the only fixed device we have. */
      return inputInfo.pointer->valuator->numMotionEvents;
  }
  
diff --cc dix/events.c
index 94e60dc,093a316..46905aa
--- a/dix/events.c
+++ b/dix/events.c
@@@ -2190,15 -2047,9 +2190,15 @@@ CheckMotion(xEvent *xE, DeviceIntPtr pD
  }
  
  _X_EXPORT void
- WindowsRestructured()
+ WindowsRestructured(void)
  {
 -    (void) CheckMotion((xEvent *)NULL);
 +    DeviceIntPtr pDev = inputInfo.devices;
 +    while(pDev)
 +    {
 +        if (DevHasCursor(pDev))
 +            CheckMotion((xEvent *)NULL, pDev);
 +        pDev = pDev->next;
 +    }
  }
  
  #ifdef PANORAMIX
diff --cc hw/xfree86/common/xf86Xinput.c
index cc98a0c,6ebb087..6a5d4ee
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@@ -381,17 -365,12 +394,22 @@@ NewInputDeviceRequest (InputOption *opt
              }
          }
      }
+     if(!idev->driver || !idev->identifier) {
+         xf86Msg(X_ERROR, "No input driver/identifier specified (ignoring)\n");
+         rval = BadRequest;
+         goto unwind;
+     }
  
 +    if (!drv) {
 +        xf86Msg(X_ERROR, "No input driver specified (ignoring)\n");
 +        return BadMatch;
 +    }
 +
 +    if (!idev->identifier) {
 +        xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n");
 +        return BadMatch;
 +    }
 +
      if (!drv->PreInit) {
          xf86Msg(X_ERROR,
                  "Input driver `%s' has no PreInit function (ignoring)\n",
@@@ -425,13 -409,43 +448,49 @@@
      if (dev->inited && dev->startup)
          EnableDevice(dev);
  
 +    if (!IsPointerDevice(dev))
 +        PairDevices(NULL, GuessFreePointerDevice(), dev);
 +
 +    /* send enter/leave event, update sprite window */
 +    CheckMotion(NULL, dev);
 +
+     *pdev = dev;
      return Success;
+ 
+ unwind:
+     if(pInfo) {
+         if(drv->UnInit)
+             drv->UnInit(drv, pInfo, 0);
+         else
+             xf86DeleteInput(pInfo, 0);
+     }
+     if(idev->driver)
+         xfree(idev->driver);
+     if(idev->identifier)
+         xfree(idev->identifier);
+     xf86optionListFree(idev->commonOptions);
+     xfree(idev);
+     return rval;
+ }
+ 
+ void
+ DeleteInputDeviceRequest(DeviceIntPtr pDev)
+ {
+     LocalDevicePtr pInfo = (LocalDevicePtr) pDev->public.devicePrivate;
+     InputDriverPtr drv = pInfo->drv;
+     IDevRec *idev = pInfo->conf_idev;
+ 
+     RemoveDevice(pDev);
+ 
+     if(drv->UnInit)
+         drv->UnInit(drv, pInfo, 0);
+     else
+         xf86DeleteInput(pInfo, 0);
+ 
+     xfree(idev->driver);
+     xfree(idev->identifier);
+     xf86optionListFree(idev->commonOptions);
+     xfree(idev);
  }
  
  /* 
diff --cc include/input.h
index 2debce9,b399d3a..4ba0cad
--- a/include/input.h
+++ b/include/input.h
@@@ -447,45 -443,12 +447,48 @@@ extern void SwitchCorePointer(DeviceInt
  extern DeviceIntPtr LookupDeviceIntRec(
      CARD8 deviceid);
  
 +/* Pairing input devices */
 +extern int PairDevices(ClientPtr client, 
 +                       DeviceIntPtr pointer, 
 +                       DeviceIntPtr keyboard);
 +
 +extern DeviceIntPtr GetPairedPointer(DeviceIntPtr kbd);
 +extern DeviceIntPtr GetPairedKeyboard(DeviceIntPtr ptr);
 +
 +extern Bool RegisterPairingClient(ClientPtr client);
 +extern Bool UnregisterPairingClient(ClientPtr client);
 +
 +extern DeviceIntPtr GuessFreePointerDevice(void);
 +
 +/* Window/device based access control */
 +extern Bool ACRegisterClient(ClientPtr client);
 +extern Bool ACUnregisterClient(ClientPtr client);
 +extern int ACClearWindowAccess(ClientPtr client,
 +                        WindowPtr win,
 +                        int what);
 +extern int ACChangeWindowAccess(ClientPtr client, 
 +                                WindowPtr win, 
 +                                int defaultRule,
 +                                DeviceIntPtr* perm_devices,
 +                                int npermit,
 +                                DeviceIntPtr* deny_devices,
 +                                int ndeny);
 +extern void ACQueryWindowAccess(WindowPtr win, 
 +                                int* defaultRule,
 +                                DeviceIntPtr** perm,
 +                                int* nperm,
 +                                DeviceIntPtr** deny,
 +                                int* ndeny);
 +
 +extern Bool ACDeviceAllowed(WindowPtr win, 
 +                            DeviceIntPtr dev);
 +
  /* Implemented by the DDX. */
  extern int NewInputDeviceRequest(
-     InputOption *options);
+     InputOption *options,
+     DeviceIntPtr *dev);
+ extern void DeleteInputDeviceRequest(
+     DeviceIntPtr dev);
  
  extern void DDXRingBell(
      int volume,
commit f1f8b562aaaa6ec32ab0d0697f964d92d6d536a4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 9 19:31:59 2007 +0930

    Alloc sprite memory in devices' devPrivates, allow undisplaying cursors.
    
    Improve memory usage by allocating the sprite's memory only to devices that
    actually have a sprite and provide means to remove a device's cursor from the
    screen (more hotplugging, yay!).
    This commit breaks ScreenRec's ABI.

diff --git a/dix/devices.c b/dix/devices.c
index 2b55679..0a91997 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -225,18 +225,29 @@ DisableDevice(DeviceIntPtr dev)
     return TRUE;
 }
 
+/**
+ * Initialize device through driver, allocate memory for cursor sprite (if
+ * applicable) and send a PresenceNotify event to all clients.
+ *
+ * Must be called before EnableDevice.
+ */
 int
 ActivateDevice(DeviceIntPtr dev)
 {
     int ret = Success;
     devicePresenceNotify ev;
     DeviceIntRec dummyDev;
+    ScreenPtr pScreen = screenInfo.screens[0];
 
     if (!dev || !dev->deviceProc)
         return BadImplementation;
 
     ret = (*dev->deviceProc) (dev, DEVICE_INIT);
     dev->inited = (ret == Success);
+
+    /* Initialize memory for sprites. */
+    if (IsPointerDevice(dev))
+        pScreen->DeviceCursorInitialize(dev, pScreen);
     
     ev.type = DevicePresenceNotify;
     ev.time = currentTime.milliseconds;
@@ -497,11 +508,16 @@ CloseDevice(DeviceIntPtr dev)
     StringFeedbackPtr s, snext;
     BellFeedbackPtr b, bnext;
     LedFeedbackPtr l, lnext;
+    ScreenPtr screen = screenInfo.screens[0];
     int j;
 
     if (dev->inited)
 	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
 
+    /* free sprite memory */
+    if (IsPointerDevice(dev))
+        screen->DeviceCursorCleanup(dev, screen);
+
     xfree(dev->name);
 
     if (dev->key) {
@@ -624,6 +640,22 @@ CloseDownDevices()
     inputInfo.pointer = NULL;
 }
 
+/**
+ * Remove the cursor sprite for all devices. This needs to be done before any
+ * resources are freed or any device is deleted.
+ */
+void 
+UndisplayDevices()
+{
+    DeviceIntPtr dev;
+    ScreenPtr screen = screenInfo.screens[0];
+
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+    {
+        screen->UndisplayCursor(dev, screen);
+    }
+}
+
 int
 RemoveDevice(DeviceIntPtr dev)
 {
@@ -631,23 +663,26 @@ RemoveDevice(DeviceIntPtr dev)
     int ret = BadMatch;
     devicePresenceNotify ev;
     DeviceIntRec dummyDev;
+    ScreenPtr screen = screenInfo.screens[0];
 
     DebugF("(dix) removing device %d\n", dev->id);
 
     if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
         return BadImplementation;
 
+    screen->UndisplayCursor(dev, screen);
+
     prev = NULL;
     for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
 	next = tmp->next;
 	if (tmp == dev) {
-	    CloseDevice(tmp);
 
 	    if (prev==NULL)
 		inputInfo.devices = next;
 	    else
 		prev->next = next;
 
+	    CloseDevice(tmp);
 	    ret = Success;
 	}
     }
diff --git a/dix/main.c b/dix/main.c
index 92c30b6..c7a0f6b 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -466,6 +466,8 @@ main(int argc, char *argv[], char *envp[])
 
 	Dispatch();
 
+        UndisplayDevices();
+
 	/* Now free up whatever must be freed */
 	if (screenIsSaved == SCREEN_SAVER_ON)
 	    SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 8458899..f826b3b 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -247,9 +247,13 @@ ProcessInputEvents ()
 
   mieqProcessInputEvents();
 
-  /* FIXME: This is a problem if we have multiple pointers */
-  miPointerGetPosition(inputInfo.pointer, &x, &y);
-  xf86SetViewport(xf86Info.currentScreen, x, y);
+  /* PIE can be called after devices have been shut down. Blame DGA. */
+  if (inputInfo.pointer)
+  {
+      /* FIXME: This is a problem if we have multiple pointers */
+      miPointerGetPosition(inputInfo.pointer, &x, &y);
+      xf86SetViewport(xf86Info.currentScreen, x, y);
+  }
 }
 
 void
diff --git a/include/dix.h b/include/dix.h
index 1b112a1..385f56c 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -424,6 +424,10 @@ extern int DeliverDeviceEvents(
 extern void DefineInitialRootWindow(
     WindowPtr /* win */);
 
+extern void SetupSprite(
+    DeviceIntPtr /* pDev */,
+    ScreenPtr    /* pScreen */);
+
 extern void InitializeSprite(
     DeviceIntPtr /* pDev */,
     WindowPtr    /* pWin */);
diff --git a/include/input.h b/include/input.h
index 765d71d..2debce9 100644
--- a/include/input.h
+++ b/include/input.h
@@ -190,6 +190,8 @@ extern int InitAndStartDevices(void);
 
 extern void CloseDownDevices(void);
 
+extern void UndisplayDevices(void);
+
 extern int RemoveDevice(
     DeviceIntPtr /*dev*/);
 
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 0d468c3..3cfd6c3 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -431,6 +431,18 @@ typedef    void (* MarkUnrealizedWindowProcPtr)(
 	WindowPtr /*pWin*/,
 	Bool /*fromConfigure*/);
 
+typedef    void (* UndisplayCursorProcPtr)(
+        DeviceIntPtr /* pDev */,
+        ScreenPtr    /* pScreen */);
+
+typedef    Bool (* DeviceCursorInitializeProcPtr)(
+        DeviceIntPtr /* pDev */,
+        ScreenPtr    /* pScreen */);
+
+typedef    void (* DeviceCursorCleanupProcPtr)(
+        DeviceIntPtr /* pDev */,
+        ScreenPtr    /* pScreen */);
+
 typedef struct _Screen {
     int			myNum;	/* index of this instance in Screens[] */
     ATOM		id;
@@ -587,6 +599,10 @@ typedef struct _Screen {
     ChangeBorderWidthProcPtr	ChangeBorderWidth;
     MarkUnrealizedWindowProcPtr	MarkUnrealizedWindow;
 
+    /* Device cursor procedures */
+    UndisplayCursorProcPtr        UndisplayCursor;
+    DeviceCursorInitializeProcPtr DeviceCursorInitialize;
+    DeviceCursorCleanupProcPtr    DeviceCursorCleanup;
 } ScreenRec;
 
 typedef struct _ScreenInfo {
diff --git a/mi/midispcur.c b/mi/midispcur.c
index 35f0fba..d4471f9 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -67,6 +67,9 @@ static unsigned long miDCGeneration = 0;
 
 static Bool	miDCCloseScreen(int index, ScreenPtr pScreen);
 
+/* per device private data */
+static int      miDCSpriteIndex;
+
 typedef struct {
     GCPtr	    pSourceGC, pMaskGC;
     GCPtr	    pSaveGC, pRestoreGC;
@@ -79,13 +82,16 @@ typedef struct {
 #endif
 } miDCBufferRec, *miDCBufferPtr;
 
+#define MIDCBUFFER(dev) \
+ ((DevHasCursor(dev)) ? \
+  (miDCBufferPtr)dev->devPrivates[miDCSpriteIndex].ptr :\
+  (miDCBufferPtr)inputInfo.pointer->devPrivates[miDCSpriteIndex].ptr)
+
 /* 
  * The core pointer buffer will point to the index of the virtual core pointer
  * in the pCursorBuffers array. 
  */
 typedef struct {
-    miDCBufferPtr pCoreBuffer; /* for core pointer */
-    miDCBufferPtr pCursorBuffers;   /* one for each device */
     CloseScreenProcPtr CloseScreen;
 } miDCScreenRec, *miDCScreenPtr;
 
@@ -121,6 +127,9 @@ static Bool	miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen,
                                int x, int y, int w, int h,	
                                int dx, int dy);
 
+static Bool     miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
+static void     miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
+
 static miSpriteCursorFuncRec miDCFuncs = {
     miDCRealizeCursor,
     miDCUnrealizeCursor,
@@ -129,6 +138,8 @@ static miSpriteCursorFuncRec miDCFuncs = {
     miDCRestoreUnderCursor,
     miDCMoveCursor,
     miDCChangeSave,
+    miDCDeviceInitialize,
+    miDCDeviceCleanup
 };
 
 _X_EXPORT Bool
@@ -137,8 +148,6 @@ miDCInitialize (pScreen, screenFuncs)
     miPointerScreenFuncPtr  screenFuncs;
 {
     miDCScreenPtr   pScreenPriv;
-    miDCBufferPtr   pBuffer;
-    int mpBufferIdx;
 
     if (miDCGeneration != serverGeneration)
     {
@@ -151,41 +160,8 @@ miDCInitialize (pScreen, screenFuncs)
     if (!pScreenPriv)
 	return FALSE;
 
-    /*
-     * initialize the entire private structure to zeros
-     */
-
-    pScreenPriv->pCursorBuffers = (miDCBufferPtr)xalloc(MAX_DEVICES *
-            sizeof(miDCBufferRec));
-    if (!pScreenPriv->pCursorBuffers)
-    {
-        xfree((pointer)pScreenPriv);
-        return FALSE;
-    }
-
-    /* virtual core pointer ID is 1 */
-    pScreenPriv->pCoreBuffer = &pScreenPriv->pCursorBuffers[1];
-
-    mpBufferIdx = 0;
-    while(mpBufferIdx < MAX_DEVICES)
-    {
-        pBuffer = &pScreenPriv->pCursorBuffers[mpBufferIdx];
-        pBuffer->pSourceGC =
-            pBuffer->pMaskGC =
-            pBuffer->pSaveGC =
-            pBuffer->pRestoreGC =
-            pBuffer->pMoveGC =
-            pBuffer->pPixSourceGC =
-            pBuffer->pPixMaskGC = NULL;
-#ifdef ARGB_CURSOR
-            pBuffer->pRootPicture = NULL;
-            pBuffer->pTempPicture = NULL;
-#endif
-        pBuffer->pSave = pBuffer->pTemp = NULL;
-
-        mpBufferIdx++;
-    }
 
+    miDCSpriteIndex = AllocateDevicePrivateIndex();
 
     pScreenPriv->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = miDCCloseScreen;
@@ -194,7 +170,6 @@ miDCInitialize (pScreen, screenFuncs)
 
     if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
     {
-        xfree ((pointer) pScreenPriv->pCursorBuffers);
 	xfree ((pointer) pScreenPriv);
 	return FALSE;
     }
@@ -211,38 +186,10 @@ miDCCloseScreen (index, pScreen)
     ScreenPtr	pScreen;
 {
     miDCScreenPtr   pScreenPriv;
-    miDCBufferPtr   pBuffer;
-    int mpBufferIdx;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
 
-    mpBufferIdx = 0;
-    while (mpBufferIdx < MAX_DEVICES) 
-    {
-        pBuffer = &pScreenPriv->pCursorBuffers[mpBufferIdx];
-
-        tossGC (pBuffer->pSourceGC);
-        tossGC (pBuffer->pMaskGC);
-        tossGC (pBuffer->pSaveGC);
-        tossGC (pBuffer->pRestoreGC);
-        tossGC (pBuffer->pMoveGC);
-        tossGC (pBuffer->pPixSourceGC);
-        tossGC (pBuffer->pPixMaskGC);
-        tossPix (pBuffer->pSave);
-        tossPix (pBuffer->pTemp);
-#ifdef ARGB_CURSOR
-#if 0				/* This has been free()d before */
-            tossPict (pScreenPriv->pRootPicture);
-#endif 
-            tossPict (pBuffer->pTempPicture);
-#endif
-
-            mpBufferIdx++;
-    }
-
-    xfree((pointer) pScreenPriv->pCursorBuffers);
-
     xfree ((pointer) pScreenPriv);
     return (*pScreen->CloseScreen) (index, pScreen);
 }
@@ -536,10 +483,7 @@ miDCPutUpCursor (pDev, pScreen, pCursor, x, y, source, mask)
     }
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pWin = WindowTable[pScreen->myNum];
-    pBuffer = pScreenPriv->pCoreBuffer;
-
-    if (DevHasCursor(pDev))
-        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+    pBuffer = MIDCBUFFER(pDev);
 
 #ifdef ARGB_CURSOR
     if (pPriv->pPicture)
@@ -587,10 +531,7 @@ miDCSaveUnderCursor (pDev, pScreen, x, y, w, h)
     GCPtr	    pGC;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pBuffer = pScreenPriv->pCoreBuffer;
-
-    if (DevHasCursor(pDev))
-        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+    pBuffer = MIDCBUFFER(pDev);
 
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
@@ -626,10 +567,7 @@ miDCRestoreUnderCursor (pDev, pScreen, x, y, w, h)
     GCPtr	    pGC;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pBuffer = pScreenPriv->pCoreBuffer;
-
-    if (DevHasCursor(pDev))
-        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+    pBuffer = MIDCBUFFER(pDev);
 
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
@@ -659,10 +597,7 @@ miDCChangeSave (pDev, pScreen, x, y, w, h, dx, dy)
     int		    sourcex, sourcey, destx, desty, copyw, copyh;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pBuffer = pScreenPriv->pCoreBuffer;
-
-    if (DevHasCursor(pDev))
-        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+    pBuffer = MIDCBUFFER(pDev);
 
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
@@ -810,10 +745,7 @@ miDCMoveCursor (pDev, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
     }
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pWin = WindowTable[pScreen->myNum];
-    pBuffer = pScreenPriv->pCoreBuffer;
-
-    if (DevHasCursor(pDev))
-        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+    pBuffer = MIDCBUFFER(pDev);
 
     pTemp = pBuffer->pTemp;
     if (!pTemp ||
@@ -905,3 +837,62 @@ miDCMoveCursor (pDev, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
 			    0, 0, w, h, x, y);
     return TRUE;
 }
+
+static Bool
+miDCDeviceInitialize(pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr pScreen;
+{
+    miDCBufferPtr pBuffer;
+
+    if (!AllocateDevicePrivate(pDev, miDCSpriteIndex))
+        return FALSE;
+
+    pBuffer = 
+       pDev->devPrivates[miDCSpriteIndex].ptr = xalloc(sizeof(miDCBufferRec));
+
+    pBuffer->pSourceGC =
+        pBuffer->pMaskGC =
+        pBuffer->pSaveGC =
+        pBuffer->pRestoreGC =
+        pBuffer->pMoveGC =
+        pBuffer->pPixSourceGC =
+        pBuffer->pPixMaskGC = NULL;
+#ifdef ARGB_CURSOR
+    pBuffer->pRootPicture = NULL;
+    pBuffer->pTempPicture = NULL;
+#endif
+    pBuffer->pSave = pBuffer->pTemp = NULL;
+
+    return TRUE;
+}
+
+static void
+miDCDeviceCleanup(pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr pScreen;
+{
+    miDCBufferPtr   pBuffer;
+
+    if (DevHasCursor(pDev))
+    {
+        pBuffer = MIDCBUFFER(pDev);
+        tossGC (pBuffer->pSourceGC);
+        tossGC (pBuffer->pMaskGC);
+        tossGC (pBuffer->pSaveGC);
+        tossGC (pBuffer->pRestoreGC);
+        tossGC (pBuffer->pMoveGC);
+        tossGC (pBuffer->pPixSourceGC);
+        tossGC (pBuffer->pPixMaskGC);
+        tossPix (pBuffer->pSave);
+        tossPix (pBuffer->pTemp);
+#ifdef ARGB_CURSOR
+#if 0				/* This has been free()d before */
+        tossPict (pScreenPriv->pRootPicture);
+#endif 
+        tossPict (pBuffer->pTempPicture);
+#endif
+        xfree(pDev->devPrivates[miDCSpriteIndex].ptr);
+        pDev->devPrivates[miDCSpriteIndex].ptr = NULL;
+    }
+}
diff --git a/mi/mipointer.c b/mi/mipointer.c
index b9f54c1..b06a0be 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -54,18 +54,12 @@ static unsigned long miPointerGeneration = 0;
 #define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr))
 #define SetupScreen(s)	miPointerScreenPtr  pScreenPriv = GetScreenPrivate(s)
 
-/*
- * until more than one pointer device exists.
- */
-
-static miPointerPtr miCorePointer;
+static int miPointerPrivatesIndex = 0;
 
-/* Multipointers 
- * ID of a device == index in this array.
- */
-static miPointerRec miPointers[MAX_DEVICES];
 #define MIPOINTER(dev) \
-    (DevHasCursor((dev))) ? &miPointers[(dev)->id] : miCorePointer
+    ((DevHasCursor((dev))) ? \
+        (miPointerPtr) dev->devPrivates[miPointerPrivatesIndex].ptr : \
+        (miPointerPtr) inputInfo.pointer->devPrivates[miPointerPrivatesIndex].ptr)
 
 static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                    CursorPtr pCursor);
@@ -73,6 +67,7 @@ static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
                                      CursorPtr pCursor);
 static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                    CursorPtr pCursor);
+static void miPointerUndisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
 static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
                                      BoxPtr pBox); 
 static void miPointerPointerNonInterestBox(DeviceIntPtr pDev, 
@@ -87,6 +82,9 @@ static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
 static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, 
                           int x, int y,
                           unsigned long time);
+static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
+static void miPointerDeviceCleanup(DeviceIntPtr pDev,
+                                   ScreenPtr pScreen);
 
 static xEvent* events; /* for WarpPointer MotionNotifies */
 
@@ -98,8 +96,6 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     Bool		    waitForUpdate;
 {
     miPointerScreenPtr	pScreenPriv;
-    miPointerPtr        pPointer;
-    int                 ptrIdx;
 
     if (miPointerGeneration != serverGeneration)
     {
@@ -131,33 +127,17 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     pScreen->ConstrainCursor = miPointerConstrainCursor;
     pScreen->CursorLimits = miPointerCursorLimits;
     pScreen->DisplayCursor = miPointerDisplayCursor;
+    pScreen->UndisplayCursor = miPointerUndisplayCursor;
+    pScreen->UndisplayCursor = miPointerUndisplayCursor;
     pScreen->RealizeCursor = miPointerRealizeCursor;
     pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
     pScreen->SetCursorPosition = miPointerSetCursorPosition;
     pScreen->RecolorCursor = miRecolorCursor;
     pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
+    pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
+    pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
 
-    /*
-     * set up the pointer object
-     * virtual core pointer ID is always 1, so we let it point to the matching
-     * index in the array.
-     */
-    miCorePointer = &miPointers[1];
-    for(ptrIdx = 0; ptrIdx < MAX_DEVICES; ptrIdx++)
-    {
-            pPointer = &miPointers[ptrIdx];
-            pPointer->pScreen = NULL;
-            pPointer->pSpriteScreen = NULL;
-            pPointer->pCursor = NULL;
-            pPointer->pSpriteCursor = NULL;
-            pPointer->limits.x1 = 0;
-            pPointer->limits.x2 = 32767;
-            pPointer->limits.y1 = 0;
-            pPointer->limits.y2 = 32767;
-            pPointer->confined = FALSE;
-            pPointer->x = 0;
-            pPointer->y = 0;
-    }
+    miPointerPrivatesIndex = AllocateDevicePrivateIndex();
 
     events = NULL;
     return TRUE;
@@ -169,20 +149,30 @@ miPointerCloseScreen (index, pScreen)
     ScreenPtr	pScreen;
 {
     miPointerPtr pPointer;
-    int ptrIdx;
+    DeviceIntPtr pDev;
 
     SetupScreen(pScreen);
 
-    for(ptrIdx = 0; ptrIdx < MAX_DEVICES; ptrIdx++)
+#if 0
+    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        pPointer = &miPointers[ptrIdx];
+        if (DevHasCursor(pDev))
+        {
+            pPointer = MIPOINTER(pDev);
 
-        if (pScreen == pPointer->pScreen)
-            pPointer->pScreen = 0;
-        if (pScreen == pPointer->pSpriteScreen)
-            pPointer->pSpriteScreen = 0;
+            if (pScreen == pPointer->pScreen)
+                pPointer->pScreen = 0;
+            if (pScreen == pPointer->pSpriteScreen)
+                pPointer->pSpriteScreen = 0;
+        }
     }
 
+    if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
+        MIPOINTER(inputInfo.pointer)->pScreen = 0;
+    if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
+        MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
+#endif
+
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
     xfree ((pointer) pScreenPriv);
     xfree ((pointer) events);
@@ -229,6 +219,15 @@ miPointerDisplayCursor (pDev, pScreen, pCursor)
 }
 
 static void
+miPointerUndisplayCursor(pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr 	 pScreen;
+{
+    SetupScreen(pScreen);
+    (*pScreenPriv->spriteFuncs->UndisplayCursor)(pDev, pScreen);
+}
+
+static void
 miPointerConstrainCursor (pDev, pScreen, pBox)
     DeviceIntPtr pDev;
     ScreenPtr	pScreen;
@@ -281,6 +280,65 @@ miPointerSetCursorPosition(pDev, pScreen, x, y, generateEvent)
     return TRUE;
 }
 
+/* Set up sprite information for the device. 
+   This function will be called once for each device after it is initialized
+   in the DIX.
+ */ 
+static Bool
+miPointerDeviceInitialize(pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr pScreen;
+{
+    miPointerPtr pPointer;
+    SetupScreen (pScreen);
+
+    if (!AllocateDevicePrivate(pDev, miPointerPrivatesIndex))
+        return FALSE;
+
+    pPointer = xalloc(sizeof(miPointerRec));
+    if (!pPointer)
+        return FALSE;
+
+    pPointer->pScreen = NULL;
+    pPointer->pSpriteScreen = NULL;
+    pPointer->pCursor = NULL;
+    pPointer->pSpriteCursor = NULL;
+    pPointer->limits.x1 = 0;
+    pPointer->limits.x2 = 32767;
+    pPointer->limits.y1 = 0;
+    pPointer->limits.y2 = 32767;
+    pPointer->confined = FALSE;
+    pPointer->x = 0;
+    pPointer->y = 0;
+
+    if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
+    {
+        xfree(pPointer);
+        return FALSE;
+    }
+
+    pDev->devPrivates[miPointerPrivatesIndex].ptr = pPointer;
+    return TRUE;
+}
+
+/* Clean up after device. 
+   This function will be called once before the device is freed in the DIX
+ */
+static void
+miPointerDeviceCleanup(pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr pScreen;
+{
+    if (DevHasCursor(pDev))
+    {
+        SetupScreen(pScreen);
+        (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
+        xfree(pDev->devPrivates[miPointerPrivatesIndex].ptr);
+        pDev->devPrivates[miPointerPrivatesIndex].ptr = NULL;
+    }
+}
+
+
 /* Once signals are ignored, the WarpCursor function can call this */
 
 _X_EXPORT void
@@ -413,7 +471,8 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
 void
 miPointerDeltaCursor (int dx, int dy, unsigned long time)
 {
-    int x = miCorePointer->x + dx, y = miCorePointer->y + dy;
+    int x = MIPOINTER(inputInfo.pointer)->x = dx;
+    int y = MIPOINTER(inputInfo.pointer)->y = dy;
 
     miPointerSetPosition(inputInfo.pointer, &x, &y, time);
 }
diff --git a/mi/mipointer.h b/mi/mipointer.h
index c483413..666a6eb 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -53,6 +53,18 @@ typedef struct _miPointerSpriteFuncRec {
                     int  /* x */,
                     int  /* y */
                     );
+    Bool        (*DeviceCursorInitialize)(
+                    DeviceIntPtr /* pDev */,
+                    ScreenPtr /* pScr */
+                    );
+    void        (*DeviceCursorCleanup)(
+                    DeviceIntPtr /* pDev */,
+                    ScreenPtr /* pScr */
+                    );
+    void        (*UndisplayCursor)(
+                    DeviceIntPtr /* pDev */,
+                    ScreenPtr /* pScr */
+                    );
 } miPointerSpriteFuncRec, *miPointerSpriteFuncPtr;
 
 typedef struct _miPointerScreenFuncRec {
diff --git a/mi/misprite.c b/mi/misprite.c
index bb67f48..60774b5 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -72,6 +72,13 @@ in this Software without prior written authorization from The Open Group.
 #define SPRITE_DEBUG(x)
 #endif
 
+
+static int miSpriteDevPrivatesIndex;
+#define MISPRITE(dev) \
+    ((DevHasCursor(dev)) ? \
+       (miCursorInfoPtr) dev->devPrivates[miSpriteDevPrivatesIndex].ptr : \
+       (miCursorInfoPtr) inputInfo.pointer->devPrivates[miSpriteDevPrivatesIndex].ptr)
+
 /*
  * screen wrappers
  */
@@ -104,6 +111,11 @@ static void	    miSpriteSaveDoomedAreas(WindowPtr pWin,
 static void	    miSpriteComputeSaved(DeviceIntPtr pDev, 
                                          ScreenPtr pScreen);
 
+static Bool         miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, 
+                                                   ScreenPtr pScreen);
+static void         miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, 
+                                                ScreenPtr pScreen);
+
 #define SCREEN_PROLOGUE(pScreen, field)\
   ((pScreen)->field = \
    ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
@@ -123,12 +135,16 @@ static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
                               CursorPtr pCursor, int x, int y);
 static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                int x, int y);
+static void miSpriteUndisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen);
 
 _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
     miSpriteRealizeCursor,
     miSpriteUnrealizeCursor,
     miSpriteSetCursor,
     miSpriteMoveCursor,
+    miSpriteDeviceCursorInitialize,
+    miSpriteDeviceCursorCleanup,
+    miSpriteUndisplayCursor
 };
 
 /*
@@ -156,7 +172,7 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
     {
         if (DevHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+            pCursorInfo = MISPRITE(pDev);
 
             if (pCursorInfo->isUp &&
                 RECT_IN_REGION (pScreen, pRegion, &pCursorInfo->saved) 
@@ -183,8 +199,6 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
 {
     miSpriteScreenPtr	pScreenPriv;
     VisualPtr		pVisual;
-    miCursorInfoPtr     pCursorInfo;
-    int cursorIdx;
     
     if (!DamageSetup (pScreen))
 	return FALSE;
@@ -231,44 +245,19 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     pScreenPriv->StoreColors = pScreen->StoreColors;
     
     pScreenPriv->BlockHandler = pScreen->BlockHandler;
-    
-    /* alloc and zero memory for all cursors */
-    pScreenPriv->pDevCursors = 
-        (miCursorInfoPtr)xalloc(MAX_DEVICES * sizeof(miCursorInfoRec));
 
-    if (!pScreenPriv->pDevCursors)
-    {
-        xfree((pointer)pScreenPriv);
-        return FALSE;
-    }
-    /* virtual core pointer's ID is 1 */
-    pScreenPriv->cp = &(pScreenPriv->pDevCursors[1]);
-
-    cursorIdx = 0;
-    while (cursorIdx < MAX_DEVICES)
-    {
-        pCursorInfo = &(pScreenPriv->pDevCursors[cursorIdx]);
-        pCursorInfo->pCursor = NULL;
-        pCursorInfo->x = 0;
-        pCursorInfo->y = 0;
-        pCursorInfo->isUp = FALSE;
-        pCursorInfo->shouldBeUp = FALSE;
-        pCursorInfo->pCacheWin = NullWindow;
-        pCursorInfo->isInCacheWin = FALSE;
-        pCursorInfo->checkPixels = TRUE;
-        pCursorInfo->pInstalledMap = NULL;
-        pCursorInfo->pColormap = NULL;
-        pCursorInfo->colors[SOURCE_COLOR].red = 0;
-        pCursorInfo->colors[SOURCE_COLOR].green = 0;
-        pCursorInfo->colors[SOURCE_COLOR].blue = 0;
-        pCursorInfo->colors[MASK_COLOR].red = 0;
-        pCursorInfo->colors[MASK_COLOR].green = 0;
-        pCursorInfo->colors[MASK_COLOR].blue = 0;
-
-        cursorIdx++;
-    }
+    pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize;
+    pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup;
 
+    pScreenPriv->pInstalledMap = NULL;
+    pScreenPriv->pColormap = NULL;
     pScreenPriv->funcs = cursorFuncs;
+    pScreenPriv->colors[SOURCE_COLOR].red = 0;
+    pScreenPriv->colors[SOURCE_COLOR].green = 0;
+    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
+    pScreenPriv->colors[MASK_COLOR].red = 0;
+    pScreenPriv->colors[MASK_COLOR].green = 0;
+    pScreenPriv->colors[MASK_COLOR].blue = 0;
     pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv;
 
     pScreen->CloseScreen = miSpriteCloseScreen;
@@ -286,6 +275,8 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     pScreen->BlockHandler = miSpriteBlockHandler;
 
     damageRegister = 0;
+    miSpriteDevPrivatesIndex = AllocateDevicePrivateIndex();
+
 
     return TRUE;
 }
@@ -318,18 +309,8 @@ miSpriteCloseScreen (i, pScreen)
     pScreen->StoreColors = pScreenPriv->StoreColors;
 
     pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
-    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
-    {
-        if (DevHasCursor(pDev))
-        {
-            miCursorInfoPtr pCursor;
-            pCursor = &pScreenPriv->pDevCursors[pDev->id];
-            miSpriteIsUpFALSE (pCursor, pScreen, pScreenPriv);
-        }
-    }
     DamageDestroy (pScreenPriv->pDamage);
 
-    xfree ((pointer)(pScreenPriv->pDevCursors));
     xfree ((pointer) pScreenPriv);
 
     return (*pScreen->CloseScreen) (i, pScreen);
@@ -356,7 +337,7 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
     {
         if (DevHasCursor(pDev))
         {
-             pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+             pCursorInfo = MISPRITE(pDev);
              if (pDrawable->type == DRAWABLE_WINDOW &&
                      pCursorInfo->isUp &&
                      ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, 
@@ -396,7 +377,7 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
     {
         if (DevHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+            pCursorInfo = MISPRITE(pDev);
 
             if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp)
             {
@@ -448,7 +429,7 @@ miSpriteSourceValidate (pDrawable, x, y, width, height)
     {
         if (DevHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+            pCursorInfo = MISPRITE(pDev);
             if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp &&
                     ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
                         x, y, width, height))
@@ -481,7 +462,7 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
     {
         if (DevHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+            pCursorInfo = MISPRITE(pDev);
             /*
              * Damage will take care of destination check
              */
@@ -522,7 +503,7 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
     {
         if (DevHasCursor(pDev))
         {
-            pCursorInfo = &pPriv->pDevCursors[pDev->id];
+            pCursorInfo = MISPRITE(pDev);
             if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
             {
                 SPRITE_DEBUG (("BlockHandler restore\n"));
@@ -534,7 +515,7 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
     {
         if (DevHasCursor(pDev))
         {
-            pCursorInfo = &pPriv->pDevCursors[pDev->id];
+            pCursorInfo = MISPRITE(pDev);
             if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
             {
                 SPRITE_DEBUG (("BlockHandler restore\n"));
@@ -550,9 +531,6 @@ miSpriteInstallColormap (pMap)
 {
     ScreenPtr		pScreen = pMap->pScreen;
     miSpriteScreenPtr	pPriv;
-    DeviceIntPtr            pDev = inputInfo.pointer;
-    miCursorInfoPtr         pCursorInfo;
-    int                     cursorIdx;
 
     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
@@ -562,29 +540,23 @@ miSpriteInstallColormap (pMap)
 
     SCREEN_EPILOGUE(pScreen, InstallColormap);
 
-    /* InstallColormap is called before devices are initialized. We cannot
-     * just run through the device list, we need to go through all possible
-     * sprite structs.*/
-    for (cursorIdx = 0; cursorIdx < MAX_DEVICES; cursorIdx++)
+    /* InstallColormap can be called before devices are initialized. */
+    pPriv->pInstalledMap = pMap;
+    if (pPriv->pColormap != pMap)
     {
-        pCursorInfo = &pPriv->pDevCursors[cursorIdx];
-        pCursorInfo->pInstalledMap = pMap;
-        if (pCursorInfo->pColormap != pMap)
+        DeviceIntPtr pDev;
+        miCursorInfoPtr     pCursorInfo;
+        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
-            pCursorInfo->checkPixels = TRUE;
-            if (pCursorInfo->isUp)
+            if (DevHasCursor(pDev))
             {
-                /* find matching device */
-                for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
-                {
-                    if (pDev->id == cursorIdx)
-                    {
-                        miSpriteRemoveCursor(pDev, pScreen);
-                        break;
-                    }
-                }
-            } 
-        } 
+                pCursorInfo = MISPRITE(pDev);
+                pCursorInfo->checkPixels = TRUE;
+                if (pCursorInfo->isUp)
+                    miSpriteRemoveCursor(pDev, pScreen);
+            }
+        }
+
     }
 }
 
@@ -599,8 +571,8 @@ miSpriteStoreColors (pMap, ndef, pdef)
     int			i;
     int			updated;
     VisualPtr		pVisual;
-    DeviceIntPtr            pDev = inputInfo.pointer;
-    miCursorInfoPtr         pCursorInfo;
+    DeviceIntPtr        pDev = inputInfo.pointer;
+    miCursorInfoPtr     pCursorInfo;
 
     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
@@ -610,6 +582,14 @@ miSpriteStoreColors (pMap, ndef, pdef)
 
     SCREEN_EPILOGUE(pScreen, StoreColors);
 
+    if (pPriv->pColormap == pMap)
+    {
+        updated = 0;
+        pVisual = pMap->pVisual;
+        if (pVisual->class == DirectColor)
+        {
+            /* Direct color - match on any of the subfields */
+
 #define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
 
 #define UpdateDAC(dev, plane,dac,mask) {\
@@ -624,48 +604,40 @@ miSpriteStoreColors (pMap, ndef, pdef)
 	    UpdateDAC(dev, plane,green,greenMask) \
 	    UpdateDAC(dev, plane,blue,blueMask)
 
-    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
-    {
-        if (DevHasCursor(pDev))
+            for (i = 0; i < ndef; i++)
+            {
+                CheckDirect (pPriv, SOURCE_COLOR)
+                CheckDirect (pPriv, MASK_COLOR)
+            }
+        }
+        else
         {
-            pCursorInfo = &pPriv->pDevCursors[pDev->id];
-            if (pCursorInfo->pColormap == pMap)
+            /* PseudoColor/GrayScale - match on exact pixel */
+            for (i = 0; i < ndef; i++)
             {
-                updated = 0;
-                pVisual = pMap->pVisual;
-                if (pVisual->class == DirectColor)
+                if (pdef[i].pixel ==
+                        pPriv->colors[SOURCE_COLOR].pixel) 
                 {
-                    /* Direct color - match on any of the subfields */
-
-                    for (i = 0; i < ndef; i++)
-                    {
-                        CheckDirect (pCursorInfo, SOURCE_COLOR)
-                            CheckDirect (pCursorInfo, MASK_COLOR)
-                    }
+                    pPriv->colors[SOURCE_COLOR] = pdef[i];
+                    if (++updated == 2)
+                        break;
                 }
-                else
+                if (pdef[i].pixel ==
+                        pPriv->colors[MASK_COLOR].pixel) 
                 {
-                    /* PseudoColor/GrayScale - match on exact pixel */
-                    for (i = 0; i < ndef; i++)
-                    {
-                        if (pdef[i].pixel ==
-                                pCursorInfo->colors[SOURCE_COLOR].pixel) 
-                        {
-                            pCursorInfo->colors[SOURCE_COLOR] = pdef[i];
-                            if (++updated == 2)
-                                break;
-                        }
-                        if (pdef[i].pixel ==
-                                pCursorInfo->colors[MASK_COLOR].pixel) 
-                        {
-                            pCursorInfo->colors[MASK_COLOR] = pdef[i];
-                            if (++updated == 2)
-                                break;
-                        }
-                    }
+                    pPriv->colors[MASK_COLOR] = pdef[i];
+                    if (++updated == 2)
+                        break;
                 }
-                if (updated)
+            }
+        }
+        if (updated)
+        {
+            for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+            {
+                if (DevHasCursor(pDev))
                 {
+                    pCursorInfo = MISPRITE(pDev);
                     pCursorInfo->checkPixels = TRUE;
                     if (pCursorInfo->isUp)
                         miSpriteRemoveCursor (pDev, pScreen);
@@ -673,19 +645,20 @@ miSpriteStoreColors (pMap, ndef, pdef)
             }
         }
     }
-
 }
 
 static void
 miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
 {
+    miSpriteScreenPtr   pScreenPriv = (miSpriteScreenPtr)
+                               pScreen->devPrivates[miSpriteScreenIndex].ptr;
     CursorPtr		pCursor;
     xColorItem		*sourceColor, *maskColor;
 
     pCursor = pDevCursor->pCursor;
-    sourceColor = &pDevCursor->colors[SOURCE_COLOR];
-    maskColor = &pDevCursor->colors[MASK_COLOR];
-    if (pDevCursor->pColormap != pDevCursor->pInstalledMap ||
+    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
+    maskColor = &pScreenPriv->colors[MASK_COLOR];
+    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
 	!(pCursor->foreRed == sourceColor->red &&
 	  pCursor->foreGreen == sourceColor->green &&
           pCursor->foreBlue == sourceColor->blue &&
@@ -693,18 +666,18 @@ miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
 	  pCursor->backGreen == maskColor->green &&
 	  pCursor->backBlue == maskColor->blue))
     {
-	pDevCursor->pColormap = pDevCursor->pInstalledMap;
+	pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
 	sourceColor->red = pCursor->foreRed;
 	sourceColor->green = pCursor->foreGreen;
 	sourceColor->blue = pCursor->foreBlue;
-	FakeAllocColor (pDevCursor->pColormap, sourceColor);
+	FakeAllocColor (pScreenPriv->pColormap, sourceColor);
 	maskColor->red = pCursor->backRed;
 	maskColor->green = pCursor->backGreen;
 	maskColor->blue = pCursor->backBlue;
-	FakeAllocColor (pDevCursor->pColormap, maskColor);
+	FakeAllocColor (pScreenPriv->pColormap, maskColor);
 	/* "free" the pixels right away, don't let this confuse you */
-	FakeFreeColor(pDevCursor->pColormap, sourceColor->pixel);
-	FakeFreeColor(pDevCursor->pColormap, maskColor->pixel);
+	FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
+	FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
     }
 
     pDevCursor->checkPixels = FALSE;
@@ -737,7 +710,7 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
     {
         if(DevHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+            pCursorInfo = MISPRITE(pDev);
             if (pCursorInfo->isUp)
             {
                 cursorBox = pCursorInfo->saved;
@@ -777,10 +750,7 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     miCursorInfoPtr pCursorInfo;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
-
-    if (DevHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+    pCursorInfo = MISPRITE(pDev);
 
     if (pCursor == pCursorInfo->pCursor)
 	pCursorInfo->checkPixels = TRUE;
@@ -811,10 +781,7 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
     miSpriteScreenPtr	pScreenPriv;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    miCursorInfoPtr pPointer = pScreenPriv->cp;
-
-    if (DevHasCursor(pDev))
-        pPointer = &pScreenPriv->pDevCursors[pDev->id];
+    miCursorInfoPtr pPointer = MISPRITE(pDev);
 
     if (!pCursor)
     {
@@ -929,12 +896,74 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
     CursorPtr pCursor;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursor = pScreenPriv->cp->pCursor;
+    pCursor = MISPRITE(pDev)->pCursor;
+
+    miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
+}
+
+
+static Bool
+miSpriteDeviceCursorInitialize(pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr pScreen;
+{
+    miSpriteScreenPtr pScreenPriv;
+    miCursorInfoPtr pCursorInfo;
+    int ret = FALSE;
+
+    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+
+    if (!AllocateDevicePrivate(pDev, miSpriteDevPrivatesIndex))
+        return FALSE;
+
+    pCursorInfo = 
+        pDev->devPrivates[miSpriteDevPrivatesIndex].ptr = 
+            xalloc(sizeof(miCursorInfoRec));
+    if (!pCursorInfo)
+        return FALSE;
 
+    pCursorInfo->pCursor = NULL;
+    pCursorInfo->x = 0;
+    pCursorInfo->y = 0;
+    pCursorInfo->isUp = FALSE;
+    pCursorInfo->shouldBeUp = FALSE;
+    pCursorInfo->pCacheWin = NullWindow;
+    pCursorInfo->isInCacheWin = FALSE;
+    pCursorInfo->checkPixels = TRUE;
+
+    ret = (*pScreenPriv->funcs->DeviceCursorInitialize)(pDev, pScreen);
+    if (!ret)
+    {
+        xfree(pCursorInfo);
+        pDev->devPrivates[miSpriteDevPrivatesIndex].ptr = NULL;
+    } 
+    return ret;
+}
+
+static void
+miSpriteDeviceCursorCleanup(pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr    pScreen;
+{
     if (DevHasCursor(pDev))
-        pCursor = pScreenPriv->pDevCursors[pDev->id].pCursor;
+    {
+        miSpriteScreenPtr pScreenPriv;
+        pScreenPriv = 
+            (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
-    miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
+        (*pScreenPriv->funcs->DeviceCursorCleanup)(pDev, pScreen);
+        pDev->devPrivates[miSpriteDevPrivatesIndex].ptr = NULL;
+        xfree(MISPRITE(pDev));
+    }
+}
+
+static void
+miSpriteUndisplayCursor(pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr    pScreen;
+{
+    if (MISPRITE(pDev)->isUp)
+        miSpriteRemoveCursor(pDev, pScreen);
 }
 
 /*
@@ -952,10 +981,7 @@ miSpriteRemoveCursor (pDev, pScreen)
 
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
-
-    if (DevHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+    pCursorInfo = MISPRITE(pDev);
 
     miSpriteIsUpFALSE (pCursorInfo, pScreen, pScreenPriv);
     pCursorInfo->pCacheWin = NullWindow;
@@ -992,10 +1018,7 @@ miSpriteSaveUnderCursor(pDev, pScreen)
 
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
-
-    if (DevHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+    pCursorInfo = MISPRITE(pDev);
 
     miSpriteComputeSaved (pDev, pScreen);
     pCursor = pCursorInfo->pCursor;
@@ -1035,10 +1058,7 @@ miSpriteRestoreCursor (pDev, pScreen)
 
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
-
-    if (DevHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+    pCursorInfo = MISPRITE(pDev);
 
     miSpriteComputeSaved (pDev, pScreen);
     pCursor = pCursorInfo->pCursor;
@@ -1051,8 +1071,8 @@ miSpriteRestoreCursor (pDev, pScreen)
         miSpriteFindColors (pCursorInfo, pScreen);
     if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen, 
                 pCursor, x, y,
-                pCursorInfo->colors[SOURCE_COLOR].pixel,
-                pCursorInfo->colors[MASK_COLOR].pixel))
+                pScreenPriv->colors[SOURCE_COLOR].pixel,
+                pScreenPriv->colors[MASK_COLOR].pixel))
     {
         miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
     }
@@ -1076,10 +1096,7 @@ miSpriteComputeSaved (pDev, pScreen)
     miCursorInfoPtr pCursorInfo;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
-
-    if (DevHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+    pCursorInfo = MISPRITE(pDev);
 
     pCursor = pCursorInfo->pCursor;
     x = pCursorInfo->x - (int)pCursor->bits->xhot;
diff --git a/mi/misprite.h b/mi/misprite.h
index 96d2d7d..72dc06f 100644
--- a/mi/misprite.h
+++ b/mi/misprite.h
@@ -89,6 +89,14 @@ typedef struct {
 		int /*dx*/,
 		int /*dy*/
 );
+    Bool	(*DeviceCursorInitialize)(
+                DeviceIntPtr /*pDev*/,
+		ScreenPtr /*pScreen*/
+);
+    void	(*DeviceCursorCleanup)(
+                DeviceIntPtr /*pDev*/,
+		ScreenPtr /*pScreen*/
+);
 
 } miSpriteCursorFuncRec, *miSpriteCursorFuncPtr;
 
diff --git a/mi/mispritest.h b/mi/mispritest.h
index 8cc2064..f4155b5 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -53,9 +53,6 @@ typedef struct {
     WindowPtr	    pCacheWin;		/* window the cursor last seen in */
     Bool	    isInCacheWin;
     Bool	    checkPixels;	/* check colormap collision */
-    xColorItem	    colors[2];
-    ColormapPtr	    pInstalledMap;
-    ColormapPtr	    pColormap;
 } miCursorInfoRec, *miCursorInfoPtr;
 
 /*
@@ -81,13 +78,17 @@ typedef struct {
     
     /* os layer procedures */
     ScreenBlockHandlerProcPtr		BlockHandler;
+    
+    /* device cursor procedures */
+    DeviceCursorInitializeProcPtr       DeviceCursorInitialize;
+    DeviceCursorCleanupProcPtr          DeviceCursorCleanup;
 
-    miCursorInfoPtr  cp;                 /* core pointer */
-
+    xColorItem	    colors[2];
+    ColormapPtr     pInstalledMap;
+    ColormapPtr     pColormap;
     VisualPtr	    pVisual;
     miSpriteCursorFuncPtr    funcs;
     DamagePtr	    pDamage;		/* damage tracking structure */
-    miCursorInfoPtr pDevCursors;         /* all cursors' info */
 } miSpriteScreenRec, *miSpriteScreenPtr;
 
 #define SOURCE_COLOR	0
commit 7cef789fa13ae53bfba6dc7b5a7928b7362b2522
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 9 18:37:48 2007 +0930

    Close down virtual core devices when closing all devices.

diff --git a/dix/devices.c b/dix/devices.c
index 4794d6f..2b55679 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -605,6 +605,9 @@ CloseDownDevices()
 {
     DeviceIntPtr dev, next;
 
+    CloseDevice(inputInfo.keyboard);
+    CloseDevice(inputInfo.pointer);
+
     for (dev = inputInfo.devices; dev; dev = next)
     {
 	next = dev->next;
commit 6081b8c76f7d934bd4e9584a2f6d55636c5289d2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 9 18:35:47 2007 +0930

    Don't explicitly init sprite for VCP, EnableDevice() will take care of that.

diff --git a/dix/devices.c b/dix/devices.c
index a080535..4794d6f 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -424,7 +424,6 @@ InitCoreDevices()
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate pointer devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
-        InitializeSprite(dev, NullWindow);
         (void)ActivateDevice(dev);
 
         /* Enable device, and then remove it from the device list. Virtual
commit 00b1d52f4103a07568dcebcdaa860b9b51f19b4d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 9 18:32:00 2007 +0930

    Adding some comments to devices.c.

diff --git a/dix/devices.c b/dix/devices.c
index 30c2670..a080535 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -85,6 +85,9 @@ static int CoreDevicePrivatesGeneration = -1;
 /* The client that is allowed to change pointer-keyboard pairings. */
 static ClientPtr pairingClient = NULL;
 
+/** 
+ * Alloc memory for new sprite, reset to default values 
+ */ 
 DeviceIntPtr
 AddInputDevice(DeviceProc deviceProc, Bool autoStart)
 {
@@ -163,6 +166,12 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
     return dev;
 }
 
+/**
+ * Enable the device through the driver, initialize the DIX sprite or pair the
+ * device, add the device to the device list.
+ *
+ * After calling EnableDevice(), a device can and will send events.
+ */
 Bool
 EnableDevice(DeviceIntPtr dev)
 {
@@ -194,6 +203,9 @@ EnableDevice(DeviceIntPtr dev)
     return TRUE;
 }
 
+/**
+ * Shut device down through drivers, remove from device list.
+ */  
 Bool
 DisableDevice(DeviceIntPtr dev)
 {
@@ -341,6 +353,14 @@ CorePointerProc(DeviceIntPtr pDev, int what)
     return Success;
 }
 
+/**
+ * Initialize a virtual core keyboard and a virtual core pointer. 
+ *
+ * Both devices are not tied to physical devices, but guarantee that there is
+ * always a keyboard and a pointer present and keep the protocol semantics.
+ * Both core devices are NOT part of the device list and act only as a
+ * fallback if no physical device is available.
+ */
 void
 InitCoreDevices()
 {
@@ -422,6 +442,13 @@ InitCoreDevices()
     }
 }
 
+/**
+ * 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.
+ */
 int
 InitAndStartDevices()
 {
@@ -459,6 +486,9 @@ InitAndStartDevices()
     return Success;
 }
 
+/**
+ * Shut down device and free memory.
+ */
 static void
 CloseDevice(DeviceIntPtr dev)
 {
commit aa77ffb510abe004802ab9acc6996e4c6fe3ebb2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 9 18:27:22 2007 +0930

    Fix: pick new ClientPointer when device is closed.

diff --git a/dix/devices.c b/dix/devices.c
index 411188d..30c2670 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -556,7 +556,10 @@ CloseDevice(DeviceIntPtr dev)
     for (j = 0; j < currentMaxClients; j++)
     {
         if (clients[j]->clientPtr == dev)
-            PickPointer(clients[j]);
+        {
+            clients[j]->clientPtr = NULL;
+            clients[j]->clientPtr = PickPointer(clients[j]);
+        }
     }
 
     if (dev->devPrivates)
commit 5c4deb71a1cb981ea7e2e25d2b3a1179f27efa5a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Apr 5 14:21:46 2007 +0930

    Synthesize WarpPointer events for the actual device rather than the VCP.

diff --git a/mi/mipointer.c b/mi/mipointer.c
index 863a405..b9f54c1 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -467,7 +467,6 @@ static void
 miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
                      unsigned long time)
 {
-    int valuators[2];
     miPointerPtr pPointer = MIPOINTER(pDev);
     SetupScreen(pScreen);
 
@@ -574,9 +573,8 @@ miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, unsigned long
         }
     }
 
-    nevents = GetPointerEvents(events, inputInfo.pointer, MotionNotify, 0,
-                               POINTER_ABSOLUTE, 0, 2, valuators);
+    nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_ABSOLUTE, 0, 2, valuators);
 
     for (i = 0; i < nevents; i++)
-        mieqEnqueue(inputInfo.pointer, &events[i]);
+        mieqEnqueue(pDev, &events[i]);
 }
commit 7f36ba57062096e9c67889d5b7dd64e2fb0004e7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 4 17:38:10 2007 +0930

    Allow for multiple animated cursors.

diff --git a/render/animcur.c b/render/animcur.c
index 7bddc0d..1172877 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -80,7 +80,8 @@ typedef struct _AnimCurState {
     CARD32			time;
 } AnimCurStateRec, *AnimCurStatePtr;
 
-static AnimCurStateRec  animCurState;
+/* What a waste. But we need an API change to alloc it per device only. */
+static AnimCurStateRec animCurState[MAX_DEVICES];
 
 static unsigned char empty[4];
 
@@ -175,35 +176,47 @@ AnimCurScreenBlockHandler (int screenNum,
 {
     ScreenPtr		pScreen = screenInfo.screens[screenNum];
     AnimCurScreenPtr    as = GetAnimCurScreen(pScreen);
+    DeviceIntPtr        dev;
+    CARD32              now = 0, 
+                        soonest = ~0; /* earliest time to wakeup again */
 
-    if (pScreen == animCurState.pScreen)
+    for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	CARD32		now = GetTimeInMillis ();
-
-	if ((INT32) (now - animCurState.time) >= 0)
+	if (IsPointerDevice(dev) && pScreen == animCurState[dev->id].pScreen)
 	{
-	    AnimCurPtr		    ac = GetAnimCur(animCurState.pCursor);
-	    int			    elt = (animCurState.elt + 1) % ac->nelt;
-	    DisplayCursorProcPtr    DisplayCursor;
-
-	    /*
-	     * Not a simple Unwrap/Wrap as this
-	     * isn't called along the DisplayCursor 
-	     * wrapper chain.
-	     */
-	    DisplayCursor = pScreen->DisplayCursor;
-	    pScreen->DisplayCursor = as->DisplayCursor;
-	    (void) (*pScreen->DisplayCursor) (inputInfo.pointer, 
-                                              pScreen, 
-                                              ac->elts[elt].pCursor);
-	    as->DisplayCursor = pScreen->DisplayCursor;
-	    pScreen->DisplayCursor = DisplayCursor;
-
-	    animCurState.elt = elt;
-	    animCurState.time = now + ac->elts[elt].delay;
+	    if (!now) now = GetTimeInMillis (); 
+
+	    if ((INT32) (now - animCurState[dev->id].time) >= 0)
+	    {
+		AnimCurPtr ac  = GetAnimCur(animCurState[dev->id].pCursor);
+		int        elt = (animCurState[dev->id].elt + 1) % ac->nelt;
+		DisplayCursorProcPtr DisplayCursor;
+
+		/*
+		 * Not a simple Unwrap/Wrap as this
+		 * isn't called along the DisplayCursor 
+		 * wrapper chain.
+		 */
+		DisplayCursor = pScreen->DisplayCursor;
+		pScreen->DisplayCursor = as->DisplayCursor;
+		(void) (*pScreen->DisplayCursor) (dev,
+						  pScreen, 
+						  ac->elts[elt].pCursor);
+		as->DisplayCursor = pScreen->DisplayCursor;
+		pScreen->DisplayCursor = DisplayCursor;
+
+		animCurState[dev->id].elt = elt;
+		animCurState[dev->id].time = now + ac->elts[elt].delay;
+	    }
+
+	    if (soonest > animCurState[dev->id].time)
+		soonest = animCurState[dev->id].time;
 	}
-	AdjustWaitForDelay (pTimeout, animCurState.time - now);
     }
+
+    if (now)
+        AdjustWaitForDelay (pTimeout, soonest - now);
+
     Unwrap (as, pScreen, BlockHandler);
     (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
     Wrap (as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
@@ -220,7 +233,7 @@ AnimCurDisplayCursor (DeviceIntPtr pDev,
     Unwrap (as, pScreen, DisplayCursor);
     if (IsAnimCur(pCursor))
     {
-	if (pCursor != animCurState.pCursor)
+	if (pCursor != animCurState[pDev->id].pCursor)
 	{
 	    AnimCurPtr		ac = GetAnimCur(pCursor);
 
@@ -228,10 +241,10 @@ AnimCurDisplayCursor (DeviceIntPtr pDev,
                 (pDev, pScreen, ac->elts[0].pCursor);
 	    if (ret)
 	    {
-		animCurState.elt = 0;
-		animCurState.time = GetTimeInMillis () + ac->elts[0].delay;
-		animCurState.pCursor = pCursor;
-		animCurState.pScreen = pScreen;
+		animCurState[pDev->id].elt = 0;
+		animCurState[pDev->id].time = GetTimeInMillis () + ac->elts[0].delay;
+		animCurState[pDev->id].pCursor = pCursor;
+		animCurState[pDev->id].pScreen = pScreen;
 	    }
 	}
 	else
@@ -239,8 +252,8 @@ AnimCurDisplayCursor (DeviceIntPtr pDev,
     }
     else
     {
-        animCurState.pCursor = 0;
-	animCurState.pScreen = 0;
+        animCurState[pDev->id].pCursor = 0;
+	animCurState[pDev->id].pScreen = 0;
 	ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
     }
     Wrap (as, pScreen, DisplayCursor, AnimCurDisplayCursor);
@@ -258,8 +271,8 @@ AnimCurSetCursorPosition (DeviceIntPtr pDev,
     Bool		ret;
     
     Unwrap (as, pScreen, SetCursorPosition);
-    if (animCurState.pCursor)
-	animCurState.pScreen = pScreen;
+    if (animCurState[pDev->id].pCursor)
+	animCurState[pDev->id].pScreen = pScreen;
     ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
     Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition);
     return ret;
@@ -324,7 +337,7 @@ AnimCurRecolorCursor (DeviceIntPtr pDev,
         for (i = 0; i < ac->nelt; i++)
 	    (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor,
 				       displayed && 
-				       animCurState.elt == i);
+				       animCurState[pDev->id].elt == i);
     }
     else
 	(*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed);
@@ -338,14 +351,17 @@ AnimCurInit (ScreenPtr pScreen)
 
     if (AnimCurGeneration != serverGeneration)
     {
+        int i;
 	AnimCurScreenPrivateIndex = AllocateScreenPrivateIndex ();
 	if (AnimCurScreenPrivateIndex < 0)
 	    return FALSE;
 	AnimCurGeneration = serverGeneration;
-	animCurState.pCursor = 0;
-	animCurState.pScreen = 0;
-	animCurState.elt = 0;
-	animCurState.time = 0;
+        for (i = 0; i < MAX_DEVICES; i++) {
+            animCurState[i].pCursor = 0;
+            animCurState[i].pScreen = 0;
+            animCurState[i].elt = 0;
+            animCurState[i].time = 0;
+        }
     }
     as = (AnimCurScreenPtr) xalloc (sizeof (AnimCurScreenRec));
     if (!as)
commit 676188531b2bd7679ee1831b5c517df3e6d215c5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Apr 4 17:35:06 2007 +0930

    Unrealize cursor only once, not per device.

diff --git a/dix/cursor.c b/dix/cursor.c
index 5886422..709c71d 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -123,11 +123,7 @@ FreeCursor(pointer value, XID cid)
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
 	pscr = screenInfo.screens[nscr];
-        for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
-        {
-            if (DevHasCursor(pDev))
-                (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
-        }
+        (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
     }
     FreeCursorBits(pCurs->bits);
     xfree( pCurs);
commit 207f710d16337839c2427aa16fad70a49834153e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 3 19:02:14 2007 +0930

    Delete all grabs from all devices when deleting a window.

diff --git a/dix/events.c b/dix/events.c
index 03d82e9..94e60dc 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4637,7 +4637,7 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
     WindowPtr		parent;
     DeviceIntPtr	mouse = inputInfo.pointer;
     DeviceIntPtr	keybd = inputInfo.keyboard;
-    FocusClassPtr	focus = keybd->focus;
+    FocusClassPtr	focus;
     OtherClientsPtr	oc;
     GrabPtr		passive;
     GrabPtr             grab; 
@@ -4650,62 +4650,82 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
 	((grab->window == pWin) || (grab->confineTo == pWin)))
 	(*mouse->coreGrab.DeactivateGrab)(mouse);
 
-    /* Deactivating a keyboard grab should cause focus events. */
 
+    /* Deactivating a keyboard grab should cause focus events. */
     grab = keybd->coreGrab.grab;
     if (grab && (grab->window == pWin))
 	(*keybd->coreGrab.DeactivateGrab)(keybd);
 
-    /* If the focus window is a root window (ie. has no parent) then don't 
-	delete the focus from it. */
-    
-    if ((pWin == focus->win) && (pWin->parent != NullWindow))
+    /* And now the real devices */
+    for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
     {
-	int focusEventMode = NotifyNormal;
+        grab = mouse->coreGrab.grab;
+        if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
+            (*mouse->coreGrab.DeactivateGrab)(mouse);
+    }
 
- 	/* If a grab is in progress, then alter the mode of focus events. */
 
-	if (keybd->coreGrab.grab)
-	    focusEventMode = NotifyWhileGrabbed;
+    for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
+    {
+        if (IsKeyboardDevice(keybd))
+        {
+            focus = keybd->focus;
 
-	switch (focus->revert)
-	{
-	case RevertToNone:
-	    DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
-	    focus->win = NoneWin;
-	    focus->traceGood = 0;
-	    break;
-	case RevertToParent:
-	    parent = pWin;
-	    do
-	    {
-		parent = parent->parent;
-		focus->traceGood--;
-	    } while (!parent->realized
-/* This would be a good protocol change -- windows being reparented
-   during SaveSet processing would cause the focus to revert to the
-   nearest enclosing window which will survive the death of the exiting
-   client, instead of ending up reverting to a dying window and thence
-   to None
- */
+            /* If the focus window is a root window (ie. has no parent) then don't 
+               delete the focus from it. */
+
+            if ((pWin == focus->win) && (pWin->parent != NullWindow))
+            {
+                int focusEventMode = NotifyNormal;
+
+                /* If a grab is in progress, then alter the mode of focus events. */
+
+                if (keybd->coreGrab.grab)
+                    focusEventMode = NotifyWhileGrabbed;
+
+                switch (focus->revert)
+                {
+                    case RevertToNone:
+                        DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
+                        focus->win = NoneWin;
+                        focus->traceGood = 0;
+                        break;
+                    case RevertToParent:
+                        parent = pWin;
+                        do
+                        {
+                            parent = parent->parent;
+                            focus->traceGood--;
+                        } while (!parent->realized
+                                /* This would be a good protocol change -- windows being reparented
+                                   during SaveSet processing would cause the focus to revert to the
+                                   nearest enclosing window which will survive the death of the exiting
+                                   client, instead of ending up reverting to a dying window and thence
+                                   to None
+                                 */
 #ifdef NOTDEF
- 	      || clients[CLIENT_ID(parent->drawable.id)]->clientGone
+                                || clients[CLIENT_ID(parent->drawable.id)]->clientGone
 #endif
-		);
-	    DoFocusEvents(keybd, pWin, parent, focusEventMode);
-	    focus->win = parent;
-	    focus->revert = RevertToNone;
-	    break;
-	case RevertToPointerRoot:
-	    DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
-	    focus->win = PointerRootWin;
-	    focus->traceGood = 0;
-	    break;
-	}
-    }
+                                );
+                        DoFocusEvents(keybd, pWin, parent, focusEventMode);
+                        focus->win = parent;
+                        focus->revert = RevertToNone;
+                        break;
+                    case RevertToPointerRoot:
+                        DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
+                        focus->win = PointerRootWin;
+                        focus->traceGood = 0;
+                        break;
+                }
+            }
+        }
 
-    if (mouse->valuator->motionHintWindow == pWin)
-	mouse->valuator->motionHintWindow = NullWindow;
+        if (IsPointerDevice(keybd))
+        {
+            if (keybd->valuator->motionHintWindow == pWin)
+                keybd->valuator->motionHintWindow = NullWindow;
+        }
+    }
 
     if (freeResources)
     {
commit 5f382c9c7fbda6eccf8e76c28a90b55ff2f0aef3
Merge: 9b0b340... f09ee16...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 3 15:07:18 2007 +0930

    Merge branch 'master' into mpx

commit f09ee168e234d0a9416e15f2916726b975cad293
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 3 15:07:00 2007 +0930

    Revert "o fix minor error in comment for GetPointerEvents()"
    
    This reverts commit 96ce17aa94413c4b8bcb61cae71167050130a307.

diff --git a/dix/getevents.c b/dix/getevents.c
index 219d1a1..3f636bc 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -470,7 +470,7 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
 
 
 /**
- * Generate a series of xEvents (returned in events) representing pointer
+ * Generate a series of xEvents (returned in xE) representing pointer
  * motion, or button presses.  Xi and XKB-aware.
  *
  * events is not NULL-terminated; the return value is the number of events.
commit 9b0b3406682b5a3161e6c3895771523214c37207
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Apr 3 15:06:26 2007 +0930

    Make GrabDevice differ between core grabs and device grabs.

diff --git a/Xi/grabdev.c b/Xi/grabdev.c
index e2809ef..143b98c 100644
--- a/Xi/grabdev.c
+++ b/Xi/grabdev.c
@@ -141,7 +141,7 @@ ProcXGrabDevice(ClientPtr client)
     error = GrabDevice(client, dev, stuff->this_device_mode,
 		       stuff->other_devices_mode, stuff->grabWindow,
 		       stuff->ownerEvents, stuff->time,
-		       tmp[stuff->deviceid].mask, &rep.status);
+		       tmp[stuff->deviceid].mask, &rep.status, FALSE);
 
     if (error != Success) {
 	SendErrorToClient(client, IReqCode, X_GrabDevice, 0, error);
diff --git a/dix/events.c b/dix/events.c
index de8ff9b..03d82e9 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4110,12 +4110,14 @@ ProcUngrabPointer(ClientPtr client)
 int
 GrabDevice(ClientPtr client, DeviceIntPtr dev, 
            unsigned this_mode, unsigned other_mode, Window grabWindow, 
-           unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status)
+           unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status,
+           Bool coreGrab)
 {
     WindowPtr pWin;
     GrabPtr grab;
     TimeStamp time;
     int rc;
+    GrabInfoPtr grabInfo = (coreGrab) ? &dev->coreGrab : &dev->deviceGrab;
 
     UpdateCurrentTime();
     if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
@@ -4137,16 +4139,16 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
     if (rc != Success)
 	return rc;
     time = ClientTimeToServerTime(ctime);
-    grab = dev->coreGrab.grab;
+    grab = grabInfo->grab;
     if (grab && !SameClient(grab, client))
 	*status = AlreadyGrabbed;
     else if (!pWin->realized)
 	*status = GrabNotViewable;
     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
-	     (CompareTimeStamps(time, dev->coreGrab.grabTime) == EARLIER))
+	     (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
 	*status = GrabInvalidTime;
-    else if (dev->coreGrab.sync.frozen &&
-	     dev->coreGrab.sync.other && !SameClient(dev->coreGrab.sync.other, client))
+    else if (grabInfo->sync.frozen &&
+	     grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
 	*status = GrabFrozen;
     else
     {
@@ -4164,7 +4166,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
 	tempGrab.device = dev;
         tempGrab.cursor = NULL;
 
-	(*dev->coreGrab.ActivateGrab)(dev, &tempGrab, time, FALSE);
+	(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
 	*status = GrabSuccess;
     }
     return Success;
@@ -4184,7 +4186,7 @@ ProcGrabKeyboard(ClientPtr client)
 	result = GrabDevice(client, keyboard, stuff->keyboardMode,
 			    stuff->pointerMode, stuff->grabWindow,
 			    stuff->ownerEvents, stuff->time,
-			    KeyPressMask | KeyReleaseMask, &rep.status);
+			    KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
     else {
 	result = Success;
 	rep.status = AlreadyGrabbed;
diff --git a/include/dix.h b/include/dix.h
index 2ad6c77..1b112a1 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -485,7 +485,8 @@ extern int GrabDevice(
     unsigned /* ownerEvents */,
     Time /* ctime */,
     Mask /* mask */,
-    CARD8 * /* status */);
+    CARD8 * /* status */,
+    Bool /* coreGrab */);
 
 extern void InitEvents(void);
 extern void InitSprite(
commit e8777a91f37d828b9df839bf3d9cf2f954bdddb0
Merge: a120547... 96ce17a...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 2 15:36:26 2007 +0930

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	Xi/closedev.c
    	Xi/exevents.c
    	Xi/extinit.c
    	Xi/listdev.c
    	dix/window.c
    	hw/xfree86/common/xf86Xinput.c
    	include/extinit.h
    	mi/mipointer.c

diff --cc Xi/chdevcur.c
index fc4b0e0,0000000..e69a266
mode 100644,000000..100644
--- a/Xi/chdevcur.c
+++ b/Xi/chdevcur.c
@@@ -1,123 -1,0 +1,123 @@@
 +/*
 +
 +Copyright 2006 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 change a given device pointer's cursor.
 + *
 + */
 +
 +#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 "chdevcur.h"
 +
 +/***********************************************************************
 + *
 + * This procedure allows a client to set one pointer's cursor.
 + *
 + */
 +
 +int
- SProcXChangeDeviceCursor(register ClientPtr client)
++SProcXChangeDeviceCursor(ClientPtr client)
 +{
-     register char n;
++    char n;
 +
 +    REQUEST(xChangeDeviceCursorReq);
 +    swaps(&stuff->length, n);
 +    REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
 +    return (ProcXChangeDeviceCursor(client));
 +}
 +
- int ProcXChangeDeviceCursor(register ClientPtr client)
++int ProcXChangeDeviceCursor(ClientPtr client)
 +{
 +    int err;
 +    WindowPtr pWin    = NULL;
 +    DeviceIntPtr pDev = NULL;
 +    CursorPtr pCursor = NULL;
 +
 +    REQUEST(xChangeDeviceCursorReq);
 +    REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
 +
 +    pDev = LookupDeviceIntRec(stuff->deviceid);
 +    if (pDev == NULL) {
 +        SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 0,
 +                BadDevice); 
 +        return Success;
 +    }
 +
 +    if (stuff->win != None)
 +    {
 +        err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
 +        if (err != Success)
 +        {
 +            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 
 +                    stuff->win, err);
 +            return Success;
 +        }
 +    }
 +
 +    if (stuff->cursor == None)
 +    {
 +        if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
 +            pCursor = rootCursor;
 +        else
 +            pCursor = (CursorPtr)None;
 +    } 
 +    else 
 +    {
 +        pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
 +                                RT_CURSOR, DixReadAccess); 
 +        if (!pCursor)
 +        {
 +            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 
 +                    stuff->cursor, BadCursor);
 +            return Success;
 +        }
 +    } 
 +
 +    ChangeWindowDeviceCursor(pWin, pDev, pCursor);
 +
 +    return Success;
 +}
 +
diff --cc Xi/chpkpair.c
index 8e79a75,0000000..fcbdcdf
mode 100644,000000..100644
--- a/Xi/chpkpair.c
+++ b/Xi/chpkpair.c
@@@ -1,110 -1,0 +1,110 @@@
 +/*
 +
 +Copyright 2006 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 change pairing between pointer and keyboard 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 "chpkpair.h"
 +
 +/***********************************************************************
 + *
 + * This procedure allows a client to change the pairing of a pointer with a
 + * a keyboard.
 + *
 + */
 +
- int SProcXChangePointerKeyboardPairing(register ClientPtr client)
++int SProcXChangePointerKeyboardPairing(ClientPtr client)
 +{
-     register char n;
++    char n;
 +
 +    REQUEST(xChangePointerKeyboardPairingReq);
 +    swaps(&stuff->length, n);
 +    return (ProcXChangePointerKeyboardPairing(client));
 +}
 +
 +int
- ProcXChangePointerKeyboardPairing(register ClientPtr client)
++ProcXChangePointerKeyboardPairing(ClientPtr client)
 +{
 +    DeviceIntPtr pPointer, pKeyboard;
 +    int ret;
 +
 +    REQUEST(xChangePointerKeyboardPairingReq);
 +    REQUEST_SIZE_MATCH(xChangePointerKeyboardPairingReq);
 +
 +    /* check if client is registered */
 +
 +    pPointer = LookupDeviceIntRec(stuff->pointer);
 +    if (pPointer == NULL)
 +    {
 +        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing, 
 +                stuff->pointer, BadDevice); 
 +        return Success;
 +    }
 +
 +    pKeyboard = LookupDeviceIntRec(stuff->keyboard);
 +    if (pKeyboard == NULL)
 +    {
 +        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing, 
 +                stuff->keyboard, BadDevice); 
 +        return Success;
 +    }
 +
 +    ret = PairDevices(client, pPointer, pKeyboard);
 +    if (ret != Success)
 +    {
 +        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing,
 +                0, ret);
 +        return Success;
 +    }
 +
 +
 +    /* TODO: generate event here... */
 +    return Success;
 +}
diff --cc Xi/closedev.c
index 7bdd373,8d38ec8..8aebe10
--- a/Xi/closedev.c
+++ b/Xi/closedev.c
@@@ -154,22 -140,36 +140,36 @@@ DeleteEventsFromChildren(DeviceIntPtr d
   *
   */
  
- void
- DeleteDeviceEvents(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
+ int
+ ProcXCloseDevice(ClientPtr client)
  {
-     InputClientsPtr others;
-     OtherInputMasks *pOthers;
-     GrabPtr grab, next;
+     int i;
+     WindowPtr pWin, p1;
+     DeviceIntPtr d;
  
-     if ((pOthers = wOtherInputMasks(pWin)) != 0)
- 	for (others = pOthers->inputClients; others; others = others->next)
- 	    if (SameClient(others, client))
- 		others->mask[dev->id] = NoEventMask;
+     REQUEST(xCloseDeviceReq);
+     REQUEST_SIZE_MATCH(xCloseDeviceReq);
  
-     for (grab = wPassiveGrabs(pWin); grab; grab = next) {
- 	next = grab->next;
- 	if ((grab->device == dev) &&
- 	    (client->clientAsMask == CLIENT_BITS(grab->resource)))
- 	    FreeResource(grab->resource, RT_NONE);
+     d = LookupDeviceIntRec(stuff->deviceid);
+     if (d == NULL) {
+ 	SendErrorToClient(client, IReqCode, X_CloseDevice, 0, BadDevice);
+ 	return Success;
      }
+ 
 -    if (d->grab && SameClient(d->grab, client))
 -	(*d->DeactivateGrab) (d);	/* release active grab */
++    if (d->deviceGrab.grab && SameClient(d->deviceGrab.grab, client))
++	(*d->deviceGrab.DeactivateGrab) (d);	/* release active grab */
+ 
+     /* Remove event selections from all windows for events from this device 
+      * and selected by this client.
+      * Delete passive grabs from all windows for this device.      */
+ 
+     for (i = 0; i < screenInfo.numScreens; i++) {
+ 	pWin = WindowTable[i];
+ 	DeleteDeviceEvents(d, pWin, client);
+ 	p1 = pWin->firstChild;
+ 	DeleteEventsFromChildren(d, p1, client);
+     }
+ 
+     CloseInputDevice(d, client);
+     return Success;
  }
diff --cc Xi/exevents.c
index 3e3f15a,9e71a9e..26f3640
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@@ -1185,10 -1154,10 +1185,10 @@@ DeviceEventMaskForClient(DeviceIntPtr d
  }
  
  void
- MaybeStopDeviceHint(register DeviceIntPtr dev, ClientPtr client)
+ MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
  {
      WindowPtr pWin;
 -    GrabPtr grab = dev->grab;
 +    GrabPtr grab = dev->deviceGrab.grab;
  
      pWin = dev->valuator->motionHintWindow;
  
diff --cc Xi/extinit.c
index 971617e,b1ec321..9d921fa
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@@ -741,41 -555,99 +632,137 @@@ SDevicePresenceNotifyEvent (devicePrese
      swaps(&to->control, n);
  }
  
- void SDeviceEnterNotifyEvent (deviceEnterNotify *from, deviceEnterNotify *to)
++static void 
++SDeviceEnterNotifyEvent (deviceEnterNotify *from, deviceEnterNotify *to)
 +{
-     register char n;
++    char n;
 +
 +    *to = *from;
 +    swaps(&to->sequenceNumber,n);
 +    swapl(&to->time, n);
 +}
 +
- void SDeviceLeaveNotifyEvent (deviceLeaveNotify *from, deviceLeaveNotify *to)
++static void 
++SDeviceLeaveNotifyEvent (deviceLeaveNotify *from, deviceLeaveNotify *to)
 +{
-     register char n;
++    char n;
 +
 +    *to = *from;
 +    swaps(&to->sequenceNumber,n);
 +    swapl(&to->time, n);
 +    swapl(&to->root, n);
 +    swapl(&to->event, n);
 +    swapl(&to->child, n);
 +    swaps(&to->rootX, n);
 +    swaps(&to->rootY, n);
 +    swaps(&to->eventX, n);
 +    swaps(&to->eventY, n);
 +}
 +
- void SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify *from, 
++static void 
++SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify *from, 
 +                                                pairingChangedNotify *to)
 +{
-     register char n;
++    char n;
 +
 +    *to = *from;
 +    swaps(&to->sequenceNumber, n);
 +    swapl(&to->time, n);
 +}
 +
+ /**************************************************************************
+  *
+  * Allow the specified event to have its propagation suppressed.
+  * The default is to not allow suppression of propagation.
+  *
+  */
+ 
+ static void
+ AllowPropagateSuppress(Mask mask)
+ {
+     int i;
+ 
+     for (i = 0; i < MAX_DEVICES; i++)
+ 	PropagateMask[i] |= mask;
+ }
+ 
+ /**************************************************************************
+  *
+  * Return the next available extension event mask.
+  *
+  */
+ 
+ static Mask
+ GetNextExtEventMask(void)
+ {
+     int i;
+     Mask mask = lastExtEventMask;
+ 
+     if (lastExtEventMask == 0) {
+ 	FatalError("GetNextExtEventMask: no more events are available.");
+     }
+     lastExtEventMask <<= 1;
+ 
+     for (i = 0; i < MAX_DEVICES; i++)
+ 	ExtValidMasks[i] |= mask;
+     return mask;
+ }
+ 
+ /**************************************************************************
+  *
+  * Record an event mask where there is no unique corresponding event type.
+  * We can't call SetMaskForEvent, since that would clobber the existing
+  * mask for that event.  MotionHint and ButtonMotion are examples.
+  *
+  * Since extension event types will never be less than 64, we can use
+  * 0-63 in the EventInfo array as the "type" to be used to look up this
+  * mask.  This means that the corresponding macros such as 
+  * DevicePointerMotionHint must have access to the same constants.
+  *
+  */
+ 
+ static void
+ SetEventInfo(Mask mask, int constant)
+ {
+     EventInfo[ExtEventIndex].mask = mask;
+     EventInfo[ExtEventIndex++].type = constant;
+ }
+ 
+ /**************************************************************************
+  *
+  * Allow the specified event to be restricted to being selected by one
+  * client at a time.
+  * The default is to allow more than one client to select the event.
+  *
+  */
+ 
+ static void
+ SetExclusiveAccess(Mask mask)
+ {
+     int i;
+ 
+     for (i = 0; i < MAX_DEVICES; i++)
+ 	ExtExclusiveMasks[i] |= mask;
+ }
+ 
+ /**************************************************************************
+  *
+  * Assign the specified mask to the specified event.
+  *
+  */
+ 
+ static void
+ SetMaskForExtEvent(Mask mask, int event)
+ {
+ 
+     EventInfo[ExtEventIndex].mask = mask;
+     EventInfo[ExtEventIndex++].type = event;
+ 
+     if ((event < LASTEvent) || (event >= 128))
+ 	FatalError("MaskForExtensionEvent: bogus event number");
+     SetMaskForEvent(mask, event);
+ }
+ 
  /************************************************************************
   *
   * This function sets up extension event types and masks.
@@@ -983,22 -832,6 +970,22 @@@ IResetProc(ExtensionEntry * unused
      RestoreExtensionEvents();
  }
  
 +/*****************************************************************
 + *
 + * Returns TRUE if the device has some sort of pointer type.
 + *
 + */
 +
- Bool
++_X_EXPORT Bool
 +DeviceIsPointerType(DeviceIntPtr dev)
 +{
 +    if (dev_type[1].type == dev->type)
 +        return TRUE;
 +
 +    return FALSE;
 +}
 +
 +
  /***********************************************************************
   *
   * Assign an id and type to an input device.
@@@ -1052,95 -885,102 +1039,113 @@@ LookupDeviceIntRec(CARD8 id
      return NULL;
  }
  
- /**************************************************************************
-  *
-  * Allow the specified event to be restricted to being selected by one
-  * client at a time.
-  * The default is to allow more than one client to select the event.
-  *
-  */
- 
- void
- SetExclusiveAccess(Mask mask)
- {
-     int i;
- 
-     for (i = 0; i < MAX_DEVICES; i++)
- 	ExtExclusiveMasks[i] |= mask;
- }
- 
- /**************************************************************************
-  *
-  * Allow the specified event to have its propagation suppressed.
-  * The default is to not allow suppression of propagation.
-  *
-  */
- 
- void
- AllowPropagateSuppress(Mask mask)
- {
-     int i;
- 
-     for (i = 0; i < MAX_DEVICES; i++)
- 	PropagateMask[i] |= mask;
- }
- 
- /**************************************************************************
+ /*****************************************************************************
   *
-  * Return the next available extension event mask.
+  *	SEventIDispatch
   *
+  *	Swap any events defined in this extension.
   */
+ #define DO_SWAP(func,type) func ((type *)from, (type *)to)
  
- Mask
- GetNextExtEventMask(void)
+ static void
+ SEventIDispatch(xEvent * from, xEvent * to)
  {
-     int i;
-     Mask mask = lastExtEventMask;
+     int type = from->u.u.type & 0177;
  
-     if (lastExtEventMask == 0) {
- 	FatalError("GetNextExtEventMask: no more events are available.");
+     if (type == DeviceValuator)
+ 	DO_SWAP(SEventDeviceValuator, deviceValuator);
+     else if (type == DeviceKeyPress) {
+ 	SKeyButtonPtrEvent(from, to);
+ 	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+     } else if (type == DeviceKeyRelease) {
+ 	SKeyButtonPtrEvent(from, to);
+ 	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+     } else if (type == DeviceButtonPress) {
+ 	SKeyButtonPtrEvent(from, to);
+ 	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+     } else if (type == DeviceButtonRelease) {
+ 	SKeyButtonPtrEvent(from, to);
+ 	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+     } else if (type == DeviceMotionNotify) {
+ 	SKeyButtonPtrEvent(from, to);
+ 	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+     } else if (type == DeviceFocusIn)
+ 	DO_SWAP(SEventFocus, deviceFocus);
+     else if (type == DeviceFocusOut)
+ 	DO_SWAP(SEventFocus, deviceFocus);
+     else if (type == ProximityIn) {
+ 	SKeyButtonPtrEvent(from, to);
+ 	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+     } else if (type == ProximityOut) {
+ 	SKeyButtonPtrEvent(from, to);
+ 	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+     } else if (type == DeviceStateNotify)
+ 	DO_SWAP(SDeviceStateNotifyEvent, deviceStateNotify);
+     else if (type == DeviceKeyStateNotify)
+ 	DO_SWAP(SDeviceKeyStateNotifyEvent, deviceKeyStateNotify);
+     else if (type == DeviceButtonStateNotify)
+ 	DO_SWAP(SDeviceButtonStateNotifyEvent, deviceButtonStateNotify);
+     else if (type == DeviceMappingNotify)
+ 	DO_SWAP(SDeviceMappingNotifyEvent, deviceMappingNotify);
+     else if (type == ChangeDeviceNotify)
+ 	DO_SWAP(SChangeDeviceNotifyEvent, changeDeviceNotify);
++    else if (type == DevicePresenceNotify)
++	DO_SWAP(SDevicePresenceNotifyEvent, devicePresenceNotify);
++    else if (type == DeviceEnterNotify)
++        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");
      }
-     lastExtEventMask <<= 1;
- 
-     for (i = 0; i < MAX_DEVICES; i++)
- 	ExtValidMasks[i] |= mask;
-     return mask;
  }
  
- /**************************************************************************
-  *
-  * Assign the specified mask to the specified event.
+ /**********************************************************************
   *
-  */
- 
- void
- SetMaskForExtEvent(Mask mask, int event)
- {
- 
-     EventInfo[ExtEventIndex].mask = mask;
-     EventInfo[ExtEventIndex++].type = event;
- 
-     if ((event < LASTEvent) || (event >= 128))
- 	FatalError("MaskForExtensionEvent: bogus event number");
-     SetMaskForEvent(mask, event);
- }
- 
- /**************************************************************************
+  * IExtensionInit - initialize the input extension.
   *
-  * Record an event mask where there is no unique corresponding event type.
-  * We can't call SetMaskForEvent, since that would clobber the existing
-  * mask for that event.  MotionHint and ButtonMotion are examples.
+  * Called from InitExtensions in main() or from QueryExtension() if the
+  * extension is dynamically loaded.
   *
-  * Since extension event types will never be less than 64, we can use
-  * 0-63 in the EventInfo array as the "type" to be used to look up this
-  * mask.  This means that the corresponding macros such as 
-  * DevicePointerMotionHint must have access to the same constants.
+  * This extension has several events and errors.
   *
   */
  
  void
- SetEventInfo(Mask mask, int constant)
+ XInputExtensionInit(void)
  {
-     EventInfo[ExtEventIndex].mask = mask;
-     EventInfo[ExtEventIndex++].type = constant;
+     ExtensionEntry *extEntry;
+ 
+     extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
+ 			    SProcIDispatch, IResetProc, StandardMinorOpcode);
+     if (extEntry) {
+ 	IReqCode = extEntry->base;
+ 	AllExtensionVersions[IReqCode - 128] = thisversion;
+ 	MakeDeviceTypeAtoms();
+ 	RT_INPUTCLIENT = CreateNewResourceType((DeleteType) InputClientGone);
+ 	FixExtensionEvents(extEntry);
+ 	ReplySwapVector[IReqCode] = (ReplySwapPtr) SReplyIDispatch;
+ 	EventSwapVector[DeviceValuator] = SEventIDispatch;
+ 	EventSwapVector[DeviceKeyPress] = SEventIDispatch;
+ 	EventSwapVector[DeviceKeyRelease] = SEventIDispatch;
+ 	EventSwapVector[DeviceButtonPress] = SEventIDispatch;
+ 	EventSwapVector[DeviceButtonRelease] = SEventIDispatch;
+ 	EventSwapVector[DeviceMotionNotify] = SEventIDispatch;
+ 	EventSwapVector[DeviceFocusIn] = SEventIDispatch;
+ 	EventSwapVector[DeviceFocusOut] = SEventIDispatch;
+ 	EventSwapVector[ProximityIn] = SEventIDispatch;
+ 	EventSwapVector[ProximityOut] = SEventIDispatch;
+ 	EventSwapVector[DeviceStateNotify] = SEventIDispatch;
+ 	EventSwapVector[DeviceKeyStateNotify] = SEventIDispatch;
+ 	EventSwapVector[DeviceButtonStateNotify] = SEventIDispatch;
+ 	EventSwapVector[DeviceMappingNotify] = SEventIDispatch;
+ 	EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
++	EventSwapVector[DeviceEnterNotify] = SEventIDispatch;
++	EventSwapVector[DeviceLeaveNotify] = SEventIDispatch;
++	EventSwapVector[PointerKeyboardPairingChangedNotify] = SEventIDispatch;
+     } else {
+ 	FatalError("IExtensionInit: AddExtensions failed\n");
+     }
  }
diff --cc Xi/grabacc.c
index db9c9f2,0000000..59888ee
mode 100644,000000..100644
--- a/Xi/grabacc.c
+++ b/Xi/grabacc.c
@@@ -1,102 -1,0 +1,102 @@@
 +/*
 +
 +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/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 "grabacc.h"
 +
 +/***********************************************************************
 + *
 + * This procedure allows a client to register as the global client to control
 + * any window access.
 + *
 + */
 +int
 +SProcXGrabAccessControl(ClientPtr client)
 +{
 +    char n;
 +    REQUEST(xGrabAccessControlReq);
 +
 +    swaps(&stuff->length, n);
 +    return ProcXGrabAccessControl(client);
 +}
 +
 +int 
 +ProcXGrabAccessControl(ClientPtr client)
 +{
 +    xGrabAccessControlReply rep;
 +    REQUEST(xGrabAccessControlReq);
 +    REQUEST_SIZE_MATCH(xGrabAccessControlReq);
 +
 +    if (stuff->ungrab)
 +        ACUnregisterClient(client);
 +
 +    rep.repType = X_Reply;
 +    rep.RepType = X_GrabAccessControl;
 +    rep.length = 0;
 +    rep.sequenceNumber = client->sequence;
 +    rep.success = stuff->ungrab || ACRegisterClient(client);
 +
 +    WriteReplyToClient(client, sizeof(xGrabAccessControlReply), &rep);
 +    return Success;
 +}
 +
 +/***********************************************************************
 + *
 + * This procedure writes the reply for the XGrabAccessControl function,
 + * if the client and server have a different byte ordering.
 + *
 + */
 +
 +void
 +SRepXGrabAccessControl(ClientPtr client, int size, 
 +        xGrabAccessControlReply* rep)
 +{
-     register char n;
++    char n;
 +
 +    swaps(&rep->sequenceNumber, n);
 +    swapl(&rep->length, n);
 +    WriteToClient(client, size, (char *)rep);
 +}
 +
diff --cc Xi/listdev.c
index 33266ae,160ad02..a9fd401
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@@ -368,6 -274,91 +274,100 @@@ CopySwapValuatorClass(ClientPtr client
  
  /***********************************************************************
   *
+  * This procedure lists information to be returned for an input device.
+  *
+  */
+ 
+ static void
+ ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev,
+ 	       char **devbuf, char **classbuf, char **namebuf)
+ {
+     CopyDeviceName(namebuf, d->name);
+     CopySwapDevice(client, d, 0, devbuf);
+     if (d->key != NULL) {
+ 	CopySwapKeyClass(client, d->key, classbuf);
+ 	dev->num_classes++;
+     }
+     if (d->button != NULL) {
+ 	CopySwapButtonClass(client, d->button, classbuf);
+ 	dev->num_classes++;
+     }
+     if (d->valuator != NULL) {
+ 	dev->num_classes +=
+ 	    CopySwapValuatorClass(client, d->valuator, classbuf);
+     }
+ }
+ 
+ /***********************************************************************
+  *
+  * This procedure lists the input devices available to the server.
+  *
+  */
+ 
+ int
+ ProcXListInputDevices(ClientPtr client)
+ {
+     xListInputDevicesReply rep;
+     int numdevs = 0;
+     int namesize = 1;	/* need 1 extra byte for strcpy */
+     int size = 0;
+     int total_length;
+     char *devbuf;
+     char *classbuf;
+     char *namebuf;
+     char *savbuf;
+     xDeviceInfo *dev;
+     DeviceIntPtr d;
+ 
+     REQUEST_SIZE_MATCH(xListInputDevicesReq);
+ 
+     rep.repType = X_Reply;
+     rep.RepType = X_ListInputDevices;
+     rep.length = 0;
+     rep.sequenceNumber = client->sequence;
+ 
+     AddOtherInputDevices();
+ 
++    SizeDeviceInfo(inputInfo.keyboard, &namesize, &size);
++    SizeDeviceInfo(inputInfo.pointer, &namesize, &size);
++    numdevs = 2;
++
+     for (d = inputInfo.devices; d; d = d->next) {
+ 	SizeDeviceInfo(d, &namesize, &size);
+         numdevs++;
+     }
+     for (d = inputInfo.off_devices; d; d = d->next) {
+ 	SizeDeviceInfo(d, &namesize, &size);
+         numdevs++;
+     }
+ 
+     total_length = numdevs * sizeof(xDeviceInfo) + size + namesize;
+     devbuf = (char *)xalloc(total_length);
+     classbuf = devbuf + (numdevs * sizeof(xDeviceInfo));
+     namebuf = classbuf + size;
+     savbuf = devbuf;
+ 
+     dev = (xDeviceInfoPtr) devbuf;
++    ListDeviceInfo(client, inputInfo.keyboard, dev++, 
++                   &devbuf, &classbuf, &namebuf);
++    ListDeviceInfo(client, inputInfo.pointer, dev++,
++                   &devbuf, &classbuf, &namebuf);
++
+     for (d = inputInfo.devices; d; d = d->next, dev++)
+ 	ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
+     for (d = inputInfo.off_devices; d; d = d->next, dev++)
+ 	ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
+ 
+     rep.ndevices = numdevs;
+     rep.length = (total_length + 3) >> 2;
+     WriteReplyToClient(client, sizeof(xListInputDevicesReply), &rep);
+     WriteToClient(client, total_length, savbuf);
+     xfree(savbuf);
+     return Success;
+ }
+ 
+ /***********************************************************************
+  *
   * This procedure writes the reply for the XListInputDevices function,
   * if the client and server have a different byte ordering.
   *
diff --cc Xi/querydp.c
index af93fed,0000000..d2ed0b8
mode 100644,000000..100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@@ -1,167 -1,0 +1,167 @@@
 +/*
 +
 +Copyright 2006 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 query the pointer location of an extension input 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 <X11/extensions/XI.h>
 +#include <X11/extensions/XIproto.h>
 +#include "extnsionst.h"
 +#include "extinit.h"	/* LookupDeviceIntRec */
 +#include "exevents.h"
 +#include "exglobals.h"
 +
 +#ifdef PANORAMIX
 +#include "panoramiXsrv.h"
 +#endif
 +
 +#include "querydp.h"
 +
 +/***********************************************************************
 + *
 + * This procedure allows a client to query the pointer of a device.
 + *
 + */
 +
 +int
- SProcXQueryDevicePointer(register ClientPtr client)
++SProcXQueryDevicePointer(ClientPtr client)
 +{
-     register char n;
++    char n;
 +
 +    REQUEST(xQueryDevicePointerReq);
 +    swaps(&stuff->length, n);
 +    return (ProcXQueryDevicePointer(client));
 +}
 +
 +int
- ProcXQueryDevicePointer(register ClientPtr client)
++ProcXQueryDevicePointer(ClientPtr client)
 +{
 +    int rc;
 +    xQueryDevicePointerReply rep;
 +    DeviceIntPtr pDev;
 +    WindowPtr pWin, t;
 +    SpritePtr pSprite;
 +
 +    REQUEST(xQueryDevicePointerReq);
 +    REQUEST_SIZE_MATCH(xQueryDevicePointerReq);
 +
 +    pDev = LookupDeviceIntRec(stuff->deviceid);
 +    if (pDev == NULL || pDev->valuator == NULL) {
 +        SendErrorToClient(client, IReqCode, X_QueryDevicePointer,
 +                stuff->deviceid, BadDevice); 
 +        return Success;
 +    }
 +
 +    rc = dixLookupWindow(&pWin, stuff->win, client, DixReadAccess);
 +    if (rc != Success)
 +    {
 +        SendErrorToClient(client, IReqCode, X_QueryDevicePointer, 
 +                stuff->win, rc);
 +        return Success;
 +    }
 +
 +    if (pDev->valuator->motionHintWindow)
 +        MaybeStopHint(pDev, client);
 +
 +    pSprite = pDev->spriteInfo->sprite;
 +    rep.repType = X_Reply;
 +    rep.RepType = X_QueryDevicePointer;
 +    rep.length = 0;
 +    rep.sequenceNumber = client->sequence;
 +    rep.mask = pDev->button->state | inputInfo.keyboard->key->state;
 +    rep.root = (GetCurrentRootWindow())->drawable.id;
 +    rep.rootX = pSprite->hot.x;
 +    rep.rootY = pSprite->hot.y;
 +    rep.child = None;
 +    rep.shared = (pDev->spriteInfo->spriteOwner) ? xFalse : xTrue; 
 +
 +    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
 +    {
 +        rep.sameScreen = xTrue;
 +        rep.winX = pSprite->hot.x - pWin->drawable.x;
 +        rep.winY = pSprite->hot.y - pWin->drawable.y;
 +        for (t = pSprite->win; t; t = t->parent)
 +            if (t->parent == pWin)
 +            {
 +                rep.child = t->drawable.id;
 +                break;
 +            }
 +    } else
 +    {
 +        rep.sameScreen = xFalse;
 +        rep.winX = 0;
 +        rep.winY = 0;
 +    }
 +
 +#ifdef PANORAMIX
 +    if(!noPanoramiXExtension) {
 +        rep.rootX += panoramiXdataPtr[0].x;
 +        rep.rootY += panoramiXdataPtr[0].y;
 +        if (stuff->win == rep.root)
 +        {
 +            rep.winX += panoramiXdataPtr[0].x;
 +            rep.winY += panoramiXdataPtr[0].y;
 +        }
 +    }
 +#endif
 +
 +    WriteReplyToClient(client, sizeof(xQueryDevicePointerReply), &rep);
 +    return Success;
 +}
 +
 +/***********************************************************************
 + *
 + * This procedure writes the reply for the XQueryDevicePointer function,
 + * if the client and server have a different byte ordering.
 + *
 + */
 +
 +void
 +SRepXQueryDevicePointer(ClientPtr client, int size, 
 +        xQueryDevicePointerReply * rep)
 +{
-     register char n;
++    char n;
 +
 +    swaps(&rep->sequenceNumber, n);
 +    swapl(&rep->length, n);
 +    WriteToClient(client, size, (char *)rep);
 +}
 +
diff --cc Xi/warpdevp.c
index 8df7e14,0000000..82d71d5
mode 100644,000000..100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@@ -1,187 -1,0 +1,187 @@@
 +/*
 +
 +Copyright 2006 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 Warp the pointer location of an extension input 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 "warpdevp.h"
 +/***********************************************************************
 + *
 + * This procedure allows a client to warp the pointer of a device.
 + *
 + */
 +
 +int
- SProcXWarpDevicePointer(register ClientPtr client)
++SProcXWarpDevicePointer(ClientPtr client)
 +{
-     register char n;
++    char n;
 +
 +    REQUEST(xWarpDevicePointerReq);
 +    swaps(&stuff->length, n);
 +    return (ProcXWarpDevicePointer(client));
 +}
 +
 +int
- ProcXWarpDevicePointer(register ClientPtr client)
++ProcXWarpDevicePointer(ClientPtr client)
 +{
 +    int err;
 +    int x, y;
 +    WindowPtr dest = NULL;
 +    DeviceIntPtr pDev;
 +    SpritePtr pSprite;
 +    ScreenPtr newScreen;
 +
 +    REQUEST(xWarpDevicePointerReq);
 +    REQUEST_SIZE_MATCH(xWarpDevicePointerReq);
 +
 +    /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */
 +
 +    pDev = LookupDeviceIntRec(stuff->deviceid);
 +    if (pDev == NULL) {
 +        SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
 +                stuff->deviceid,
 +                BadDevice); 
 +        return Success;
 +    }
 +
 +    if (stuff->dst_win != None)
 +    {
 +        err = dixLookupWindow(&dest, stuff->dst_win, client, DixReadAccess);
 +        if (err != Success)
 +        {
 +            SendErrorToClient(client, IReqCode, X_WarpDevicePointer, 
 +                    stuff->dst_win, err);
 +            return Success;
 +        }
 +    }
 +
 +    pSprite = pDev->spriteInfo->sprite;
 +    x = pSprite->hotPhys.x;
 +    y = pSprite->hotPhys.y;
 +
 +    if (stuff->src_win != None)
 +    {
 +        int winX, winY;
 +        WindowPtr src;
 +
 +        err = dixLookupWindow(&src, stuff->src_win, client, DixReadAccess);
 +        if (err != Success)
 +        {
 +            SendErrorToClient(client, IReqCode, X_WarpDevicePointer, 
 +                    stuff->src_win, err);
 +            return Success;
 +        }
 +
 +        winX = src->drawable.x;
 +        winY = src->drawable.y;
 +        if (src->drawable.pScreen != pSprite->hotPhys.pScreen || 
 +                x < winX + stuff->src_x ||
 +                y < winY + stuff->src_y ||
 +                (stuff->src_width != 0 &&
 +                 winX + stuff->src_x + (int)stuff->src_width < 0) ||
 +                (stuff->src_height != 0 &&
 +                 winY + stuff->src_y + (int)stuff->src_height < y) ||
 +                !PointInWindowIsVisible(src, x, y))
 +            return Success;
 +    }
 +
 +    if (dest)
 +    {
 +        x = dest->drawable.x;
 +        y = dest->drawable.y;
 +        newScreen = dest->drawable.pScreen;
 +    } else
 +        newScreen = pSprite->hotPhys.pScreen;
 +
 +    x += stuff->dst_x;
 +    y += stuff->dst_y;
 +
 +    if (x < 0)
 +        x = 0;
 +    else if (x > newScreen->width)
 +        x = newScreen->width - 1;
 +
 +    if (y < 0)
 +        y = 0;
 +    else if (y > newScreen->height)
 +        y = newScreen->height - 1;
 +
 +    if (newScreen == pSprite->hotPhys.pScreen)
 +    {
 +        if (x < pSprite->physLimits.x1)
 +            x = pSprite->physLimits.x1;
 +        else if (x >= pSprite->physLimits.x2)
 +            x = pSprite->physLimits.x2 - 1;
 +
 +        if (y < pSprite->physLimits.y1)
 +            y = pSprite->physLimits.y1;
 +        else if (y >= pSprite->physLimits.y2)
 +            y = pSprite->physLimits.y2 - 1;
 +
 +#if defined(SHAPE)
 +        if (pSprite->hotShape)
 +            ConfineToShape(pDev, pSprite->hotShape, &x, &y);
 +#endif
 +        (*newScreen->SetCursorPosition)(pDev, newScreen, x, y, TRUE);
 +    } else if (!PointerConfinedToScreen(pDev))
 +    {
 +        NewCurrentScreen(pDev, newScreen, x, y);
 +    }
 +
 +    /* if we don't update the device, we get a jump next time it moves */
 +    pDev->valuator->lastx = x;
 +    pDev->valuator->lasty = x;
 +    miPointerUpdateSprite(pDev);
 +
 +    /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
 +       here though. */
 +    return Success;
 +}
 +
diff --cc dix/devices.c
index 724ef98,f622be7..411188d
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -79,11 -79,9 +79,12 @@@ SOFTWARE
  #include "exglobals.h"
  #include "exevents.h"
  
- int CoreDevicePrivatesIndex = 0, CoreDevicePrivatesGeneration = -1;
+ int CoreDevicePrivatesIndex = 0;
+ static int CoreDevicePrivatesGeneration = -1;
  
 +/* The client that is allowed to change pointer-keyboard pairings. */
 +static ClientPtr pairingClient = NULL;
 +
  DeviceIntPtr
  AddInputDevice(DeviceProc deviceProc, Bool autoStart)
  {
diff --cc dix/window.c
index f0d4cf8,96002eb..4e55319
--- a/dix/window.c
+++ b/dix/window.c
@@@ -854,6 -832,26 +850,46 @@@ CreateWindow(Window wid, WindowPtr pPar
  }
  
  static void
+ DisposeWindowOptional (WindowPtr pWin)
+ {
+     if (!pWin->optional)
+ 	return;
+     /*
+      * everything is peachy.  Delete the optional record
+      * and clean up
+      */
+     if (pWin->optional->cursor)
+     {
+ 	FreeCursor (pWin->optional->cursor, (Cursor)0);
+ 	pWin->cursorIsNone = FALSE;
+     }
+     else
+ 	pWin->cursorIsNone = TRUE;
++
++    if (pWin->optional->deviceCursors)
++    {
++        DevCursorList pList;
++        DevCursorList pPrev;
++        pList = pWin->optional->deviceCursors;
++        while(pList)
++        {
++            if (pList->cursor)
++                FreeCursor(pList->cursor, (XID)0);
++            pPrev = pList;
++            pList = pList->next;
++            xfree(pPrev);
++        }
++        pWin->optional->deviceCursors = NULL;
++    }
++
++    xfree(pWin->optional->access.perm);
++    xfree(pWin->optional->access.deny);
++
+     xfree (pWin->optional);
+     pWin->optional = NULL;
+ }
+ 
+ static void
  FreeWindowResources(WindowPtr pWin)
  {
      ScreenPtr pScreen = pWin->drawable.pScreen;
@@@ -3738,270 -3701,6 +3759,216 @@@ MakeWindowOptional (WindowPtr pWin
      return TRUE;
  }
  
- void
- DisposeWindowOptional (WindowPtr pWin)
- {
-     if (!pWin->optional)
- 	return;
-     /*
-      * everything is peachy.  Delete the optional record
-      * and clean up
-      */
-     /*
-      * TOG changed this code to:
-      *
-      *	    if (pWin->cursorIsNone == FALSE)
-      *		FreeCursor (pWin->optional->cursor, (Cursor)0);
-      *	    pWin->cursorIsNone = TRUE;
-      *
-      * This is blatently wrong; windows without optionals can have
-      * two different cursor values, either None or sharing their
-      * parents cursor.  This difference is controlled by the
-      * cursorIsNone value; when TRUE, the window has no cursor,
-      * when false, it shares its cursor with its parent; TOG
-      * made it impossible for a window to have a cursor without
-      * an optional record.
-      */
-     if (pWin->optional->cursor)
-     {
- 	FreeCursor (pWin->optional->cursor, (Cursor)0);
- 	pWin->cursorIsNone = FALSE;
-     }
-     else
- 	pWin->cursorIsNone = TRUE;
- 
-     if (pWin->optional->deviceCursors)
-     {
-         DevCursorList pList;
-         DevCursorList pPrev;
-         pList = pWin->optional->deviceCursors;
-         while(pList)
-         {
-             if (pList->cursor)
-                 FreeCursor(pList->cursor, (XID)0);
-             pPrev = pList;
-             pList = pList->next;
-             xfree(pPrev);
-         }
-         pWin->optional->deviceCursors = NULL;
-     }
- 
-     xfree(pWin->optional->access.perm);
-     xfree(pWin->optional->access.deny);
- 
-     xfree (pWin->optional);
-     pWin->optional = NULL;
- }
- 
 +/*
 + * Changes the cursor struct for the given device and the given window.
 + * A cursor that does not have a device cursor set will use whatever the
 + * standard cursor is for the window. If all devices have a cursor set,
 + * changing the window cursor (e.g. using XDefineCursor()) will not have any
 + * visible effect. Only when one of the device cursors is set to None again,
 + * this device's cursor will display the changed standard cursor.
 + * 
 + * CursorIsNone of the window struct is NOT modified if you set a device
 + * cursor. 
 + *
 + * Assumption: If there is a node for a device in the list, the device has a
 + * cursor. If the cursor is set to None, it is inherited by the parent.
 + */
- int ChangeWindowDeviceCursor(register WindowPtr pWin, 
-                               DeviceIntPtr pDev, 
-                               CursorPtr pCursor) 
++_X_EXPORT int
++ChangeWindowDeviceCursor(WindowPtr pWin, 
++                         DeviceIntPtr pDev, 
++                         CursorPtr pCursor) 
 +{
 +    DevCursNodePtr pNode, pPrev;
 +    CursorPtr pOldCursor = NULL;
 +    ScreenPtr pScreen;
 +    WindowPtr pChild;
 +
 +    if (!pWin->optional && !MakeWindowOptional(pWin))
 +        return BadAlloc;
 +
 +    /* 1) Check if window has device cursor set
 +     *  Yes: 1.1) swap cursor with given cursor if parent does not have same
 +     *            cursor, free old cursor
 +     *       1.2) free old cursor, use parent cursor
 +     *  No: 1.1) add node to beginning of list.
 +     *      1.2) add cursor to node if parent does not have same cursor
 +     *      1.3) use parent cursor if parent does not have same cursor
 +     *  2) Patch up children if child has a devcursor
 +     *  2.1) if child has cursor None, it inherited from parent, set to old
 +     *  cursor
 +     *  2.2) if child has same cursor as new cursor, remove and set to None
 +     */
 +
 +    pScreen = pWin->drawable.pScreen;
 +
 +    if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev))
 +    {
 +        /* has device cursor */
 +
 +        if (pNode->cursor == pCursor)
 +            return Success;
 +
 +        pOldCursor = pNode->cursor;
 +
 +        if (!pCursor) /* remove from list */
 +        {
 +            pPrev->next = pNode->next;
 +            xfree(pNode);
 +        }
 +
 +    } else
 +    {
 +        /* no device cursor yet */
 +        DevCursNodePtr pNewNode;
 +
 +        if (!pCursor)
 +            return Success;
 +
 +        pNewNode = (DevCursNodePtr)xalloc(sizeof(DevCursNodeRec));
 +        pNewNode->dev = pDev;
 +        pNewNode->next = pWin->optional->deviceCursors;
 +        pWin->optional->deviceCursors = pNewNode;
 +        pNode = pNewNode;
 +
 +    }
 +
 +    if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
 +        pNode->cursor = None;
 +    else
 +    {
 +        pNode->cursor = pCursor;
 +        pCursor->refcnt++;
 +    }
 +
 +    pNode = pPrev = NULL;
 +    /* fix up children */
 +    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
 +    {
 +        if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev))
 +        {
 +            if (pNode->cursor == None) /* inherited from parent */
 +            {
 +                pNode->cursor = pOldCursor;
 +                pOldCursor->refcnt++;
 +            } else if (pNode->cursor == pCursor)
 +            {
 +                pNode->cursor = None;
 +                FreeCursor(pCursor, (Cursor)0); /* fix up refcnt */
 +            }
 +        }
 +    }
 +
 +    if (pWin->realized)
 +        WindowHasNewCursor(pWin);
 +
 +    if (pOldCursor)
 +        FreeCursor(pOldCursor, (Cursor)0);
 +
 +    /* FIXME: We SHOULD check for an error value here XXX  
 +       (comment taken from ChangeWindowAttributes) */
 +    (*pScreen->ChangeWindowAttributes)(pWin, CWCursor);
 +
 +    return Success;
 +}
 +
 +/* Get device cursor for given device or None if none is set */
- CursorPtr WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
++_X_EXPORT CursorPtr 
++WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
 +{
 +    DevCursorList pList;
 +
 +    if (!pWin->optional || !pWin->optional->deviceCursors)
 +        return NULL;
 +
 +    pList = pWin->optional->deviceCursors;
 +
 +    while(pList)
 +    {
 +        if (pList->dev == pDev)
 +        {
 +            if (pList->cursor == None) /* inherited from parent */
 +                return WindowGetDeviceCursor(pWin->parent, pDev);
 +            else
 +                return pList->cursor;
 +        }
 +        pList = pList->next;
 +    }
 +    return NULL;
 +}
 +
 +/* Searches for a DevCursorNode for the given window and device. If one is
 + * found, return True and set pNode and pPrev to the node and to the node
 + * before the node respectively. Otherwise return False.
 + * If the device is the first in list, pPrev is set to NULL.
 + */
 +static Bool 
 +WindowSeekDeviceCursor(WindowPtr pWin, 
 +                       DeviceIntPtr pDev, 
 +                       DevCursNodePtr* pNode, 
 +                       DevCursNodePtr* pPrev)
 +{
 +    DevCursorList pList;
 +
 +    if (!pWin->optional)
 +        return FALSE;
 +
 +    pList = pWin->optional->deviceCursors;
 +
 +    if (pList && pList->dev == pDev)
 +    {
 +        *pNode = pList;
 +        *pPrev = NULL;
 +        return TRUE;
 +    }
 +
 +    while(pList)
 +    {
 +        if (pList->next)
 +        {
 +            if (pList->next->dev == pDev)
 +            {
 +                *pNode = pList->next;
 +                *pPrev = pList;
 +                return TRUE;
 +            }
 +        }
 +        pList = pList->next;
 +    }
 +    return FALSE;
 +}
 +
 +/* Return True if a parent has the same device cursor set or False if
 + * otherwise 
 + */ 
 +static Bool 
 +WindowParentHasDeviceCursor(WindowPtr pWin, 
 +                            DeviceIntPtr pDev, 
 +                            CursorPtr pCursor)
 +{
 +    WindowPtr pParent;
 +    DevCursNodePtr pParentNode, pParentPrev;
 +
 +    pParent = pWin->parent;
 +    while(pParent)
 +    {
 +        if (WindowSeekDeviceCursor(pParent, pDev, 
 +                    &pParentNode, &pParentPrev))
 +        {
 +            /* if there is a node in the list, the win has a dev cursor */
 +            if (!pParentNode->cursor) /* inherited. loop needs to cont. */
 +            {
 +            } else if (pParentNode->cursor == pCursor) /* inherit */
 +                return TRUE;
 +            else  /* different cursor */
 +                return FALSE;
 +        } 
 +        else 
 +            /* parent does not have a device cursor for our device */
 +            return FALSE;
 +    }
 +    return FALSE;
 +}
 +
- 
  #ifndef NOLOGOHACK
  static void
  DrawLogo(WindowPtr pWin)
diff --cc hw/xfree86/common/xf86Xinput.c
index 2c74001,17ffed8..cc98a0c
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@@ -521,13 -504,16 +549,15 @@@ xf86PostButtonEvent(DeviceIntPtr	device
      va_list var;
      int *valuators = NULL;
      int i = 0, nevents = 0;
-     int flags = 0;
- 
-     if (is_absolute)
-         flags = POINTER_ABSOLUTE;
-     else
-         flags = POINTER_RELATIVE;
+     int index;
  
+ #if XFreeXDGA
+     if (miPointerGetScreen(inputInfo.pointer)) {
+         index = miPointerGetScreen(inputInfo.pointer)->myNum;
+         if (DGAStealButtonEvent(index, button, is_down))
+             return;
+     }
+ #endif
 -    
      valuators = xcalloc(sizeof(int), num_valuators);
  
      va_start(var, num_valuators);
@@@ -542,7 -528,8 +572,7 @@@
  
      nevents = GetPointerEvents(xf86Events, device,
                                 is_down ? ButtonPress : ButtonRelease, button,
-                                flags,
 -                               is_absolute ? POINTER_ABSOLUTE :
 -                                             POINTER_RELATIVE,
++                               (is_absolute) ? POINTER_ABSOLUTE : POINTER_RELATIVE,
                                 first_valuator, num_valuators, valuators);
  
      for (i = 0; i < nevents; i++)
diff --cc include/extinit.h
index 7a12b1b,e616b6d..d008651
--- a/include/extinit.h
+++ b/include/extinit.h
@@@ -37,116 -37,6 +37,11 @@@ XInputExtensionInit
  	void
  	);
  
- 
- int
- ProcIDispatch (
- 	ClientPtr              /* client */
- 	);
- 
- int
- SProcIDispatch(
- 	ClientPtr              /* client */
- 	);
- 
- void
- SReplyIDispatch (
- 	ClientPtr              /* client */,
- 	int                    /* len */,
- 	xGrabDeviceReply *     /* rep */
- 	);
- 
- void
- SEventIDispatch (
- 	xEvent *               /* from */,
- 	xEvent *               /* to */
- 	);
- 
- void
- SEventDeviceValuator (
- 	deviceValuator *       /* from */,
- 	deviceValuator *       /* to */
- 	);
- 
- void
- SEventFocus (
- 	deviceFocus *          /* from */,
- 	deviceFocus *          /* to */
- 	);
- 
- void
- SDeviceStateNotifyEvent (
- 	deviceStateNotify *    /* from */,
- 	deviceStateNotify *    /* to */
- 	);
- 
- void
- SDeviceKeyStateNotifyEvent (
- 	deviceKeyStateNotify * /* from */,
- 	deviceKeyStateNotify * /* to */
- 	);
- 
- void
- SDeviceButtonStateNotifyEvent (
- 	deviceButtonStateNotify * /* from */,
- 	deviceButtonStateNotify * /* to */
- 	);
- 
- void
- SChangeDeviceNotifyEvent (
- 	changeDeviceNotify *   /* from */,
- 	changeDeviceNotify *   /* to */
- 	);
- 
- void
- SDeviceMappingNotifyEvent (
- 	deviceMappingNotify *  /* from */,
- 	deviceMappingNotify *  /* to */
- 	);
- 
- void
- SDevicePresenceNotifyEvent (
-        devicePresenceNotify * /* from */,
-        devicePresenceNotify * /* to */
-        );
- 
- void
- SDeviceEnterNotifyEvent (
-         deviceEnterNotify * /* from */,
-         deviceEnterNotify * /* to */
-         );
- 
- void
- SDeviceLeaveNotifyEvent (
-         deviceLeaveNotify * /* from */,
-         deviceLeaveNotify * /* to */
-         );
- 
- void 
- SPointerKeyboardPairingChangedNotifyEvent (
-         pairingChangedNotify * /* from */,
-         pairingChangedNotify * /* to */
-         );
- 
- void
- FixExtensionEvents (
- 	ExtensionEntry 	*      /* extEntry */
- 	);
- 
- void
- RestoreExtensionEvents (
- 	void
- 	);
- 
- void
- IResetProc(
- 	ExtensionEntry *       /* unused */
- 	);
- 
 +Bool
 +DeviceIsPointerType(
 +        DeviceIntPtr dev
 +        );
 +
  void
  AssignTypeAndName (
  	DeviceIntPtr           /* dev */,
diff --cc mi/mipointer.c
index 3c09064,b86a26a..863a405
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@@ -467,6 -404,27 +462,30 @@@ miPointerAbsoluteCursor (int x, int y, 
      miPointerSetPosition(inputInfo.pointer, &x, &y, time);
  }
  
+ /* Move the pointer on the current screen,  and update the sprite. */
+ static void
+ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
+                      unsigned long time)
+ {
++    int valuators[2];
++    miPointerPtr pPointer = MIPOINTER(pDev);
+     SetupScreen(pScreen);
+ 
 -    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer) &&
 -        !pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
++
++    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer)
++        && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
+     {
 -	miPointer.devx = x;
 -	miPointer.devy = y;
 -	if(!miPointer.pCursor->bits->emptyMask)
 -	    (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
++	pPointer->devx = x;
++	pPointer->devy = y;
++	if(!pPointer->pCursor->bits->emptyMask)
++	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
+     }
+ 
 -    miPointer.x = x;
 -    miPointer.y = y;
 -    miPointer.pScreen = pScreen;
++    pPointer->x = x;
++    pPointer->y = y;
++    pPointer->pScreen = pScreen;
+ }
+ 
  _X_EXPORT void
  miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
  {
commit 96ce17aa94413c4b8bcb61cae71167050130a307
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 15 17:50:02 2006 +1030

    o fix minor error in comment for GetPointerEvents()

diff --git a/dix/getevents.c b/dix/getevents.c
index 3f636bc..219d1a1 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -470,7 +470,7 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
 
 
 /**
- * Generate a series of xEvents (returned in xE) representing pointer
+ * Generate a series of xEvents (returned in events) representing pointer
  * motion, or button presses.  Xi and XKB-aware.
  *
  * events is not NULL-terminated; the return value is the number of events.
commit a12054757d21edacc1c24c3077b9214726652829
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Apr 2 11:20:44 2007 +0930

    Xi:     fix ProcXListInputDevices to include the virtual core devices.

diff --git a/Xi/listdev.c b/Xi/listdev.c
index 02d55ad..33266ae 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -116,6 +116,10 @@ ProcXListInputDevices(register ClientPtr client)
 
     AddOtherInputDevices();
 
+    SizeDeviceInfo(inputInfo.keyboard, &namesize, &size);
+    SizeDeviceInfo(inputInfo.pointer, &namesize, &size);
+    numdevs = 2;
+
     for (d = inputInfo.devices; d; d = d->next) {
 	SizeDeviceInfo(d, &namesize, &size);
         numdevs++;
@@ -132,6 +136,11 @@ ProcXListInputDevices(register ClientPtr client)
     savbuf = devbuf;
 
     dev = (xDeviceInfoPtr) devbuf;
+    ListDeviceInfo(client, inputInfo.keyboard, dev++, 
+                   &devbuf, &classbuf, &namebuf);
+    ListDeviceInfo(client, inputInfo.pointer, dev++,
+                   &devbuf, &classbuf, &namebuf);
+
     for (d = inputInfo.devices; d; d = d->next, dev++)
 	ListDeviceInfo(client, d, dev, &devbuf, &classbuf, &namebuf);
     for (d = inputInfo.off_devices; d; d = d->next, dev++)
commit 63d8f01819ef44ea3bf0d4fb20ba1d698ae91cd2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Mar 30 14:59:43 2007 +0930

    dix:    Fix wrong cursor refcount.
    
            Calloc cursor struct to ensure devPrivates are zeroed out and don't
            increase the refcnt for devices automatically when allocating a new
            cursor. Use new DeviceIsPointerType() to detect if device is a pointer
            _before_ device has been activated and can thus be identified and set
            up grab functions accordingly. This way we can increase the refcnt
            when we get a pointer grab.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index bc26189..3e3f15a 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -101,7 +101,7 @@ RegisterOtherDevice(DeviceIntPtr device)
     device->public.realInputProc = ProcessOtherEvent;
     (device)->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
     (device)->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
-    if (IsPointerDevice(device))
+    if (DeviceIsPointerType(device))
     {
         (device)->coreGrab.ActivateGrab = ActivatePointerGrab;
         (device)->coreGrab.DeactivateGrab = DeactivatePointerGrab;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 3766a95..971617e 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -983,6 +983,22 @@ IResetProc(ExtensionEntry * unused)
     RestoreExtensionEvents();
 }
 
+/*****************************************************************
+ *
+ * Returns TRUE if the device has some sort of pointer type.
+ *
+ */
+
+Bool
+DeviceIsPointerType(DeviceIntPtr dev)
+{
+    if (dev_type[1].type == dev->type)
+        return TRUE;
+
+    return FALSE;
+}
+
+
 /***********************************************************************
  *
  * Assign an id and type to an input device.
diff --git a/dix/cursor.c b/dix/cursor.c
index 27ae9f1..5886422 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -179,7 +179,7 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
     ScreenPtr 	pscr;
     DeviceIntPtr pDev; 
 
-    pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
+    pCurs = (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1);
     if (!pCurs)
     {
 	xfree(psrcbits);
@@ -196,7 +196,7 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
     bits->height = cm->height;
     bits->xhot = cm->xhot;
     bits->yhot = cm->yhot;
-    pCurs->refcnt = 0;		
+    pCurs->refcnt = 1;		
     CheckForEmptyMask(bits);
 
     pCurs->bits = bits;
@@ -215,6 +215,8 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
 
     /*
      * realize the cursor for every screen
+     * Do not change the refcnt, this will be changed when ChangeToCursor
+     * actually changes the sprite.
      */
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
@@ -223,7 +225,6 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
         {
             if (DevHasCursor(pDev))
             {
-                pCurs->refcnt++;
                 if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
                 {
                     /* Realize failed for device pDev on screen pscr.
@@ -325,7 +326,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     }
     if (pShare)
     {
-	pCurs = (CursorPtr)xalloc(sizeof(CursorRec));
+	pCurs = (CursorPtr)xcalloc(sizeof(CursorRec), 1);
 	if (!pCurs)
 	    return BadAlloc;
 	bits = pShare->bits;
@@ -367,7 +368,8 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
 	}
 	if (sourcefont != maskfont)
 	{
-	    pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
+	    pCurs = 
+                (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1);
 	    if (pCurs)
 		bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
 	    else
@@ -375,9 +377,9 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
 	}
 	else
 	{
-	    pCurs = (CursorPtr)xalloc(sizeof(CursorRec));
+	    pCurs = (CursorPtr)xcalloc(sizeof(CursorRec), 1);
 	    if (pCurs)
-		bits = (CursorBitsPtr)xalloc(sizeof(CursorBits));
+		bits = (CursorBitsPtr)xcalloc(sizeof(CursorBits), 1);
 	    else
 		bits = (CursorBitsPtr)NULL;
 	}
@@ -417,9 +419,10 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
 	    sharedGlyphs = pShare;
 	}
     }
+
     CheckForEmptyMask(bits);
     pCurs->bits = bits;
-    pCurs->refcnt = 0;
+    pCurs->refcnt = 1;
 #ifdef XFIXES
     pCurs->serialNumber = ++cursorSerial;
     pCurs->name = None;
@@ -440,38 +443,10 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     {
         pscr = screenInfo.screens[nscr];
 
-        pCurs->refcnt++;
-        if (!(*pscr->RealizeCursor)(inputInfo.pointer, pscr, pCurs))
-        {
-            DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
-            /* Realize for core pointer failed. Unrealize everything from
-             * previous screens.
-             */ 
-            while (--nscr >= 0)
-            {
-                pscr = screenInfo.screens[nscr];
-                /* now unrealize all devices on previous screens */
-                ( *pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs);
-
-                pDevIt = inputInfo.devices;
-                while (pDevIt)
-                {
-                    if (DevHasCursor(pDevIt))
-                        ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
-                    pDevIt = pDevIt->next;
-                }
-                ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
-            }
-            FreeCursorBits(bits);
-            xfree(pCurs);
-            return BadAlloc;
-        }
-
         for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
             if (DevHasCursor(pDev))
             {
-                pCurs->refcnt++;
                 if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
                 {
                     /* Realize failed for device pDev on screen pscr.
diff --git a/dix/events.c b/dix/events.c
index a51a56c..c482f5c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4024,7 +4024,6 @@ ProcGrabPointer(ClientPtr client)
 	    oldCursor = grab->cursor;
 	}
 	tempGrab.cursor = cursor;
-        /* FIXME: refcnt?? */
 	tempGrab.resource = client->clientAsMask;
 	tempGrab.ownerEvents = stuff->ownerEvents;
 	tempGrab.eventMask = stuff->eventMask;
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index a9ce211..2c74001 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -174,7 +174,7 @@ xf86ActivateDevice(LocalDevicePtr local)
         dev->spriteInfo->spriteOwner = !(local->flags & XI86_SHARED_POINTER);
 
 #ifdef XKB
-        if (!IsPointerDevice(dev))
+        if (!DeviceIsPointerType(dev))
         {
         /* FIXME: that's not the nice way to do it. XKB wraps the previously
          * set procs, so if we don't have them here, our event will disappear
diff --git a/include/extinit.h b/include/extinit.h
index ead59be..7a12b1b 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -142,6 +142,11 @@ IResetProc(
 	ExtensionEntry *       /* unused */
 	);
 
+Bool
+DeviceIsPointerType(
+        DeviceIntPtr dev
+        );
+
 void
 AssignTypeAndName (
 	DeviceIntPtr           /* dev */,
commit 20e4314b178e1a093bce85e93329d4bcfb4f4210
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Mar 29 19:12:32 2007 +0930

    dix:    Try to get closer to the correct refcnt for cursors.
    
            This commit introduces a memory leak, as the refcnt never seems to get
            down to 0 and thus cursors will not be freed. Solves the problems with
            GNOME segfaulting every 30 seconds though.

diff --git a/dix/cursor.c b/dix/cursor.c
index c58e2fa..27ae9f1 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -196,11 +196,10 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
     bits->height = cm->height;
     bits->xhot = cm->xhot;
     bits->yhot = cm->yhot;
-    bits->refcnt = -1;
+    pCurs->refcnt = 0;		
     CheckForEmptyMask(bits);
 
     pCurs->bits = bits;
-    pCurs->refcnt = 1;		
 #ifdef XFIXES
     pCurs->serialNumber = ++cursorSerial;
     pCurs->name = None;
@@ -224,6 +223,7 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
         {
             if (DevHasCursor(pDev))
             {
+                pCurs->refcnt++;
                 if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
                 {
                     /* Realize failed for device pDev on screen pscr.
@@ -419,7 +419,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     }
     CheckForEmptyMask(bits);
     pCurs->bits = bits;
-    pCurs->refcnt = 1;
+    pCurs->refcnt = 0;
 #ifdef XFIXES
     pCurs->serialNumber = ++cursorSerial;
     pCurs->name = None;
@@ -440,6 +440,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     {
         pscr = screenInfo.screens[nscr];
 
+        pCurs->refcnt++;
         if (!(*pscr->RealizeCursor)(inputInfo.pointer, pscr, pCurs))
         {
             DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
@@ -470,6 +471,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
         {
             if (DevHasCursor(pDev))
             {
+                pCurs->refcnt++;
                 if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
                 {
                     /* Realize failed for device pDev on screen pscr.
commit 0c607f4b1902f993597e09ea7a2c83bc1cca9b96
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Mar 29 14:43:50 2007 +0930

    dix:    Pick keyboard instead of using virtual keyboard in Grab/UngrabKey.

diff --git a/dix/events.c b/dix/events.c
index 9f7e08d..a51a56c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4433,7 +4433,7 @@ ProcUngrabKey(ClientPtr client)
     REQUEST(xUngrabKeyReq);
     WindowPtr pWin;
     GrabRec tempGrab;
-    DeviceIntPtr keybd = inputInfo.keyboard;
+    DeviceIntPtr keybd = PickKeyboard(client);
     int rc;
 
     REQUEST_SIZE_MATCH(xUngrabKeyReq);
@@ -4475,7 +4475,7 @@ ProcGrabKey(ClientPtr client)
     WindowPtr pWin;
     REQUEST(xGrabKeyReq);
     GrabPtr grab;
-    DeviceIntPtr keybd = inputInfo.keyboard;
+    DeviceIntPtr keybd = PickKeyboard(client);
     int rc;
 
     REQUEST_SIZE_MATCH(xGrabKeyReq);
commit 5f9c10e8da0d9d96cc00a38cdf9a8c3030063e03
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Mar 25 15:00:03 2007 +0930

    Clean up DeviceIntPtr, prepare for Server 1.4 ABI. Move sprite-related
    information into a new SpriteInfoRec, remove isMPDev flag.

diff --git a/Xi/querydp.c b/Xi/querydp.c
index a24dad0..af93fed 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -101,7 +101,7 @@ ProcXQueryDevicePointer(register ClientPtr client)
     if (pDev->valuator->motionHintWindow)
         MaybeStopHint(pDev, client);
 
-    pSprite = pDev->pSprite;
+    pSprite = pDev->spriteInfo->sprite;
     rep.repType = X_Reply;
     rep.RepType = X_QueryDevicePointer;
     rep.length = 0;
@@ -111,7 +111,7 @@ ProcXQueryDevicePointer(register ClientPtr client)
     rep.rootX = pSprite->hot.x;
     rep.rootY = pSprite->hot.y;
     rep.child = None;
-    rep.shared = (pDev->isMPDev) ? xFalse : xTrue; 
+    rep.shared = (pDev->spriteInfo->spriteOwner) ? xFalse : xTrue; 
 
     if (pSprite->hot.pScreen == pWin->drawable.pScreen)
     {
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index a9ddb0b..8df7e14 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -102,7 +102,7 @@ ProcXWarpDevicePointer(register ClientPtr client)
         }
     }
 
-    pSprite = pDev->pSprite;
+    pSprite = pDev->spriteInfo->sprite;
     x = pSprite->hotPhys.x;
     y = pSprite->hotPhys.y;
 
diff --git a/dix/devices.c b/dix/devices.c
index 10843d4..724ef98 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -147,6 +147,13 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
     dev->inited = FALSE;
     dev->enabled = FALSE;
 
+    /* sprite defaults */
+    dev->spriteInfo = (SpriteInfoPtr)xcalloc(sizeof(SpriteInfoRec), 1);
+    if (!dev->spriteInfo)
+        return (DeviceIntPtr)NULL;
+    dev->spriteInfo->sprite = NULL;
+    dev->spriteInfo->spriteOwner = FALSE;
+
     for (prev = &inputInfo.off_devices; *prev; prev = &(*prev)->next)
         ;
     *prev = dev;
@@ -173,7 +180,7 @@ EnableDevice(DeviceIntPtr dev)
     dev->enabled = TRUE;
     *prev = dev->next;
 
-    if (IsPointerDevice(dev) && dev->isMPDev)
+    if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner)
         InitializeSprite(dev, GetCurrentRootWindow());
     else
         PairDevices(NULL, inputInfo.pointer, dev);
@@ -360,7 +367,7 @@ InitCoreDevices()
         dev->coreGrab.ActivateGrab = ActivateKeyboardGrab;
         dev->coreGrab.DeactivateGrab = DeactivateKeyboardGrab;
         dev->coreEvents = FALSE;
-        dev->spriteOwner = FALSE;
+        dev->spriteInfo->spriteOwner = FALSE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate keyboard devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
@@ -542,7 +549,7 @@ CloseDevice(DeviceIntPtr dev)
 #endif
     
     if (DevHasCursor(dev))
-        xfree((pointer)dev->pSprite);
+        xfree((pointer)dev->spriteInfo->sprite);
 
     /* a client may have the device set as client pointer */
     for (j = 0; j < currentMaxClients; j++)
@@ -556,6 +563,7 @@ CloseDevice(DeviceIntPtr dev)
 
     xfree(dev->coreGrab.sync.event);
     xfree(dev->deviceGrab.sync.event);
+    xfree(dev->spriteInfo);
     xfree(dev);
 }
 
@@ -2009,14 +2017,14 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
     else if (pairingClient != client)
         return BadAccess;
 
-    if (kbd->spriteOwner)
+    if (kbd->spriteInfo->spriteOwner)
     {
-        xfree(kbd->pSprite);
-        kbd->pSprite = NULL;
-        kbd->spriteOwner = FALSE;
+        xfree(kbd->spriteInfo->sprite);
+        kbd->spriteInfo->sprite = NULL;
+        kbd->spriteInfo->spriteOwner = FALSE;
     }
 
-    kbd->pSprite = ptr->pSprite;
+    kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
     return Success;
 }
 
@@ -2029,7 +2037,8 @@ GetPairedPointer(DeviceIntPtr kbd)
     DeviceIntPtr ptr = inputInfo.devices;
     while(ptr)
     {
-        if (ptr->pSprite == kbd->pSprite && ptr->spriteOwner)
+        if (ptr->spriteInfo->sprite == kbd->spriteInfo->sprite && 
+                ptr->spriteInfo->spriteOwner)
         {
             return ptr;
         }
@@ -2053,7 +2062,7 @@ GetPairedKeyboard(DeviceIntPtr ptr)
     {
         if (ptr != dev && 
             IsKeyboardDevice(dev) &&
-            ptr->pSprite == dev->pSprite)
+            ptr->spriteInfo->sprite == dev->spriteInfo->sprite)
             return dev;
         dev = dev->next;
     }
@@ -2109,7 +2118,7 @@ GuessFreePointerDevice()
     while(it)
     {
         /* found device with a sprite? */
-        if (it->spriteOwner)
+        if (it->spriteInfo->spriteOwner)
         {
             lastRealPtr = it;
 
@@ -2117,7 +2126,8 @@ GuessFreePointerDevice()
             while(it2)
             {
                 /* something paired with it? */
-                if (it != it2 && it2->pSprite == it->pSprite)
+                if (it != it2 && 
+                        it2->spriteInfo->sprite == it->spriteInfo->sprite)
                     break;
 
                 it2 = it2->next;
diff --git a/dix/events.c b/dix/events.c
index 65d6eae..9f7e08d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -247,7 +247,7 @@ static int spriteTraceGood;
 _X_EXPORT Bool
 DevHasCursor(DeviceIntPtr pDev) 
 {
-    return (pDev != inputInfo.pointer && pDev->spriteOwner);
+    return (pDev != inputInfo.pointer && pDev->spriteInfo->spriteOwner);
 }
 
 /*
@@ -346,7 +346,7 @@ static void PostNewCursor(DeviceIntPtr pDev);
 
 #define SyntheticMotion(dev, x, y) \
     PostSyntheticMotion(dev, x, y, noPanoramiXExtension ? 0 : \
-                              dev->pSprite->screen->myNum, \
+                              dev->spriteInfo->sprite->screen->myNum, \
                         syncEvents.playingEvents ? \
                           syncEvents.time.milliseconds : \
                           currentTime.milliseconds);
@@ -361,7 +361,7 @@ XineramaSetCursorPosition(
     ScreenPtr pScreen;
     BoxRec box;
     int i;
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     /* x,y are in Screen 0 coordinates.  We need to decide what Screen
        to send the message too and what the coordinates relative to 
@@ -399,7 +399,7 @@ XineramaSetCursorPosition(
 static void
 XineramaConstrainCursor(DeviceIntPtr pDev)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
     ScreenPtr pScreen;
     BoxRec newBox;
 
@@ -423,7 +423,7 @@ XineramaCheckPhysLimits(
     Bool generateEvents
 ){
     HotSpot new;
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if (!cursor)
 	return;
@@ -463,7 +463,7 @@ XineramaCheckPhysLimits(
 static Bool
 XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if(pWin == WindowTable[0]) {
 	    memcpy(pSprite->windows, WindowTable, 
@@ -492,7 +492,7 @@ XineramaCheckVirtualMotion(
    QdEventPtr qe,
    WindowPtr pWin) 
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if (qe)
     {
@@ -564,7 +564,7 @@ static Bool
 XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
     WindowPtr prevSpriteWin;
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     prevSpriteWin = pSprite->win;
 
@@ -629,7 +629,7 @@ XineramaConfineCursorToWindow(DeviceIntPtr pDev,
                               WindowPtr pWin, 
                               Bool generateEvents)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if (syncEvents.playingEvents)
     {
@@ -683,7 +683,7 @@ XineramaConfineCursorToWindow(DeviceIntPtr pDev,
 static void
 XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if (cursor != pSprite->current)
     {
@@ -723,7 +723,7 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
     BoxRec box;
     int x = *px, y = *py;
     int incx = 1, incy = 1;
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box))
 	return;
@@ -764,7 +764,7 @@ CheckPhysLimits(
     ScreenPtr pScreen)
 {
     HotSpot new;
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if (!cursor)
 	return;
@@ -809,7 +809,7 @@ CheckVirtualMotion(
     QdEventPtr qe,
     WindowPtr pWin)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
@@ -865,7 +865,7 @@ static void
 ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
 {
     ScreenPtr pScreen = pWin->drawable.pScreen;
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
@@ -894,13 +894,13 @@ ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bo
 _X_EXPORT Bool
 PointerConfinedToScreen(DeviceIntPtr pDev)
 {
-    return pDev->pSprite->confined;
+    return pDev->spriteInfo->sprite->confined;
 }
 
 static void
 ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
@@ -938,7 +938,7 @@ PostNewCursor(DeviceIntPtr pDev)
 {
     WindowPtr win;
     GrabPtr grab = pDev->coreGrab.grab;
-    SpritePtr   pSprite = pDev->pSprite;
+    SpritePtr   pSprite = pDev->spriteInfo->sprite;
     CursorPtr   pCursor;
 
     if (syncEvents.playingEvents)
@@ -982,19 +982,19 @@ GetCurrentRootWindow()
 _X_EXPORT WindowPtr
 GetSpriteWindow(DeviceIntPtr pDev)
 {
-    return pDev->pSprite->win;
+    return pDev->spriteInfo->sprite->win;
 }
 
 _X_EXPORT CursorPtr
 GetSpriteCursor(DeviceIntPtr pDev)
 {
-    return pDev->pSprite->current;
+    return pDev->spriteInfo->sprite->current;
 }
 
 _X_EXPORT void
 GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
     *px = pSprite->hotPhys.x;
     *py = pSprite->hotPhys.y;
 }
@@ -1004,7 +1004,7 @@ _X_EXPORT int
 XineramaGetCursorScreen(DeviceIntPtr pDev)
 {
     if(!noPanoramiXExtension) {
-	return pDev->pSprite->screen->myNum;
+	return pDev->spriteInfo->sprite->screen->myNum;
     } else {
 	return 0;
     }
@@ -1049,7 +1049,7 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
     QdEventPtr tail = *syncEvents.pendtail;
     QdEventPtr qe;
     xEvent		*qxE;
-    SpritePtr pSprite = device->pSprite;
+    SpritePtr pSprite = device->spriteInfo->sprite;
 
     NoticeTime(xE);
 
@@ -1146,10 +1146,10 @@ PlayReleasedEvents(void)
 	    if(!noPanoramiXExtension) {
 		qe->event->u.keyButtonPointer.rootX += 
 			panoramiXdataPtr[0].x - 
-			panoramiXdataPtr[pDev->pSprite->screen->myNum].x;
+			panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].x;
 		qe->event->u.keyButtonPointer.rootY += 
 			panoramiXdataPtr[0].y - 
-			panoramiXdataPtr[pDev->pSprite->screen->myNum].y;
+			panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].y;
 	    }
 #endif
 	    (*qe->device->public.processInputProc)(qe->event, qe->device,
@@ -1241,14 +1241,14 @@ playmore:
             if ((grab = dev->coreGrab.grab) && grab->confineTo)
             {
                 if (grab->confineTo->drawable.pScreen !=
-                        dev->pSprite->hotPhys.pScreen) 
-                    dev->pSprite->hotPhys.x =
-                        dev->pSprite->hotPhys.y = 0;
+                        dev->spriteInfo->sprite->hotPhys.pScreen) 
+                    dev->spriteInfo->sprite->hotPhys.x =
+                        dev->spriteInfo->sprite->hotPhys.y = 0;
                 ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
             }
             else
                 ConfineCursorToWindow(dev,
-                        WindowTable[dev->pSprite->hotPhys.pScreen->myNum],
+                        WindowTable[dev->spriteInfo->sprite->hotPhys.pScreen->myNum],
                         TRUE, FALSE);
             PostNewCursor(dev);
         }
@@ -1270,13 +1270,13 @@ ScreenRestructured (ScreenPtr pScreen)
         if ((grab = pDev->coreGrab.grab) && grab->confineTo)
         {
             if (grab->confineTo->drawable.pScreen 
-                    != pDev->pSprite->hotPhys.pScreen)
-                pDev->pSprite->hotPhys.x = pDev->pSprite->hotPhys.y = 0;
+                    != pDev->spriteInfo->sprite->hotPhys.pScreen)
+                pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
             ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
         }
         else
             ConfineCursorToWindow(pDev, 
-                    WindowTable[pDev->pSprite->hotPhys.pScreen->myNum],
+                    WindowTable[pDev->spriteInfo->sprite->hotPhys.pScreen->myNum],
                     TRUE, FALSE);
     }
 }
@@ -1322,13 +1322,14 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
 {
     WindowPtr oldWin = (mouse->coreGrab.grab) ? 
                         mouse->coreGrab.grab->window
-                        : mouse->pSprite->win;
+                        : mouse->spriteInfo->sprite->win;
 
     if (grab->confineTo)
     {
 	if (grab->confineTo->drawable.pScreen 
-                != mouse->pSprite->hotPhys.pScreen)
-	    mouse->pSprite->hotPhys.x = mouse->pSprite->hotPhys.y = 0;
+                != mouse->spriteInfo->sprite->hotPhys.pScreen)
+	    mouse->spriteInfo->sprite->hotPhys.x = 
+                mouse->spriteInfo->sprite->hotPhys.y = 0;
 	ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
     }
     DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
@@ -1362,7 +1363,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
 	    dev->coreGrab.sync.other = NullGrab;
     }
     DoEnterLeaveEvents(mouse, grab->window, 
-                       mouse->pSprite->win, NotifyUngrab);
+                       mouse->spriteInfo->sprite->win, NotifyUngrab);
     if (grab->confineTo)
 	ConfineCursorToWindow(mouse, ROOT, FALSE, FALSE);
     PostNewCursor(mouse);
@@ -1381,7 +1382,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass
     else if (keybd->focus)
 	oldWin = keybd->focus->win;
     else
-	oldWin = keybd->pSprite->win;
+	oldWin = keybd->spriteInfo->sprite->win;
     if (oldWin == FollowKeyboardWin)
 	oldWin = inputInfo.keyboard->focus->win;
     if (keybd->valuator)
@@ -1403,7 +1404,7 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
     GrabPtr grab = keybd->coreGrab.grab;
     DeviceIntPtr dev;
     WindowPtr focusWin = keybd->focus ? keybd->focus->win
-					       : keybd->pSprite->win;
+                                           : keybd->spriteInfo->sprite->win;
 
     if (focusWin == FollowKeyboardWin)
 	focusWin = inputInfo.keyboard->focus->win;
@@ -1883,7 +1884,7 @@ FixUpEventFromWindow(
     Window child,
     Bool calcChild)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     if (calcChild)
     {
@@ -2039,7 +2040,7 @@ static Bool
 PointInBorderSize(WindowPtr pWin, int x, int y)
 {
     BoxRec box;
-    SpritePtr pSprite = inputInfo.pointer->pSprite;
+    SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
 
     if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box))
 	return TRUE;
@@ -2114,7 +2115,7 @@ Bool
 CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
     WindowPtr prevSpriteWin;
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
         
     prevSpriteWin = pSprite->win;
 
@@ -2219,7 +2220,7 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
     {
         if (DevHasCursor(pDev))
         {
-            pSprite = pDev->pSprite;
+            pSprite = pDev->spriteInfo->sprite;
             pSprite->hot.x        -= xoff;
             pSprite->hot.y        -= yoff;
 
@@ -2280,15 +2281,15 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
     SpritePtr pSprite;
     ScreenPtr pScreen; 
 
-    if (!pDev->pSprite)
+    if (!pDev->spriteInfo->sprite)
     {
-        pDev->pSprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec));
-        if (!pDev->pSprite)
+        pDev->spriteInfo->sprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec));
+        if (!pDev->spriteInfo->sprite)
             FatalError("InitializeSprite: failed to allocate sprite struct");
     }
 
-    pSprite = pDev->pSprite;
-    pDev->spriteOwner = TRUE;
+    pSprite = pDev->spriteInfo->sprite;
+    pDev->spriteInfo->spriteOwner = TRUE;
 
     pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
     pSprite->hot.pScreen = pScreen;
@@ -2363,7 +2364,7 @@ WindowHasNewCursor(WindowPtr pWin)
 _X_EXPORT void
 NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
 {
-    SpritePtr pSprite = pDev->pSprite;
+    SpritePtr pSprite = pDev->spriteInfo->sprite;
 
     pSprite->hotPhys.x = x;
     pSprite->hotPhys.y = y;
@@ -2423,7 +2424,7 @@ XineramaPointInWindowIsVisible(
     yoff = y + panoramiXdataPtr[0].y;  
 
     for(i = 1; i < PanoramiXNumScreens; i++) {
-	pWin = inputInfo.pointer->pSprite->windows[i];
+	pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
 	pScreen = pWin->drawable.pScreen;
 	x = xoff - panoramiXdataPtr[i].x;
 	y = yoff - panoramiXdataPtr[i].y;
@@ -2446,7 +2447,7 @@ XineramaWarpPointer(ClientPtr client)
 {
     WindowPtr	dest = NULL;
     int		x, y, rc;
-    SpritePtr   pSprite = PickPointer(client)->pSprite;
+    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
 
     REQUEST(xWarpPointerReq);
 
@@ -2521,7 +2522,7 @@ ProcWarpPointer(ClientPtr client)
     WindowPtr	dest = NULL;
     int		x, y, rc;
     ScreenPtr	newScreen;
-    SpritePtr   pSprite = PickPointer(client)->pSprite;
+    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
 
     REQUEST(xWarpPointerReq);
 
@@ -2609,7 +2610,7 @@ ProcWarpPointer(ClientPtr client)
 static Bool 
 BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
 {
-     if(REGION_NOTEMPTY(pDev->pSprite->hotPhys.pScreen, &pWin->borderSize))
+     if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->hotPhys.pScreen, &pWin->borderSize))
 	return TRUE;
 
 #ifdef PANORAMIX
@@ -2617,8 +2618,8 @@ BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
 	int i;
 
 	for(i = 1; i < PanoramiXNumScreens; i++) {
-	    if(REGION_NOTEMPTY(pDev->pSprite->screen, 
-                        &pDev->pSprite->windows[i]->borderSize))
+	    if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen, 
+                        &pDev->spriteInfo->sprite->windows[i]->borderSize))
 		return TRUE;
 	}
      }
@@ -2817,7 +2818,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
     int deliveries = 0;
     DeviceIntPtr dev;
     xEvent *dxE;
-    SpritePtr pSprite = thisDev->pSprite;
+    SpritePtr pSprite = thisDev->spriteInfo->sprite;
 
     if (xE->u.u.type & EXTENSION_EVENT_BASE)
         grabinfo = &thisDev->deviceGrab;
@@ -2988,8 +2989,8 @@ drawable.id:0;
     )))
 #endif
     XE_KBPTR.state = (keyc->state | GetPairedPointer(keybd)->button->state);
-    XE_KBPTR.rootX = keybd->pSprite->hot.x;
-    XE_KBPTR.rootY = keybd->pSprite->hot.y;
+    XE_KBPTR.rootX = keybd->spriteInfo->sprite->hot.x;
+    XE_KBPTR.rootY = keybd->spriteInfo->sprite->hot.y;
     key = xE->u.u.detail;
     kptr = &keyc->down[key >> 3];
     bit = 1 << (key & 7);
@@ -3065,7 +3066,7 @@ drawable.id:0;
     if (grab)
 	DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
     else
-	DeliverFocusedEvent(keybd, xE, keybd->pSprite->win, count);
+	DeliverFocusedEvent(keybd, xE, keybd->spriteInfo->sprite->win, count);
     if (deactivateGrab)
         (*grabinfo->DeactivateGrab)(keybd);
 
@@ -3117,7 +3118,7 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
     GrabPtr	        grab = mouse->coreGrab.grab;
     Bool                deactivateGrab = FALSE;
     ButtonClassPtr      butc = mouse->button;
-    SpritePtr           pSprite = mouse->pSprite;
+    SpritePtr           pSprite = mouse->spriteInfo->sprite;
 
 #ifdef XKB
     XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
@@ -3468,8 +3469,8 @@ EnterLeaveEvent(
     event.u.u.type = type;
     event.u.u.detail = detail;
     event.u.enterLeave.time = currentTime.milliseconds;
-    event.u.enterLeave.rootX = pDev->pSprite->hot.x;
-    event.u.enterLeave.rootY = pDev->pSprite->hot.y;
+    event.u.enterLeave.rootX = pDev->spriteInfo->sprite->hot.x;
+    event.u.enterLeave.rootY = pDev->spriteInfo->sprite->hot.y;
     /* Counts on the same initial structure of crossing & button events! */
     FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
     /* Enter/Leave events always set child */
@@ -3696,7 +3697,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
     int     out, in;		       /* for holding details for to/from
 				          PointerRoot/None */
     int     i;
-    SpritePtr pSprite = dev->pSprite;
+    SpritePtr pSprite = dev->spriteInfo->sprite;
 
     if (fromWin == toWin)
 	return;
@@ -4224,7 +4225,7 @@ ProcQueryPointer(ClientPtr client)
     xQueryPointerReply rep;
     WindowPtr pWin, t;
     DeviceIntPtr mouse = PickPointer(client);
-    SpritePtr pSprite = mouse->pSprite;
+    SpritePtr pSprite = mouse->spriteInfo->sprite;
     int rc;
 
     REQUEST(xResourceReq);
@@ -4343,7 +4344,7 @@ ProcSendEvent(ClientPtr client)
 {
     WindowPtr pWin;
     WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
-    SpritePtr pSprite = PickPointer(client)->pSprite;
+    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
     REQUEST(xSendEventReq);
 
     REQUEST_SIZE_MATCH(xSendEventReq);
@@ -4771,7 +4772,7 @@ ProcRecolorCursor(ClientPtr client)
     int		nscr;
     ScreenPtr	pscr;
     Bool 	displayed;
-    SpritePtr   pSprite = PickPointer(client)->pSprite;
+    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
     REQUEST(xRecolorCursorReq);
 
     REQUEST_SIZE_MATCH(xRecolorCursorReq);
@@ -4914,7 +4915,7 @@ PickPointer(ClientPtr client)
         DeviceIntPtr it = inputInfo.devices;
         while (it)
         {
-            if (it != inputInfo.pointer && it->spriteOwner)
+            if (it != inputInfo.pointer && it->spriteInfo->spriteOwner)
             {
                 client->clientPtr = it;
                 break;
@@ -4947,7 +4948,7 @@ PickKeyboard(ClientPtr client)
     {
         if (ptr != kbd && 
             IsKeyboardDevice(kbd) && 
-            ptr->pSprite == kbd->pSprite)
+            ptr->spriteInfo->sprite == kbd->spriteInfo->sprite)
             return kbd;
         kbd = kbd->next;
     }
diff --git a/dix/getevents.c b/dix/getevents.c
index 3f113fc..e95cadd 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -505,7 +505,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
         return 0;
 
-    if (!coreOnly && (pDev->coreEvents || pDev->isMPDev))
+    if (!coreOnly && (pDev->coreEvents))
         num_events = 2;
     else
         num_events = 1;
@@ -529,10 +529,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
 
     ms = GetTimeInMillis();
 
-    if (!pDev->coreEvents || pDev->isMPDev)
-        pointer = pDev;
-    else 
-        pointer = inputInfo.pointer;
+    pointer = pDev;
 
     /* Set x and y based on whether this is absolute or relative, and
      * accelerate if we need to. */
@@ -585,11 +582,6 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
-    if (pDev->coreEvents && !pDev->isMPDev) {
-        /* set the virtual core pointer's coordinates */
-        inputInfo.pointer->valuator->lastx = x;
-        inputInfo.pointer->valuator->lasty = y;
-    }
     pDev->valuator->lastx = x;
     pDev->valuator->lasty = y;
 
@@ -623,8 +615,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
         }
     }
 
-    /* MPX devices always send core events */
-    if (coreOnly || pDev->coreEvents || pDev->isMPDev) {
+    if (coreOnly || pDev->coreEvents) {
         events->u.u.type = type;
         events->u.keyButtonPointer.time = ms;
         events->u.keyButtonPointer.rootX = x;
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index db39980..a9ce211 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -171,7 +171,7 @@ xf86ActivateDevice(LocalDevicePtr local)
         local->dev = dev;      
         
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE; 
-        dev->isMPDev = !(local->flags & XI86_SHARED_POINTER);
+        dev->spriteInfo->spriteOwner = !(local->flags & XI86_SHARED_POINTER);
 
 #ifdef XKB
         if (!IsPointerDevice(dev))
diff --git a/include/inputstr.h b/include/inputstr.h
index 8c3e560..d4ba811 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -322,6 +322,15 @@ typedef struct _GrabInfoRec {
     } sync;
 } GrabInfoRec, *GrabInfoPtr;
 
+typedef struct _SpriteInfoRec {
+    /* sprite must always point to a valid sprite. For devices sharing the
+     * sprite, let sprite point to a paired spriteOwner's sprite. */
+    SpritePtr           sprite;      /* sprite information */
+    Bool                spriteOwner; /* True if device owns the sprite */
+    DeviceIntPtr        paired;      /* the real owner of the sprite or
+                                        NULL if spriteOwner is TRUE*/
+} SpriteInfoRec, *SpriteInfoPtr;
+
 typedef struct _DeviceIntRec {
     DeviceRec	public;
     DeviceIntPtr next;
@@ -358,13 +367,7 @@ typedef struct _DeviceIntRec {
     DevUnion		*devPrivates;
     int			nPrivates;
     DeviceUnwrapProc    unwrapProc;
-    Bool                isMPDev;           /* TRUE if multipointer device */
-    /* Each device has a sprite. However, keyboards and shared pointers do
-       not in fact own a sprite but rather have their pointer set to the
-       sprite of another device. pSprite always has to point to a valid
-       sprite. spriteOwner indicates whether it is the device's sprite. */
-    SpritePtr           pSprite;        /* sprite information */
-    Bool                spriteOwner;    /* FALSE if shared sprite, see above*/
+    SpriteInfoPtr       spriteInfo;
 } DeviceIntRec;
 
 typedef struct {
diff --git a/mi/mieq.c b/mi/mieq.c
index 6ed5ef3..4949f20 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -115,7 +115,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
                                       &laste->event[0];
 
     /* avoid merging events from different devices */
-    if (e->u.u.type == MotionNotify && pDev->isMPDev)
+    if (e->u.u.type == MotionNotify)
         isMotion = pDev->id;
     else if (e->u.u.type == MotionNotify)
         isMotion = inputInfo.pointer->id;
@@ -235,10 +235,7 @@ mieqProcessInputEvents()
             else if (e->event[0].u.u.type == MotionNotify ||
                      e->event[0].u.u.type == ButtonPress ||
                      e->event[0].u.u.type == ButtonRelease) {
-                if (!e->pDev->isMPDev)
-                    SwitchCorePointer(e->pDev);
                 dev = inputInfo.pointer;
-
             }
             else {
                 dev = e->pDev;
@@ -252,8 +249,7 @@ mieqProcessInputEvents()
         }
 
         /* Update the sprite now. Next event may be from different device. */
-        if (e->event[0].u.u.type == MotionNotify && 
-                (e->pDev->isMPDev || e->pDev->coreEvents))
+        if (e->event[0].u.u.type == MotionNotify && e->pDev->coreEvents)
         {
             miPointerUpdateSprite(e->pDev);
         }
diff --git a/mi/mipointer.c b/mi/mipointer.c
index edb5c5f..3c09064 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -346,8 +346,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     int			x, y, devx, devy;
     miPointerPtr        pPointer;
 
-    if (!pDev || pDev == inputInfo.pointer || 
-            !(pDev->coreEvents || pDev->isMPDev))
+    if (!pDev || pDev == inputInfo.pointer || !pDev->coreEvents)
         return;
 
     pPointer = MIPOINTER(pDev);
@@ -481,8 +480,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     if (!pScreen)
 	return;	    /* called before ready */
 
-    if (!pDev || 
-            !(pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev))
+    if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer))
         return;
 
     if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
@@ -574,7 +572,7 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
     SetupScreen(pScreen);
 
 
-    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev)
+    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer)
         && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
     {
 	pPointer->devx = x;
commit e54311395e1e7ae458c8ce59da0914706c4a04f6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Mar 25 09:41:33 2007 +0930

    dix:    Increase allocation size for core keyboard keymap to avoid buffer
            overrun when copying keymap from extension devices.

diff --git a/dix/devices.c b/dix/devices.c
index 579203f..10843d4 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -259,7 +259,7 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
         keySyms.mapWidth = 4;
         keySyms.map = (KeySym *)xcalloc(sizeof(KeySym),
                                         (keySyms.maxKeyCode -
-                                         keySyms.minKeyCode) *
+                                         keySyms.minKeyCode + 1) *
                                         keySyms.mapWidth);
         if (!keySyms.map) {
             ErrorF("Couldn't allocate core keymap\n");
commit f8cd19bd1692d12a6047c088a626a6ae715d469d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Mar 22 17:47:01 2007 +1030

    Xi:     add GetClientPointer and GetPointerPairing requests.
    
    dix:    use PickKeyboard for ProcSetInputFocus and ProcGetInputFocus instead
            of the core keyboard.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 16d0e8d..9b1253e 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -32,6 +32,8 @@ libXi_la_SOURCES =	\
 	extinit.c \
 	getbmap.c \
 	getbmap.h \
+	getcptr.c \
+	getcptr.h \
 	getdctl.c \
 	getdctl.h \
 	getfctl.c \
@@ -42,6 +44,8 @@ libXi_la_SOURCES =	\
 	getkmap.h \
 	getmmap.c \
 	getmmap.h \
+	getpairp.c \
+	getpairp.h \
 	getprop.c \
 	getprop.h \
 	getselev.c \
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 672d333..3766a95 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -86,11 +86,13 @@ SOFTWARE.
 #include "devbell.h"
 #include "getbmap.h"
 #include "getbmap.h"
+#include "getcptr.h"
 #include "getdctl.h"
 #include "getfctl.h"
 #include "getfocus.h"
 #include "getkmap.h"
 #include "getmmap.h"
+#include "getpairp.h"
 #include "getprop.h"
 #include "getselev.h"
 #include "getvers.h"
@@ -370,6 +372,10 @@ ProcIDispatch(register ClientPtr client)
         return ProcXQueryWindowAccess(client);
     else if (stuff->data == X_SetClientPointer)
         return ProcXSetClientPointer(client);
+    else if (stuff->data == X_GetClientPointer)
+        return ProcXGetClientPointer(client);
+    else if (stuff->data == X_GetPairedPointer)
+        return ProcXGetPairedPointer(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -477,6 +483,10 @@ SProcIDispatch(register ClientPtr client)
         return SProcXQueryWindowAccess(client);
     else if (stuff->data == X_SetClientPointer)
         return SProcXSetClientPointer(client);
+    else if (stuff->data == X_GetClientPointer)
+        return SProcXGetClientPointer(client);
+    else if (stuff->data == X_GetPairedPointer)
+        return SProcXGetPairedPointer(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -561,6 +571,10 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
     else if (rep->RepType == X_QueryWindowAccess)
         SRepXQueryWindowAccess(client, len,
                                (xQueryWindowAccessReply*) rep);
+    else if (rep->RepType == X_GetClientPointer)
+        SRepXGetClientPointer(client, len, (xGetClientPointerReply*) rep);
+    else if (rep->RepType == X_GetPairedPointer)
+        SRepXGetPairedPointer(client, len, (xGetPairedPointerReply*) rep);
     else {
 	FatalError("XINPUT confused sending swapped reply");
     }
diff --git a/Xi/getcptr.c b/Xi/getcptr.c
new file mode 100644
index 0000000..d9ca4d3
--- /dev/null
+++ b/Xi/getcptr.c
@@ -0,0 +1,111 @@
+/*
+
+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/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 "getcptr.h"
+
+/***********************************************************************
+ * This procedure allows a client to query another client's client pointer
+ * setting.
+ */
+
+int
+SProcXGetClientPointer(ClientPtr client)
+{
+    char n;
+    REQUEST(xGetClientPointerReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->win, n);
+    return ProcXGetClientPointer(client);
+}
+
+int ProcXGetClientPointer(ClientPtr client)
+{
+    int err;
+    WindowPtr win;
+    ClientPtr winclient;
+    xGetClientPointerReply rep;
+    REQUEST(xGetClientPointerReq);
+    REQUEST_SIZE_MATCH(xGetClientPointerReq);
+
+    err = dixLookupWindow(&win, stuff->win, client, DixReadAccess);
+    if (err != Success)
+    {
+        SendErrorToClient(client, IReqCode, X_GetClientPointer, 
+                stuff->win, err); 
+        return Success;
+    }
+
+    winclient = wClient(win);
+
+    rep.repType = X_Reply;
+    rep.RepType = X_GetClientPointer;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.set = (winclient->clientPtr != NULL);
+    rep.deviceid = (winclient->clientPtr) ? winclient->clientPtr->id : 0;
+
+    WriteReplyToClient(client, sizeof(xGetClientPointerReply), &rep);
+    return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XGetClientPointer function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void 
+SRepXGetClientPointer(ClientPtr client, int size, 
+        xGetClientPointerReply* rep)
+{
+    char n;
+    swaps(&rep->sequenceNumber, n);
+    swapl(&rep->length, n);
+    WriteToClient(client, size, (char *)rep);
+}
+
diff --git a/Xi/getcptr.h b/Xi/getcptr.h
new file mode 100644
index 0000000..456d1ba
--- /dev/null
+++ b/Xi/getcptr.h
@@ -0,0 +1,43 @@
+/************************************************************
+
+Copyright 2007 by Peter Hutterer <peter at cs.unisa.edu.au>
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the above listed
+copyright holder(s) not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef GETCPTR_H
+#define GETCPTR_H 1
+int SProcXGetClientPointer(ClientPtr /* client */
+        );
+
+int ProcXGetClientPointer(ClientPtr /* client */
+        );
+
+void SRepXGetClientPointer(ClientPtr /* client */,
+        int /* size */,
+        xGetClientPointerReply* /* rep */
+        );
+
+#endif /* GETCPTR_H */
diff --git a/Xi/getpairp.c b/Xi/getpairp.c
new file mode 100644
index 0000000..4f1ff03
--- /dev/null
+++ b/Xi/getpairp.c
@@ -0,0 +1,110 @@
+/*
+
+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 <X11/X.h>	/* for inputstr.h    */
+#include <X11/Xproto.h>	/* Request macro     */
+#include "inputstr.h"	/* DeviceIntPtr      */
+#include "windowstr.h"	/* window structure  */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "extinit.h"	/* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+#endif
+
+#include "getpairp.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to query the paired pointer for a keyboard
+ * device.
+ *
+ */
+
+int
+SProcXGetPairedPointer(ClientPtr client)
+{
+    char n;
+    REQUEST(xGetPairedPointerReq);
+    swaps(&stuff->length, n);
+    return (ProcXGetPairedPointer(client));
+}
+
+int 
+ProcXGetPairedPointer(ClientPtr client)
+{
+    xGetPairedPointerReply rep;
+    DeviceIntPtr kbd, ptr;
+
+    REQUEST(xGetPairedPointerReq);
+    REQUEST_SIZE_MATCH(xGetPairedPointerReq);
+
+    kbd = LookupDeviceIntRec(stuff->deviceid);
+    if (!kbd || !kbd->key) {
+        SendErrorToClient(client, IReqCode, X_GetPairedPointer,
+                stuff->deviceid, BadDevice);
+        return Success;
+    }
+
+    ptr = GetPairedPointer(kbd);
+
+    rep.repType = X_Reply;
+    rep.RepType = X_GetPairedPointer;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    if (ptr == inputInfo.pointer)
+    {
+        rep.paired = FALSE;
+        rep.deviceid = 0;
+    } else 
+    {
+        rep.paired = TRUE;
+        rep.deviceid = ptr->id;
+    }
+    WriteReplyToClient(client, sizeof(xGetPairedPointerReply), &rep);
+    return Success;
+}
+
+void
+SRepXGetPairedPointer(ClientPtr client, int size,
+        xGetPairedPointerReply* rep)
+{
+    char n;
+
+    swaps(&rep->sequenceNumber, n);
+    swapl(&rep->length, n);
+    WriteToClient(client, size, (char *)rep);
+}
diff --git a/Xi/getpairp.h b/Xi/getpairp.h
new file mode 100644
index 0000000..9b4759e
--- /dev/null
+++ b/Xi/getpairp.h
@@ -0,0 +1,45 @@
+/*
+
+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 GETPAIRP_H
+#define GETPAIRP_H 1
+
+int SProcXGetPairedPointer(ClientPtr /* client */
+        );
+int ProcXGetPairedPointer(ClientPtr /* client */
+        );
+void SRepXGetPairedPointer(ClientPtr /* client */,
+        int /* size */,
+        xGetPairedPointerReply* /* rep */
+        );
+
+#endif /* GETPAIRP_H */
diff --git a/Xi/querydp.c b/Xi/querydp.c
index c1ba2ee..a24dad0 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -164,3 +164,4 @@ SRepXQueryDevicePointer(ClientPtr client, int size,
     swapl(&rep->length, n);
     WriteToClient(client, size, (char *)rep);
 }
+
diff --git a/dix/cursor.c b/dix/cursor.c
index 5b5c498..c58e2fa 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -131,7 +131,6 @@ FreeCursor(pointer value, XID cid)
     }
     FreeCursorBits(pCurs->bits);
     xfree( pCurs);
-    MPXDBG("freeing memory for cursor\n");
     return(Success);
 }
 
diff --git a/dix/events.c b/dix/events.c
index c9b5a4f..65d6eae 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3897,6 +3897,7 @@ int
 ProcSetInputFocus(client)
     ClientPtr client;
 {
+    DeviceIntPtr kbd = PickKeyboard(client);
     REQUEST(xSetInputFocusReq);
 
     REQUEST_SIZE_MATCH(xSetInputFocusReq);
@@ -3904,16 +3905,17 @@ ProcSetInputFocus(client)
     if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
 	return Success;
 
-    return SetInputFocus(client, inputInfo.keyboard, stuff->focus,
+    return SetInputFocus(client, kbd, stuff->focus,
 			 stuff->revertTo, stuff->time, FALSE);
 }
 
 int
 ProcGetInputFocus(ClientPtr client)
 {
+    DeviceIntPtr kbd = PickKeyboard(client);
     xGetInputFocusReply rep;
     /* REQUEST(xReq); */
-    FocusClassPtr focus = inputInfo.keyboard->focus;
+    FocusClassPtr focus = kbd->focus;
 
     REQUEST_SIZE_MATCH(xReq);
     rep.type = X_Reply;
commit 0acf993e2878d0866fd4e2db8252c1ea6841e494
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Mar 19 16:11:01 2007 +1030

    dix:    Move sprite initalization/pairing from ActivateDevice to
            EnableDevice.
            zero out spriteTrace, otherwise GetCurrentRootWindow() may return
            invalid data.
    
            Evdev adds previously hotplugged devices on its own when rescanning,
            and ActivateDevice does not get called for those devices. Sprites need
            to be initialized or paired before the device gets started, so the
            safest place to do so is EnableDevice (which actually does get called
            by the evdev driver).

diff --git a/dix/devices.c b/dix/devices.c
index 927d16e..579203f 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -173,6 +173,11 @@ EnableDevice(DeviceIntPtr dev)
     dev->enabled = TRUE;
     *prev = dev->next;
 
+    if (IsPointerDevice(dev) && dev->isMPDev)
+        InitializeSprite(dev, GetCurrentRootWindow());
+    else
+        PairDevices(NULL, inputInfo.pointer, dev);
+
     for (prev = &inputInfo.devices; *prev; prev = &(*prev)->next)
         ;
     *prev = dev;
@@ -221,11 +226,6 @@ ActivateDevice(DeviceIntPtr dev)
     SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
                           (xEvent *) &ev, 1);
 
-    if (IsPointerDevice(dev) && dev->isMPDev)
-        InitializeSprite(dev, GetCurrentRootWindow());
-    else
-        PairDevices(NULL, inputInfo.pointer, dev);
-
     return ret;
 }
 
@@ -448,7 +448,6 @@ InitAndStartDevices()
             PairDevices(NULL, GuessFreePointerDevice(), dev);
     }
 
-
     return Success;
 }
 
diff --git a/dix/events.c b/dix/events.c
index dc9c4e5..c9b5a4f 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4290,6 +4290,11 @@ InitEvents()
     {
 	spriteTraceSize = 32;
 	spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr));
+        /* FIXME: spriteTrace[0] needs to be NULL, otherwise
+         * GetCurrentRootWindow() in EnableDevice() may return a invalid
+         * value. (whot)
+         */
+        memset(spriteTrace, 0, 32 * sizeof(WindowPtr));
 	if (!spriteTrace)
 	    FatalError("failed to allocate spriteTrace");
     }
commit 015d728bcde5b16a72a976579755421e3023626b
Merge: 65b0eb6... b167583...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Mar 19 09:42:56 2007 +1030

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	dix/devices.c
    	dix/events.c
    	mi/misprite.c

diff --cc dix/devices.c
index 0c1553e,8eb54f7..927d16e
--- a/dix/devices.c
+++ b/dix/devices.c
@@@ -541,19 -493,11 +541,22 @@@ CloseDevice(DeviceIntPtr dev
      while (dev->xkb_interest)
  	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
  #endif
 +    
 +    if (DevHasCursor(dev))
 +        xfree((pointer)dev->pSprite);
 +
 +    /* a client may have the device set as client pointer */
 +    for (j = 0; j < currentMaxClients; j++)
 +    {
 +        if (clients[j]->clientPtr == dev)
 +            PickPointer(clients[j]);
 +    }
  
+     if (dev->devPrivates)
+ 	xfree(dev->devPrivates);
+ 
 -    xfree(dev->sync.event);
 +    xfree(dev->coreGrab.sync.event);
 +    xfree(dev->deviceGrab.sync.event);
      xfree(dev);
  }
  
@@@ -1888,9 -1822,9 +1891,9 @@@ ProcGetPointerControl(ClientPtr client
  }
  
  void
- MaybeStopHint(register DeviceIntPtr dev, ClientPtr client)
+ MaybeStopHint(DeviceIntPtr dev, ClientPtr client)
  {
 -    GrabPtr grab = dev->grab;
 +    GrabPtr grab = dev->coreGrab.grab;
  
      if ((grab && SameClient(grab, client) &&
  	 ((grab->eventMask & PointerMotionHintMask) ||
diff --cc dix/events.c
index ca12d22,c0b62b8..dc9c4e5
--- a/dix/events.c
+++ b/dix/events.c
@@@ -805,15 -761,12 +805,15 @@@ CheckPhysLimits
  
  static void
  CheckVirtualMotion(
-     register DeviceIntPtr pDev,
-     register QdEventPtr qe,
-     register WindowPtr pWin)
++    DeviceIntPtr pDev,
+     QdEventPtr qe,
+     WindowPtr pWin)
  {
 +    SpritePtr pSprite = pDev->pSprite;
 +
  #ifdef PANORAMIX
      if(!noPanoramiXExtension) {
 -	XineramaCheckVirtualMotion(qe, pWin);
 +	XineramaCheckVirtualMotion(pDev, qe, pWin);
  	return;
      }
  #endif
@@@ -934,12 -883,10 +934,12 @@@ IsParent(WindowPtr a, WindowPtr b
  }
  
  static void
 -PostNewCursor(void)
 +PostNewCursor(DeviceIntPtr pDev)
  {
-     register    WindowPtr win;
-     register    GrabPtr grab = pDev->coreGrab.grab;
+     WindowPtr win;
 -    GrabPtr grab = inputInfo.pointer->grab;
++    GrabPtr grab = pDev->coreGrab.grab;
 +    SpritePtr   pSprite = pDev->pSprite;
 +    CursorPtr   pCursor;
  
      if (syncEvents.playingEvents)
  	return;
@@@ -1046,10 -984,9 +1046,10 @@@ NoticeEventTime(xEvent *xE
  void
  EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
  {
-     register QdEventPtr tail = *syncEvents.pendtail;
-     register QdEventPtr qe;
+     QdEventPtr tail = *syncEvents.pendtail;
+     QdEventPtr qe;
      xEvent		*qxE;
 +    SpritePtr pSprite = device->pSprite;
  
      NoticeTime(xE);
  
@@@ -1122,9 -1059,8 +1122,9 @@@
  static void
  PlayReleasedEvents(void)
  {
-     register QdEventPtr *prev, qe;
-     register DeviceIntPtr dev;
+     QdEventPtr *prev, qe;
+     DeviceIntPtr dev;
 +    DeviceIntPtr pDev;
  
      prev = &syncEvents.pending;
      while ( (qe = *prev) )
@@@ -1169,9 -1104,9 +1169,9 @@@
  }
  
  static void
- FreezeThaw(register DeviceIntPtr dev, Bool frozen)
+ FreezeThaw(DeviceIntPtr dev, Bool frozen)
  {
 -    dev->sync.frozen = frozen;
 +    dev->coreGrab.sync.frozen = frozen;
      if (frozen)
  	dev->public.processInputProc = dev->public.enqueueInputProc;
      else
@@@ -1181,17 -1116,16 +1181,17 @@@
  void
  ComputeFreezes()
  {
-     register DeviceIntPtr replayDev = syncEvents.replayDev;
-     register int i;
+     DeviceIntPtr replayDev = syncEvents.replayDev;
+     int i;
      WindowPtr w;
-     register xEvent *xE;
+     xEvent *xE;
      int count;
      GrabPtr grab;
-     register DeviceIntPtr dev;
+     DeviceIntPtr dev;
  
      for (dev = inputInfo.devices; dev; dev = dev->next)
 -	FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
 +	FreezeThaw(dev, dev->coreGrab.sync.other || 
 +                (dev->coreGrab.sync.state >= FROZEN));
      if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
  	return;
      syncEvents.playingEvents = TRUE;
@@@ -1283,20 -1198,20 +1283,20 @@@ ScreenRestructured (ScreenPtr pScreen
  #endif
  
  void
- CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
+ CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
  {
-     register GrabPtr grab = thisDev->coreGrab.grab;
-     register DeviceIntPtr dev;
 -    GrabPtr grab = thisDev->grab;
++    GrabPtr grab = thisDev->coreGrab.grab;
+     DeviceIntPtr dev;
  
      if (thisMode == GrabModeSync)
 -	thisDev->sync.state = FROZEN_NO_EVENT;
 +	thisDev->coreGrab.sync.state = FROZEN_NO_EVENT;
      else
      {	/* free both if same client owns both */
 -	thisDev->sync.state = THAWED;
 -	if (thisDev->sync.other &&
 -	    (CLIENT_BITS(thisDev->sync.other->resource) ==
 +	thisDev->coreGrab.sync.state = THAWED;
 +	if (thisDev->coreGrab.sync.other &&
 +	    (CLIENT_BITS(thisDev->coreGrab.sync.other->resource) ==
  	     CLIENT_BITS(grab->resource)))
 -	    thisDev->sync.other = NullGrab;
 +	    thisDev->coreGrab.sync.other = NullGrab;
      }
      for (dev = inputInfo.devices; dev; dev = dev->next)
      {
@@@ -1317,12 -1232,11 +1317,12 @@@
  }
  
  void
- ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab, 
+ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 
                      TimeStamp time, Bool autoGrab)
  {
 -    WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
 -				     : sprite.win;
 +    WindowPtr oldWin = (mouse->coreGrab.grab) ? 
 +                        mouse->coreGrab.grab->window
 +                        : mouse->pSprite->win;
  
      if (grab->confineTo)
      {
@@@ -1347,25 -1260,24 +1347,25 @@@
  }
  
  void
- DeactivatePointerGrab(register DeviceIntPtr mouse)
+ DeactivatePointerGrab(DeviceIntPtr mouse)
  {
-     register GrabPtr grab = mouse->coreGrab.grab;
-     register DeviceIntPtr dev;
 -    GrabPtr grab = mouse->grab;
++    GrabPtr grab = mouse->coreGrab.grab;
+     DeviceIntPtr dev;
  
      mouse->valuator->motionHintWindow = NullWindow;
 -    mouse->grab = NullGrab;
 -    mouse->sync.state = NOT_GRABBED;
 -    mouse->fromPassiveGrab = FALSE;
 +    mouse->coreGrab.grab = NullGrab;
 +    mouse->coreGrab.sync.state = NOT_GRABBED;
 +    mouse->coreGrab.fromPassiveGrab = FALSE;
      for (dev = inputInfo.devices; dev; dev = dev->next)
      {
 -	if (dev->sync.other == grab)
 -	    dev->sync.other = NullGrab;
 +	if (dev->coreGrab.sync.other == grab)
 +	    dev->coreGrab.sync.other = NullGrab;
      }
 -    DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
 +    DoEnterLeaveEvents(mouse, grab->window, 
 +                       mouse->pSprite->win, NotifyUngrab);
      if (grab->confineTo)
 -	ConfineCursorToWindow(ROOT, FALSE, FALSE);
 -    PostNewCursor();
 +	ConfineCursorToWindow(mouse, ROOT, FALSE, FALSE);
 +    PostNewCursor(mouse);
      if (grab->cursor)
  	FreeCursor(grab->cursor, (Cursor)0);
      ComputeFreezes();
@@@ -1398,12 -1310,12 +1398,12 @@@ ActivateKeyboardGrab(DeviceIntPtr keybd
  }
  
  void
- DeactivateKeyboardGrab(register DeviceIntPtr keybd)
+ DeactivateKeyboardGrab(DeviceIntPtr keybd)
  {
-     register GrabPtr grab = keybd->coreGrab.grab;
-     register DeviceIntPtr dev;
-     register WindowPtr focusWin = keybd->focus ? keybd->focus->win
 -    GrabPtr grab = keybd->grab;
++    GrabPtr grab = keybd->coreGrab.grab;
+     DeviceIntPtr dev;
+     WindowPtr focusWin = keybd->focus ? keybd->focus->win
 -					       : sprite.win;
 +					       : keybd->pSprite->win;
  
      if (focusWin == FollowKeyboardWin)
  	focusWin = inputInfo.keyboard->focus->win;
@@@ -1434,11 -1338,9 +1434,11 @@@ AllowSome(ClientPtr client
  {
      Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
      TimeStamp grabTime;
-     register DeviceIntPtr dev;
+     DeviceIntPtr dev;
 +    GrabInfoPtr devgrabinfo, 
 +                grabinfo = (core) ? &thisDev->coreGrab : &thisDev->deviceGrab;
  
 -    thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
 +    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
      thisSynced = FALSE;
      otherGrabbed = FALSE;
      othersFrozen = TRUE;
@@@ -1551,11 -1442,11 +1551,11 @@@
  }
  
  int
- ProcAllowEvents(register ClientPtr client)
+ ProcAllowEvents(ClientPtr client)
  {
      TimeStamp		time;
 -    DeviceIntPtr	mouse = inputInfo.pointer;
 -    DeviceIntPtr	keybd = inputInfo.keyboard;
 +    DeviceIntPtr	mouse = PickPointer(client);
 +    DeviceIntPtr	keybd = PickKeyboard(client);
      REQUEST(xAllowEventsReq);
  
      REQUEST_SIZE_MATCH(xAllowEventsReq);
@@@ -1704,8 -1589,8 +1704,8 @@@ TryClientEvents (ClientPtr client, xEve
  }
  
  int
- DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 -DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, 
 -                      Mask filter, GrabPtr grab, int mskidx)
++DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
 +        *pEvents, int count, Mask filter, GrabPtr grab, int mskidx)
  {
      int deliveries = 0, nondeliveries = 0;
      int attempt;
@@@ -2255,90 -2092,46 +2255,90 @@@ void ReinitializeRootWindow(WindowPtr w
  #endif
  
  void
- DefineInitialRootWindow(register WindowPtr win)
+ DefineInitialRootWindow(WindowPtr win)
  {
 -    ScreenPtr pScreen = win->drawable.pScreen;
 -
 -    sprite.hotPhys.pScreen = pScreen;
 -    sprite.hotPhys.x = pScreen->width / 2;
 -    sprite.hotPhys.y = pScreen->height / 2;
 -    sprite.hot = sprite.hotPhys;
 -    sprite.hotLimits.x2 = pScreen->width;
 -    sprite.hotLimits.y2 = pScreen->height;
 +    DeviceIntPtr pDev = inputInfo.devices;
 +
  #ifdef XEVIE
 -    xeviewin =
 +    xeviewin = win;
  #endif
 -    sprite.win = win;
 -    sprite.current = wCursor (win);
 -    sprite.current->refcnt++;
 -    spriteTraceGood = 1;
      ROOT = win;
 -    (*pScreen->CursorLimits) (
 -	pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
 -    sprite.confined = FALSE;
 -    (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
 -    (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
 -    (*pScreen->DisplayCursor) (pScreen, sprite.current);
  
 +    InitializeSprite(inputInfo.pointer, win);
 +
 +    while (pDev)
 +    {
 +        if (DevHasCursor(pDev))
 +            InitializeSprite(pDev, win);
 +        pDev = pDev->next;
 +    }
 +}
 +
 +void 
 +InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
 +{
 +    SpritePtr pSprite;
 +    ScreenPtr pScreen; 
 +
 +    if (!pDev->pSprite)
 +    {
 +        pDev->pSprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec));
 +        if (!pDev->pSprite)
 +            FatalError("InitializeSprite: failed to allocate sprite struct");
 +    }
 +
 +    pSprite = pDev->pSprite;
 +    pDev->spriteOwner = TRUE;
 +
 +    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
 +    pSprite->hot.pScreen = pScreen;
 +    pSprite->hotPhys.pScreen = pScreen;
 +    if (pScreen)
 +    {
 +        pSprite->hotPhys.x = pScreen->width / 2;
 +        pSprite->hotPhys.y = pScreen->height / 2;
 +        pSprite->hotLimits.x2 = pScreen->width;
 +        pSprite->hotLimits.y2 = pScreen->height;
 +    }
 +
 +    pSprite->hot = pSprite->hotPhys;
 +    pSprite->win = pWin;
 +
 +    if (pWin)
 +    {
 +        pSprite->current = wCursor(pWin);
 +        pSprite->current->refcnt++;
 +    } else
 +        pSprite->current = NullCursor;
 +
 +    if (pScreen)
 +    {
 +        (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
 +                                   &pSprite->hotLimits, &pSprite->physLimits);
 +        pSprite->confined = FALSE;
 +
 +        (*pScreen->ConstrainCursor) (pDev, pScreen,
 +                                     &pSprite->physLimits);
 +        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
 +                                       pSprite->hot.y,
 +                                       FALSE); 
 +        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
 +    }
  #ifdef PANORAMIX
      if(!noPanoramiXExtension) {
 -	sprite.hotLimits.x1 = -panoramiXdataPtr[0].x;
 -	sprite.hotLimits.y1 = -panoramiXdataPtr[0].y;
 -	sprite.hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
 -	sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
 -	sprite.physLimits = sprite.hotLimits;
 -	sprite.confineWin = NullWindow;
 +        pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
 +        pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
 +        pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
 +        pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
 +        pSprite->physLimits = pSprite->hotLimits;
 +        pSprite->confineWin = NullWindow;
  #ifdef SHAPE
 -        sprite.hotShape = NullRegion;
 +        pSprite->hotShape = NullRegion;
  #endif
 -	sprite.screen = pScreen;
 -	/* gotta UNINIT these someplace */
 -	REGION_NULL(pScreen, &sprite.Reg1);
 -	REGION_NULL(pScreen, &sprite.Reg2);
 +        pSprite->screen = pScreen;
 +        /* gotta UNINIT these someplace */
 +        REGION_NULL(pScreen, &pSprite->Reg1);
 +        REGION_NULL(pScreen, &pSprite->Reg2);
      }
  #endif
  }
@@@ -2632,14 -2411,13 +2632,14 @@@ BorderSizeNotEmpty(DeviceIntPtr pDev, W
  static Bool
  CheckPassiveGrabsOnWindow(
      WindowPtr pWin,
-     register DeviceIntPtr device,
-     register xEvent *xE,
+     DeviceIntPtr device,
+     xEvent *xE,
      int count)
  {
-     register GrabPtr grab = wPassiveGrabs(pWin);
+     GrabPtr grab = wPassiveGrabs(pWin);
      GrabRec tempGrab;
 +    GrabInfoPtr grabinfo;
-     register xEvent *dxE;
+     xEvent *dxE;
  
      if (!grab)
  	return FALSE;
@@@ -2809,22 -2585,13 +2809,22 @@@ DeliverFocusedEvent(DeviceIntPtr keybd
  }
  
  void
- DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev, 
+ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, 
                      Bool deactivateGrab, int count)
  {
-     register GrabPtr grab;
 -    GrabPtr grab = thisDev->grab;
++    GrabPtr grab;
 +    GrabInfoPtr grabinfo;
      int deliveries = 0;
-     register DeviceIntPtr dev;
-     register xEvent *dxE;
+     DeviceIntPtr dev;
+     xEvent *dxE;
 +    SpritePtr pSprite = thisDev->pSprite;
 +
 +    if (xE->u.u.type & EXTENSION_EVENT_BASE)
 +        grabinfo = &thisDev->deviceGrab;
 +    else
 +        grabinfo = &thisDev->coreGrab;
 +
 +    grab = grabinfo->grab;
  
      if (grab->ownerEvents)
      {
@@@ -2912,15 -2674,13 +2912,14 @@@ ProcessKeyboardEvent (xEvent *xE, Devic
  #endif
  {
      int             key, bit;
-     register BYTE   *kptr;
-     register int    i;
-     register CARD8  modifiers;
-     register CARD16 mask;
-     register GrabPtr         grab;
+     BYTE   *kptr;
+     int    i;
+     CARD8  modifiers;
+     CARD16 mask;
 -    GrabPtr         grab = keybd->grab;
++    GrabPtr         grab;
 +    GrabInfoPtr     grabinfo;
      Bool            deactivateGrab = FALSE;
-     register KeyClassPtr keyc = keybd->key;
- 
+     KeyClassPtr keyc = keybd->key;
  #ifdef XEVIE
      static Window           rootWin = 0;
  
@@@ -3110,16 -2863,14 +3109,16 @@@ FixKeyState (xEvent *xE, DeviceIntPtr k
  
  void
  #ifdef XKB
- CoreProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count)
+ CoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
  #else
- ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count)
+ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
  #endif
  {
 -    GrabPtr	grab = mouse->grab;
 +    GrabPtr	        grab = mouse->coreGrab.grab;
      Bool                deactivateGrab = FALSE;
-     register ButtonClassPtr butc = mouse->button;
 -    ButtonClassPtr butc = mouse->button;
++    ButtonClassPtr      butc = mouse->button;
 +    SpritePtr           pSprite = mouse->pSprite;
 +
  #ifdef XKB
      XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
  #endif
@@@ -3163,12 -2914,12 +3162,12 @@@
      }
      if (xE->u.u.type != MotionNotify)
      {
- 	register int  key;
- 	register BYTE *kptr;
+ 	int  key;
+ 	BYTE *kptr;
  	int           bit;
  
 -	XE_KBPTR.rootX = sprite.hot.x;
 -	XE_KBPTR.rootY = sprite.hot.y;
 +	XE_KBPTR.rootX = pSprite->hot.x;
 +	XE_KBPTR.rootY = pSprite->hot.y;
  
  	key = xE->u.u.detail;
  	kptr = &butc->down[key >> 3];
@@@ -3437,21 -3187,16 +3436,21 @@@ EnterLeaveEvent
      int type,
      int mode,
      int detail,
-     register WindowPtr pWin,
+     WindowPtr pWin,
      Window child)
  {
 -    xEvent		event;
 -    DeviceIntPtr keybd = inputInfo.keyboard;
 +    xEvent              event;
-     register DeviceIntPtr keybd = inputInfo.keyboard;
++    DeviceIntPtr        keybd = inputInfo.keyboard;
      WindowPtr		focus;
-     register DeviceIntPtr mouse = pDev;
 -    DeviceIntPtr mouse = inputInfo.pointer;
 -    GrabPtr	grab = mouse->grab;
++    DeviceIntPtr        mouse = pDev;
 +    GrabPtr	        grab = mouse->coreGrab.grab;
 +    GrabPtr	        devgrab = mouse->deviceGrab.grab;
      Mask		mask;
  
 +    deviceEnterNotify   *devEnterLeave;
 +    int                 mskidx;
 +    OtherInputMasks     *inputMasks;
 +
      if ((pWin == mouse->valuator->motionHintWindow) &&
  	(detail != NotifyInferior))
  	mouse->valuator->motionHintWindow = NullWindow;
@@@ -3553,18 -3271,14 +3552,18 @@@ EnterNotifies(DeviceIntPtr pDev
  
      if (ancestor == parent)
  	return;
 -    EnterNotifies(ancestor, parent, mode, detail);
 -    EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id);
 -}
 +    EnterNotifies(pDev, ancestor, parent, mode, detail);
 +    EnterLeaveEvent(pDev, EnterNotify, mode, detail, parent,
 +                    child->drawable.id); }
  
  static void
 -LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
 +LeaveNotifies(DeviceIntPtr pDev, 
 +              WindowPtr child, 
 +              WindowPtr ancestor, 
 +              int mode, 
 +              int detail)
  {
-     register WindowPtr  pWin;
+     WindowPtr  pWin;
  
      if (ancestor == child)
  	return;
@@@ -4044,8 -3744,8 +4043,8 @@@ ProcGrabPointer(ClientPtr client
  int
  ProcChangeActivePointerGrab(ClientPtr client)
  {
 -    DeviceIntPtr device = inputInfo.pointer;
 -    GrabPtr grab = device->grab;
 +    DeviceIntPtr device = PickPointer(client);
-     register GrabPtr grab = device->coreGrab.grab;
++    GrabPtr      grab = device->coreGrab.grab;
      CursorPtr newCursor, oldCursor;
      REQUEST(xChangeActivePointerGrabReq);
      TimeStamp time;
diff --cc hw/xfree86/dri/dri.c
index a4413c7,7bd07c0..05df54a
--- a/hw/xfree86/dri/dri.c
+++ b/hw/xfree86/dri/dri.c
@@@ -70,8 -70,9 +70,10 @@@ SOFTWARE OR THE USE OR OTHER DEALINGS I
  #include "mi.h"
  #include "mipointer.h"
  #include "xf86_OSproc.h"
 +#include "inputstr.h"
  
+ #define PCI_BUS_NO_DOMAIN(bus) ((bus) & 0xffu)
+ 
  #if !defined(PANORAMIX)
  extern Bool noPanoramiXExtension;
  #endif
diff --cc hw/xfree86/modes/xf86Cursors.c
index 0000000,009cccf..1564182
mode 000000,100644..100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@@ -1,0 -1,607 +1,608 @@@
+ /*
+  * Copyright © 2007 Keith Packard
+  *
+  * Permission to use, copy, modify, distribute, and sell this software and its
+  * documentation for any purpose is hereby granted without fee, provided that
+  * the above copyright notice appear in all copies and that both that copyright
+  * notice and this permission notice appear in supporting documentation, and
+  * that the name of the copyright holders not be used in advertising or
+  * publicity pertaining to distribution of the software without specific,
+  * written prior permission.  The copyright holders make no representations
+  * about the suitability of this software for any purpose.  It is provided "as
+  * is" without express or implied warranty.
+  *
+  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+  * OF THIS SOFTWARE.
+  */
+ 
+ #ifdef HAVE_XORG_CONFIG_H
+ #include <xorg-config.h>
+ #else
+ #ifdef HAVE_CONFIG_H
+ #include <config.h>
+ #endif
+ #endif
+ 
+ #include <stddef.h>
+ #include <string.h>
+ #include <stdio.h>
+ 
+ #include "xf86.h"
+ #include "xf86DDC.h"
+ #include "xf86Crtc.h"
+ #include "xf86Modes.h"
+ #include "xf86RandR12.h"
+ #include "X11/extensions/render.h"
+ #define DPMS_SERVER
+ #include "X11/extensions/dpms.h"
+ #include "X11/Xatom.h"
+ #ifdef RENDER
+ #include "picturestr.h"
+ #endif
+ #include "cursorstr.h"
++#include "inputstr.h"
+ 
+ /*
+  * Given a screen coordinate, rotate back to a cursor source coordinate
+  */
+ static void
+ xf86_crtc_rotate_coord (Rotation    rotation,
+ 			int	    width,
+ 			int	    height,
+ 			int	    x_dst,
+ 			int	    y_dst,
+ 			int	    *x_src,
+ 			int	    *y_src)
+ {
+     if (rotation & RR_Reflect_X)
+ 	x_dst = width - x_dst - 1;
+     if (rotation & RR_Reflect_Y)
+ 	y_dst = height - y_dst - 1;
+     
+     switch (rotation & 0xf) {
+     case RR_Rotate_0:
+ 	*x_src = x_dst;
+ 	*y_src = y_dst;
+ 	break;
+     case RR_Rotate_90:
+ 	*x_src = height - y_dst - 1;
+ 	*y_src = x_dst;
+ 	break;
+     case RR_Rotate_180:
+ 	*x_src = width - x_dst - 1;
+ 	*y_src = height - y_dst - 1;
+ 	break;
+     case RR_Rotate_270:
+ 	*x_src = y_dst;
+ 	*y_src = width - x_dst - 1;
+ 	break;
+     }
+ }
+ 
+ /*
+  * Convert an x coordinate to a position within the cursor bitmap
+  */
+ static int
+ cursor_bitpos (int flags, int x, Bool mask)
+ {
+     if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)
+ 	mask = !mask;
+     if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED)
+ 	x = (x & ~3) | (3 - (x & 3));
+     if (flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST)
+ 	x = (x & ~7) | (7 - (x & 7));
+     if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1)
+ 	x = (x << 1) + mask;
+     else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8)
+ 	x = ((x & ~7) << 1) | (mask << 3) | (x & 7);
+     else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16)
+ 	x = ((x & ~15) << 1) | (mask << 4) | (x & 15);
+     else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32)
+ 	x = ((x & ~31) << 1) | (mask << 5) | (x & 31);
+     else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)
+ 	x = ((x & ~63) << 1) | (mask << 6) | (x & 63);
+     return x;
+ }
+ 
+ /*
+  * Fetch one bit from a cursor bitmap
+  */
+ static CARD8
+ get_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask)
+ {
+     x = cursor_bitpos (flags, x, mask);
+     image += y * stride;
+     return (image[(x >> 3)] >> (x & 7)) & 1;
+ }
+ 
+ /*
+  * Set one bit in a cursor bitmap
+  */
+ static void
+ set_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask)
+ {
+     x = cursor_bitpos (flags, x, mask);
+     image += y * stride;
+     image[(x >> 3)] |= 1 << (x & 7);
+ }
+     
+ /*
+  * Load a two color cursor into a driver that supports only ARGB cursors
+  */
+ static void
+ xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
+ {
+     ScrnInfoPtr		scrn = crtc->scrn;
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+     CARD32		*cursor_image = (CARD32 *) xf86_config->cursor_image;
+     int			x, y;
+     int			xin, yin;
+     int			stride = cursor_info->MaxWidth >> 2;
+     int			flags = cursor_info->Flags;
+     CARD32		bits;
+ 
+ #ifdef ARGB_CURSOR
+     crtc->cursor_argb = FALSE;
+ #endif
+ 
+     for (y = 0; y < cursor_info->MaxHeight; y++)
+ 	for (x = 0; x < cursor_info->MaxWidth; x++) 
+ 	{
+ 	    xf86_crtc_rotate_coord (crtc->rotation,
+ 				    cursor_info->MaxWidth,
+ 				    cursor_info->MaxHeight,
+ 				    x, y, &xin, &yin);
+ 	    if (get_bit (src, stride, flags, xin, yin, TRUE) ==
+ 		((flags & HARDWARE_CURSOR_INVERT_MASK) == 0))
+ 	    {
+ 		if (get_bit (src, stride, flags, xin, yin, FALSE))
+ 		    bits = xf86_config->cursor_fg;
+ 		else
+ 		    bits = xf86_config->cursor_bg;
+ 	    }
+ 	    else
+ 		bits = 0;
+ 	    cursor_image[y * cursor_info->MaxWidth + x] = bits;
+ 	}
+     crtc->funcs->load_cursor_argb (crtc, cursor_image);
+ }
+ 
+ /*
+  * Set the colors for a two-color cursor (ignore for ARGB cursors)
+  */
+ static void
+ xf86_set_cursor_colors (ScrnInfoPtr scrn, int bg, int fg)
+ {
+     ScreenPtr		screen = scrn->pScreen;
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     CursorPtr		cursor = xf86_config->cursor;
+     int			c;
+     CARD8		*bits = cursor ? cursor->devPriv[screen->myNum] : NULL;
+ 
+     /* Save ARGB versions of these colors */
+     xf86_config->cursor_fg = (CARD32) fg | 0xff000000;
+     xf86_config->cursor_bg = (CARD32) bg | 0xff000000;
+     
+     for (c = 0; c < xf86_config->num_crtc; c++)
+     {
+ 	xf86CrtcPtr crtc = xf86_config->crtc[c];
+ 
+ 	if (crtc->enabled && !crtc->cursor_argb)
+ 	{
+ 	    if (crtc->funcs->load_cursor_image)
+ 		crtc->funcs->set_cursor_colors (crtc, bg, fg);
+ 	    else if (bits)
+ 		xf86_crtc_convert_cursor_to_argb (crtc, bits);
+ 	}
+     }
+ }
+ 
+ static void
+ xf86_crtc_hide_cursor (xf86CrtcPtr crtc)
+ {
+     if (crtc->cursor_shown)
+     {
+ 	crtc->funcs->hide_cursor (crtc);
+ 	crtc->cursor_shown = FALSE;
+     }
+ }
+ 
+ void
+ xf86_hide_cursors (ScrnInfoPtr scrn)
+ {
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     int			c;
+ 
+     xf86_config->cursor_on = FALSE;
+     for (c = 0; c < xf86_config->num_crtc; c++)
+     {
+ 	xf86CrtcPtr crtc = xf86_config->crtc[c];
+ 
+ 	if (crtc->enabled)
+ 	    xf86_crtc_hide_cursor (crtc);
+     }
+ }
+     
+ static void
+ xf86_crtc_show_cursor (xf86CrtcPtr crtc)
+ {
+     if (!crtc->cursor_shown && crtc->cursor_in_range)
+     {
+ 	crtc->funcs->show_cursor (crtc);
+ 	crtc->cursor_shown = TRUE;
+     }
+ }
+ 
+ void
+ xf86_show_cursors (ScrnInfoPtr scrn)
+ {
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     int			c;
+ 
+     xf86_config->cursor_on = TRUE;
+     for (c = 0; c < xf86_config->num_crtc; c++)
+     {
+ 	xf86CrtcPtr crtc = xf86_config->crtc[c];
+ 
+ 	if (crtc->enabled)
+ 	    xf86_crtc_show_cursor (crtc);
+     }
+ }
+     
+ static void
+ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+ {
+     ScrnInfoPtr		scrn = crtc->scrn;
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+     DisplayModePtr	mode = &crtc->mode;
+     int			x_temp;
+     int			y_temp;
+     Bool		in_range;
+ 
+     /* 
+      * Move to crtc coordinate space
+      */
+     x -= crtc->x;
+     y -= crtc->y;
+     
+     /*
+      * Rotate
+      */
+     switch ((crtc->rotation) & 0xf) {
+     case RR_Rotate_0:
+ 	break;
+     case RR_Rotate_90:
+ 	x_temp = y;
+ 	y_temp = mode->VDisplay - cursor_info->MaxWidth - x;
+ 	x = x_temp;
+ 	y = y_temp;
+ 	break;
+     case RR_Rotate_180:
+ 	x_temp = mode->HDisplay - cursor_info->MaxWidth - x;
+ 	y_temp = mode->VDisplay - cursor_info->MaxHeight - y;
+ 	x = x_temp;
+ 	y = y_temp;
+ 	break;
+     case RR_Rotate_270:
+ 	x_temp = mode->HDisplay - cursor_info->MaxHeight -  y;
+ 	y_temp = x;
+ 	x = x_temp;
+ 	y = y_temp;
+ 	break;
+     }
+     
+     /*
+      * Reflect
+      */
+     if (crtc->rotation & RR_Reflect_X)
+ 	x = mode->HDisplay - cursor_info->MaxWidth - x;
+     if (crtc->rotation & RR_Reflect_Y)
+ 	y = mode->VDisplay - cursor_info->MaxHeight - y;
+ 
+     /*
+      * Disable the cursor when it is outside the viewport
+      */
+     in_range = TRUE;
+     if (x >= mode->HDisplay || y >= mode->VDisplay ||
+ 	x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight) 
+     {
+ 	in_range = FALSE;
+ 	x = 0;
+ 	y = 0;
+     }
+ 
+     crtc->cursor_in_range = in_range;
+     
+     if (in_range)
+     {
+ 	crtc->funcs->set_cursor_position (crtc, x, y);
+ 	xf86_crtc_show_cursor (crtc);
+     }
+     else
+ 	xf86_crtc_hide_cursor (crtc);
+ }
+ 
+ static void
+ xf86_set_cursor_position (ScrnInfoPtr scrn, int x, int y)
+ {
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     int			c;
+ 
+     /* undo what xf86HWCurs did to the coordinates */
+     x += scrn->frameX0;
+     y += scrn->frameY0;
+     for (c = 0; c < xf86_config->num_crtc; c++)
+     {
+ 	xf86CrtcPtr crtc = xf86_config->crtc[c];
+ 
+ 	if (crtc->enabled)
+ 	    xf86_crtc_set_cursor_position (crtc, x, y);
+     }
+ }
+     
+ /*
+  * Load a two-color cursor into a crtc, performing rotation as needed
+  */
+ static void
+ xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
+ {
+     ScrnInfoPtr		scrn = crtc->scrn;
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+     CARD8		*cursor_image;
+ 
+ #ifdef ARGB_CURSOR
+     crtc->cursor_argb = FALSE;
+ #endif
+ 
+     if (crtc->rotation == RR_Rotate_0)
+ 	cursor_image = src;
+     else
+     {
+         int x, y;
+     	int xin, yin;
+ 	int stride = cursor_info->MaxWidth >> 2;
+ 	int flags = cursor_info->Flags;
+ 	
+ 	cursor_image = xf86_config->cursor_image;
+ 	memset(cursor_image, 0, cursor_info->MaxWidth * stride);
+ 	
+         for (y = 0; y < cursor_info->MaxHeight; y++)
+ 	    for (x = 0; x < cursor_info->MaxWidth; x++) 
+ 	    {
+ 		xf86_crtc_rotate_coord (crtc->rotation,
+ 					cursor_info->MaxWidth,
+ 					cursor_info->MaxHeight,
+ 					x, y, &xin, &yin);
+ 		if (get_bit(src, stride, flags, xin, yin, FALSE))
+ 		    set_bit(cursor_image, stride, flags, x, y, FALSE);
+ 		if (get_bit(src, stride, flags, xin, yin, TRUE))
+ 		    set_bit(cursor_image, stride, flags, x, y, TRUE);
+ 	    }
+     }
+     crtc->funcs->load_cursor_image (crtc, cursor_image);
+ }
+     
+ /*
+  * Load a cursor image into all active CRTCs
+  */
+ static void
+ xf86_load_cursor_image (ScrnInfoPtr scrn, unsigned char *src)
+ {
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     int			c;
+ 
+     for (c = 0; c < xf86_config->num_crtc; c++)
+     {
+ 	xf86CrtcPtr crtc = xf86_config->crtc[c];
+ 
+ 	if (crtc->enabled)
+ 	{
+ 	    if (crtc->funcs->load_cursor_image)
+ 		xf86_crtc_load_cursor_image (crtc, src);
+ 	    else if (crtc->funcs->load_cursor_argb)
+ 		xf86_crtc_convert_cursor_to_argb (crtc, src);
+ 	}
+     }
+ }
+ 
+ static Bool
+ xf86_use_hw_cursor (ScreenPtr screen, CursorPtr cursor)
+ {
+     ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+ 
+     xf86_config->cursor = cursor;
+     
+     if (cursor->bits->width > cursor_info->MaxWidth ||
+ 	cursor->bits->height> cursor_info->MaxHeight)
+ 	return FALSE;
+ 
+     return TRUE;
+ }
+ 
+ static Bool
+ xf86_use_hw_cursor_argb (ScreenPtr screen, CursorPtr cursor)
+ {
+     ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+     
+     xf86_config->cursor = cursor;
+     
+     /* Make sure ARGB support is available */
+     if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0)
+ 	return FALSE;
+     
+     if (cursor->bits->width > cursor_info->MaxWidth ||
+ 	cursor->bits->height> cursor_info->MaxHeight)
+ 	return FALSE;
+ 
+     return TRUE;
+ }
+ 
+ static void
+ xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor)
+ {
+     ScrnInfoPtr		scrn = crtc->scrn;
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+     CARD32		*cursor_image = (CARD32 *) xf86_config->cursor_image;
+     CARD32		*cursor_source = (CARD32 *) cursor->bits->argb;
+     int			x, y;
+     int			xin, yin;
+     CARD32		bits;
+     int			source_width = cursor->bits->width;
+     int			source_height = cursor->bits->height;
+     int			image_width = cursor_info->MaxWidth;
+     int			image_height = cursor_info->MaxHeight;
+     
+     for (y = 0; y < image_height; y++)
+ 	for (x = 0; x < image_width; x++)
+ 	{
+ 	    xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height,
+ 				    x, y, &xin, &yin);
+ 	    if (xin < source_width && yin < source_height)
+ 		bits = cursor_source[yin * source_width + xin];
+ 	    else
+ 		bits = 0;
+ 	    cursor_image[y * image_width + x] = bits;
+ 	}
+     
+     crtc->funcs->load_cursor_argb (crtc, cursor_image);
+ }
+ 
+ static void
+ xf86_load_cursor_argb (ScrnInfoPtr scrn, CursorPtr cursor)
+ {
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     int			c;
+ 
+     for (c = 0; c < xf86_config->num_crtc; c++)
+     {
+ 	xf86CrtcPtr crtc = xf86_config->crtc[c];
+ 
+ 	if (crtc->enabled)
+ 	    xf86_crtc_load_cursor_argb (crtc, cursor);
+     }
+ }
+ 
+ Bool
+ xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags)
+ {
+     ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     xf86CursorInfoPtr	cursor_info;
+ 
+     cursor_info = xf86CreateCursorInfoRec();
+     if (!cursor_info)
+ 	return FALSE;
+ 
+     xf86_config->cursor_image = xalloc (max_width * max_height * 4);
+ 
+     if (!xf86_config->cursor_image)
+     {
+ 	xf86DestroyCursorInfoRec (cursor_info);
+ 	return FALSE;
+     }
+ 	
+     xf86_config->cursor_info = cursor_info;
+ 
+     cursor_info->MaxWidth = max_width;
+     cursor_info->MaxHeight = max_height;
+     cursor_info->Flags = flags;
+ 
+     cursor_info->SetCursorColors = xf86_set_cursor_colors;
+     cursor_info->SetCursorPosition = xf86_set_cursor_position;
+     cursor_info->LoadCursorImage = xf86_load_cursor_image;
+     cursor_info->HideCursor = xf86_hide_cursors;
+     cursor_info->ShowCursor = xf86_show_cursors;
+     cursor_info->UseHWCursor = xf86_use_hw_cursor;
+ #ifdef ARGB_CURSOR
+     if (flags & HARDWARE_CURSOR_ARGB)
+     {
+ 	cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
+ 	cursor_info->LoadCursorARGB = xf86_load_cursor_argb;
+     }
+ #endif
+     
+     xf86_config->cursor = NULL;
+     xf86_hide_cursors (scrn);
+     
+     return xf86InitCursor (screen, cursor_info);
+ }
+ 
+ /**
+  * Called when anything on the screen is reconfigured.
+  *
+  * Reloads cursor images as needed, then adjusts cursor positions
+  */
+ 
+ void
+ xf86_reload_cursors (ScreenPtr screen)
+ {
+     ScrnInfoPtr		scrn;
+     xf86CrtcConfigPtr   xf86_config;
+     xf86CursorInfoPtr   cursor_info;
+     CursorPtr		cursor;
+     int			x, y;
+     
+     /* initial mode setting will not have set a screen yet */
+     if (!screen)
+ 	return;
+     scrn = xf86Screens[screen->myNum];
+     xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ 
+     /* make sure the cursor code has been initialized */
+     cursor_info = xf86_config->cursor_info;
+     if (!cursor_info)
+ 	return;
+     
+     cursor = xf86_config->cursor;
 -    GetSpritePosition (&x, &y);
++    GetSpritePosition (inputInfo.pointer, &x, &y);
+     if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
+ 	(*cursor_info->HideCursor)(scrn);
+ 
+     if (cursor)
+     {
+ #ifdef ARGB_CURSOR
+ 	if (cursor->bits->argb && cursor_info->LoadCursorARGB)
+ 	    (*cursor_info->LoadCursorARGB) (scrn, cursor);
+ 	else
+ #endif
+ 	    (*cursor_info->LoadCursorImage)(cursor_info->pScrn,
+ 					    cursor->devPriv[screen->myNum]);
+ 
+ 	(*cursor_info->SetCursorPosition)(cursor_info->pScrn, x, y);
+ 	(*cursor_info->ShowCursor)(cursor_info->pScrn);
+     }
+ }
+ 
+ /**
+  * Clean up CRTC-based cursor code
+  */
+ void
+ xf86_cursors_fini (ScreenPtr screen)
+ {
+     ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+     
+     if (xf86_config->cursor_info)
+     {
+ 	xf86DestroyCursorInfoRec (xf86_config->cursor_info);
+ 	xf86_config->cursor_info = NULL;
+     }
+     if (xf86_config->cursor_image)
+     {
+ 	xfree (xf86_config->cursor_image);
+ 	xf86_config->cursor_image = NULL;
+     }
+ }
diff --cc mi/misprite.c
index 8639c56,c0560a4..bb67f48
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@@ -392,37 -318,29 +392,37 @@@ miSpriteGetSpans (pDrawable, wMax, ppt
  
      pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
  
 -    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
 +    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
      {
 -	DDXPointPtr    	pts;
 -	int    		*widths;
 -	int    		nPts;
 -	int    		xorg,
 -			yorg;
 -
 -	xorg = pDrawable->x;
 -	yorg = pDrawable->y;
 -
 -	for (pts = ppt, widths = pwidth, nPts = nspans;
 -	     nPts--;
 -	     pts++, widths++)
 - 	{
 -	    if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
 -			     pts->x+xorg,*widths))
 -	    {
 -		SPRITE_DEBUG (("GetSpans remove\n"));
 -		miSpriteRemoveCursor (pScreen);
 -		break;
 -	    }
 -	}
 +        if (DevHasCursor(pDev))
 +        {
 +            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 +
 +            if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp)
 +            {
-                 register DDXPointPtr    pts;
-                 register int    	*widths;
-                 register int    	nPts;
-                 register int    	xorg,
-                          yorg;
++                DDXPointPtr    pts;
++                int    	       *widths;
++                int    	       nPts;
++                int    	       xorg,
++                               yorg;
 +
 +                xorg = pDrawable->x;
 +                yorg = pDrawable->y;
 +
 +                for (pts = ppt, widths = pwidth, nPts = nspans;
 +                        nPts--;
 +                        pts++, widths++)
 +                {
 +                    if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
 +                                pts->x+xorg,*widths))
 +                    {
 +                        SPRITE_DEBUG (("GetSpans remove\n"));
 +                        miSpriteRemoveCursor (pDev, pScreen);
 +                        break;
 +                    }
 +                }
 +            }
 +        }
      }
  
      (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
commit b167583fe234a536aa6187e17f21da85be4f0b7f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 15 17:50:02 2006 +1030

    o fix minor error in comment for GetPointerEvents()

diff --git a/dix/getevents.c b/dix/getevents.c
index 935112d..77d1e21 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -470,7 +470,7 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
 
 
 /**
- * Generate a series of xEvents (returned in xE) representing pointer
+ * Generate a series of xEvents (returned in events) representing pointer
  * motion, or button presses.  Xi and XKB-aware.
  *
  * events is not NULL-terminated; the return value is the number of events.
commit 65b0eb60b0b9e6405aa2e3d4c712ec4d2f0da070
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Mar 16 15:52:24 2007 +1030

    Xi:     move IsPointerDevice into dix.
    dix:    IsPointerDevice and IsKeyboardDevice, use same ways to identify type
            of device as XI does for the XListInputDevices reply.
            Autopair each non-pointer device with VCP when activating, pair with
            real device after activation.
            Don't return non-keyboard devices when calling GetPairedKeyboard or
            PickKeyboard, otherwise we segfault for 'evdev brain'.

diff --git a/Xi/extinit.c b/Xi/extinit.c
index ff6e4ac..672d333 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -985,21 +985,6 @@ AssignTypeAndName(DeviceIntPtr dev, Atom type, char *name)
 
 /***********************************************************************
  *
- * Returns true if a device may require a pointer (is a mouse).
- * FIXME: Other devices should be able to get a pointer too...
- *
- */
-_X_EXPORT Bool
-IsPointerDevice(DeviceIntPtr dev)
-{
-    if (dev_type[1].type == dev->type)
-        return TRUE;
-  
-    return FALSE;
-}
-
-/***********************************************************************
- *
  * Make device type atoms.
  *
  */
diff --git a/dix/devices.c b/dix/devices.c
index 42eebf1..0c1553e 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -221,6 +221,11 @@ ActivateDevice(DeviceIntPtr dev)
     SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
                           (xEvent *) &ev, 1);
 
+    if (IsPointerDevice(dev) && dev->isMPDev)
+        InitializeSprite(dev, GetCurrentRootWindow());
+    else
+        PairDevices(NULL, inputInfo.pointer, dev);
+
     return ret;
 }
 
@@ -403,7 +408,6 @@ InitCoreDevices()
         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);
@@ -1995,6 +1999,9 @@ ProcQueryKeymap(ClientPtr client)
 int 
 PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
 {
+    if (!ptr)
+        return BadDevice;
+
     if (!pairingClient)
         RegisterPairingClient(client);
     else if (pairingClient != client)
@@ -2032,6 +2039,8 @@ GetPairedPointer(DeviceIntPtr kbd)
 
 /* Find the keyboard device that is paired with the given pointer. If none is
  * found, return NULL.
+ * We also check if the paired device is a keyboard. If not (e.g. evdev brain)
+ * we don't return it. This probably needs to be fixed.
  */
 _X_EXPORT DeviceIntPtr
 GetPairedKeyboard(DeviceIntPtr ptr)
@@ -2040,7 +2049,9 @@ GetPairedKeyboard(DeviceIntPtr ptr)
 
     while(dev)
     {
-        if (ptr != dev && ptr->pSprite == dev->pSprite)
+        if (ptr != dev && 
+            IsKeyboardDevice(dev) &&
+            ptr->pSprite == dev->pSprite)
             return dev;
         dev = dev->next;
     }
diff --git a/dix/events.c b/dix/events.c
index fbbae1d..ca12d22 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -250,6 +250,27 @@ DevHasCursor(DeviceIntPtr pDev)
     return (pDev != inputInfo.pointer && pDev->spriteOwner);
 }
 
+/*
+ * Return true if a device is a pointer, check is the same as used by XI to
+ * fill the 'use' field.
+ */
+_X_EXPORT Bool
+IsPointerDevice(DeviceIntPtr dev)
+{
+    return ((dev->valuator && dev->button) || dev == inputInfo.pointer);
+}
+
+/*
+ * Return true if a device is a keyboard, check is the same as used by XI to
+ * fill the 'use' field.
+ */
+_X_EXPORT Bool
+IsKeyboardDevice(DeviceIntPtr dev)
+{
+    return ((dev->key && dev->kbdfeed) || dev == inputInfo.keyboard);
+}
+
+
 #ifdef XEVIE
 _X_EXPORT WindowPtr xeviewin;
 _X_EXPORT HotSpot xeviehot;
@@ -4914,9 +4935,16 @@ _X_EXPORT DeviceIntPtr
 PickKeyboard(ClientPtr client)
 {
     DeviceIntPtr ptr = PickPointer(client);
-    DeviceIntPtr kbd;
+    DeviceIntPtr kbd = inputInfo.devices;
 
-    kbd = GetPairedKeyboard(ptr);
+    while(kbd)
+    {
+        if (ptr != kbd && 
+            IsKeyboardDevice(kbd) && 
+            ptr->pSprite == kbd->pSprite)
+            return kbd;
+        kbd = kbd->next;
+    }
 
     return (kbd) ? kbd : inputInfo.keyboard;
 }
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index c6d6b36..db39980 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -186,14 +186,6 @@ xf86ActivateDevice(LocalDevicePtr local)
         }
 #endif
 
-        /* Only create a new sprite if it's a non-shared pointer */
-        if (IsPointerDevice(dev) && dev->isMPDev)
-            InitializeSprite(dev, GetCurrentRootWindow());
-        else {
-            /* pair with a free device */
-            PairDevices(NULL, GuessFreePointerDevice(), dev);
-        }
-
         RegisterOtherDevice(dev);
 
         if (serverGeneration == 1) 
@@ -426,6 +418,9 @@ NewInputDeviceRequest (InputOption *options)
     if (dev->inited && dev->startup)
         EnableDevice(dev);
 
+    if (!IsPointerDevice(dev))
+        PairDevices(NULL, GuessFreePointerDevice(), dev);
+
     /* send enter/leave event, update sprite window */
     CheckMotion(NULL, dev);
 
diff --git a/include/dix.h b/include/dix.h
index 57cdce3..44862ad 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -757,4 +757,7 @@ extern int ffs(int i);
 
 extern Bool DevHasCursor(DeviceIntPtr pDev);
 
+extern Bool IsPointerDevice( DeviceIntPtr dev);
+extern Bool IsKeyboardDevice(DeviceIntPtr dev);
+
 #endif /* DIX_H */
diff --git a/include/extinit.h b/include/extinit.h
index d7aa541..ead59be 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -149,10 +149,6 @@ AssignTypeAndName (
 	char *                 /* name */
 	);
 
-Bool IsPointerDevice(
-        DeviceIntPtr            /* dev */
-        );
-
 void
 MakeDeviceTypeAtoms (
 	void
commit 456f429ad655ab4d80e30c58291d801966a613b2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Mar 15 21:48:19 2007 +1030

    dix:    fix: don't return when device is same as argument.
            fix: set access default rule to 0 on init.

diff --git a/dix/devices.c b/dix/devices.c
index 6c17786..42eebf1 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2040,7 +2040,7 @@ GetPairedKeyboard(DeviceIntPtr ptr)
 
     while(dev)
     {
-        if (ptr->pSprite == dev->pSprite)
+        if (ptr != dev && ptr->pSprite == dev->pSprite)
             return dev;
         dev = dev->next;
     }
diff --git a/dix/window.c b/dix/window.c
index 6c35583..38bd74f 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -3721,6 +3721,7 @@ MakeWindowOptional (register WindowPtr pWin)
     optional->access.ndeny = 0;
     optional->access.perm = NULL;
     optional->access.deny = NULL;
+    optional->access.defaultRule = 0;
     parentOptional = FindWindowWithOptional(pWin)->optional;
     optional->visual = parentOptional->visual;
     if (!pWin->cursorIsNone)
commit c5b07fb717289f61b54d7b093421bcb92124b839
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Mar 14 17:42:30 2007 +1030

    kdrive: update kdrive to new mi API with additional device argument. Includes
            an update of ati_cursor.c and i810_cursor.c

diff --git a/autogen.sh b/autogen.sh
index 1176abd..66acd28 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -9,4 +9,4 @@ cd $srcdir
 autoreconf -v --install || exit 1
 cd $ORIGDIR || exit $?
 
-$srcdir/configure --enable-maintainer-mode --disable-dmx "$@"
+$srcdir/configure --enable-maintainer-mode --disable-dmx --enable-kdrive "$@"
diff --git a/hw/kdrive/ati/ati_cursor.c b/hw/kdrive/ati/ati_cursor.c
index e8c7117..082062d 100644
--- a/hw/kdrive/ati/ati_cursor.c
+++ b/hw/kdrive/ati/ati_cursor.c
@@ -28,9 +28,10 @@
 #include "ati_reg.h"
 #include "cursorstr.h"
 #include "ati_draw.h"
+#include "inputstr.h"
 
 static void
-ATIMoveCursor(ScreenPtr pScreen, int x, int y)
+ATIMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
 	KdScreenPriv(pScreen);
 	ATICardInfo(pScreenPriv);
@@ -360,7 +361,7 @@ ATIUnloadCursor(ScreenPtr pScreen)
 }
 
 static Bool
-ATIRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+ATIRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
 	KdScreenPriv(pScreen);
 	ATICardInfo(pScreenPriv);
@@ -375,26 +376,26 @@ ATIRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
 	{
 		int x, y;
 
-		miPointerPosition(&x, &y);
+		miPointerGetPosition(pDev, &x, &y);
 		if (atic->is_radeon)
 			RadeonLoadCursor (pScreen);
 		else
 			ClassicLoadCursor(pScreen);
 		/* Move to new position */
-		ATIMoveCursor(pScreen, x, y);
+		ATIMoveCursor(pDev, pScreen, x, y);
 	}
 
 	return TRUE;
 }
 
 static Bool
-ATIUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+ATIUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
 	return TRUE;
 }
 
 static void
-ATISetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+ATISetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
 {
 	KdScreenPriv(pScreen);
 	ATICardInfo(pScreenPriv);
@@ -413,7 +414,7 @@ ATISetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
 		else
 			ClassicLoadCursor(pScreen);
 		/* Move to new position */
-		ATIMoveCursor(pScreen, x, y);
+		ATIMoveCursor(pDev, pScreen, x, y);
 	}
 	else
 		ATIUnloadCursor(pScreen);
@@ -465,6 +466,7 @@ ATICursorSave(ScreenPtr pScreen, KdOffscreenArea *area)
 void
 ATICursorEnable(ScreenPtr pScreen)
 {
+	DeviceIntPtr pDev = inputInfo.pointer;
 	KdScreenPriv(pScreen);
 	ATICardInfo(pScreenPriv);
 	ATIScreenInfo(pScreenPriv);
@@ -489,13 +491,13 @@ ATICursorEnable(ScreenPtr pScreen)
 	if (pCurPriv->pCursor) {
 		int x, y;
 
-		miPointerPosition(&x, &y);
+		miPointerGetPosition(pDev, &x, &y);
 		if (atic->is_radeon)
 			RadeonLoadCursor(pScreen);
 		else
 			ClassicLoadCursor(pScreen);
 		/* Move to new position */
-		ATIMoveCursor(pScreen, x, y);
+		ATIMoveCursor(pDev, pScreen, x, y);
 	}
 	else
 		ATIUnloadCursor(pScreen);
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index a77b87e..8310f65 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -151,25 +151,25 @@ OsVendorInit (void)
 /* 'Fake' cursor stuff, could be improved */
 
 static Bool
-ephyrRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+ephyrRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
   return TRUE;
 }
 
 static Bool
-ephyrUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+ephyrUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
   return TRUE;
 }
 
 static void
-ephyrSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+ephyrSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
 {
   ;
 }
 
 static void
-ephyrMoveCursor(ScreenPtr pScreen, int x, int y)
+ephyrMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
   ;
 }
diff --git a/hw/kdrive/i810/i810_cursor.c b/hw/kdrive/i810/i810_cursor.c
index cf4f717..d361bf0 100644
--- a/hw/kdrive/i810/i810_cursor.c
+++ b/hw/kdrive/i810/i810_cursor.c
@@ -78,6 +78,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "kxv.h"
 #include "i810.h"
 #include "cursorstr.h"
+#include "inputstr.h"
 
 #define SetupCursor(s)	    KdScreenPriv(pScreen); \
 			    i810CardInfo(pScreenPriv); \
@@ -129,7 +130,7 @@ _i810MoveCursor(ScreenPtr pScreen, int x, int y)
 static void i810LoadCursor(ScreenPtr pScreen, int x, int y);
 
 static void
-i810MoveCursor (ScreenPtr pScreen, int x, int y)
+i810MoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     KdScreenPriv(pScreen);
     i810ScreenInfo(pScreenPriv);
@@ -281,7 +282,7 @@ i810UnloadCursor(ScreenPtr pScreen)
 
 
 static Bool
-i810RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+i810RealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
     KdScreenPriv(pScreen);
     i810ScreenInfo(pScreenPriv);
@@ -297,7 +298,7 @@ i810RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
 	{
 	    int	    x, y;
 	    
-	    miPointerPosition (&x, &y);
+	    miPointerGetPosition (pDev, &x, &y);
 	    i810LoadCursor (pScreen, x, y);
 	}
     }
@@ -305,13 +306,13 @@ i810RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
 }
 
 static Bool
-i810UnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+i810UnrealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
 {
     return TRUE;
 }
 
 static void
-i810SetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+i810SetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
 {
     KdScreenPriv(pScreen);
     i810ScreenInfo(pScreenPriv);
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 3bf6bad..23fede2 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -2219,11 +2219,11 @@ KdCrossScreen(ScreenPtr pScreen, Bool entering)
 int KdCurScreen;	/* current event screen */
 
 static void
-KdWarpCursor (ScreenPtr pScreen, int x, int y)
+KdWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     KdBlockSigio ();
     KdCurScreen = pScreen->myNum;
-    miPointerWarpCursor (pScreen, x, y);
+    miPointerWarpCursor(pDev, pScreen, x, y);
     KdUnblockSigio ();
 }
 
@@ -2238,7 +2238,7 @@ void
 ProcessInputEvents ()
 {
     mieqProcessInputEvents();
-    miPointerUpdate();
+    miPointerUpdateSprite(inputInfo.pointer);
     if (kdSwitchPending)
 	KdProcessSwitch ();
     KdCheckLock ();
commit c3eb248cf93a3afd9168acfb88254606beddd7a8
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Mar 14 13:21:33 2007 +1030

    dix:    fix: don't skip first item in list when seeking for a device cursor.

diff --git a/dix/window.c b/dix/window.c
index 3d79728..6c35583 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -3930,6 +3930,7 @@ CursorPtr WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
 /* Searches for a DevCursorNode for the given window and device. If one is
  * found, return True and set pNode and pPrev to the node and to the node
  * before the node respectively. Otherwise return False.
+ * If the device is the first in list, pPrev is set to NULL.
  */
 static Bool 
 WindowSeekDeviceCursor(WindowPtr pWin, 
@@ -3943,6 +3944,14 @@ WindowSeekDeviceCursor(WindowPtr pWin,
         return FALSE;
 
     pList = pWin->optional->deviceCursors;
+
+    if (pList && pList->dev == pDev)
+    {
+        *pNode = pList;
+        *pPrev = NULL;
+        return TRUE;
+    }
+
     while(pList)
     {
         if (pList->next)
commit ce9409acebd994cf1809050f2cc8e1db66130f12
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Mar 13 19:16:56 2007 +1030

    dix:    Get the state from the paired device and the real device to fill the
            state field in the event, rather than using the virtual devices.
            ProcessPointerEvent: name argument "device" instead of "other".
            Add GetPairedKeyboard().

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 6cedafb..bc26189 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -113,29 +113,46 @@ RegisterOtherDevice(DeviceIntPtr device)
 }
 
  /*ARGSUSED*/ void
-ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
+ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
 {
     BYTE *kptr;
     int i;
     CARD16 modifiers;
     CARD16 mask;
-    GrabPtr grab = other->deviceGrab.grab;
+    GrabPtr grab = device->deviceGrab.grab;
     Bool deactivateDeviceGrab = FALSE;
     int key = 0, bit = 0, rootX, rootY;
-    ButtonClassPtr b = other->button;
-    KeyClassPtr k = other->key;
-    ValuatorClassPtr v = other->valuator;
+    ButtonClassPtr b = device->button;
+    KeyClassPtr k = device->key;
+    ValuatorClassPtr v = device->valuator;
     deviceValuator *xV = (deviceValuator *) xE;
 
-
     if (xE->u.u.type != DeviceValuator) {
-	GetSpritePosition(other, &rootX, &rootY);
+        DeviceIntPtr mouse = NULL, kbd = NULL;
+	GetSpritePosition(device, &rootX, &rootY);
 	xE->u.keyButtonPointer.rootX = rootX;
 	xE->u.keyButtonPointer.rootY = rootY;
 	key = xE->u.u.detail;
 	NoticeEventTime(xE);
-	xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state |
-	    inputInfo.pointer->button->state; /* FIXME: change for MPX */
+
+        /* If 'device' is a pointer device, we need to get the paired keyboard
+         * for the state. If there is none, the kbd bits of state are 0.
+         * If 'device' is a keyboard device, get the paired pointer and use the
+         * pointer's state for the button bits.
+         */
+        if (IsPointerDevice(device))
+        {
+            kbd = GetPairedKeyboard(device);
+            mouse = device;
+        }
+        else
+        {
+            mouse = GetPairedPointer(device);
+            kbd = device;
+        }
+        xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0;
+        xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0;
+
 	bit = 1 << (key & 7);
     }
     if (DeviceEventCallback) {
@@ -155,7 +172,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 		    || (xV->num_valuators
 			&& (first + xV->num_valuators > v->numAxes))))
 		FatalError("Bad valuators reported for device %s\n",
-			   other->name);
+			   device->name);
 	    xV->device_state = 0;
 	    if (k)
 		xV->device_state |= k->state;
@@ -192,15 +209,15 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
 	    if (!modifiers) {
 		xE->u.u.type = DeviceKeyRelease;
-		ProcessOtherEvent(xE, other, count);
+		ProcessOtherEvent(xE, device, count);
 		xE->u.u.type = DeviceKeyPress;
 		/* release can have side effects, don't fall through */
-		ProcessOtherEvent(xE, other, count);
+		ProcessOtherEvent(xE, device, count);
 	    }
 	    return;
 	}
-	if (other->valuator)
-	    other->valuator->motionHintWindow = NullWindow;
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
 	*kptr |= bit;
 	k->prev_state = k->state;
 	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
@@ -211,8 +228,8 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 		modifiers &= ~mask;
 	    }
 	}
-	if (!grab && CheckDeviceGrabs(other, xE, 0, count)) {
-	    other->deviceGrab.activatingKey = key;
+	if (!grab && CheckDeviceGrabs(device, xE, 0, count)) {
+	    device->deviceGrab.activatingKey = key;
 	    return;
 	}
     } else if (xE->u.u.type == DeviceKeyRelease) {
@@ -223,8 +240,8 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 	if (!(*kptr & bit))	/* guard against duplicates */
 	    return;
 	modifiers = k->modifierMap[key];
-	if (other->valuator)
-	    other->valuator->motionHintWindow = NullWindow;
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
 	*kptr &= ~bit;
 	k->prev_state = k->state;
 	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
@@ -238,9 +255,9 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 	    }
 	}
 
-	if (other->deviceGrab.fromPassiveGrab && 
-            !other->deviceGrab.grab->coreGrab &&
-            (key == other->deviceGrab.activatingKey))
+	if (device->deviceGrab.fromPassiveGrab && 
+            !device->deviceGrab.grab->coreGrab &&
+            (key == device->deviceGrab.activatingKey))
 	    deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == DeviceButtonPress) {
         if (!b)
@@ -248,8 +265,8 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 
 	kptr = &b->down[key >> 3];
 	*kptr |= bit;
-	if (other->valuator)
-	    other->valuator->motionHintWindow = NullWindow;
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
 	b->buttonsDown++;
 	b->motionMask = DeviceButtonMotionMask;
 	xE->u.u.detail = b->map[key];
@@ -259,7 +276,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
         if (!grab)
-            if (CheckDeviceGrabs(other, xE, 0, count))
+            if (CheckDeviceGrabs(device, xE, 0, count))
                 return;
 
     } else if (xE->u.u.type == DeviceButtonRelease) {
@@ -268,8 +285,8 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 
 	kptr = &b->down[key >> 3];
 	*kptr &= ~bit;
-	if (other->valuator)
-	    other->valuator->motionHintWindow = NullWindow;
+	if (device->valuator)
+	    device->valuator->motionHintWindow = NullWindow;
 	if (!--b->buttonsDown)
 	    b->motionMask = 0;
 	xE->u.u.detail = b->map[key];
@@ -279,24 +296,24 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
         if (!b->state 
-            && other->deviceGrab.fromPassiveGrab
-            && !other->deviceGrab.grab->coreGrab)
+            && device->deviceGrab.fromPassiveGrab
+            && !device->deviceGrab.grab->coreGrab)
             deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == ProximityIn)
-	other->valuator->mode &= ~OutOfProximity;
+	device->valuator->mode &= ~OutOfProximity;
     else if (xE->u.u.type == ProximityOut)
-	other->valuator->mode |= OutOfProximity;
+	device->valuator->mode |= OutOfProximity;
 
     if (grab)
-	DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count);
-    else if (other->focus)
-	DeliverFocusedEvent(other, xE, GetSpriteWindow(other), count);
+	DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
+    else if (device->focus)
+	DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
     else
-	DeliverDeviceEvents(GetSpriteWindow(other), xE, NullGrab, NullWindow,
-			    other, count);
+	DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
+			    device, count);
 
     if (deactivateDeviceGrab == TRUE)
-	(*other->deviceGrab.DeactivateGrab) (other);
+	(*device->deviceGrab.DeactivateGrab) (device);
 }
 
 _X_EXPORT int
diff --git a/dix/devices.c b/dix/devices.c
index 05a03b5..6c17786 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2030,6 +2030,23 @@ GetPairedPointer(DeviceIntPtr kbd)
     return inputInfo.pointer;
 }
 
+/* Find the keyboard device that is paired with the given pointer. If none is
+ * found, return NULL.
+ */
+_X_EXPORT DeviceIntPtr
+GetPairedKeyboard(DeviceIntPtr ptr)
+{
+    DeviceIntPtr dev = inputInfo.devices;
+
+    while(dev)
+    {
+        if (ptr->pSprite == dev->pSprite)
+            return dev;
+        dev = dev->next;
+    }
+    return dev;
+}
+
 /*
  * Register a client to be able to pair devices. 
  */
diff --git a/dix/events.c b/dix/events.c
index b4b929f..fbbae1d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4913,18 +4913,12 @@ PickPointer(ClientPtr client)
 _X_EXPORT DeviceIntPtr
 PickKeyboard(ClientPtr client)
 {
-    DeviceIntPtr ptr;
-    DeviceIntPtr dev = inputInfo.devices;
-    ptr = PickPointer(client);
+    DeviceIntPtr ptr = PickPointer(client);
+    DeviceIntPtr kbd;
 
-    while(dev)
-    {
-        if (ptr->pSprite == dev->pSprite)
-            return dev;
-        dev = dev->next;
-    }
+    kbd = GetPairedKeyboard(ptr);
 
-    return inputInfo.keyboard;
+    return (kbd) ? kbd : inputInfo.keyboard;
 }
 
 /* A client that has one or more core grabs does not get core events from
diff --git a/include/input.h b/include/input.h
index 2d72f83..765d71d 100644
--- a/include/input.h
+++ b/include/input.h
@@ -451,6 +451,7 @@ extern int PairDevices(ClientPtr client,
                        DeviceIntPtr keyboard);
 
 extern DeviceIntPtr GetPairedPointer(DeviceIntPtr kbd);
+extern DeviceIntPtr GetPairedKeyboard(DeviceIntPtr ptr);
 
 extern Bool RegisterPairingClient(ClientPtr client);
 extern Bool UnregisterPairingClient(ClientPtr client);
commit 577464af4362e5a32cf7165b5128655dd86c6200
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Mar 9 17:13:05 2007 +1030

    dix:    restore commit b3b2a6a0d43d1724e04d69588f8a55c3270e5523 that for some
            reason got wiped.
            fix ProcGrabKeyboard to use PickKeyboard
            fix PickKeyboard to actually work.

diff --git a/dix/events.c b/dix/events.c
index 4e77577..b4b929f 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1706,6 +1706,11 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 	if (filter != CantBeFiltered &&
 	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
 	    return 0;
+        
+        if (!(type & EXTENSION_EVENT_BASE) && 
+            IsInterferingGrab(wClient(pWin), pDev, pEvents))
+                return 0;
+
 	if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
 				      pWin->eventMask, filter, grab)) )
 	{
@@ -1734,6 +1739,11 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 	    other = (InputClients *)wOtherClients(pWin);
 	for (; other; other = other->next)
 	{
+            /* core event? check for grab interference */
+            if (!(type & EXTENSION_EVENT_BASE) &&
+                    IsInterferingGrab(rClient(other), pDev, pEvents))
+                continue;
+
 	    if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
 					  other->mask[mskidx], filter, grab)) )
 	    {
@@ -4144,11 +4154,12 @@ ProcGrabKeyboard(ClientPtr client)
     xGrabKeyboardReply rep;
     REQUEST(xGrabKeyboardReq);
     int result;
+    DeviceIntPtr keyboard = PickKeyboard(client);
 
     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
 
-    if (XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
-	result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode,
+    if (XaceHook(XACE_DEVICE_ACCESS, client, keyboard, TRUE))
+	result = GrabDevice(client, keyboard, stuff->keyboardMode,
 			    stuff->pointerMode, stuff->grabWindow,
 			    stuff->ownerEvents, stuff->time,
 			    KeyPressMask | KeyReleaseMask, &rep.status);
@@ -4169,7 +4180,7 @@ ProcGrabKeyboard(ClientPtr client)
 int
 ProcUngrabKeyboard(ClientPtr client)
 {
-    DeviceIntPtr device = inputInfo.keyboard;
+    DeviceIntPtr device = PickKeyboard(client);
     GrabPtr grab;
     TimeStamp time;
     REQUEST(xResourceReq);
@@ -4902,8 +4913,8 @@ PickPointer(ClientPtr client)
 _X_EXPORT DeviceIntPtr
 PickKeyboard(ClientPtr client)
 {
-    DeviceIntPtr dev;
-    DeviceIntPtr ptr = inputInfo.devices;
+    DeviceIntPtr ptr;
+    DeviceIntPtr dev = inputInfo.devices;
     ptr = PickPointer(client);
 
     while(dev)
@@ -4916,3 +4927,49 @@ PickKeyboard(ClientPtr client)
     return inputInfo.keyboard;
 }
 
+/* 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.
+ * 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, DeviceIntPtr dev, xEvent* event)
+{
+    DeviceIntPtr it = inputInfo.devices;
+
+    if (dev->coreGrab.grab && SameClient(dev->coreGrab.grab, client))
+        return FALSE;
+
+    switch(event->u.u.type)
+    {
+        case KeyPress:
+        case KeyRelease:
+        case ButtonPress:
+        case ButtonRelease:
+        case MotionNotify:
+        case EnterNotify:
+        case LeaveNotify:
+            break;
+        default:
+            return FALSE;
+    }
+
+    while(it)
+    {
+        if (it != dev)
+        {
+            if (it->coreGrab.grab && SameClient(it->coreGrab.grab, client))
+            {
+                return TRUE;
+
+            }
+        }
+        it = it->next;
+    }
+
+    return FALSE;
+}
+
diff --git a/include/dix.h b/include/dix.h
index 06dafbb..57cdce3 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -614,6 +614,11 @@ extern DeviceIntPtr PickPointer(
 extern DeviceIntPtr PickKeyboard(
     ClientPtr /* client */);
 
+extern Bool IsInterferingGrab(
+        ClientPtr /* client */,
+        DeviceIntPtr /* dev */,
+        xEvent* /* events */);
+
 #ifdef PANORAMIX
 extern void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
 #endif
commit 07806f4081f8dcd3b5733b590eb6e5b4cae734ad
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Mar 9 15:45:25 2007 +1030

    Xi:     Add SetClientPointer request handling.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index e77c8a3..16d0e8d 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -76,6 +76,8 @@ libXi_la_SOURCES =	\
 	sendexev.h \
 	setbmap.c \
 	setbmap.h \
+	setcptr.c \
+	setcptr.h \
 	setdval.c \
 	setdval.h \
 	setfocus.c \
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 598348e..ff6e4ac 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -110,6 +110,7 @@ SOFTWARE.
 #include "sendexev.h"
 #include "chgkmap.h"
 #include "setbmap.h"
+#include "setcptr.h"
 #include "setdval.h"
 #include "setfocus.h"
 #include "setmmap.h"
@@ -367,6 +368,8 @@ ProcIDispatch(register ClientPtr client)
         return (ProcXChangeWindowAccess(client));
     else if (stuff->data == X_QueryWindowAccess)
         return ProcXQueryWindowAccess(client);
+    else if (stuff->data == X_SetClientPointer)
+        return ProcXSetClientPointer(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -472,6 +475,8 @@ SProcIDispatch(register ClientPtr client)
         return (SProcXChangeWindowAccess(client));
     else if (stuff->data == X_QueryWindowAccess)
         return SProcXQueryWindowAccess(client);
+    else if (stuff->data == X_SetClientPointer)
+        return SProcXSetClientPointer(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
diff --git a/Xi/setcptr.c b/Xi/setcptr.c
new file mode 100644
index 0000000..25874f0
--- /dev/null
+++ b/Xi/setcptr.c
@@ -0,0 +1,105 @@
+/*
+
+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 set the client pointer for the owner of the given window.
+ * All subsequent calls that are ambiguous will choose the client pointer as
+ * default value.
+ */
+
+
+#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 "setcptr.h"
+
+int
+SProcXSetClientPointer(ClientPtr client)
+{
+    char n;
+
+    REQUEST(xSetClientPointerReq);
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(xSetClientPointerReq);
+    return (ProcXSetClientPointer(client));
+}
+
+int
+ProcXSetClientPointer(ClientPtr client)
+{
+    DeviceIntPtr pDev;
+    WindowPtr pWin;
+    int err;
+
+    REQUEST(xSetClientPointerReq);
+    REQUEST_SIZE_MATCH(xSetClientPointerReq);
+
+
+    pDev = LookupDeviceIntRec(stuff->deviceid);
+    if (pDev == NULL || !IsPointerDevice(pDev))
+    {
+        SendErrorToClient(client, IReqCode, X_SetClientPointer, 0,
+                BadDevice); 
+        return Success;
+    }
+
+    if (stuff->win != None)
+    {
+        err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
+        if (err != Success)
+        {
+            SendErrorToClient(client, IReqCode, X_SetClientPointer, 
+                    stuff->win, err);
+            return Success;
+        }
+    }
+    
+    if (!SetClientPointer(wClient(pWin), client, pDev))
+    {
+        SendErrorToClient(client, IReqCode, X_SetClientPointer, 
+                stuff->win, BadAccess);
+        return Success;
+    }
+    return Success;
+}
diff --git a/Xi/setcptr.h b/Xi/setcptr.h
new file mode 100644
index 0000000..0c24fd4
--- /dev/null
+++ b/Xi/setcptr.h
@@ -0,0 +1,39 @@
+/*
+
+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 SETCPTR_H
+#define SETCPTR_H 1
+
+int SProcXSetClientPointer(ClientPtr /* client */);
+int ProcXSetClientPointer(ClientPtr /* client */);
+
+#endif /* SETCPTR_H */
diff --git a/dix/cursor.c b/dix/cursor.c
index 23a2cc9..e44a5ef 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -131,6 +131,7 @@ FreeCursor(pointer value, XID cid)
     }
     FreeCursorBits(pCurs->bits);
     xfree( pCurs);
+    MPXDBG("freeing memory for cursor\n");
     return(Success);
 }
 
diff --git a/dix/events.c b/dix/events.c
index f6d6438..4e77577 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1706,12 +1706,6 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 	if (filter != CantBeFiltered &&
 	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
 	    return 0;
-
-       /* core event? check for grab interference */
-        if (!(type & EXTENSION_EVENT_BASE) && 
-            IsInterferingGrab(wClient(pWin), pDev, pEvents))
-                return 0;
-
 	if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
 				      pWin->eventMask, filter, grab)) )
 	{
@@ -1740,11 +1734,6 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 	    other = (InputClients *)wOtherClients(pWin);
 	for (; other; other = other->next)
 	{
-           /* core event? check for grab interference */
-            if (!(type & EXTENSION_EVENT_BASE) && 
-                IsInterferingGrab(rClient(other), pDev, pEvents))
-                    continue;
-
 	    if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
 					  other->mask[mskidx], filter, grab)) )
 	    {
@@ -4861,11 +4850,22 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
     }
 }
 
+/*
+ * Set the client pointer for the given client. Second parameter setter could
+ * be used in the future to determine access rights. Unused for now.
+ */
+_X_EXPORT Bool
+SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device)
+{
+    client->clientPtr = device;
+    return TRUE;
+}
+
 /* PickPointer will pick an appropriate pointer for the given client.
  *
  * If a client pointer is set, it will pick the client pointer, otherwise the
  * first available pointer in the list. If no physical device is attached, it
- * will pick the core pointer.
+ * will pick the core pointer, but will not store it on the client.
  */
 _X_EXPORT DeviceIntPtr
 PickPointer(ClientPtr client)
@@ -4887,7 +4887,7 @@ PickPointer(ClientPtr client)
         if (!it)
         {
             ErrorF("Picking VCP\n");
-            client->clientPtr = inputInfo.pointer;
+            return inputInfo.pointer;
         }
     }
     return client->clientPtr;
@@ -4916,49 +4916,3 @@ PickKeyboard(ClientPtr client)
     return inputInfo.keyboard;
 }
 
-/* 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.
- * 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, DeviceIntPtr dev, xEvent* event)
-{
-    DeviceIntPtr it = inputInfo.devices;
-
-    if (dev->coreGrab.grab && SameClient(dev->coreGrab.grab, client))
-        return FALSE;
-
-    switch(event->u.u.type)
-    {
-        case KeyPress:
-        case KeyRelease:
-        case ButtonPress:
-        case ButtonRelease:
-        case MotionNotify:
-        case EnterNotify:
-        case LeaveNotify:
-            break;
-        default:
-            return FALSE;
-    }
-
-    while(it)
-    {
-        if (it != dev)
-        {
-            if (it->coreGrab.grab && SameClient(it->coreGrab.grab, client))
-            {
-                return TRUE;
-
-            }
-        }
-        it = it->next;
-    }
-
-    return FALSE;
-}
-
diff --git a/include/dix.h b/include/dix.h
index 56d2f17..06dafbb 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -603,17 +603,17 @@ extern int TryClientEvents(
 
 extern void WindowsRestructured(void);
 
+extern Bool SetClientPointer(
+        ClientPtr /* client */, 
+        ClientPtr /* setter */, 
+        DeviceIntPtr /* device */);
+
 extern DeviceIntPtr PickPointer(
     ClientPtr /* client */);
 
 extern DeviceIntPtr PickKeyboard(
     ClientPtr /* client */);
 
-extern Bool IsInterferingGrab(
-    ClientPtr /* client */,
-    DeviceIntPtr /* dev */,
-    xEvent* /* events */);
-
 #ifdef PANORAMIX
 extern void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
 #endif
commit b3b2a6a0d43d1724e04d69588f8a55c3270e5523
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Mar 8 22:16:17 2007 +1030

    dix:    Check if client has a grab on any other device before mouse/kbd
            event is delivered to the client. Client's don't cope well with
            receiving core events from other devices when having a grab on a
            pointer or keyboard.

diff --git a/dix/cursor.c b/dix/cursor.c
index e44a5ef..23a2cc9 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -131,7 +131,6 @@ FreeCursor(pointer value, XID cid)
     }
     FreeCursorBits(pCurs->bits);
     xfree( pCurs);
-    MPXDBG("freeing memory for cursor\n");
     return(Success);
 }
 
diff --git a/dix/events.c b/dix/events.c
index 66d63cc..f6d6438 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1706,6 +1706,12 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 	if (filter != CantBeFiltered &&
 	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
 	    return 0;
+
+       /* core event? check for grab interference */
+        if (!(type & EXTENSION_EVENT_BASE) && 
+            IsInterferingGrab(wClient(pWin), pDev, pEvents))
+                return 0;
+
 	if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
 				      pWin->eventMask, filter, grab)) )
 	{
@@ -1734,6 +1740,11 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 	    other = (InputClients *)wOtherClients(pWin);
 	for (; other; other = other->next)
 	{
+           /* core event? check for grab interference */
+            if (!(type & EXTENSION_EVENT_BASE) && 
+                IsInterferingGrab(rClient(other), pDev, pEvents))
+                    continue;
+
 	    if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
 					  other->mask[mskidx], filter, grab)) )
 	    {
@@ -4905,3 +4916,49 @@ PickKeyboard(ClientPtr client)
     return inputInfo.keyboard;
 }
 
+/* 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.
+ * 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, DeviceIntPtr dev, xEvent* event)
+{
+    DeviceIntPtr it = inputInfo.devices;
+
+    if (dev->coreGrab.grab && SameClient(dev->coreGrab.grab, client))
+        return FALSE;
+
+    switch(event->u.u.type)
+    {
+        case KeyPress:
+        case KeyRelease:
+        case ButtonPress:
+        case ButtonRelease:
+        case MotionNotify:
+        case EnterNotify:
+        case LeaveNotify:
+            break;
+        default:
+            return FALSE;
+    }
+
+    while(it)
+    {
+        if (it != dev)
+        {
+            if (it->coreGrab.grab && SameClient(it->coreGrab.grab, client))
+            {
+                return TRUE;
+
+            }
+        }
+        it = it->next;
+    }
+
+    return FALSE;
+}
+
diff --git a/include/dix.h b/include/dix.h
index f22f489..56d2f17 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -609,6 +609,11 @@ extern DeviceIntPtr PickPointer(
 extern DeviceIntPtr PickKeyboard(
     ClientPtr /* client */);
 
+extern Bool IsInterferingGrab(
+    ClientPtr /* client */,
+    DeviceIntPtr /* dev */,
+    xEvent* /* events */);
+
 #ifdef PANORAMIX
 extern void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
 #endif
commit ceca5670fee99b5feceaa2453f1ac32d1bfe7dcd
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Mar 8 17:17:23 2007 +1030

    dix:    Each device needs to differ between a core grab and an XI grab,
            otherwise a Xi grab may overwrite or release a core grab.
            Replace grab and associates with coreGrab and deviceGrab structures,
            adjust rest of dix/Xi/etc to compile.
    
    xfree86: Don't check for core devices, we'll have the virtual ones anyway.
             If we check, the first mouse device is duplicated and sends
             double events.

diff --git a/Xext/security.c b/Xext/security.c
index 6e58b09..e9d2875 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -822,10 +822,13 @@ CALLBACK(SecurityCheckDeviceAccess)
     untrusted_got_event = FALSE;
     found_event_window = FALSE;
 
-    if (dev->grab)
+    /* 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)
     {
 	untrusted_got_event =
-	    (TRUSTLEVEL(rClient(dev->grab)) != XSecurityClientTrusted);
+          (TRUSTLEVEL(rClient(dev->coreGrab.grab)) != XSecurityClientTrusted);
     }
     else
     {
diff --git a/Xi/allowev.c b/Xi/allowev.c
index ea9c5de..c9e4c87 100644
--- a/Xi/allowev.c
+++ b/Xi/allowev.c
@@ -111,22 +111,22 @@ ProcXAllowDeviceEvents(register ClientPtr client)
 
     switch (stuff->mode) {
     case ReplayThisDevice:
-	AllowSome(client, time, thisdev, NOT_GRABBED);
+	AllowSome(client, time, thisdev, NOT_GRABBED, FALSE);
 	break;
     case SyncThisDevice:
-	AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT);
+	AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT, FALSE);
 	break;
     case AsyncThisDevice:
-	AllowSome(client, time, thisdev, THAWED);
+	AllowSome(client, time, thisdev, THAWED, FALSE);
 	break;
     case AsyncOtherDevices:
-	AllowSome(client, time, thisdev, THAW_OTHERS);
+	AllowSome(client, time, thisdev, THAW_OTHERS, FALSE);
 	break;
     case SyncAll:
-	AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT);
+	AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT, FALSE);
 	break;
     case AsyncAll:
-	AllowSome(client, time, thisdev, THAWED_BOTH);
+	AllowSome(client, time, thisdev, THAWED_BOTH, FALSE);
 	break;
     default:
 	SendErrorToClient(client, IReqCode, X_AllowDeviceEvents, 0, BadValue);
diff --git a/Xi/chgdctl.c b/Xi/chgdctl.c
index badd938..899015a 100644
--- a/Xi/chgdctl.c
+++ b/Xi/chgdctl.c
@@ -138,7 +138,7 @@ ProcXChangeDeviceControl(ClientPtr client)
             ret = BadMatch;
             goto out;
 	}
-	if ((dev->grab) && !SameClient(dev->grab, client)) {
+	if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) {
 	    rep.status = AlreadyGrabbed;
             ret = Success;
             goto out;
diff --git a/Xi/closedev.c b/Xi/closedev.c
index cc83e6a..7bdd373 100644
--- a/Xi/closedev.c
+++ b/Xi/closedev.c
@@ -109,8 +109,8 @@ ProcXCloseDevice(register ClientPtr client)
 	return Success;
     }
 
-    if (d->grab && SameClient(d->grab, client))
-	(*d->DeactivateGrab) (d);	/* release active grab */
+    if (d->deviceGrab.grab && SameClient(d->deviceGrab.grab, client))
+	(*d->deviceGrab.DeactivateGrab) (d);	/* release active grab */
 
     /* Remove event selections from all windows for events from this device 
      * and selected by this client.
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 5dbb0e2..6cedafb 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -99,8 +99,17 @@ RegisterOtherDevice(DeviceIntPtr device)
 {
     device->public.processInputProc = ProcessOtherEvent;
     device->public.realInputProc = ProcessOtherEvent;
-    (device)->ActivateGrab = ActivateKeyboardGrab;
-    (device)->DeactivateGrab = DeactivateKeyboardGrab;
+    (device)->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
+    (device)->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
+    if (IsPointerDevice(device))
+    {
+        (device)->coreGrab.ActivateGrab = ActivatePointerGrab;
+        (device)->coreGrab.DeactivateGrab = DeactivatePointerGrab;
+    } else
+    {
+        (device)->coreGrab.ActivateGrab = ActivateKeyboardGrab;
+        (device)->coreGrab.DeactivateGrab = DeactivateKeyboardGrab;
+    }
 }
 
  /*ARGSUSED*/ void
@@ -110,7 +119,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
     int i;
     CARD16 modifiers;
     CARD16 mask;
-    GrabPtr grab = other->grab;
+    GrabPtr grab = other->deviceGrab.grab;
     Bool deactivateDeviceGrab = FALSE;
     int key = 0, bit = 0, rootX, rootY;
     ButtonClassPtr b = other->button;
@@ -203,7 +212,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 	    }
 	}
 	if (!grab && CheckDeviceGrabs(other, xE, 0, count)) {
-	    other->activatingKey = key;
+	    other->deviceGrab.activatingKey = key;
 	    return;
 	}
     } else if (xE->u.u.type == DeviceKeyRelease) {
@@ -229,9 +238,9 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 	    }
 	}
 
-	if (other->fromPassiveGrab && 
-            !other->grab->coreGrab &&
-            (key == other->activatingKey))
+	if (other->deviceGrab.fromPassiveGrab && 
+            !other->deviceGrab.grab->coreGrab &&
+            (key == other->deviceGrab.activatingKey))
 	    deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == DeviceButtonPress) {
         if (!b)
@@ -270,8 +279,8 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
         if (!b->state 
-            && other->fromPassiveGrab
-            && !other->grab->coreGrab)
+            && other->deviceGrab.fromPassiveGrab
+            && !other->deviceGrab.grab->coreGrab)
             deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == ProximityIn)
 	other->valuator->mode &= ~OutOfProximity;
@@ -287,7 +296,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 			    other, count);
 
     if (deactivateDeviceGrab == TRUE)
-	(*other->DeactivateGrab) (other);
+	(*other->deviceGrab.DeactivateGrab) (other);
 }
 
 _X_EXPORT int
@@ -663,7 +672,7 @@ SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
     if (dev->valuator)
 	if ((dev->valuator->motionHintWindow == pWin) &&
 	    (mask & DevicePointerMotionHintMask) &&
-	    !(check & DevicePointerMotionHintMask) && !dev->grab)
+	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
 	    dev->valuator->motionHintWindow = NullWindow;
     RecalculateDeviceDeliverableEvents(pWin);
     return Success;
@@ -1034,8 +1043,8 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
      * any input focus changes.
      * Deactivating a device grab should cause focus events. */
 
-    if (dev->grab && (dev->grab->window == pWin))
-	(*dev->DeactivateGrab) (dev);
+    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
+	(*dev->deviceGrab.DeactivateGrab) (dev);
 
     /* If the focus window is a root window (ie. has no parent) 
      * then don't delete the focus from it. */
@@ -1045,7 +1054,7 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
 
 	/* If a grab is in progress, then alter the mode of focus events. */
 
-	if (dev->grab)
+	if (dev->deviceGrab.grab)
 	    focusEventMode = NotifyWhileGrabbed;
 
 	switch (dev->focus->revert) {
@@ -1139,7 +1148,7 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
 	tempGrab.pointerMode = GrabModeAsync;
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
-	(*dev->ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
+	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
     }
 }
 
@@ -1162,7 +1171,7 @@ void
 MaybeStopDeviceHint(register DeviceIntPtr dev, ClientPtr client)
 {
     WindowPtr pWin;
-    GrabPtr grab = dev->grab;
+    GrabPtr grab = dev->deviceGrab.grab;
 
     pWin = dev->valuator->motionHintWindow;
 
diff --git a/Xi/setdval.c b/Xi/setdval.c
index 958b2ac..ce9b02d 100644
--- a/Xi/setdval.c
+++ b/Xi/setdval.c
@@ -125,7 +125,7 @@ ProcXSetDeviceValuators(register ClientPtr client)
 	return Success;
     }
 
-    if ((dev->grab) && !SameClient(dev->grab, client))
+    if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client))
 	rep.status = AlreadyGrabbed;
     else
 	rep.status = SetDeviceValuators(client, dev, (int *)&stuff[1],
diff --git a/Xi/setmode.c b/Xi/setmode.c
index 11feb6d..ff5a3bc 100644
--- a/Xi/setmode.c
+++ b/Xi/setmode.c
@@ -113,7 +113,7 @@ ProcXSetDeviceMode(register ClientPtr client)
 	SendErrorToClient(client, IReqCode, X_SetDeviceMode, 0, BadMatch);
 	return Success;
     }
-    if ((dev->grab) && !SameClient(dev->grab, client))
+    if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client))
 	rep.status = AlreadyGrabbed;
     else
 	rep.status = SetDeviceMode(client, dev, stuff->mode);
diff --git a/Xi/ungrdev.c b/Xi/ungrdev.c
index 980fa93..a028a22 100644
--- a/Xi/ungrdev.c
+++ b/Xi/ungrdev.c
@@ -106,12 +106,12 @@ ProcXUngrabDevice(register ClientPtr client)
 	SendErrorToClient(client, IReqCode, X_UngrabDevice, 0, BadDevice);
 	return Success;
     }
-    grab = dev->grab;
+    grab = dev->deviceGrab.grab;
 
     time = ClientTimeToServerTime(stuff->time);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
-	(CompareTimeStamps(time, dev->grabTime) != EARLIER) &&
+	(CompareTimeStamps(time, dev->deviceGrab.grabTime) != EARLIER) &&
 	(grab) && SameClient(grab, client))
-	(*dev->DeactivateGrab) (dev);
+	(*dev->deviceGrab.DeactivateGrab) (dev);
     return Success;
 }
diff --git a/dix/devices.c b/dix/devices.c
index 9e08794..05a03b5 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -104,14 +104,27 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
     dev->public.enqueueInputProc = EnqueueEvent;
     dev->deviceProc = deviceProc;
     dev->startup = autoStart;
-    dev->sync.frozen = FALSE;
-    dev->sync.other = NullGrab;
-    dev->sync.state = NOT_GRABBED;
-    dev->sync.event = (xEvent *) NULL;
-    dev->sync.evcount = 0;
-    dev->grab = NullGrab;
-    dev->grabTime = currentTime;
-    dev->fromPassiveGrab = FALSE;
+
+    /* 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;
+    dev->deviceGrab.sync.state = NOT_GRABBED;
+    dev->deviceGrab.sync.event = (xEvent *) NULL;
+    dev->deviceGrab.sync.evcount = 0;
+    dev->deviceGrab.grab = NullGrab;
+    dev->deviceGrab.grabTime = currentTime;
+    dev->deviceGrab.fromPassiveGrab = FALSE;
+
     dev->key = (KeyClassPtr)NULL;
     dev->valuator = (ValuatorClassPtr)NULL;
     dev->button = (ButtonClassPtr)NULL;
@@ -339,8 +352,8 @@ InitCoreDevices()
         dev->public.processInputProc = ProcessKeyboardEvent;
         dev->public.realInputProc = ProcessKeyboardEvent;
 #endif
-        dev->ActivateGrab = ActivateKeyboardGrab;
-        dev->DeactivateGrab = DeactivateKeyboardGrab;
+        dev->coreGrab.ActivateGrab = ActivateKeyboardGrab;
+        dev->coreGrab.DeactivateGrab = DeactivateKeyboardGrab;
         dev->coreEvents = FALSE;
         dev->spriteOwner = FALSE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
@@ -372,8 +385,8 @@ InitCoreDevices()
         dev->public.processInputProc = ProcessPointerEvent;
         dev->public.realInputProc = ProcessPointerEvent;
 #endif
-        dev->ActivateGrab = ActivatePointerGrab;
-        dev->DeactivateGrab = DeactivatePointerGrab;
+        dev->coreGrab.ActivateGrab = ActivatePointerGrab;
+        dev->coreGrab.DeactivateGrab = DeactivatePointerGrab;
         dev->coreEvents = FALSE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate pointer devPrivates\n");
@@ -535,7 +548,8 @@ CloseDevice(register DeviceIntPtr dev)
             PickPointer(clients[j]);
     }
 
-    xfree(dev->sync.event);
+    xfree(dev->coreGrab.sync.event);
+    xfree(dev->deviceGrab.sync.event);
     xfree(dev);
 }
 
@@ -1872,7 +1886,7 @@ ProcGetPointerControl(ClientPtr client)
 void
 MaybeStopHint(register DeviceIntPtr dev, ClientPtr client)
 {
-    GrabPtr grab = dev->grab;
+    GrabPtr grab = dev->coreGrab.grab;
 
     if ((grab && SameClient(grab, client) &&
 	 ((grab->eventMask & PointerMotionHintMask) ||
diff --git a/dix/events.c b/dix/events.c
index 23d5f22..66d63cc 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -478,7 +478,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->grab ? pDev->grab->confineTo :
+	pWin = pDev->coreGrab.grab ? pDev->coreGrab.grab->confineTo :
 					 NullWindow;
     }
     if (pWin)
@@ -801,7 +801,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->grab ? pDev->grab->confineTo : NullWindow;
+	pWin = pDev->coreGrab.grab ? pDev->coreGrab.grab->confineTo : NullWindow;
     }
     if (pWin)
     {
@@ -916,7 +916,7 @@ static void
 PostNewCursor(DeviceIntPtr pDev)
 {
     register    WindowPtr win;
-    register    GrabPtr grab = pDev->grab;
+    register    GrabPtr grab = pDev->coreGrab.grab;
     SpritePtr   pSprite = pDev->pSprite;
     CursorPtr   pCursor;
 
@@ -1108,7 +1108,7 @@ PlayReleasedEvents(void)
     prev = &syncEvents.pending;
     while ( (qe = *prev) )
     {
-	if (!qe->device->sync.frozen)
+	if (!qe->device->coreGrab.sync.frozen)
 	{
 	    *prev = qe->next;
             pDev = qe->device;
@@ -1134,7 +1134,7 @@ PlayReleasedEvents(void)
 	    (*qe->device->public.processInputProc)(qe->event, qe->device,
 						   qe->evcount);
 	    xfree(qe);
-	    for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next)
+	    for (dev = inputInfo.devices; dev && dev->coreGrab.sync.frozen; dev = dev->next)
 		;
 	    if (!dev)
 		break;
@@ -1150,7 +1150,7 @@ PlayReleasedEvents(void)
 static void
 FreezeThaw(register DeviceIntPtr dev, Bool frozen)
 {
-    dev->sync.frozen = frozen;
+    dev->coreGrab.sync.frozen = frozen;
     if (frozen)
 	dev->public.processInputProc = dev->public.enqueueInputProc;
     else
@@ -1169,14 +1169,15 @@ ComputeFreezes()
     register DeviceIntPtr dev;
 
     for (dev = inputInfo.devices; dev; dev = dev->next)
-	FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
+	FreezeThaw(dev, dev->coreGrab.sync.other || 
+                (dev->coreGrab.sync.state >= FROZEN));
     if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
 	return;
     syncEvents.playingEvents = TRUE;
     if (replayDev)
     {
-	xE = replayDev->sync.event;
-	count = replayDev->sync.evcount;
+	xE = replayDev->coreGrab.sync.event;
+	count = replayDev->coreGrab.sync.evcount;
 	syncEvents.replayDev = (DeviceIntPtr)NULL;
 
         w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY);
@@ -1203,7 +1204,7 @@ ComputeFreezes()
 playmore:
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	if (!dev->sync.frozen)
+	if (!dev->coreGrab.sync.frozen)
 	{
 	    PlayReleasedEvents();
 	    break;
@@ -1216,7 +1217,7 @@ playmore:
         {
             /* the following may have been skipped during replay, 
               so do it now */
-            if ((grab = dev->grab) && grab->confineTo)
+            if ((grab = dev->coreGrab.grab) && grab->confineTo)
             {
                 if (grab->confineTo->drawable.pScreen !=
                         dev->pSprite->hotPhys.pScreen) 
@@ -1243,7 +1244,9 @@ ScreenRestructured (ScreenPtr pScreen)
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
 
-        if ((grab = pDev->grab) && grab->confineTo)
+        /* 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->confineTo->drawable.pScreen 
                     != pDev->pSprite->hotPhys.pScreen)
@@ -1261,31 +1264,31 @@ ScreenRestructured (ScreenPtr pScreen)
 void
 CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
 {
-    register GrabPtr grab = thisDev->grab;
+    register GrabPtr grab = thisDev->coreGrab.grab;
     register DeviceIntPtr dev;
 
     if (thisMode == GrabModeSync)
-	thisDev->sync.state = FROZEN_NO_EVENT;
+	thisDev->coreGrab.sync.state = FROZEN_NO_EVENT;
     else
     {	/* free both if same client owns both */
-	thisDev->sync.state = THAWED;
-	if (thisDev->sync.other &&
-	    (CLIENT_BITS(thisDev->sync.other->resource) ==
+	thisDev->coreGrab.sync.state = THAWED;
+	if (thisDev->coreGrab.sync.other &&
+	    (CLIENT_BITS(thisDev->coreGrab.sync.other->resource) ==
 	     CLIENT_BITS(grab->resource)))
-	    thisDev->sync.other = NullGrab;
+	    thisDev->coreGrab.sync.other = NullGrab;
     }
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
 	if (dev != thisDev)
 	{
 	    if (otherMode == GrabModeSync)
-		dev->sync.other = grab;
+		dev->coreGrab.sync.other = grab;
 	    else
 	    {	/* free both if same client owns both */
-		if (dev->sync.other &&
-		    (CLIENT_BITS(dev->sync.other->resource) ==
+		if (dev->coreGrab.sync.other &&
+		    (CLIENT_BITS(dev->coreGrab.sync.other->resource) ==
 		     CLIENT_BITS(grab->resource)))
-		    dev->sync.other = NullGrab;
+		    dev->coreGrab.sync.other = NullGrab;
 	    }
 	}
     }
@@ -1296,8 +1299,9 @@ void
 ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab, 
                     TimeStamp time, Bool autoGrab)
 {
-    WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
-				     : mouse->pSprite->win;
+    WindowPtr oldWin = (mouse->coreGrab.grab) ? 
+                        mouse->coreGrab.grab->window
+                        : mouse->pSprite->win;
 
     if (grab->confineTo)
     {
@@ -1309,14 +1313,14 @@ ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
     DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
     mouse->valuator->motionHintWindow = NullWindow;
     if (syncEvents.playingEvents)
-	mouse->grabTime = syncEvents.time;
+        mouse->coreGrab.grabTime = syncEvents.time;
     else
-	mouse->grabTime = time;
+	mouse->coreGrab.grabTime = time;
     if (grab->cursor)
 	grab->cursor->refcnt++;
-    mouse->activeGrab = *grab;
-    mouse->grab = &mouse->activeGrab;
-    mouse->fromPassiveGrab = autoGrab;
+    mouse->coreGrab.activeGrab = *grab;
+    mouse->coreGrab.grab = &mouse->coreGrab.activeGrab;
+    mouse->coreGrab.fromPassiveGrab = autoGrab;
     PostNewCursor(mouse);
     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
 }
@@ -1324,17 +1328,17 @@ ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
 void
 DeactivatePointerGrab(register DeviceIntPtr mouse)
 {
-    register GrabPtr grab = mouse->grab;
+    register GrabPtr grab = mouse->coreGrab.grab;
     register DeviceIntPtr dev;
 
     mouse->valuator->motionHintWindow = NullWindow;
-    mouse->grab = NullGrab;
-    mouse->sync.state = NOT_GRABBED;
-    mouse->fromPassiveGrab = FALSE;
+    mouse->coreGrab.grab = NullGrab;
+    mouse->coreGrab.sync.state = NOT_GRABBED;
+    mouse->coreGrab.fromPassiveGrab = FALSE;
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	if (dev->sync.other == grab)
-	    dev->sync.other = NullGrab;
+	if (dev->coreGrab.sync.other == grab)
+	    dev->coreGrab.sync.other = NullGrab;
     }
     DoEnterLeaveEvents(mouse, grab->window, 
                        mouse->pSprite->win, NotifyUngrab);
@@ -1351,8 +1355,8 @@ ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
 {
     WindowPtr oldWin;
 
-    if (keybd->grab)
-	oldWin = keybd->grab->window;
+    if (keybd->coreGrab.grab)
+	oldWin = keybd->coreGrab.grab->window;
     else if (keybd->focus)
 	oldWin = keybd->focus->win;
     else
@@ -1363,19 +1367,19 @@ ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
 	keybd->valuator->motionHintWindow = NullWindow;
     DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
     if (syncEvents.playingEvents)
-	keybd->grabTime = syncEvents.time;
+	keybd->coreGrab.grabTime = syncEvents.time;
     else
-	keybd->grabTime = time;
-    keybd->activeGrab = *grab;
-    keybd->grab = &keybd->activeGrab;
-    keybd->fromPassiveGrab = passive;
+	keybd->coreGrab.grabTime = time;
+    keybd->coreGrab.activeGrab = *grab;
+    keybd->coreGrab.grab = &keybd->coreGrab.activeGrab;
+    keybd->coreGrab.fromPassiveGrab = passive;
     CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
 }
 
 void
 DeactivateKeyboardGrab(register DeviceIntPtr keybd)
 {
-    register GrabPtr grab = keybd->grab;
+    register GrabPtr grab = keybd->coreGrab.grab;
     register DeviceIntPtr dev;
     register WindowPtr focusWin = keybd->focus ? keybd->focus->win
 					       : keybd->pSprite->win;
@@ -1384,49 +1388,61 @@ DeactivateKeyboardGrab(register DeviceIntPtr keybd)
 	focusWin = inputInfo.keyboard->focus->win;
     if (keybd->valuator)
 	keybd->valuator->motionHintWindow = NullWindow;
-    keybd->grab = NullGrab;
-    keybd->sync.state = NOT_GRABBED;
-    keybd->fromPassiveGrab = FALSE;
+    keybd->coreGrab.grab = NullGrab;
+    keybd->coreGrab.sync.state = NOT_GRABBED;
+    keybd->coreGrab.fromPassiveGrab = FALSE;
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	if (dev->sync.other == grab)
-	    dev->sync.other = NullGrab;
+	if (dev->coreGrab.sync.other == grab)
+	    dev->coreGrab.sync.other = NullGrab;
     }
     DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
     ComputeFreezes();
 }
 
+/* 
+ * Core flag decides whether to work on the coreGrab or deviceGrab sync
+ * fields.
+ */
 void
-AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
+AllowSome(ClientPtr client, 
+          TimeStamp time, 
+          DeviceIntPtr thisDev, 
+          int newState, 
+          Bool core)
 {
     Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
     TimeStamp grabTime;
     register DeviceIntPtr dev;
+    GrabInfoPtr devgrabinfo, 
+                grabinfo = (core) ? &thisDev->coreGrab : &thisDev->deviceGrab;
 
-    thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
+    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
     thisSynced = FALSE;
     otherGrabbed = FALSE;
     othersFrozen = TRUE;
-    grabTime = thisDev->grabTime;
+    grabTime = grabinfo->grabTime;
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
+        devgrabinfo = (core) ? &dev->coreGrab : &dev->deviceGrab;
+
 	if (dev == thisDev)
 	    continue;
-	if (dev->grab && SameClient(dev->grab, client))
+	if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
 	{
 	    if (!(thisGrabbed || otherGrabbed) ||
-		(CompareTimeStamps(dev->grabTime, grabTime) == LATER))
-		grabTime = dev->grabTime;
+		(CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
+		grabTime = devgrabinfo->grabTime;
 	    otherGrabbed = TRUE;
-	    if (thisDev->sync.other == dev->grab)
+	    if (grabinfo->sync.other == devgrabinfo->grab)
 		thisSynced = TRUE;
-	    if (dev->sync.state < FROZEN)
+	    if (devgrabinfo->sync.state < FROZEN)
 		othersFrozen = FALSE;
 	}
-	else if (!dev->sync.other || !SameClient(dev->sync.other, client))
+	else if (!devgrabinfo->sync.other || !SameClient(devgrabinfo->sync.other, client))
 	    othersFrozen = FALSE;
     }
-    if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced))
+    if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
 	return;
     if ((CompareTimeStamps(time, currentTime) == LATER) ||
 	(CompareTimeStamps(time, grabTime) == EARLIER))
@@ -1435,17 +1451,17 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
     {
 	case THAWED:	 	       /* Async */
 	    if (thisGrabbed)
-		thisDev->sync.state = THAWED;
+		grabinfo->sync.state = THAWED;
 	    if (thisSynced)
-		thisDev->sync.other = NullGrab;
+		grabinfo->sync.other = NullGrab;
 	    ComputeFreezes();
 	    break;
 	case FREEZE_NEXT_EVENT:		/* Sync */
 	    if (thisGrabbed)
 	    {
-		thisDev->sync.state = FREEZE_NEXT_EVENT;
+		grabinfo->sync.state = FREEZE_NEXT_EVENT;
 		if (thisSynced)
-		    thisDev->sync.other = NullGrab;
+		    grabinfo->sync.other = NullGrab;
 		ComputeFreezes();
 	    }
 	    break;
@@ -1454,10 +1470,13 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
 	    {
 		for (dev = inputInfo.devices; dev; dev = dev->next)
 		{
-		    if (dev->grab && SameClient(dev->grab, client))
-			dev->sync.state = THAWED;
-		    if (dev->sync.other && SameClient(dev->sync.other, client))
-			dev->sync.other = NullGrab;
+                    devgrabinfo = (core) ? &dev->coreGrab : &dev->deviceGrab;
+		    if (devgrabinfo->grab 
+                            && SameClient(devgrabinfo->grab, client))
+			devgrabinfo->sync.state = THAWED;
+		    if (devgrabinfo->sync.other && 
+                            SameClient(devgrabinfo->sync.other, client))
+			devgrabinfo->sync.other = NullGrab;
 		}
 		ComputeFreezes();
 	    }
@@ -1467,22 +1486,25 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
 	    {
 		for (dev = inputInfo.devices; dev; dev = dev->next)
 		{
-		    if (dev->grab && SameClient(dev->grab, client))
-			dev->sync.state = FREEZE_BOTH_NEXT_EVENT;
-		    if (dev->sync.other && SameClient(dev->sync.other, client))
-			dev->sync.other = NullGrab;
+                    devgrabinfo = (core) ? &dev->coreGrab : &dev->deviceGrab;
+		    if (devgrabinfo->grab 
+                            && SameClient(devgrabinfo->grab, client))
+			devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
+		    if (devgrabinfo->sync.other 
+                            && SameClient(devgrabinfo->sync.other, client))
+			devgrabinfo->sync.other = NullGrab;
 		}
 		ComputeFreezes();
 	    }
 	    break;
 	case NOT_GRABBED:		/* Replay */
-	    if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT)
+	    if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
 	    {
 		if (thisSynced)
-		    thisDev->sync.other = NullGrab;
+		    grabinfo->sync.other = NullGrab;
 		syncEvents.replayDev = thisDev;
-		syncEvents.replayWin = thisDev->grab->window;
-		(*thisDev->DeactivateGrab)(thisDev);
+		syncEvents.replayWin = grabinfo->grab->window;
+		(*grabinfo->DeactivateGrab)(thisDev);
 		syncEvents.replayDev = (DeviceIntPtr)NULL;
 	    }
 	    break;
@@ -1493,10 +1515,13 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
 		{
 		    if (dev == thisDev)
 			continue;
-		    if (dev->grab && SameClient(dev->grab, client))
-			dev->sync.state = THAWED;
-		    if (dev->sync.other && SameClient(dev->sync.other, client))
-			dev->sync.other = NullGrab;
+                    devgrabinfo = (core) ? &dev->coreGrab : &dev->deviceGrab;
+		    if (devgrabinfo->grab 
+                            && SameClient(devgrabinfo->grab, client))
+			devgrabinfo->sync.state = THAWED;
+		    if (devgrabinfo->sync.other 
+                            && SameClient(devgrabinfo->sync.other, client))
+			devgrabinfo->sync.other = NullGrab;
 		}
 		ComputeFreezes();
 	    }
@@ -1517,28 +1542,28 @@ ProcAllowEvents(register ClientPtr client)
     switch (stuff->mode)
     {
 	case ReplayPointer:
-	    AllowSome(client, time, mouse, NOT_GRABBED);
+	    AllowSome(client, time, mouse, NOT_GRABBED, True);
 	    break;
 	case SyncPointer: 
-	    AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
+	    AllowSome(client, time, mouse, FREEZE_NEXT_EVENT, True);
 	    break;
 	case AsyncPointer: 
-	    AllowSome(client, time, mouse, THAWED);
+	    AllowSome(client, time, mouse, THAWED, True);
 	    break;
 	case ReplayKeyboard: 
-	    AllowSome(client, time, keybd, NOT_GRABBED);
+	    AllowSome(client, time, keybd, NOT_GRABBED, True);
 	    break;
 	case SyncKeyboard: 
-	    AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
+	    AllowSome(client, time, keybd, FREEZE_NEXT_EVENT, True);
 	    break;
 	case AsyncKeyboard: 
-	    AllowSome(client, time, keybd, THAWED);
+	    AllowSome(client, time, keybd, THAWED, True);
 	    break;
 	case SyncBoth:
-	    AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
+	    AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT, True);
 	    break;
 	case AsyncBoth:
-	    AllowSome(client, time, keybd, THAWED_BOTH);
+	    AllowSome(client, time, keybd, THAWED_BOTH, True);
 	    break;
 	default: 
 	    client->errorValue = stuff->mode;
@@ -1560,9 +1585,15 @@ ReleaseActiveGrabs(ClientPtr client)
     	done = TRUE;
     	for (dev = inputInfo.devices; dev; dev = dev->next)
     	{
-	    if (dev->grab && SameClient(dev->grab, client))
+	    if (dev->coreGrab.grab && SameClient(dev->coreGrab.grab, client))
+	    {
+	    	(*dev->coreGrab.DeactivateGrab)(dev);
+	    	done = FALSE;
+	    }
+
+	    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
 	    {
-	    	(*dev->DeactivateGrab)(dev);
+	    	(*dev->deviceGrab.DeactivateGrab)(dev);
 	    	done = FALSE;
 	    }
     	}
@@ -1730,7 +1761,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
         tempGrab.coreGrab = True;
-	(*inputInfo.pointer->ActivateGrab)(pDev, &tempGrab,
+	(*inputInfo.pointer->coreGrab.ActivateGrab)(pDev, &tempGrab,
 					   currentTime, TRUE);
     }
     else if ((type == MotionNotify) && deliveries)
@@ -2175,7 +2206,7 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
                 REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2,    xoff, yoff);
 
             /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
-            if ((grab = pDev->grab) && grab->confineTo) {
+            if ((grab = pDev->coreGrab.grab) && grab->confineTo) {
                 if (grab->confineTo->drawable.pScreen 
                         != pSprite->hotPhys.pScreen)
                     pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
@@ -2576,6 +2607,7 @@ CheckPassiveGrabsOnWindow(
 {
     register GrabPtr grab = wPassiveGrabs(pWin);
     GrabRec tempGrab;
+    GrabInfoPtr grabinfo;
     register xEvent *dxE;
 
     if (!grab)
@@ -2629,7 +2661,9 @@ CheckPassiveGrabsOnWindow(
 				tempGrab.modifiersDetail.exact&(~0x1f00);
 	    }
 #endif
-	    (*device->ActivateGrab)(device, grab, currentTime, TRUE);
+            grabinfo = (xE->u.u.type & EXTENSION_EVENT_BASE) ? 
+                &device->deviceGrab : &device->coreGrab;
+	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
  
 	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
 
@@ -2637,20 +2671,20 @@ CheckPassiveGrabsOnWindow(
 				   filters[xE->u.u.type],
 				   filters[xE->u.u.type],  grab);
 
-	    if (device->sync.state == FROZEN_NO_EVENT)
+	    if (grabinfo->sync.state == FROZEN_NO_EVENT)
 	    {
-		if (device->sync.evcount < count)
+		if (grabinfo->sync.evcount < count)
 		{
 		    Must_have_memory = TRUE; /* XXX */
-		    device->sync.event = (xEvent *)xrealloc(device->sync.event,
+		    grabinfo->sync.event = (xEvent *)xrealloc(grabinfo->sync.event,
 							    count*
 							    sizeof(xEvent));
 		    Must_have_memory = FALSE; /* XXX */
 		}
-		device->sync.evcount = count;
-		for (dxE = device->sync.event; --count >= 0; dxE++, xE++)
+		grabinfo->sync.evcount = count;
+		for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++)
 		    *dxE = *xE;
-	    	device->sync.state = FROZEN_WITH_EVENT;
+	    	grabinfo->sync.state = FROZEN_WITH_EVENT;
             }	
 	    return TRUE;
 	}
@@ -2747,12 +2781,20 @@ void
 DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev, 
                     Bool deactivateGrab, int count)
 {
-    register GrabPtr grab = thisDev->grab;
+    register GrabPtr grab;
+    GrabInfoPtr grabinfo;
     int deliveries = 0;
     register DeviceIntPtr dev;
     register xEvent *dxE;
     SpritePtr pSprite = thisDev->pSprite;
 
+    if (xE->u.u.type & EXTENSION_EVENT_BASE)
+        grabinfo = &thisDev->deviceGrab;
+    else
+        grabinfo = &thisDev->coreGrab;
+
+    grab = grabinfo->grab;
+
     if (grab->ownerEvents)
     {
 	WindowPtr focus;
@@ -2798,7 +2840,7 @@ DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev,
 					  && xE->u.u.type != DeviceMotionNotify
 #endif
 					  ))
-	switch (thisDev->sync.state)
+	switch (grabinfo->sync.state)
 	{
 	case FREEZE_BOTH_NEXT_EVENT:
 	    for (dev = inputInfo.devices; dev; dev = dev->next)
@@ -2806,26 +2848,26 @@ DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev,
 		if (dev == thisDev)
 		    continue;
 		FreezeThaw(dev, TRUE);
-		if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
-		    (CLIENT_BITS(dev->grab->resource) ==
-		     CLIENT_BITS(thisDev->grab->resource)))
-		    dev->sync.state = FROZEN_NO_EVENT;
+		if ((grabinfo->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
+		    (CLIENT_BITS(grab->resource) ==
+		     CLIENT_BITS(grab->resource)))
+		    grabinfo->sync.state = FROZEN_NO_EVENT;
 		else
-		    dev->sync.other = thisDev->grab;
+		    grabinfo->sync.other = grab;
 	    }
 	    /* fall through */
 	case FREEZE_NEXT_EVENT:
-	    thisDev->sync.state = FROZEN_WITH_EVENT;
+	    grabinfo->sync.state = FROZEN_WITH_EVENT;
 	    FreezeThaw(thisDev, TRUE);
-	    if (thisDev->sync.evcount < count)
+	    if (grabinfo->sync.evcount < count)
 	    {
 		Must_have_memory = TRUE; /* XXX */
-		thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event,
+		grabinfo->sync.event = (xEvent *)xrealloc(grabinfo->sync.event,
 							 count*sizeof(xEvent));
 		Must_have_memory = FALSE; /* XXX */
 	    }
-	    thisDev->sync.evcount = count;
-	    for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++)
+	    grabinfo->sync.evcount = count;
+	    for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++)
 		*dxE = *xE;
 	    break;
 	}
@@ -2843,9 +2885,11 @@ ProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int coun
     register int    i;
     register CARD8  modifiers;
     register CARD16 mask;
-    GrabPtr         grab = keybd->grab;
+    register GrabPtr         grab;
+    GrabInfoPtr     grabinfo;
     Bool            deactivateGrab = FALSE;
     register KeyClassPtr keyc = keybd->key;
+
 #ifdef XEVIE
     static Window           rootWin = 0;
 
@@ -2886,6 +2930,13 @@ drawable.id:0;
     }
 #endif
 
+    if (xE->u.u.type & EXTENSION_EVENT_BASE)
+        grabinfo = &keybd->deviceGrab;
+    else
+        grabinfo = &keybd->coreGrab;
+
+    grab = grabinfo->grab;
+
     if (!syncEvents.playingEvents)
     {
 	NoticeTime(xE);
@@ -2954,7 +3005,7 @@ drawable.id:0;
 	    }
 	    if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
 	    {
-		keybd->activatingKey = key;
+		grabinfo->activatingKey = key;
 		return;
 	    }
 	    break;
@@ -2975,7 +3026,7 @@ drawable.id:0;
 		    modifiers &= ~mask;
 		}
 	    }
-	    if (keybd->fromPassiveGrab && (key == keybd->activatingKey))
+	    if (grabinfo->fromPassiveGrab && (key == grabinfo->activatingKey))
 		deactivateGrab = TRUE;
 	    break;
 	default: 
@@ -2986,7 +3037,7 @@ drawable.id:0;
     else
 	DeliverFocusedEvent(keybd, xE, keybd->pSprite->win, count);
     if (deactivateGrab)
-        (*keybd->DeactivateGrab)(keybd);
+        (*grabinfo->DeactivateGrab)(keybd);
 
     XaceHook(XACE_KEY_AVAIL, xE, keybd, count);
 }
@@ -3033,7 +3084,7 @@ CoreProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int c
 ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count)
 #endif
 {
-    register GrabPtr	grab = mouse->grab;
+    GrabPtr	        grab = mouse->coreGrab.grab;
     Bool                deactivateGrab = FALSE;
     register ButtonClassPtr butc = mouse->button;
     SpritePtr           pSprite = mouse->pSprite;
@@ -3120,7 +3171,7 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
 	    if (xE->u.u.detail <= 5)
 		butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	    filters[MotionNotify] = Motion_Filter(butc);
-	    if (!butc->state && mouse->fromPassiveGrab)
+	    if (!butc->state && mouse->coreGrab.fromPassiveGrab)
 		deactivateGrab = TRUE;
 	    break;
 	default: 
@@ -3135,7 +3186,7 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
 	DeliverDeviceEvents(pSprite->win, xE, NullGrab, NullWindow,
 			    mouse, count);
     if (deactivateGrab)
-        (*mouse->DeactivateGrab)(mouse);
+        (*mouse->coreGrab.DeactivateGrab)(mouse);
 }
 
 #define AtMostOneClient \
@@ -3277,7 +3328,7 @@ maskSet:
     if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
 	(mask & PointerMotionHintMask) &&
 	!(check & PointerMotionHintMask) &&
-	!inputInfo.pointer->grab)
+	!inputInfo.pointer->coreGrab.grab) /* VCP shouldn't have deviceGrab */
 	inputInfo.pointer->valuator->motionHintWindow = NullWindow;
     RecalculateDeliverableEvents(pWin);
     return Success;
@@ -3362,7 +3413,8 @@ EnterLeaveEvent(
     register DeviceIntPtr keybd = inputInfo.keyboard;
     WindowPtr		focus;
     register DeviceIntPtr mouse = pDev;
-    register GrabPtr	grab = mouse->grab;
+    GrabPtr	        grab = mouse->coreGrab.grab;
+    GrabPtr	        devgrab = mouse->deviceGrab.grab;
     Mask		mask;
 
     deviceEnterNotify   *devEnterLeave;
@@ -3430,9 +3482,9 @@ EnterLeaveEvent(
     if (inputMasks && 
        (filters[devEnterLeave->type] & inputMasks->deliverableEvents[mskidx]))
     {
-        if (grab)
-            (void)TryClientEvents(rClient(grab), (xEvent*)devEnterLeave, 1,
-                                  mask, filters[devEnterLeave->type], grab);
+        if (devgrab)
+            (void)TryClientEvents(rClient(devgrab), (xEvent*)devEnterLeave, 1,
+                                mask, filters[devEnterLeave->type], devgrab);
 	else
 	    (void)DeliverEventsToWindow(pDev, pWin, (xEvent*)devEnterLeave, 
                                         1, filters[devEnterLeave->type], 
@@ -3776,7 +3828,7 @@ SetInputFocus(
     if ((CompareTimeStamps(time, currentTime) == LATER) ||
 	(CompareTimeStamps(time, focus->time) == EARLIER))
 	return Success;
-    mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal;
+    mode = (dev->coreGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
     if (focus->win == FollowKeyboardWin)
 	DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode);
     else
@@ -3912,7 +3964,7 @@ ProcGrabPointer(ClientPtr client)
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
     rep.length = 0;
-    grab = device->grab;
+    grab = device->coreGrab.grab;
     if ((grab) && !SameClient(grab, client))
 	rep.status = AlreadyGrabbed;
     else if ((!pWin->realized) ||
@@ -3920,11 +3972,12 @@ ProcGrabPointer(ClientPtr client)
                 !(confineTo->realized 
                     && BorderSizeNotEmpty(device, confineTo))))
 	rep.status = GrabNotViewable;
-    else if (device->sync.frozen &&
-	     device->sync.other && !SameClient(device->sync.other, client))
+    else if (device->coreGrab.sync.frozen &&
+	     device->coreGrab.sync.other && 
+             !SameClient(device->coreGrab.sync.other, client))
 	rep.status = GrabFrozen;
     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
-	     (CompareTimeStamps(time, device->grabTime) == EARLIER))
+	     (CompareTimeStamps(time, device->coreGrab.grabTime) == EARLIER))
 	rep.status = GrabInvalidTime;
     else
     {
@@ -3948,7 +4001,7 @@ ProcGrabPointer(ClientPtr client)
 	tempGrab.pointerMode = stuff->pointerMode;
 	tempGrab.device = device;
         tempGrab.coreGrab = True;
-	(*device->ActivateGrab)(device, &tempGrab, time, FALSE);
+	(*device->coreGrab.ActivateGrab)(device, &tempGrab, time, FALSE);
 	if (oldCursor)
 	    FreeCursor (oldCursor, (Cursor)0);
 	rep.status = GrabSuccess;
@@ -3961,7 +4014,7 @@ int
 ProcChangeActivePointerGrab(ClientPtr client)
 {
     DeviceIntPtr device = PickPointer(client);
-    register GrabPtr grab = device->grab;
+    register GrabPtr grab = device->coreGrab.grab;
     CursorPtr newCursor, oldCursor;
     REQUEST(xChangeActivePointerGrabReq);
     TimeStamp time;
@@ -3990,7 +4043,7 @@ ProcChangeActivePointerGrab(ClientPtr client)
 	return Success;
     time = ClientTimeToServerTime(stuff->time);
     if ((CompareTimeStamps(time, currentTime) == LATER) ||
-	     (CompareTimeStamps(time, device->grabTime) == EARLIER))
+	     (CompareTimeStamps(time, device->coreGrab.grabTime) == EARLIER))
 	return Success;
     oldCursor = grab->cursor;
     grab->cursor = newCursor;
@@ -4013,12 +4066,12 @@ ProcUngrabPointer(ClientPtr client)
 
     REQUEST_SIZE_MATCH(xResourceReq);
     UpdateCurrentTime();
-    grab = device->grab;
+    grab = device->coreGrab.grab;
     time = ClientTimeToServerTime(stuff->id);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
-	    (CompareTimeStamps(time, device->grabTime) != EARLIER) &&
+	    (CompareTimeStamps(time, device->coreGrab.grabTime) != EARLIER) &&
 	    (grab) && SameClient(grab, client))
-	(*device->DeactivateGrab)(device);
+	(*device->coreGrab.DeactivateGrab)(device);
     return Success;
 }
 
@@ -4052,16 +4105,16 @@ GrabDevice(register ClientPtr client, register DeviceIntPtr dev,
     if (rc != Success)
 	return rc;
     time = ClientTimeToServerTime(ctime);
-    grab = dev->grab;
+    grab = dev->coreGrab.grab;
     if (grab && !SameClient(grab, client))
 	*status = AlreadyGrabbed;
     else if (!pWin->realized)
 	*status = GrabNotViewable;
     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
-	     (CompareTimeStamps(time, dev->grabTime) == EARLIER))
+	     (CompareTimeStamps(time, dev->coreGrab.grabTime) == EARLIER))
 	*status = GrabInvalidTime;
-    else if (dev->sync.frozen &&
-	     dev->sync.other && !SameClient(dev->sync.other, client))
+    else if (dev->coreGrab.sync.frozen &&
+	     dev->coreGrab.sync.other && !SameClient(dev->coreGrab.sync.other, client))
 	*status = GrabFrozen;
     else
     {
@@ -4079,7 +4132,7 @@ GrabDevice(register ClientPtr client, register DeviceIntPtr dev,
 	tempGrab.device = dev;
         tempGrab.cursor = NULL;
 
-	(*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
+	(*dev->coreGrab.ActivateGrab)(dev, &tempGrab, time, FALSE);
 	*status = GrabSuccess;
     }
     return Success;
@@ -4123,12 +4176,12 @@ ProcUngrabKeyboard(ClientPtr client)
 
     REQUEST_SIZE_MATCH(xResourceReq);
     UpdateCurrentTime();
-    grab = device->grab;
+    grab = device->coreGrab.grab;
     time = ClientTimeToServerTime(stuff->id);
     if ((CompareTimeStamps(time, currentTime) != LATER) &&
-	(CompareTimeStamps(time, device->grabTime) != EARLIER) &&
+	(CompareTimeStamps(time, device->coreGrab.grabTime) != EARLIER) &&
 	(grab) && SameClient(grab, client))
-	(*device->DeactivateGrab)(device);
+	(*device->coreGrab.DeactivateGrab)(device);
     return Success;
 }
 
@@ -4547,19 +4600,21 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
     FocusClassPtr	focus = keybd->focus;
     OtherClientsPtr	oc;
     GrabPtr		passive;
+    GrabPtr             grab; 
 
 
     /* Deactivate any grabs performed on this window, before making any
 	input focus changes. */
-
-    if (mouse->grab &&
-	((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin)))
-	(*mouse->DeactivateGrab)(mouse);
+    grab = mouse->coreGrab.grab;
+    if (grab &&
+	((grab->window == pWin) || (grab->confineTo == pWin)))
+	(*mouse->coreGrab.DeactivateGrab)(mouse);
 
     /* Deactivating a keyboard grab should cause focus events. */
 
-    if (keybd->grab && (keybd->grab->window == pWin))
-	(*keybd->DeactivateGrab)(keybd);
+    grab = keybd->coreGrab.grab;
+    if (grab && (grab->window == pWin))
+	(*keybd->coreGrab.DeactivateGrab)(keybd);
 
     /* If the focus window is a root window (ie. has no parent) then don't 
 	delete the focus from it. */
@@ -4570,7 +4625,7 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
 
  	/* If a grab is in progress, then alter the mode of focus events. */
 
-	if (keybd->grab)
+	if (keybd->coreGrab.grab)
 	    focusEventMode = NotifyWhileGrabbed;
 
 	switch (focus->revert)
@@ -4644,11 +4699,11 @@ CheckCursorConfinement(WindowPtr pWin)
     {
         if (DevHasCursor(pDev))
         {
-            grab = pDev->grab;
+            grab = pDev->coreGrab.grab;
             if (grab && (confineTo = grab->confineTo))
             {
                 if (!BorderSizeNotEmpty(pDev, confineTo))
-                    (*inputInfo.pointer->DeactivateGrab)(pDev);
+                    (*inputInfo.pointer->coreGrab.DeactivateGrab)(pDev);
                 else if ((pWin == confineTo) || IsParent(pWin, confineTo))
                     ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
             }
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
index c0e21dd..2981e17 100644
--- a/hw/xfree86/common/xf86Config.c
+++ b/hw/xfree86/common/xf86Config.c
@@ -2478,8 +2478,6 @@ xf86HandleConfigFile(Bool autoconfig)
              return CONFIG_PARSE_ERROR;
     }
 
-    checkInput(&xf86ConfigLayout);
-
     /*
      * Handle some command line options that can override some of the
      * ServerFlags settings.
diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c
index 204457f..9a24040 100644
--- a/hw/xfree86/common/xf86DGA.c
+++ b/hw/xfree86/common/xf86DGA.c
@@ -1030,9 +1030,11 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd)
     else
     {
 	/* If the keyboard is actively grabbed, deliver a grabbed core event */
-	if (keybd->grab && !keybd->fromPassiveGrab)
+	if (keybd->coreGrab.grab && !keybd->coreGrab.fromPassiveGrab)
 	{
-	    core.u.u.type		    = coreEquiv;
+            /* I've got no clue if that is correct but only working on core
+             * grabs seems the right thing here. (whot) */
+            core.u.u.type		    = coreEquiv;
 	    core.u.u.detail		    = de->u.u.detail;
 	    core.u.keyButtonPointer.time    = de->u.event.time;
 	    core.u.keyButtonPointer.eventX  = de->u.event.dx;
@@ -1109,8 +1111,10 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse)
     else
     {
 	/* If the pointer is actively grabbed, deliver a grabbed core event */
-	if (mouse->grab && !mouse->fromPassiveGrab)
+	if (mouse->coreGrab.grab && !mouse->coreGrab.fromPassiveGrab)
 	{
+            /* I've got no clue if that is correct but only working on core
+             * grabs seems the right thing here. (whot) */
 	    core.u.u.type		    = coreEquiv;
 	    core.u.u.detail		    = de->u.u.detail;
 	    core.u.keyButtonPointer.time    = de->u.event.time;
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 5f43714..a91f6b3 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -290,12 +290,13 @@ xf86ProcessActionEvent(ActionEvent action, void *arg)
 	break;
     case ACTION_DISABLEGRAB:
 	if (!xf86Info.grabInfo.disabled && xf86Info.grabInfo.allowDeactivate) {
-	  if (inputInfo.pointer && inputInfo.pointer->grab != NULL &&
-	      inputInfo.pointer->DeactivateGrab)
-	    inputInfo.pointer->DeactivateGrab(inputInfo.pointer);
-	  if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL &&
-	      inputInfo.keyboard->DeactivateGrab)
-	    inputInfo.keyboard->DeactivateGrab(inputInfo.keyboard);
+	  if (inputInfo.pointer && inputInfo.pointer->coreGrab.grab != NULL &&
+	      inputInfo.pointer->coreGrab.DeactivateGrab)
+	    inputInfo.pointer->coreGrab.DeactivateGrab(inputInfo.pointer);
+	  if (inputInfo.keyboard && 
+                  inputInfo.keyboard->coreGrab.grab != NULL &&
+	      inputInfo.keyboard->coreGrab.DeactivateGrab)
+	    inputInfo.keyboard->coreGrab.DeactivateGrab(inputInfo.keyboard);
 	}
 	break;
     case ACTION_CLOSECLIENT:
@@ -303,10 +304,11 @@ xf86ProcessActionEvent(ActionEvent action, void *arg)
 	  ClientPtr pointer, keyboard, server;
 
 	  pointer = keyboard = server = NULL;
-	  if (inputInfo.pointer && inputInfo.pointer->grab != NULL)
-	    pointer = clients[CLIENT_ID(inputInfo.pointer->grab->resource)];
-	  if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL) {
-	    keyboard = clients[CLIENT_ID(inputInfo.keyboard->grab->resource)];
+	  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)
+          {
+	    keyboard = clients[CLIENT_ID(inputInfo.keyboard->coreGrab.grab->resource)];
 	    if (keyboard == pointer)
 	      keyboard = NULL;
 	  }
diff --git a/include/dix.h b/include/dix.h
index 95c69f0..f22f489 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -469,7 +469,8 @@ extern void AllowSome(
     ClientPtr	/* client */,
     TimeStamp /* time */,
     DeviceIntPtr /* thisDev */,
-    int /* newState */);
+    int /* newState */,
+    Bool /* core */);
 
 extern void ReleaseActiveGrabs(
     ClientPtr client);
diff --git a/include/input.h b/include/input.h
index ca81b1a..2d72f83 100644
--- a/include/input.h
+++ b/include/input.h
@@ -455,7 +455,7 @@ extern DeviceIntPtr GetPairedPointer(DeviceIntPtr kbd);
 extern Bool RegisterPairingClient(ClientPtr client);
 extern Bool UnregisterPairingClient(ClientPtr client);
 
-extern DeviceIntPtr GuessFreePointerDevice();
+extern DeviceIntPtr GuessFreePointerDevice(void);
 
 /* Window/device based access control */
 extern Bool ACRegisterClient(ClientPtr client);
diff --git a/include/inputstr.h b/include/inputstr.h
index 90a985b..8c3e560 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -300,11 +300,31 @@ typedef struct {
 #define FROZEN_NO_EVENT		5
 #define FROZEN_WITH_EVENT	6
 #define THAW_OTHERS		7
+typedef struct _GrabInfoRec {
+    TimeStamp	    grabTime;
+    Bool            fromPassiveGrab;
+    GrabRec         activeGrab;
+    GrabPtr         grab;
+    CARD8           activatingKey;
+    void	    (*ActivateGrab) (
+                    DeviceIntPtr /*device*/,
+                    GrabPtr /*grab*/,
+                    TimeStamp /*time*/,
+                    Bool /*autoGrab*/);
+    void	    (*DeactivateGrab)(
+                    DeviceIntPtr /*device*/);
+    struct {
+	Bool		frozen;
+	int		state;
+	GrabPtr		other;		/* if other grab has this frozen */
+	xEvent		*event;		/* saved to be replayed */
+	int		evcount;
+    } sync;
+} GrabInfoRec, *GrabInfoPtr;
 
 typedef struct _DeviceIntRec {
     DeviceRec	public;
     DeviceIntPtr next;
-    TimeStamp	grabTime;
     Bool	startup;		/* true if needs to be turned on at
 				          server intialization time */
     DeviceProc	deviceProc;		/* proc(DevicePtr, DEVICE_xx). It is
@@ -313,27 +333,11 @@ 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 */
-    GrabPtr	grab;			/* the grabber - used by DIX */
-    struct {
-	Bool		frozen;
-	int		state;
-	GrabPtr		other;		/* if other grab has this frozen */
-	xEvent		*event;		/* saved to be replayed */
-	int		evcount;
-    } sync;
+    GrabInfoRec coreGrab;               /* grab on core events */
+    GrabInfoRec deviceGrab;             /* grab on device events */
     Atom		type;
     char		*name;
     CARD8		id;
-    CARD8		activatingKey;
-    Bool		fromPassiveGrab;
-    GrabRec		activeGrab;
-    void		(*ActivateGrab) (
-			DeviceIntPtr /*device*/,
-			GrabPtr /*grab*/,
-			TimeStamp /*time*/,
-			Bool /*autoGrab*/);
-    void		(*DeactivateGrab)(
-			DeviceIntPtr /*device*/);
     KeyClassPtr		key;
     ValuatorClassPtr	valuator;
     ButtonClassPtr	button;
diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c
index 139221f..eeb9dec 100644
--- a/xkb/xkbEvents.c
+++ b/xkb/xkbEvents.c
@@ -808,6 +808,7 @@ XkbFilterEvents(ClientPtr pClient,int nEvents,xEvent *xE)
 int	i, button_mask;
 DeviceIntPtr pXDev = (DeviceIntPtr)LookupKeyboardDevice();
 XkbSrvInfoPtr	xkbi;
+GrabInfoPtr grabinfo;
 
     xkbi= pXDev->key->xkbInfo;
     if ( pClient->xkbClientFlags & _XkbClientInitialized ) {
@@ -831,7 +832,9 @@ XkbSrvInfoPtr	xkbi;
 	     	(_XkbIsReleaseEvent(xE[0].u.u.type)) ) {
 	    return False;
 	}
-	if ((pXDev->grab != NullGrab) && pXDev->fromPassiveGrab &&
+        /* just coreGrab is fine, pXDev is inputInfo.keyboard (see above) */
+	if ((pXDev->coreGrab.grab != NullGrab) 
+                && pXDev->coreGrab.fromPassiveGrab &&
 	    ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease))) {
 	    register unsigned state,flags;
 
commit 537bc2ead4d154552cbdc3a19e335f82af63792c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Mar 7 18:19:20 2007 +1030

    Xi:    Don't deactivate core grabs from non-core button/key releases.
    
    dix:    set coreGrab flag for grabs caused by GrabPointer and button presses.
            remove virtual core devices from device list, only real devices are in
            the list now.
            Auto-pair each keyboard with a real pointer if one is available,
              provides multiple keyboards automatically after startup if devices
              are configured.
            fix GuessFreePointerDevice() to do what it's supposed to do.
    
    mi:     fix: call miPointerMove from miPointerWarpCursor.
            fix: remove unused id field from miCursorInfoRec
            don't update sprite for virtual core pointer.

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 7e80926..5dbb0e2 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -104,12 +104,12 @@ RegisterOtherDevice(DeviceIntPtr device)
 }
 
  /*ARGSUSED*/ void
-ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
+ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
 {
-    register BYTE *kptr;
-    register int i;
-    register CARD16 modifiers;
-    register CARD16 mask;
+    BYTE *kptr;
+    int i;
+    CARD16 modifiers;
+    CARD16 mask;
     GrabPtr grab = other->grab;
     Bool deactivateDeviceGrab = FALSE;
     int key = 0, bit = 0, rootX, rootY;
@@ -229,7 +229,9 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 	    }
 	}
 
-	if (other->fromPassiveGrab && (key == other->activatingKey))
+	if (other->fromPassiveGrab && 
+            !other->grab->coreGrab &&
+            (key == other->activatingKey))
 	    deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == DeviceButtonPress) {
         if (!b)
@@ -267,7 +269,9 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 	if (xE->u.u.detail <= 5)
 	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
-        if (!b->state && other->fromPassiveGrab)
+        if (!b->state 
+            && other->fromPassiveGrab
+            && !other->grab->coreGrab)
             deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == ProximityIn)
 	other->valuator->mode &= ~OutOfProximity;
diff --git a/dix/cursor.c b/dix/cursor.c
index cf515c1..e44a5ef 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -440,6 +440,33 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
         pscr = screenInfo.screens[nscr];
+
+        if (!(*pscr->RealizeCursor)(inputInfo.pointer, pscr, pCurs))
+        {
+            DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
+            /* Realize for core pointer failed. Unrealize everything from
+             * previous screens.
+             */ 
+            while (--nscr >= 0)
+            {
+                pscr = screenInfo.screens[nscr];
+                /* now unrealize all devices on previous screens */
+                ( *pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs);
+
+                pDevIt = inputInfo.devices;
+                while (pDevIt)
+                {
+                    if (DevHasCursor(pDevIt))
+                        ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
+                    pDevIt = pDevIt->next;
+                }
+                ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
+            }
+            FreeCursorBits(bits);
+            xfree(pCurs);
+            return BadAlloc;
+        }
+
         for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
             if (DevHasCursor(pDev))
@@ -459,10 +486,15 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
                             ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                         pDevIt = pDevIt->next;
                     }
+
+                    (*pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs);
+
                     while (--nscr >= 0)
                     {
                         pscr = screenInfo.screens[nscr];
                         /* now unrealize all devices on previous screens */
+                        ( *pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs);
+
                         pDevIt = inputInfo.devices;
                         while (pDevIt)
                         {
diff --git a/dix/devices.c b/dix/devices.c
index 9195586..9e08794 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -347,7 +347,15 @@ InitCoreDevices()
             FatalError("Couldn't allocate keyboard 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.keyboard = dev;
+        inputInfo.keyboard->next = NULL;
     }
 
     if (!inputInfo.pointer) {
@@ -372,7 +380,17 @@ InitCoreDevices()
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
         InitializeSprite(dev, NullWindow);
         (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);
@@ -382,7 +400,7 @@ InitCoreDevices()
 int
 InitAndStartDevices()
 {
-    register DeviceIntPtr dev, next;
+    DeviceIntPtr dev, next;
 
     for (dev = inputInfo.off_devices; dev; dev = dev->next) {
         DebugF("(dix) initialising device %d\n", dev->id);
@@ -395,21 +413,25 @@ InitAndStartDevices()
 	if (dev->inited && dev->startup)
 	    (void)EnableDevice(dev);
     }
-    for (dev = inputInfo.devices;
-	 dev && (dev != inputInfo.keyboard);
-	 dev = dev->next)
-    if (!dev || (dev != inputInfo.keyboard)) {
+
+    if (!inputInfo.keyboard) {
 	ErrorF("No core keyboard\n");
 	return BadImplementation;
     }
-    for (dev = inputInfo.devices;
-	 dev && (dev != inputInfo.pointer);
-	 dev = dev->next)
-	;
-    if (!dev || (dev != inputInfo.pointer)) {
+    if (!inputInfo.pointer) {
 	ErrorF("No core pointer\n");
 	return BadImplementation;
     }
+
+    /* All of the devices are started up now. Try to pair each keyboard with a
+     * real pointer, if possible. */
+    for (dev = inputInfo.devices; dev; dev = dev->next)
+    {
+        if (!DevHasCursor(dev))
+            PairDevices(NULL, GuessFreePointerDevice(), dev);
+    }
+
+
     return Success;
 }
 
@@ -2043,7 +2065,7 @@ GuessFreePointerDevice()
     while(it)
     {
         /* found device with a sprite? */
-        if (it != inputInfo.pointer && it->spriteOwner)
+        if (it->spriteOwner)
         {
             lastRealPtr = it;
 
@@ -2057,11 +2079,9 @@ GuessFreePointerDevice()
                 it2 = it2->next;
             }
 
-            if (it2)
-                break;
-
             /* woohoo! no pairing set up for 'it' yet */
-            return it;
+            if (!it2)
+                return it;
         }
         it = it->next;
     }
diff --git a/dix/events.c b/dix/events.c
index 5be923a..23d5f22 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -247,7 +247,7 @@ static int spriteTraceGood;
 _X_EXPORT Bool
 DevHasCursor(DeviceIntPtr pDev) 
 {
-    return pDev->spriteOwner;
+    return (pDev != inputInfo.pointer && pDev->spriteOwner);
 }
 
 #ifdef XEVIE
@@ -1663,6 +1663,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 		              this mask is the mask of the grab. */
     int type = pEvents->u.u.type;
     
+    /* if a  is denied, we return 0. This could cause the caller to
+     * traverse the parent. May be bad! (whot) */
     if (!ACDeviceAllowed(pWin, pDev))
         return 0;
 
@@ -1727,6 +1729,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
 	tempGrab.pointerMode = GrabModeAsync;
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
+        tempGrab.coreGrab = True;
 	(*inputInfo.pointer->ActivateGrab)(pDev, &tempGrab,
 					   currentTime, TRUE);
     }
@@ -1868,8 +1871,8 @@ FixUpEventFromWindow(
 }
 
 int
-DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab, 
-                    register WindowPtr stopAt, DeviceIntPtr dev, int count)
+DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, 
+                    WindowPtr stopAt, DeviceIntPtr dev, int count)
 {
     Window child = None;
     int type = xE->u.u.type;
@@ -1878,7 +1881,7 @@ DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
 
     if (type & EXTENSION_EVENT_BASE)
     {
-	register OtherInputMasks *inputMasks;
+	OtherInputMasks *inputMasks;
 	int mskidx = dev->id;
 
 	inputMasks = wOtherInputMasks(pWin);
@@ -2199,6 +2202,8 @@ DefineInitialRootWindow(register WindowPtr win)
 #endif
     ROOT = win;
 
+    InitializeSprite(inputInfo.pointer, win);
+
     while (pDev)
     {
         if (DevHasCursor(pDev))
@@ -2274,7 +2279,6 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
         REGION_NULL(pScreen, &pSprite->Reg2);
     }
 #endif
-
 }
 
 /*
@@ -3943,6 +3947,7 @@ ProcGrabPointer(ClientPtr client)
 	tempGrab.keyboardMode = stuff->keyboardMode;
 	tempGrab.pointerMode = stuff->pointerMode;
 	tempGrab.device = device;
+        tempGrab.coreGrab = True;
 	(*device->ActivateGrab)(device, &tempGrab, time, FALSE);
 	if (oldCursor)
 	    FreeCursor (oldCursor, (Cursor)0);
diff --git a/include/input.h b/include/input.h
index 433cc94..ca81b1a 100644
--- a/include/input.h
+++ b/include/input.h
@@ -455,6 +455,8 @@ extern DeviceIntPtr GetPairedPointer(DeviceIntPtr kbd);
 extern Bool RegisterPairingClient(ClientPtr client);
 extern Bool UnregisterPairingClient(ClientPtr client);
 
+extern DeviceIntPtr GuessFreePointerDevice();
+
 /* Window/device based access control */
 extern Bool ACRegisterClient(ClientPtr client);
 extern Bool ACUnregisterClient(ClientPtr client);
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 5df7a0a..edb5c5f 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -302,7 +302,7 @@ miPointerWarpCursor (pDev, pScreen, x, y)
 
     if (GenerateEvent)
     {
-	miPointerMoved (pDev, pScreen, x, y, GetTimeInMillis()); 
+	miPointerMove (pDev, pScreen, x, y, GetTimeInMillis()); 
     }
     else
     {
@@ -346,8 +346,8 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     int			x, y, devx, devy;
     miPointerPtr        pPointer;
 
-    if (!pDev || 
-            !(pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev))
+    if (!pDev || pDev == inputInfo.pointer || 
+            !(pDev->coreEvents || pDev->isMPDev))
         return;
 
     pPointer = MIPOINTER(pDev);
@@ -540,7 +540,7 @@ miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, unsigned long
     int i, nevents;
     int valuators[2];
 
-    miPointerMoved(inputInfo.pointer, pScreen, x, y, time);
+    miPointerMoved(pDev, pScreen, x, y, time);
 
     /* generate motion notify */
     valuators[0] = x;
diff --git a/mi/mispritest.h b/mi/mispritest.h
index 8c8cd53..8cc2064 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -44,7 +44,6 @@ in this Software without prior written authorization from The Open Group.
 # include   "damage.h"
 
 typedef struct {
-    int             id;                 /* id, corresponds with device id */
     CursorPtr	    pCursor;
     int		    x;			/* cursor hotspot */
     int		    y;
commit 39aa79177196e21bcdbaf8e44adead9ef91e6ee5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Mar 5 15:31:16 2007 +1030

    dix:    Add GuessFreePointerDevice(). Runs through device list and tries to
            find a pointer that hasn't been paired yet.
    
    xfree86:  Use GuessFreePointerDevice() for newly connected non-sprite devices.

diff --git a/dix/devices.c b/dix/devices.c
index 87b3927..9195586 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2026,3 +2026,45 @@ UnregisterPairingClient(ClientPtr client)
     }
     return True;
 }
+
+/* Guess a pointer that could be a good one for pairing. Any pointer that is
+ * not yet paired with keyboard is considered a good one. 
+ * If no pointer is found, the last real pointer is chosen. If that doesn't
+ * work either, we take the core pointer.
+ */
+DeviceIntPtr
+GuessFreePointerDevice()
+{
+    DeviceIntPtr it, it2;
+    DeviceIntPtr lastRealPtr = NULL;
+        
+    it = inputInfo.devices;
+
+    while(it)
+    {
+        /* found device with a sprite? */
+        if (it != inputInfo.pointer && it->spriteOwner)
+        {
+            lastRealPtr = it;
+
+            it2 = inputInfo.devices;
+            while(it2)
+            {
+                /* something paired with it? */
+                if (it != it2 && it2->pSprite == it->pSprite)
+                    break;
+
+                it2 = it2->next;
+            }
+
+            if (it2)
+                break;
+
+            /* woohoo! no pairing set up for 'it' yet */
+            return it;
+        }
+        it = it->next;
+    }
+
+    return (lastRealPtr) ? lastRealPtr : inputInfo.pointer;
+}
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 31be1e3..c6d6b36 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -189,8 +189,10 @@ xf86ActivateDevice(LocalDevicePtr local)
         /* Only create a new sprite if it's a non-shared pointer */
         if (IsPointerDevice(dev) && dev->isMPDev)
             InitializeSprite(dev, GetCurrentRootWindow());
-        else 
-            PairDevices(NULL, inputInfo.pointer, dev);
+        else {
+            /* pair with a free device */
+            PairDevices(NULL, GuessFreePointerDevice(), dev);
+        }
 
         RegisterOtherDevice(dev);
 
commit 1f0075786fedde538a95e2f39681052e25021d88
Merge: 57aa5e9... 12175b6...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Mar 5 12:37:17 2007 +1030

    Merge branch 'master' into mpx
    
    Conflicts:
    
    	configure.ac
    	dix/getevents.c
    	hw/xfree86/ramdac/xf86Cursor.c
    	mi/mipointer.c
    	xkb/xkbUtils.c

diff --cc hw/xfree86/modes/xf86RandR12.c
index 0000000,052d12a..020fbb1
mode 000000,100644..100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@@ -1,0 -1,960 +1,961 @@@
+ /* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.3 2004/07/30 21:53:09 eich Exp $ */
+ /*
+  * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.7tsi Exp $
+  *
+  * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+  *
+  * Permission to use, copy, modify, distribute, and sell this software and its
+  * documentation for any purpose is hereby granted without fee, provided that
+  * the above copyright notice appear in all copies and that both that copyright
+  * notice and this permission notice appear in supporting documentation, and
+  * that the name of the copyright holders not be used in advertising or
+  * publicity pertaining to distribution of the software without specific,
+  * written prior permission.  The copyright holders make no representations
+  * about the suitability of this software for any purpose.  It is provided "as
+  * is" without express or implied warranty.
+  *
+  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+  * OF THIS SOFTWARE.
+  */
+ 
+ #ifdef HAVE_XORG_CONFIG_H
+ #include <xorg-config.h>
+ #else
+ #ifdef HAVE_CONFIG_H
+ #include <config.h>
+ #endif
+ #endif
+ 
+ #include "xf86.h"
+ #include "os.h"
+ #include "mibank.h"
+ #include "globals.h"
+ #include "xf86.h"
+ #include "xf86Priv.h"
+ #include "xf86DDC.h"
+ #include "mipointer.h"
+ #include "windowstr.h"
++#include "inputstr.h"
+ #include <randrstr.h>
+ #include <X11/extensions/render.h>
+ 
+ #include "xf86Crtc.h"
+ #include "xf86RandR12.h"
+ 
+ typedef struct _xf86RandR12Info {
+     int				    virtualX;
+     int				    virtualY;
+     int				    mmWidth;
+     int				    mmHeight;
+     int				    maxX;
+     int				    maxY;
+     Rotation			    rotation; /* current mode */
+     Rotation                        supported_rotations; /* driver supported */
+ } XF86RandRInfoRec, *XF86RandRInfoPtr;
+ 
+ #ifdef RANDR_12_INTERFACE
+ static Bool xf86RandR12Init12 (ScreenPtr pScreen);
+ static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
+ #endif
+ 
+ static int	    xf86RandR12Index;
+ static int	    xf86RandR12Generation;
+ 
+ #define XF86RANDRINFO(p) \
+ 	((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
+ 
+ static int
+ xf86RandR12ModeRefresh (DisplayModePtr mode)
+ {
+     if (mode->VRefresh)
+ 	return (int) (mode->VRefresh + 0.5);
+     else
+ 	return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
+ }
+ 
+ static Bool
+ xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
+ {
+     RRScreenSizePtr	    pSize;
+     ScrnInfoPtr		    scrp = XF86SCRNINFO(pScreen);
+     XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
+     DisplayModePtr	    mode;
+     int			    refresh0 = 60;
+     int			    maxX = 0, maxY = 0;
+ 
+     *rotations = randrp->supported_rotations;
+ 
+     if (randrp->virtualX == -1 || randrp->virtualY == -1)
+     {
+ 	randrp->virtualX = scrp->virtualX;
+ 	randrp->virtualY = scrp->virtualY;
+     }
+ 
+     /* Re-probe the outputs for new monitors or modes */
+     xf86ProbeOutputModes (scrp, 0, 0);
+     xf86SetScrnInfoModes (scrp);
+     xf86DiDGAReInit (pScreen);
+ 
+     for (mode = scrp->modes; ; mode = mode->next)
+     {
+ 	int refresh = xf86RandR12ModeRefresh (mode);
+ 	if (randrp->maxX == 0 || randrp->maxY == 0)
+ 	{
+ 		if (maxX < mode->HDisplay)
+ 			maxX = mode->HDisplay;
+ 		if (maxY < mode->VDisplay)
+ 			maxY = mode->VDisplay;
+ 	}
+ 	if (mode == scrp->modes)
+ 	    refresh0 = refresh;
+ 	pSize = RRRegisterSize (pScreen,
+ 				mode->HDisplay, mode->VDisplay,
+ 				randrp->mmWidth, randrp->mmHeight);
+ 	if (!pSize)
+ 	    return FALSE;
+ 	RRRegisterRate (pScreen, pSize, refresh);
+ 
+ 	if (xf86ModesEqual(mode, scrp->currentMode) &&
+ 	    mode->HDisplay == scrp->virtualX &&
+ 	    mode->VDisplay == scrp->virtualY)
+ 	{
+ 	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
+ 	}
+ 	if (mode->next == scrp->modes)
+ 	    break;
+     }
+ 
+     if (randrp->maxX == 0 || randrp->maxY == 0)
+     {
+ 	randrp->maxX = maxX;
+ 	randrp->maxY = maxY;
+     }
+ 
+     if (scrp->currentMode->HDisplay != randrp->virtualX ||
+ 	scrp->currentMode->VDisplay != randrp->virtualY)
+     {
+ 	pSize = RRRegisterSize (pScreen,
+ 				randrp->virtualX, randrp->virtualY,
+ 				randrp->mmWidth,
+ 				randrp->mmHeight);
+ 	if (!pSize)
+ 	    return FALSE;
+ 	RRRegisterRate (pScreen, pSize, refresh0);
+ 	if (scrp->virtualX == randrp->virtualX &&
+ 	    scrp->virtualY == randrp->virtualY)
+ 	{
+ 	    RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
+ 	}
+     }
+ 
+     return TRUE;
+ }
+ 
+ static Bool
+ xf86RandR12SetMode (ScreenPtr	    pScreen,
+ 		  DisplayModePtr    mode,
+ 		  Bool		    useVirtual,
+ 		  int		    mmWidth,
+ 		  int		    mmHeight)
+ {
+     ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
+     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+     int			oldWidth = pScreen->width;
+     int			oldHeight = pScreen->height;
+     int			oldmmWidth = pScreen->mmWidth;
+     int			oldmmHeight = pScreen->mmHeight;
+     WindowPtr		pRoot = WindowTable[pScreen->myNum];
+     DisplayModePtr      currentMode = NULL;
+     Bool 		ret = TRUE;
+     PixmapPtr 		pspix = NULL;
+ 
+     if (pRoot)
+ 	(*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+     if (useVirtual)
+     {
+ 	scrp->virtualX = randrp->virtualX;
+ 	scrp->virtualY = randrp->virtualY;
+     }
+     else
+     {
+ 	scrp->virtualX = mode->HDisplay;
+ 	scrp->virtualY = mode->VDisplay;
+     }
+ 
+     if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
+     {
+ 	/* If the screen is rotated 90 or 270 degrees, swap the sizes. */
+ 	pScreen->width = scrp->virtualY;
+ 	pScreen->height = scrp->virtualX;
+ 	pScreen->mmWidth = mmHeight;
+ 	pScreen->mmHeight = mmWidth;
+     }
+     else
+     {
+ 	pScreen->width = scrp->virtualX;
+ 	pScreen->height = scrp->virtualY;
+ 	pScreen->mmWidth = mmWidth;
+ 	pScreen->mmHeight = mmHeight;
+     }
+     if (scrp->currentMode == mode) {
+         /* Save current mode */
+         currentMode = scrp->currentMode;
+         /* Reset, just so we ensure the drivers SwitchMode is called */
+         scrp->currentMode = NULL;
+     }
+     /*
+      * We know that if the driver failed to SwitchMode to the rotated
+      * version, then it should revert back to it's prior mode.
+      */
+     if (!xf86SwitchMode (pScreen, mode))
+     {
+         ret = FALSE;
+ 	scrp->virtualX = pScreen->width = oldWidth;
+ 	scrp->virtualY = pScreen->height = oldHeight;
+ 	pScreen->mmWidth = oldmmWidth;
+ 	pScreen->mmHeight = oldmmHeight;
+         scrp->currentMode = currentMode;
+     }
+     /*
+      * Get the new Screen pixmap ptr as SwitchMode might have called
+      * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
+      * Unfortunately.
+      */
+     pspix = (*pScreen->GetScreenPixmap) (pScreen);
+     if (pspix->devPrivate.ptr)
+        scrp->pixmapPrivate = pspix->devPrivate;
+ 
+     /*
+      * Make sure the layout is correct
+      */
+     xf86ReconfigureLayout();
+ 
+     /*
+      * Make sure the whole screen is visible
+      */
+     xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+     xf86SetViewport (pScreen, 0, 0);
+     if (pRoot)
+ 	(*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+     return ret;
+ }
+ 
+ Bool
+ xf86RandR12SetConfig (ScreenPtr		pScreen,
+ 		    Rotation		rotation,
+ 		    int			rate,
+ 		    RRScreenSizePtr	pSize)
+ {
+     ScrnInfoPtr		scrp = XF86SCRNINFO(pScreen);
+     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+     DisplayModePtr	mode;
+     int			px, py;
+     Bool		useVirtual = FALSE;
+     int			maxX = 0, maxY = 0;
+     Rotation		oldRotation = randrp->rotation;
+ 
+     randrp->rotation = rotation;
+ 
+     if (randrp->virtualX == -1 || randrp->virtualY == -1)
+     {
+ 	randrp->virtualX = scrp->virtualX;
+ 	randrp->virtualY = scrp->virtualY;
+     }
+ 
 -    miPointerPosition (&px, &py);
++    miPointerGetPosition (inputInfo.pointer, &px, &py);
+     for (mode = scrp->modes; ; mode = mode->next)
+     {
+ 	if (randrp->maxX == 0 || randrp->maxY == 0)
+ 	{
+ 		if (maxX < mode->HDisplay)
+ 			maxX = mode->HDisplay;
+ 		if (maxY < mode->VDisplay)
+ 			maxY = mode->VDisplay;
+ 	}
+ 	if (mode->HDisplay == pSize->width &&
+ 	    mode->VDisplay == pSize->height &&
+ 	    (rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
+ 	    break;
+ 	if (mode->next == scrp->modes)
+ 	{
+ 	    if (pSize->width == randrp->virtualX &&
+ 		pSize->height == randrp->virtualY)
+ 	    {
+ 		mode = scrp->modes;
+ 		useVirtual = TRUE;
+ 		break;
+ 	    }
+     	    if (randrp->maxX == 0 || randrp->maxY == 0)
+     	    {
+ 		randrp->maxX = maxX;
+ 		randrp->maxY = maxY;
+     	    }
+ 	    return FALSE;
+ 	}
+     }
+ 
+     if (randrp->maxX == 0 || randrp->maxY == 0)
+     {
+ 	randrp->maxX = maxX;
+ 	randrp->maxY = maxY;
+     }
+ 
+     if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
+ 			   pSize->mmHeight)) {
+         randrp->rotation = oldRotation;
+ 	return FALSE;
+     }
+ 
+     /*
+      * Move the cursor back where it belongs; SwitchMode repositions it
+      */
 -    if (pScreen == miPointerCurrentScreen ())
++    if (pScreen == miPointerGetScreen(inputInfo.pointer))
+     {
+         px = (px >= pScreen->width ? (pScreen->width - 1) : px);
+         py = (py >= pScreen->height ? (pScreen->height - 1) : py);
+ 
+ 	xf86SetViewport(pScreen, px, py);
+ 
 -	(*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
++	(*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE);
+     }
+ 
+     return TRUE;
+ }
+ 
+ static Bool
+ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
+ 			CARD16		width,
+ 			CARD16		height,
+ 			CARD32		mmWidth,
+ 			CARD32		mmHeight)
+ {
+     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+     ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
+     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+     WindowPtr		pRoot = WindowTable[pScreen->myNum];
+     Bool		ret = FALSE;
+ 
+     if (randrp->virtualX == -1 || randrp->virtualY == -1)
+     {
+ 	randrp->virtualX = pScrn->virtualX;
+ 	randrp->virtualY = pScrn->virtualY;
+     }
+     if (pRoot)
+ 	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+ 
+     /* Let the driver update virtualX and virtualY */
+     if (!(*config->funcs->resize)(pScrn, width, height))
+ 	goto finish;
+ 
+     ret = TRUE;
+ 
+     pScreen->width = width;
+     pScreen->height = height;
+     pScreen->mmWidth = mmWidth;
+     pScreen->mmHeight = mmHeight;
+ 
+     xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
+     xf86SetViewport (pScreen, 0, 0);
+ 
+ finish:
+     if (pRoot)
+ 	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+ #if RANDR_12_INTERFACE
+     if (WindowTable[pScreen->myNum] && ret)
+ 	RRScreenSizeNotify (pScreen);
+ #endif
+     return ret;
+ }
+ 
+ Rotation
+ xf86RandR12GetRotation(ScreenPtr pScreen)
+ {
+     XF86RandRInfoPtr	    randrp = XF86RANDRINFO(pScreen);
+ 
+     return randrp->rotation;
+ }
+ 
+ Bool
+ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
+ {
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+     int			c;
+     int			width, height;
+     int			mmWidth, mmHeight;
+ #ifdef PANORAMIX
+     /* XXX disable RandR when using Xinerama */
+     if (!noPanoramiXExtension)
+ 	return TRUE;
+ #endif
+ 
+     /*
+      * Compute size of screen
+      */
+     width = 0; height = 0;
+     for (c = 0; c < config->num_crtc; c++)
+     {
+ 	xf86CrtcPtr crtc = config->crtc[c];
+ 	int	    crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+ 	int	    crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+ 	
+ 	if (crtc->enabled && crtc_width > width)
+ 	    width = crtc_width;
+ 	if (crtc->enabled && crtc_height > height)
+ 	    height = crtc_height;
+     }
+     
+     if (width && height)
+     {
+ 	/*
+ 	 * Compute physical size of screen
+ 	 */
+ 	if (monitorResolution) 
+ 	{
+ 	    mmWidth = width * 25.4 / monitorResolution;
+ 	    mmHeight = height * 25.4 / monitorResolution;
+ 	}
+ 	else
+ 	{
+ 	    mmWidth = pScreen->mmWidth;
+ 	    mmHeight = pScreen->mmHeight;
+ 	}
+ 	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ 		   "Setting screen physical size to %d x %d\n",
+ 		   mmWidth, mmHeight);
+ 	xf86RandR12ScreenSetSize (pScreen,
+ 				  width,
+ 				  height,
+ 				  mmWidth,
+ 				  mmHeight);
+     }
+ 
+     if (randrp->virtualX == -1 || randrp->virtualY == -1)
+     {
+ 	randrp->virtualX = pScrn->virtualX;
+ 	randrp->virtualY = pScrn->virtualY;
+     }
+     xf86CrtcSetScreenSubpixelOrder (pScreen);
+ #if RANDR_12_INTERFACE
+     if (xf86RandR12CreateScreenResources12 (pScreen))
+ 	return TRUE;
+ #endif
+     return TRUE;
+ }
+ 
+ 
+ Bool
+ xf86RandR12Init (ScreenPtr pScreen)
+ {
+     rrScrPrivPtr	rp;
+     XF86RandRInfoPtr	randrp;
+ 
+ #ifdef PANORAMIX
+     /* XXX disable RandR when using Xinerama */
+     if (!noPanoramiXExtension)
+ 	return TRUE;
+ #endif
+     if (xf86RandR12Generation != serverGeneration)
+     {
+ 	xf86RandR12Index = AllocateScreenPrivateIndex();
+ 	xf86RandR12Generation = serverGeneration;
+     }
+ 
+     randrp = xalloc (sizeof (XF86RandRInfoRec));
+     if (!randrp)
+ 	return FALSE;
+ 
+     if (!RRScreenInit(pScreen))
+     {
+ 	xfree (randrp);
+ 	return FALSE;
+     }
+     rp = rrGetScrPriv(pScreen);
+     rp->rrGetInfo = xf86RandR12GetInfo;
+     rp->rrSetConfig = xf86RandR12SetConfig;
+ 
+     randrp->virtualX = -1;
+     randrp->virtualY = -1;
+     randrp->mmWidth = pScreen->mmWidth;
+     randrp->mmHeight = pScreen->mmHeight;
+ 
+     randrp->rotation = RR_Rotate_0; /* initial rotated mode */
+ 
+     randrp->supported_rotations = RR_Rotate_0;
+ 
+     randrp->maxX = randrp->maxY = 0;
+ 
+     pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
+ 
+ #if RANDR_12_INTERFACE
+     if (!xf86RandR12Init12 (pScreen))
+ 	return FALSE;
+ #endif
+     return TRUE;
+ }
+ 
+ void
+ xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
+ {
+     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+ #if RANDR_12_INTERFACE
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+     int			c;
+     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+ 
+     for (c = 0; c < config->num_crtc; c++) {
+ 	xf86CrtcPtr    crtc = config->crtc[c];
+ 
+ 	RRCrtcSetRotations (crtc->randr_crtc, rotations);
+     }
+ #endif
+     randrp->supported_rotations = rotations;
+ }
+ 
+ void
+ xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
+ {
+     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+ 
+     if (xf86RandR12Generation != serverGeneration ||
+ 	XF86RANDRINFO(pScreen)->virtualX == -1)
+     {
+ 	*x = pScrn->virtualX;
+ 	*y = pScrn->virtualY;
+     } else {
+ 	XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ 
+ 	*x = randrp->virtualX;
+ 	*y = randrp->virtualY;
+     }
+ }
+ 
+ #if RANDR_12_INTERFACE
+ static Bool
+ xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
+ {
+     ScreenPtr		pScreen = randr_crtc->pScreen;
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+     RRModePtr		randr_mode = NULL;
+     int			x;
+     int			y;
+     Rotation		rotation;
+     int			numOutputs;
+     RROutputPtr		*randr_outputs;
+     RROutputPtr		randr_output;
+     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+     xf86OutputPtr	output;
+     int			i, j;
+     DisplayModePtr	mode = &crtc->mode;
+     Bool		ret;
+ 
+     randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
+     if (!randr_outputs)
+ 	return FALSE;
+     x = crtc->x;
+     y = crtc->y;
+     rotation = crtc->rotation;
+     numOutputs = 0;
+     randr_mode = NULL;
+     for (i = 0; i < config->num_output; i++)
+     {
+ 	output = config->output[i];
+ 	if (output->crtc == crtc)
+ 	{
+ 	    randr_output = output->randr_output;
+ 	    randr_outputs[numOutputs++] = randr_output;
+ 	    /*
+ 	     * We make copies of modes, so pointer equality 
+ 	     * isn't sufficient
+ 	     */
+ 	    for (j = 0; j < randr_output->numModes; j++)
+ 	    {
+ 		DisplayModePtr	outMode = randr_output->modes[j]->devPrivate;
+ 		if (xf86ModesEqual(mode, outMode))
+ 		{
+ 		    randr_mode = randr_output->modes[j];
+ 		    break;
+ 		}
+ 	    }
+ 	}
+     }
+     ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
+ 			rotation, numOutputs, randr_outputs);
+     DEALLOCATE_LOCAL(randr_outputs);
+     return ret;
+ }
+ 
+ static Bool
+ xf86RandR12CrtcSet (ScreenPtr	pScreen,
+ 		  RRCrtcPtr	randr_crtc,
+ 		  RRModePtr	randr_mode,
+ 		  int		x,
+ 		  int		y,
+ 		  Rotation	rotation,
+ 		  int		num_randr_outputs,
+ 		  RROutputPtr	*randr_outputs)
+ {
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+     DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
+     Bool		changed = FALSE;
+     int			o, ro;
+     xf86CrtcPtr		*save_crtcs;
+     Bool		save_enabled = crtc->enabled;
+ 
+     save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
+     if ((mode != NULL) != crtc->enabled)
+ 	changed = TRUE;
+     else if (mode && !xf86ModesEqual (&crtc->mode, mode))
+ 	changed = TRUE;
+     
+     if (rotation != crtc->rotation)
+ 	changed = TRUE;
+ 
+     if (x != crtc->x || y != crtc->y)
+ 	changed = TRUE;
+     for (o = 0; o < config->num_output; o++) 
+     {
+ 	xf86OutputPtr  output = config->output[o];
+ 	xf86CrtcPtr    new_crtc;
+ 
+ 	save_crtcs[o] = output->crtc;
+ 	
+ 	if (output->crtc == crtc)
+ 	    new_crtc = NULL;
+ 	else
+ 	    new_crtc = output->crtc;
+ 	for (ro = 0; ro < num_randr_outputs; ro++) 
+ 	    if (output->randr_output == randr_outputs[ro])
+ 	    {
+ 		new_crtc = crtc;
+ 		break;
+ 	    }
+ 	if (new_crtc != output->crtc)
+ 	{
+ 	    changed = TRUE;
+ 	    output->crtc = new_crtc;
+ 	}
+     }
+     /* XXX need device-independent mode setting code through an API */
+     if (changed)
+     {
+ 	crtc->enabled = mode != NULL;
+ 
+ 	if (mode)
+ 	{
+ 	    if (!xf86CrtcSetMode (crtc, mode, rotation, x, y))
+ 	    {
+ 		crtc->enabled = save_enabled;
+ 		for (o = 0; o < config->num_output; o++)
+ 		{
+ 		    xf86OutputPtr	output = config->output[o];
+ 		    output->crtc = save_crtcs[o];
+ 		}
+ 		DEALLOCATE_LOCAL(save_crtcs);
+ 		return FALSE;
+ 	    }
+ 	    /*
+ 	     * Save the last successful setting for EnterVT
+ 	     */
+ 	    crtc->desiredMode = *mode;
+ 	    crtc->desiredRotation = rotation;
+ 	    crtc->desiredX = x;
+ 	    crtc->desiredY = y;
+ 	}
+ 	xf86DisableUnusedFunctions (pScrn);
+     }
+     DEALLOCATE_LOCAL(save_crtcs);
+     return xf86RandR12CrtcNotify (randr_crtc);
+ }
+ 
+ static Bool
+ xf86RandR12CrtcSetGamma (ScreenPtr    pScreen,
+ 			 RRCrtcPtr    randr_crtc)
+ {
+     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+ 
+     if (crtc->funcs->gamma_set == NULL)
+ 	return FALSE;
+ 
+     crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
+ 			   randr_crtc->gammaBlue, randr_crtc->gammaSize);
+ 
+     return TRUE;
+ }
+ 
+ static Bool
+ xf86RandR12OutputSetProperty (ScreenPtr pScreen,
+ 			      RROutputPtr randr_output,
+ 			      Atom property,
+ 			      RRPropertyValuePtr value)
+ {
+     xf86OutputPtr output = randr_output->devPrivate;
+ 
+     /* If we don't have any property handler, then we don't care what the
+      * user is setting properties to.
+      */
+     if (output->funcs->set_property == NULL)
+ 	return TRUE;
+ 
+     return output->funcs->set_property(output, property, value);
+ }
+ 
+ /**
+  * Given a list of xf86 modes and a RandR Output object, construct
+  * RandR modes and assign them to the output
+  */
+ static Bool
+ xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
+ {
+     DisplayModePtr  mode;
+     RRModePtr	    *rrmodes = NULL;
+     int		    nmode = 0;
+     int		    npreferred = 0;
+     Bool	    ret = TRUE;
+     int		    pref;
+ 
+     for (mode = modes; mode; mode = mode->next)
+ 	nmode++;
+ 
+     if (nmode) {
+ 	rrmodes = xalloc (nmode * sizeof (RRModePtr));
+ 	
+ 	if (!rrmodes)
+ 	    return FALSE;
+ 	nmode = 0;
+ 
+ 	for (pref = 1; pref >= 0; pref--) {
+ 	    for (mode = modes; mode; mode = mode->next) {
+ 		if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
+ 		    xRRModeInfo		modeInfo;
+ 		    RRModePtr		rrmode;
+ 		    
+ 		    modeInfo.nameLength = strlen (mode->name);
+ 		    modeInfo.width = mode->HDisplay;
+ 		    modeInfo.dotClock = mode->Clock * 1000;
+ 		    modeInfo.hSyncStart = mode->HSyncStart;
+ 		    modeInfo.hSyncEnd = mode->HSyncEnd;
+ 		    modeInfo.hTotal = mode->HTotal;
+ 		    modeInfo.hSkew = mode->HSkew;
+ 
+ 		    modeInfo.height = mode->VDisplay;
+ 		    modeInfo.vSyncStart = mode->VSyncStart;
+ 		    modeInfo.vSyncEnd = mode->VSyncEnd;
+ 		    modeInfo.vTotal = mode->VTotal;
+ 		    modeInfo.modeFlags = mode->Flags;
+ 
+ 		    rrmode = RRModeGet (&modeInfo, mode->name);
+ 		    if (rrmode) {
+ 			rrmode->devPrivate = mode;
+ 			rrmodes[nmode++] = rrmode;
+ 			npreferred += pref;
+ 		    }
+ 		}
+ 	    }
+ 	}
+     }
+     
+     ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
+     xfree (rrmodes);
+     return ret;
+ }
+ 
+ /*
+  * Mirror the current mode configuration to RandR
+  */
+ static Bool
+ xf86RandR12SetInfo12 (ScreenPtr pScreen)
+ {
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+     RROutputPtr		*clones;
+     RRCrtcPtr		*crtcs;
+     int			ncrtc;
+     int			o, c, l;
+     RRCrtcPtr		randr_crtc;
+     int			nclone;
+     
+     clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
+     crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr));
+     for (o = 0; o < config->num_output; o++)
+     {
+ 	xf86OutputPtr	output = config->output[o];
+ 	
+ 	ncrtc = 0;
+ 	for (c = 0; c < config->num_crtc; c++)
+ 	    if (output->possible_crtcs & (1 << c))
+ 		crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
+ 
+ 	if (output->crtc)
+ 	    randr_crtc = output->crtc->randr_crtc;
+ 	else
+ 	    randr_crtc = NULL;
+ 
+ 	if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
+ 	{
+ 	    DEALLOCATE_LOCAL (crtcs);
+ 	    DEALLOCATE_LOCAL (clones);
+ 	    return FALSE;
+ 	}
+ 
+ 	RROutputSetCrtc (output->randr_output, randr_crtc);
+ 	RROutputSetPhysicalSize(output->randr_output, 
+ 				output->mm_width,
+ 				output->mm_height);
+ 	xf86RROutputSetModes (output->randr_output, output->probed_modes);
+ 
+ 	switch (output->status) {
+ 	case XF86OutputStatusConnected:
+ 	    RROutputSetConnection (output->randr_output, RR_Connected);
+ 	    break;
+ 	case XF86OutputStatusDisconnected:
+ 	    RROutputSetConnection (output->randr_output, RR_Disconnected);
+ 	    break;
+ 	case XF86OutputStatusUnknown:
+ 	    RROutputSetConnection (output->randr_output, RR_UnknownConnection);
+ 	    break;
+ 	}
+ 
+ 	RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
+ 
+ 	/*
+ 	 * Valid clones
+ 	 */
+ 	nclone = 0;
+ 	for (l = 0; l < config->num_output; l++)
+ 	{
+ 	    xf86OutputPtr	    clone = config->output[l];
+ 	    
+ 	    if (l != o && (output->possible_clones & (1 << l)))
+ 		clones[nclone++] = clone->randr_output;
+ 	}
+ 	if (!RROutputSetClones (output->randr_output, clones, nclone))
+ 	{
+ 	    DEALLOCATE_LOCAL (crtcs);
+ 	    DEALLOCATE_LOCAL (clones);
+ 	    return FALSE;
+ 	}
+     }
+     DEALLOCATE_LOCAL (crtcs);
+     DEALLOCATE_LOCAL (clones);
+     return TRUE;
+ }
+ 
+ 
+ 
+ /*
+  * Query the hardware for the current state, then mirror
+  * that to RandR
+  */
+ static Bool
+ xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
+ {
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+ 
+     xf86ProbeOutputModes (pScrn, 0, 0);
+     xf86SetScrnInfoModes (pScrn);
+     xf86DiDGAReInit (pScreen);
+     return xf86RandR12SetInfo12 (pScreen);
+ }
+ 
+ static Bool
+ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
+ {
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+     int			c;
+     int			o;
+     
+     if (!RRInit ())
+ 	return FALSE;
+ 
+     /*
+      * Configure crtcs
+      */
+     for (c = 0; c < config->num_crtc; c++)
+     {
+ 	xf86CrtcPtr    crtc = config->crtc[c];
+ 	
+ 	crtc->randr_crtc = RRCrtcCreate (crtc);
+ 	RRCrtcAttachScreen (crtc->randr_crtc, pScreen);
+ 	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
+     }
+     /*
+      * Configure outputs
+      */
+     for (o = 0; o < config->num_output; o++)
+     {
+ 	xf86OutputPtr	output = config->output[o];
+ 
+ 	output->randr_output = RROutputCreate (output->name, 
+ 					       strlen (output->name),
+ 					       output);
+ 	RROutputAttachScreen (output->randr_output, pScreen);
+ 
+ 	if (output->funcs->create_resources != NULL)
+ 	    output->funcs->create_resources(output);
+     }
+     return TRUE;
+ }
+ 
+ static Bool
+ xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
+ {
+     int			c;
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+ 
+     for (c = 0; c < config->num_crtc; c++)
+ 	xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
+     
+     
+     RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight,
+ 			  config->maxWidth, config->maxHeight);
+     return TRUE;
+ }
+ 
+ static void
+ xf86RandR12PointerMoved (int scrnIndex, int x, int y)
+ {
+ }
+ 
+ static Bool
+ xf86RandR12Init12 (ScreenPtr pScreen)
+ {
+     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+     rrScrPrivPtr	rp = rrGetScrPriv(pScreen);
+ 
+     rp->rrGetInfo = xf86RandR12GetInfo12;
+     rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
+     rp->rrCrtcSet = xf86RandR12CrtcSet;
+     rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
+     rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
+     rp->rrSetConfig = NULL;
+     pScrn->PointerMoved = xf86RandR12PointerMoved;
+     if (!xf86RandR12CreateObjects12 (pScreen))
+ 	return FALSE;
+ 
+     /*
+      * Configure output modes
+      */
+     if (!xf86RandR12SetInfo12 (pScreen))
+ 	return FALSE;
+     return TRUE;
+ }
+ 
+ #endif
+ 
+ Bool
+ xf86RandR12PreInit (ScrnInfoPtr pScrn)
+ {
+     return TRUE;
+ }
diff --cc hw/xfree86/ramdac/xf86Cursor.c
index 5a8509b,4578076..c968f18
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@@ -212,11 -199,11 +212,12 @@@ xf86CursorEnableDisableFBAccess
  	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
  
      if (!enable && ScreenPriv->CurrentCursor != NullCursor) {
- 	ScreenPriv->SavedCursor = ScreenPriv->CurrentCursor;
 -	CursorPtr   currentCursor = ScreenPriv->CurrentCursor;
 -	xf86CursorSetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
 -	ScreenPriv->isUp = FALSE;
++        CursorPtr currentCursor = ScreenPriv->CurrentCursor;
 +        xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x,
 +                ScreenPriv->y); 
 +        ScreenPriv->isUp = FALSE;
  	ScreenPriv->SWCursor = TRUE;
+ 	ScreenPriv->SavedCursor = currentCursor;
      }
  
      if (ScreenPriv->EnableDisableFBAccess)
diff --cc mi/mipointer.c
index ed82fcd,b94feaa..5df7a0a
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@@ -63,36 -56,22 +63,38 @@@ static unsigned long miPointerGeneratio
   * until more than one pointer device exists.
   */
  
 -static miPointerRec miPointer;
 +static miPointerPtr miCorePointer;
  
 -static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 -static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 -static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
 -static void miPointerConstrainCursor(ScreenPtr pScreen, BoxPtr pBox);
 -static void miPointerPointerNonInterestBox(ScreenPtr pScreen, BoxPtr pBox);
 -static void miPointerCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
 -				  BoxPtr pHotBox, BoxPtr pTopLeftBox);
 -static Bool miPointerSetCursorPosition(ScreenPtr pScreen, int x, int y,
 +/* Multipointers 
 + * ID of a device == index in this array.
 + */
 +static miPointerRec miPointers[MAX_DEVICES];
 +#define MIPOINTER(dev) \
 +    (DevHasCursor((dev))) ? &miPointers[(dev)->id] : miCorePointer
 +
 +static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                                   CursorPtr pCursor);
 +static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                                     CursorPtr pCursor);
 +static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                                   CursorPtr pCursor);
 +static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
 +                                     BoxPtr pBox); 
 +static void miPointerPointerNonInterestBox(DeviceIntPtr pDev, 
 +                                           ScreenPtr pScreen, BoxPtr pBox);
 +static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
 +                                  CursorPtr pCursor, BoxPtr pHotBox, 
 +                                  BoxPtr pTopLeftBox);
 +static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                                       int x, int y,
  				       Bool generateEvent);
  static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
 -static void miPointerMove(ScreenPtr pScreen, int x, int y, unsigned long time);
 +static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, 
 +                          int x, int y,
 +                          unsigned long time);
  
+ static xEvent* events; /* for WarpPointer MotionNotifies */
+ 
  _X_EXPORT Bool
  miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
      ScreenPtr		    pScreen;
@@@ -139,29 -116,23 +141,30 @@@
      pScreen->SetCursorPosition = miPointerSetCursorPosition;
      pScreen->RecolorCursor = miRecolorCursor;
      pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
 +
      /*
       * set up the pointer object
 +     * virtual core pointer ID is always 1, so we let it point to the matching
 +     * index in the array.
       */
 -    miPointer.pScreen = NULL;
 -    miPointer.pSpriteScreen = NULL;
 -    miPointer.pCursor = NULL;
 -    miPointer.pSpriteCursor = NULL;
 -    miPointer.limits.x1 = 0;
 -    miPointer.limits.x2 = 32767;
 -    miPointer.limits.y1 = 0;
 -    miPointer.limits.y2 = 32767;
 -    miPointer.confined = FALSE;
 -    miPointer.x = 0;
 -    miPointer.y = 0;
 +    miCorePointer = &miPointers[1];
 +    for(ptrIdx = 0; ptrIdx < MAX_DEVICES; ptrIdx++)
 +    {
 +            pPointer = &miPointers[ptrIdx];
 +            pPointer->pScreen = NULL;
 +            pPointer->pSpriteScreen = NULL;
 +            pPointer->pCursor = NULL;
 +            pPointer->pSpriteCursor = NULL;
 +            pPointer->limits.x1 = 0;
 +            pPointer->limits.x2 = 32767;
 +            pPointer->limits.y1 = 0;
 +            pPointer->limits.y2 = 32767;
 +            pPointer->confined = FALSE;
 +            pPointer->x = 0;
 +            pPointer->y = 0;
 +    }
  
+     events = NULL;
 -
      return TRUE;
  }
  
@@@ -170,23 -141,16 +173,25 @@@ miPointerCloseScreen (index, pScreen
      int		index;
      ScreenPtr	pScreen;
  {
 +    miPointerPtr pPointer;
 +    int ptrIdx;
 +
      SetupScreen(pScreen);
  
 -    if (pScreen == miPointer.pScreen)
 -	miPointer.pScreen = 0;
 -    if (pScreen == miPointer.pSpriteScreen)
 -	miPointer.pSpriteScreen = 0;
 +    for(ptrIdx = 0; ptrIdx < MAX_DEVICES; ptrIdx++)
 +    {
 +        pPointer = &miPointers[ptrIdx];
 +
 +        if (pScreen == pPointer->pScreen)
 +            pPointer->pScreen = 0;
 +        if (pScreen == pPointer->pSpriteScreen)
 +            pPointer->pSpriteScreen = 0;
 +    }
 +
      pScreen->CloseScreen = pScreenPriv->CloseScreen;
      xfree ((pointer) pScreenPriv);
+     xfree ((pointer) events);
+     events = NULL;
      return (*pScreen->CloseScreen) (index, pScreen);
  }
  
@@@ -530,9 -471,33 +535,33 @@@ miPointerGetPosition(DeviceIntPtr pDev
  }
  
  void
 -miPointerMove (ScreenPtr pScreen, int x, int y, unsigned long time)
 +miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, unsigned long time)
  {
-     miPointerMoved(pDev, pScreen, x, y, time);
+     int i, nevents;
+     int valuators[2];
+ 
+     miPointerMoved(inputInfo.pointer, pScreen, x, y, time);
+ 
+     /* generate motion notify */
+     valuators[0] = x;
+     valuators[1] = y;
+ 
+     if (!events)
+     {
+         events = (xEvent*)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+ 
+         if (!events)
+         {
+             FatalError("Could not allocate event store.\n");
+             return;
+         }
+     }
+ 
+     nevents = GetPointerEvents(events, inputInfo.pointer, MotionNotify, 0,
+                                POINTER_ABSOLUTE, 0, 2, valuators);
+ 
+     for (i = 0; i < nevents; i++)
+         mieqEnqueue(inputInfo.pointer, &events[i]);
  }
  
  /* Move the pointer on the current screen,  and update the sprite. */
@@@ -540,41 -505,18 +569,21 @@@ voi
  miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
                       unsigned long time)
  {
-     xEvent* events;
-     int i, nevents;
 +    int valuators[2];
 +    miPointerPtr pPointer = MIPOINTER(pDev);
      SetupScreen(pScreen);
  
 -    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer) &&
 -        !pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
 +
 +    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev)
 +        && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
      {
 -	miPointer.devx = x;
 -	miPointer.devy = y;
 -	if(!miPointer.pCursor->bits->emptyMask)
 -	    (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
 +	pPointer->devx = x;
 +	pPointer->devy = y;
 +	if(!pPointer->pCursor->bits->emptyMask)
 +	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
      }
  
 -    miPointer.x = x;
 -    miPointer.y = y;
 -    miPointer.pScreen = pScreen;
 +    pPointer->x = x;
 +    pPointer->y = y;
 +    pPointer->pScreen = pScreen;
- 
-     /* generate event here */
-     valuators[0] = x;
-     valuators[1] = y;
-     events = (xEvent*)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
-     if (!events)
-     {
-         FatalError("Could not allocate event store.\n");
- 	return;
-     }
- 
-     nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
-                                POINTER_ABSOLUTE, 0, 2, valuators);
- 
-     for (i = 0; i < nevents; i++)
-         mieqEnqueue(pDev, &events[i]);
- 
-     xfree(events);
  }
commit 12175b668a94e23994f724b366a691ec312cce69
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 15 17:50:02 2006 +1030

    o fix minor error in comment for GetPointerEvents()

diff --git a/dix/getevents.c b/dix/getevents.c
index 935112d..77d1e21 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -470,7 +470,7 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
 
 
 /**
- * Generate a series of xEvents (returned in xE) representing pointer
+ * Generate a series of xEvents (returned in events) representing pointer
  * motion, or button presses.  Xi and XKB-aware.
  *
  * events is not NULL-terminated; the return value is the number of events.
commit 57aa5e908dc11d5d8c27ed705c526f1416c1e8ad
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Mar 2 17:14:37 2007 +1030

    dix, Xext, Xtrap, Xi: replace inputInfo.pointer with PickPointer where
                          possible. More replacements to come.

diff --git a/XTrap/xtrapddmi.c b/XTrap/xtrapddmi.c
index c633b8d..ec094ec 100644
--- a/XTrap/xtrapddmi.c
+++ b/XTrap/xtrapddmi.c
@@ -97,8 +97,8 @@ int XETrapSimulateXEvent(register xXTrapInputReq *request,
     xEvent xev;
     register int x = request->input.x;
     register int y = request->input.y;
-    DevicePtr keydev = LookupKeyboardDevice();
-    DevicePtr ptrdev = LookupPointerDevice();
+    DevicePtr keydev = (DevicePtr)PickKeyboard(client);
+    DevicePtr ptrdev = (DevicePtr)PickPointer(client);
 
     if (request->input.screen < screenInfo.numScreens)
     {
diff --git a/Xext/xtest.c b/Xext/xtest.c
index cb7b5b8..93e88c4 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -316,7 +316,7 @@ ProcXTestFakeInput(client)
 #ifdef XINPUT
 	if (!extension)
 #endif /* XINPUT */
-	    dev = (DeviceIntPtr)LookupKeyboardDevice();
+	    dev = PickKeyboard(client);
 	if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
 	    ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
 	{
@@ -361,7 +361,7 @@ ProcXTestFakeInput(client)
 	}
 #endif /* XINPUT */
         if (!dev)
-            dev = (DeviceIntPtr*)LookupPointerDevice();
+            dev = PickPointer(client);
 	if (ev->u.keyButtonPointer.root == None)
 	    root = GetCurrentRootWindow();
 	else
@@ -451,7 +451,7 @@ ProcXTestFakeInput(client)
 #ifdef XINPUT
 	if (!extension)
 #endif /* XINPUT */
-            dev = (DeviceIntPtr*)LookupPointerDevice();
+            dev = PickPointer(client);
 	if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
 	{
 	    client->errorValue = ev->u.u.detail;
diff --git a/Xi/grabdevb.c b/Xi/grabdevb.c
index 4333550..d79a36c 100644
--- a/Xi/grabdevb.c
+++ b/Xi/grabdevb.c
@@ -140,7 +140,7 @@ ProcXGrabDeviceButton(ClientPtr client)
 	    return Success;
 	}
     } else
-	mdev = (DeviceIntPtr) LookupKeyboardDevice();
+	mdev = PickKeyboard(client);
 
     class = (XEventClass *) (&stuff[1]);	/* first word of values */
 
diff --git a/Xi/grabdevk.c b/Xi/grabdevk.c
index 71e72d5..1120149 100644
--- a/Xi/grabdevk.c
+++ b/Xi/grabdevk.c
@@ -137,7 +137,7 @@ ProcXGrabDeviceKey(ClientPtr client)
 	    return Success;
 	}
     } else
-	mdev = (DeviceIntPtr) LookupKeyboardDevice();
+	mdev = PickKeyboard(client);
 
     class = (XEventClass *) (&stuff[1]);	/* first word of values */
 
diff --git a/Xi/ungrdevb.c b/Xi/ungrdevb.c
index 8db9307..b75916f 100644
--- a/Xi/ungrdevb.c
+++ b/Xi/ungrdevb.c
@@ -133,7 +133,7 @@ ProcXUngrabDeviceButton(ClientPtr client)
 	    return Success;
 	}
     } else
-	mdev = (DeviceIntPtr) LookupKeyboardDevice();
+	mdev = PickKeyboard(client);
 
     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixUnknownAccess);
     if (rc != Success) {
diff --git a/Xi/ungrdevk.c b/Xi/ungrdevk.c
index ebb83bc..e8c006a 100644
--- a/Xi/ungrdevk.c
+++ b/Xi/ungrdevk.c
@@ -132,7 +132,7 @@ ProcXUngrabDeviceKey(ClientPtr client)
 	    return Success;
 	}
     } else
-	mdev = (DeviceIntPtr) LookupKeyboardDevice();
+	mdev = PickKeyboard(client);
 
     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixUnknownAccess);
     if (rc != Success) {
diff --git a/dix/devices.c b/dix/devices.c
index f053e34..87b3927 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -597,6 +597,8 @@ RemoveDevice(DeviceIntPtr dev)
 int
 NumMotionEvents()
 {
+    /* only called to fill data in initial connection reply. 
+     * VCP is ok here, it is the only fixed device we have. */
     return inputInfo.pointer->valuator->numMotionEvents;
 }
 
@@ -1376,6 +1378,7 @@ ProcSetPointerMapping(ClientPtr client)
     REQUEST(xSetPointerMappingReq);
     BYTE *map;
     int ret;
+    DeviceIntPtr ptr = PickPointer(client);
     xSetPointerMappingReply rep;
 
     REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
@@ -1389,14 +1392,18 @@ ProcSetPointerMapping(ClientPtr client)
     
     /* So we're bounded here by the number of core buttons.  This check
      * probably wants disabling through XFixes. */
-    if (stuff->nElts != inputInfo.pointer->button->numButtons) {
+    /* MPX: With ClientPointer, we can return the right number of buttons.
+     * Let's just hope nobody changed ClientPointer between GetPointerMapping
+     * and SetPointerMapping
+     */
+    if (stuff->nElts != ptr->button->numButtons) {
 	client->errorValue = stuff->nElts;
 	return BadValue;
     }
     if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue))
 	return BadValue;
 
-    ret = DoSetPointerMapping(inputInfo.pointer, map, stuff->nElts);
+    ret = DoSetPointerMapping(ptr, map, stuff->nElts);
     if (ret != Success) {
         rep.success = ret;
         WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
@@ -1404,7 +1411,7 @@ ProcSetPointerMapping(ClientPtr client)
     }
 
     /* FIXME: Send mapping notifies for all the extended devices as well. */
-    SendMappingNotify(inputInfo.pointer, MappingPointer, 0, 0, client);
+    SendMappingNotify(ptr, MappingPointer, 0, 0, client);
     WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
     return Success;
 }
@@ -1414,7 +1421,8 @@ ProcGetKeyboardMapping(ClientPtr client)
 {
     xGetKeyboardMappingReply rep;
     REQUEST(xGetKeyboardMappingReq);
-    KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
+    DeviceIntPtr kbd = PickKeyboard(client);
+    KeySymsPtr curKeySyms = &kbd->key->curKeySyms;
 
     REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
 
@@ -1449,7 +1457,9 @@ int
 ProcGetPointerMapping(ClientPtr client)
 {
     xGetPointerMappingReply rep;
-    ButtonClassPtr butc = inputInfo.pointer->button;
+    /* Apps may get different values each time they call GetPointerMapping as
+     * the ClientPointer could change. */
+    ButtonClassPtr butc = PickPointer(client)->button;
 
     REQUEST_SIZE_MATCH(xReq);
     rep.type = X_Reply;
@@ -1753,7 +1763,7 @@ ProcBell(ClientPtr client)
 int
 ProcChangePointerControl(ClientPtr client)
 {
-    DeviceIntPtr mouse = inputInfo.pointer;
+    DeviceIntPtr mouse = PickPointer(client);
     PtrCtrl ctrl;		/* might get BadValue part way through */
     REQUEST(xChangePointerControlReq);
 
@@ -1809,7 +1819,7 @@ ProcChangePointerControl(ClientPtr client)
 
 
     for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
-        if ((mouse->coreEvents || mouse == inputInfo.pointer) &&
+        if ((mouse->coreEvents || mouse == PickPointer(client)) &&
             mouse->ptrfeed && mouse->ptrfeed->CtrlProc) {
             mouse->ptrfeed->ctrl = ctrl;
             (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl);
@@ -1822,7 +1832,8 @@ ProcChangePointerControl(ClientPtr client)
 int
 ProcGetPointerControl(ClientPtr client)
 {
-    register PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl;
+    DeviceIntPtr ptr = PickPointer(client);
+    PtrCtrl *ctrl = &ptr->ptrfeed->ctrl;
     xGetPointerControlReply rep;
 
     REQUEST_SIZE_MATCH(xReq);
@@ -1860,7 +1871,7 @@ ProcGetMotionEvents(ClientPtr client)
     xGetMotionEventsReply rep;
     int i, count, xmin, xmax, ymin, ymax, rc;
     unsigned long nEvents;
-    DeviceIntPtr mouse = inputInfo.pointer;
+    DeviceIntPtr mouse = PickPointer(client);
     TimeStamp start, stop;
     REQUEST(xGetMotionEventsReq);
 
commit e43b8a4e40991ca6e545bda4cf9b9bd7a2bf22e2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Mar 2 15:21:46 2007 +1030

    dix:    Add ClientPointer to client, used for picking which pointer to use in
            ambiguious request. PickPointer and PickKeyboard are used for getting
            the appropriate pointer when situation is unclear.
            Fix some issues with InitializeSprite.
    
    dix, xfree86: Remove last traces of InitSprite.

diff --git a/dix/devices.c b/dix/devices.c
index 747d782..f053e34 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -342,6 +342,7 @@ InitCoreDevices()
         dev->ActivateGrab = ActivateKeyboardGrab;
         dev->DeactivateGrab = DeactivateKeyboardGrab;
         dev->coreEvents = FALSE;
+        dev->spriteOwner = FALSE;
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate keyboard devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
@@ -369,12 +370,12 @@ InitCoreDevices()
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate pointer devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
-        InitSprite(dev, TRUE);
+        InitializeSprite(dev, NullWindow);
         (void)ActivateDevice(dev);
         inputInfo.pointer = dev;
         /* the core keyboard is initialised by now. set the keyboard's sprite
          * to the core pointer's sprite. */
-        InitSprite(inputInfo.keyboard, FALSE);
+        PairDevices(pairingClient, inputInfo.pointer, inputInfo.keyboard);
     }
 }
 
@@ -421,6 +422,7 @@ CloseDevice(register DeviceIntPtr dev)
     StringFeedbackPtr s, snext;
     BellFeedbackPtr b, bnext;
     LedFeedbackPtr l, lnext;
+    int j;
 
     if (dev->inited)
 	(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
@@ -504,6 +506,13 @@ CloseDevice(register DeviceIntPtr dev)
     if (DevHasCursor(dev))
         xfree((pointer)dev->pSprite);
 
+    /* a client may have the device set as client pointer */
+    for (j = 0; j < currentMaxClients; j++)
+    {
+        if (clients[j]->clientPtr == dev)
+            PickPointer(clients[j]);
+    }
+
     xfree(dev->sync.event);
     xfree(dev);
 }
@@ -1955,6 +1964,25 @@ PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
     return Success;
 }
 
+/* Return the pointer that is paired with the given keyboard. If no pointer is
+ * paired, return the virtual core pointer 
+ */ 
+DeviceIntPtr
+GetPairedPointer(DeviceIntPtr kbd)
+{
+    DeviceIntPtr ptr = inputInfo.devices;
+    while(ptr)
+    {
+        if (ptr->pSprite == kbd->pSprite && ptr->spriteOwner)
+        {
+            return ptr;
+        }
+        ptr = ptr->next;
+    }
+
+    return inputInfo.pointer;
+}
+
 /*
  * Register a client to be able to pair devices. 
  */
diff --git a/dix/dispatch.c b/dix/dispatch.c
index 98183cc..54931a1 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3730,6 +3730,8 @@ void InitClient(ClientPtr client, int i, pointer ospriv)
     client->smart_stop_tick = SmartScheduleTime;
     client->smart_check_tick = SmartScheduleTime;
 #endif
+
+    client->clientPtr = NULL;
 }
 
 int
diff --git a/dix/events.c b/dix/events.c
index a1e72f1..5be923a 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1508,8 +1508,8 @@ int
 ProcAllowEvents(register ClientPtr client)
 {
     TimeStamp		time;
-    DeviceIntPtr	mouse = inputInfo.pointer;
-    DeviceIntPtr	keybd = inputInfo.keyboard;
+    DeviceIntPtr	mouse = PickPointer(client);
+    DeviceIntPtr	keybd = PickKeyboard(client);
     REQUEST(xAllowEventsReq);
 
     REQUEST_SIZE_MATCH(xAllowEventsReq);
@@ -2103,7 +2103,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
     pSprite->win = XYToWindow(pSprite->hot.x, pSprite->hot.y);
 #ifdef notyet
     if (!(pSprite->win->deliverableEvents &
-	  Motion_Filter(inputInfo.pointer->button))
+	  Motion_Filter(pDev->button))
 	!syncEvents.playingEvents)
     {
 	/* XXX Do PointerNonInterestBox here */
@@ -2220,15 +2220,23 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
             FatalError("InitializeSprite: failed to allocate sprite struct");
     }
 
-    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
     pSprite = pDev->pSprite;
+    pDev->spriteOwner = TRUE;
+
+    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
+    pSprite->hot.pScreen = pScreen;
     pSprite->hotPhys.pScreen = pScreen;
-    pSprite->hotPhys.x = pScreen->width / 2;
-    pSprite->hotPhys.y = pScreen->height / 2;
+    if (pScreen)
+    {
+        pSprite->hotPhys.x = pScreen->width / 2;
+        pSprite->hotPhys.y = pScreen->height / 2;
+        pSprite->hotLimits.x2 = pScreen->width;
+        pSprite->hotLimits.y2 = pScreen->height;
+    }
+
     pSprite->hot = pSprite->hotPhys;
-    pSprite->hotLimits.x2 = pScreen->width;
-    pSprite->hotLimits.y2 = pScreen->height;
     pSprite->win = pWin;
+
     if (pWin)
     {
         pSprite->current = wCursor(pWin);
@@ -2236,16 +2244,19 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
     } else
         pSprite->current = NullCursor;
 
-    (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
-                               &pSprite->hotLimits, &pSprite->physLimits);
-    pSprite->confined = FALSE;
+    if (pScreen)
+    {
+        (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
+                                   &pSprite->hotLimits, &pSprite->physLimits);
+        pSprite->confined = FALSE;
 
-    (*pScreen->ConstrainCursor) (pDev, pScreen,
-                                 &pSprite->physLimits);
-    (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
-                                   pSprite->hot.y,
-                                   FALSE); 
-    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
+        (*pScreen->ConstrainCursor) (pDev, pScreen,
+                                     &pSprite->physLimits);
+        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
+                                       pSprite->hot.y,
+                                       FALSE); 
+        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
+    }
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
         pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
@@ -2264,7 +2275,6 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
     }
 #endif
 
-    pDev->spriteOwner = TRUE;
 }
 
 /*
@@ -2370,7 +2380,7 @@ XineramaWarpPointer(ClientPtr client)
 {
     WindowPtr	dest = NULL;
     int		x, y, rc;
-    SpritePtr   pSprite = inputInfo.pointer->pSprite;
+    SpritePtr   pSprite = PickPointer(client)->pSprite;
 
     REQUEST(xWarpPointerReq);
 
@@ -2429,9 +2439,9 @@ XineramaWarpPointer(ClientPtr client)
     else if (y >= pSprite->physLimits.y2)
 	y = pSprite->physLimits.y2 - 1;
     if (pSprite->hotShape)
-	ConfineToShape(inputInfo.pointer, pSprite->hotShape, &x, &y);
+	ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
 
-    XineramaSetCursorPosition(inputInfo.pointer, x, y, TRUE);
+    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
 
     return Success;
 }
@@ -2445,7 +2455,7 @@ ProcWarpPointer(ClientPtr client)
     WindowPtr	dest = NULL;
     int		x, y, rc;
     ScreenPtr	newScreen;
-    SpritePtr   pSprite = inputInfo.pointer->pSprite;
+    SpritePtr   pSprite = PickPointer(client)->pSprite;
 
     REQUEST(xWarpPointerReq);
 
@@ -2518,14 +2528,14 @@ ProcWarpPointer(ClientPtr client)
 	    y = pSprite->physLimits.y2 - 1;
 #if defined(SHAPE)
 	if (pSprite->hotShape)
-	    ConfineToShape(inputInfo.pointer, pSprite->hotShape, &x, &y);
+	    ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
 #endif
-        (*newScreen->SetCursorPosition)(inputInfo.pointer, newScreen, x, y,
+        (*newScreen->SetCursorPosition)(PickPointer(client), newScreen, x, y,
                                         TRUE); 
     }
-    else if (!PointerConfinedToScreen(inputInfo.pointer))
+    else if (!PointerConfinedToScreen(PickPointer(client)))
     {
-	NewCurrentScreen(inputInfo.pointer, newScreen, x, y);
+	NewCurrentScreen(PickPointer(client), newScreen, x, y);
     }
     return Success;
 }
@@ -2892,7 +2902,7 @@ drawable.id:0;
 #endif
     )))
 #endif
-    XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state);
+    XE_KBPTR.state = (keyc->state | GetPairedPointer(keybd)->button->state);
     XE_KBPTR.rootX = keybd->pSprite->hot.x;
     XE_KBPTR.rootY = keybd->pSprite->hot.y;
     key = xE->u.u.detail;
@@ -2925,7 +2935,7 @@ drawable.id:0;
 		}
 		return;
 	    }
-	    inputInfo.pointer->valuator->motionHintWindow = NullWindow;
+	    GetPairedPointer(keybd)->valuator->motionHintWindow = NullWindow;
 	    *kptr |= bit;
 	    keyc->prev_state = keyc->state;
 	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
@@ -2947,7 +2957,7 @@ drawable.id:0;
 	case KeyRelease: 
 	    if (!(*kptr & bit)) /* guard against duplicates */
 		return;
-	    inputInfo.pointer->valuator->motionHintWindow = NullWindow;
+	    GetPairedPointer(keybd)->valuator->motionHintWindow = NullWindow;
 	    *kptr &= ~bit;
 	    keyc->prev_state = keyc->state;
 	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
@@ -3837,7 +3847,7 @@ int
 ProcGrabPointer(ClientPtr client)
 {
     xGrabPointerReply rep;
-    DeviceIntPtr device = inputInfo.pointer;
+    DeviceIntPtr device = PickPointer(client);
     GrabPtr grab;
     WindowPtr pWin, confineTo;
     CursorPtr cursor, oldCursor;
@@ -3945,7 +3955,7 @@ ProcGrabPointer(ClientPtr client)
 int
 ProcChangeActivePointerGrab(ClientPtr client)
 {
-    DeviceIntPtr device = inputInfo.pointer;
+    DeviceIntPtr device = PickPointer(client);
     register GrabPtr grab = device->grab;
     CursorPtr newCursor, oldCursor;
     REQUEST(xChangeActivePointerGrabReq);
@@ -3991,7 +4001,7 @@ ProcChangeActivePointerGrab(ClientPtr client)
 int
 ProcUngrabPointer(ClientPtr client)
 {
-    DeviceIntPtr device = inputInfo.pointer;
+    DeviceIntPtr device = PickPointer(client);
     GrabPtr grab;
     TimeStamp time;
     REQUEST(xResourceReq);
@@ -4122,7 +4132,7 @@ ProcQueryPointer(ClientPtr client)
 {
     xQueryPointerReply rep;
     WindowPtr pWin, t;
-    DeviceIntPtr mouse = inputInfo.pointer;
+    DeviceIntPtr mouse = PickPointer(client);
     SpritePtr pSprite = mouse->pSprite;
     int rc;
 
@@ -4224,37 +4234,6 @@ InitEvents()
 }
 
 
-/**
- * Initialize a sprite structure for the given device. If hasCursor is False,
- * let the device use the core pointer's sprite structure.
- */
-void 
-InitSprite(DeviceIntPtr pDev, Bool hasCursor)
-{
-    if (hasCursor)
-    {
-        SpritePtr pSprite = (SpritePtr)xalloc(sizeof(SpriteRec));
-        if (!pSprite)
-            FatalError("failed to allocate sprite struct");
-        memset(pSprite, 0, sizeof(SpriteRec));
-        pSprite->hot.pScreen = pSprite->hotPhys.pScreen = (ScreenPtr)NULL;
-        pSprite->win = NullWindow;
-        pSprite->current = NullCursor;
-        pSprite->hotLimits.x1 = 0;
-        pSprite->hotLimits.y1 = 0;
-        pSprite->hotLimits.x2 = 0;
-        pSprite->hotLimits.y2 = 0;
-        pSprite->confined = FALSE;
-
-        pDev->pSprite = pSprite;
-        pDev->spriteOwner = TRUE;
-    } else
-    {
-        pDev->pSprite = inputInfo.pointer->pSprite;
-        pDev->spriteOwner = FALSE;
-    }
-}
-
 void
 CloseDownEvents(void)
 {
@@ -4268,7 +4247,7 @@ ProcSendEvent(ClientPtr client)
 {
     WindowPtr pWin;
     WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
-    SpritePtr pSprite = inputInfo.pointer->pSprite;
+    SpritePtr pSprite = PickPointer(client)->pSprite;
     REQUEST(xSendEventReq);
 
     REQUEST_SIZE_MATCH(xSendEventReq);
@@ -4335,8 +4314,8 @@ ProcSendEvent(ClientPtr client)
     {
 	for (;pWin; pWin = pWin->parent)
 	{
-            if (DeliverEventsToWindow(inputInfo.pointer, pWin, &stuff->event,
-                                    1, stuff->eventMask, NullGrab, 0))
+            if (DeliverEventsToWindow(PickPointer(client), pWin,
+                        &stuff->event, 1, stuff->eventMask, NullGrab, 0))
 		return Success;
 	    if (pWin == effectiveFocus)
 		return Success;
@@ -4346,8 +4325,8 @@ ProcSendEvent(ClientPtr client)
 	}
     }
     else
-        (void)DeliverEventsToWindow(inputInfo.pointer, pWin, &stuff->event, 1,
-                                    stuff->eventMask, NullGrab, 0);
+        (void)DeliverEventsToWindow(PickPointer(client), pWin, &stuff->event,
+                                    1, stuff->eventMask, NullGrab, 0);
     return Success;
 }
 
@@ -4511,7 +4490,7 @@ ProcGrabButton(ClientPtr client)
     }
 
 
-    grab = CreateGrab(client->index, inputInfo.pointer, pWin, 
+    grab = CreateGrab(client->index, PickPointer(client), pWin, 
         (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
         (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode,
         inputInfo.keyboard, stuff->modifiers, ButtonPress,
@@ -4540,7 +4519,7 @@ ProcUngrabButton(ClientPtr client)
     if (rc != Success)
 	return rc;
     tempGrab.resource = client->clientAsMask;
-    tempGrab.device = inputInfo.pointer;
+    tempGrab.device = PickPointer(client);
     tempGrab.window = pWin;
     tempGrab.modifiersDetail.exact = stuff->modifiers;
     tempGrab.modifiersDetail.pMask = NULL;
@@ -4694,7 +4673,7 @@ ProcRecolorCursor(ClientPtr client)
     int		nscr;
     ScreenPtr	pscr;
     Bool 	displayed;
-    SpritePtr   pSprite = inputInfo.pointer->pSprite;
+    SpritePtr   pSprite = PickPointer(client)->pSprite;
     REQUEST(xRecolorCursorReq);
 
     REQUEST_SIZE_MATCH(xRecolorCursorReq);
@@ -4723,7 +4702,7 @@ ProcRecolorCursor(ClientPtr client)
 	else
 #endif
 	    displayed = (pscr == pSprite->hotPhys.pScreen);
-	( *pscr->RecolorCursor)(inputInfo.pointer, pscr, pCursor,
+	( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
 				(pCursor == pSprite->current) && displayed);
     }
     return (Success);
@@ -4810,3 +4789,59 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
 	(void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
     }
 }
+
+/* PickPointer will pick an appropriate pointer for the given client.
+ *
+ * If a client pointer is set, it will pick the client pointer, otherwise the
+ * first available pointer in the list. If no physical device is attached, it
+ * will pick the core pointer.
+ */
+_X_EXPORT DeviceIntPtr
+PickPointer(ClientPtr client)
+{
+    if (!client->clientPtr)
+    {
+        /* look if there is a real device attached */
+        DeviceIntPtr it = inputInfo.devices;
+        while (it)
+        {
+            if (it != inputInfo.pointer && it->spriteOwner)
+            {
+                client->clientPtr = it;
+                break;
+            }
+            it = it->next;
+        }
+
+        if (!it)
+        {
+            ErrorF("Picking VCP\n");
+            client->clientPtr = inputInfo.pointer;
+        }
+    }
+    return client->clientPtr;
+}
+
+/* PickKeyboard will pick an appropriate keyboard for the given client by
+ * searching the list of devices for the keyboard device that is paired with
+ * the client's pointer.
+ * If no pointer is paired with the keyboard, the virtual core keyboard is
+ * returned.
+ */
+_X_EXPORT DeviceIntPtr
+PickKeyboard(ClientPtr client)
+{
+    DeviceIntPtr dev;
+    DeviceIntPtr ptr = inputInfo.devices;
+    ptr = PickPointer(client);
+
+    while(dev)
+    {
+        if (ptr->pSprite == dev->pSprite)
+            return dev;
+        dev = dev->next;
+    }
+
+    return inputInfo.keyboard;
+}
+
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 41118c0..31be1e3 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -188,9 +188,9 @@ xf86ActivateDevice(LocalDevicePtr local)
 
         /* Only create a new sprite if it's a non-shared pointer */
         if (IsPointerDevice(dev) && dev->isMPDev)
-            InitializeSprite(pDev, NullWindow);
+            InitializeSprite(dev, GetCurrentRootWindow());
         else 
-            PairDevices(pairingClient, inputInfo.pointer, pDev);
+            PairDevices(NULL, inputInfo.pointer, dev);
 
         RegisterOtherDevice(dev);
 
@@ -425,8 +425,6 @@ NewInputDeviceRequest (InputOption *options)
         EnableDevice(dev);
 
     /* send enter/leave event, update sprite window */
-    if (dev->spriteOwner)
-        InitializeSprite(dev, GetCurrentRootWindow());
     CheckMotion(NULL, dev);
 
     return Success;
diff --git a/include/dix.h b/include/dix.h
index 1c6b163..95c69f0 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -602,6 +602,12 @@ extern int TryClientEvents(
 
 extern void WindowsRestructured(void);
 
+extern DeviceIntPtr PickPointer(
+    ClientPtr /* client */);
+
+extern DeviceIntPtr PickKeyboard(
+    ClientPtr /* client */);
+
 #ifdef PANORAMIX
 extern void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
 #endif
diff --git a/include/dixstruct.h b/include/dixstruct.h
index b5ffcca..530009a 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -140,6 +140,8 @@ typedef struct _Client {
     long    smart_stop_tick;
     long    smart_check_tick;
 #endif
+    
+    DeviceIntPtr clientPtr;
 }           ClientRec;
 
 #ifdef SMART_SCHEDULE
diff --git a/include/input.h b/include/input.h
index a7b1e84..433cc94 100644
--- a/include/input.h
+++ b/include/input.h
@@ -450,6 +450,8 @@ extern int PairDevices(ClientPtr client,
                        DeviceIntPtr pointer, 
                        DeviceIntPtr keyboard);
 
+extern DeviceIntPtr GetPairedPointer(DeviceIntPtr kbd);
+
 extern Bool RegisterPairingClient(ClientPtr client);
 extern Bool UnregisterPairingClient(ClientPtr client);
 
commit 43bd35fcf85b51b7e5714844bade90184dbd746f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Mar 1 17:19:37 2007 +1030

    dix:    Remove InitSprite, work can be done by InitializeSprite.
            Free sprite struct if a spriteOwner is paired.
    
    xfree86: Use PairDevices instead of passing booleans around when creating a
             sprite.
    
    Xext:    Switch back to using LookupPointer/KeyboardDevice instead of
             inputInfo.xyz.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index d46d6e7..cb7b5b8 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -316,7 +316,7 @@ ProcXTestFakeInput(client)
 #ifdef XINPUT
 	if (!extension)
 #endif /* XINPUT */
-	    dev = inputInfo.keyboard;
+	    dev = (DeviceIntPtr)LookupKeyboardDevice();
 	if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
 	    ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
 	{
@@ -361,7 +361,7 @@ ProcXTestFakeInput(client)
 	}
 #endif /* XINPUT */
         if (!dev)
-            dev = inputInfo.pointer;
+            dev = (DeviceIntPtr*)LookupPointerDevice();
 	if (ev->u.keyButtonPointer.root == None)
 	    root = GetCurrentRootWindow();
 	else
@@ -427,7 +427,7 @@ ProcXTestFakeInput(client)
 #ifdef PANORAMIX
 	if ((!noPanoramiXExtension
 	     && root->drawable.pScreen->myNum 
-                != XineramaGetCursorScreen(inputInfo.pointer))
+                != XineramaGetCursorScreen(dev))
 	    || (noPanoramiXExtension && root != GetCurrentRootWindow()))
 
 #else
@@ -451,7 +451,7 @@ ProcXTestFakeInput(client)
 #ifdef XINPUT
 	if (!extension)
 #endif /* XINPUT */
-	    dev = inputInfo.pointer;
+            dev = (DeviceIntPtr*)LookupPointerDevice();
 	if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
 	{
 	    client->errorValue = ev->u.u.detail;
diff --git a/autogen.sh b/autogen.sh
index 904cd67..1176abd 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -9,4 +9,4 @@ cd $srcdir
 autoreconf -v --install || exit 1
 cd $ORIGDIR || exit $?
 
-$srcdir/configure --enable-maintainer-mode "$@"
+$srcdir/configure --enable-maintainer-mode --disable-dmx "$@"
diff --git a/dix/devices.c b/dix/devices.c
index ad5cd50..747d782 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1937,14 +1937,21 @@ ProcQueryKeymap(ClientPtr client)
  * pointer sprite. 
  */
 int 
-PairDevices(ClientPtr client, DeviceIntPtr pointer, DeviceIntPtr keyboard)
+PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
 {
     if (!pairingClient)
         RegisterPairingClient(client);
     else if (pairingClient != client)
         return BadAccess;
 
-    keyboard->pSprite = pointer->pSprite;
+    if (kbd->spriteOwner)
+    {
+        xfree(kbd->pSprite);
+        kbd->pSprite = NULL;
+        kbd->spriteOwner = FALSE;
+    }
+
+    kbd->pSprite = ptr->pSprite;
     return Success;
 }
 
diff --git a/dix/events.c b/dix/events.c
index 5ea9a65..a1e72f1 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -240,7 +240,6 @@ static WindowPtr *spriteTrace = (WindowPtr *)NULL;
 static int spriteTraceSize = 0;
 static int spriteTraceGood;
 
-
 /** 
  * True if device owns a cursor, false if device shares a cursor sprite with
  * another device.
@@ -2212,8 +2211,16 @@ void
 InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
 {
     SpritePtr pSprite;
-    ScreenPtr pScreen = pWin->drawable.pScreen;
+    ScreenPtr pScreen; 
+
+    if (!pDev->pSprite)
+    {
+        pDev->pSprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec));
+        if (!pDev->pSprite)
+            FatalError("InitializeSprite: failed to allocate sprite struct");
+    }
 
+    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
     pSprite = pDev->pSprite;
     pSprite->hotPhys.pScreen = pScreen;
     pSprite->hotPhys.x = pScreen->width / 2;
@@ -2222,8 +2229,12 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
     pSprite->hotLimits.x2 = pScreen->width;
     pSprite->hotLimits.y2 = pScreen->height;
     pSprite->win = pWin;
-    pSprite->current = wCursor (pWin);
-    pSprite->current->refcnt++;
+    if (pWin)
+    {
+        pSprite->current = wCursor(pWin);
+        pSprite->current->refcnt++;
+    } else
+        pSprite->current = NullCursor;
 
     (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
                                &pSprite->hotLimits, &pSprite->physLimits);
@@ -2252,6 +2263,8 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
         REGION_NULL(pScreen, &pSprite->Reg2);
     }
 #endif
+
+    pDev->spriteOwner = TRUE;
 }
 
 /*
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 608fa9b..41118c0 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -187,7 +187,11 @@ xf86ActivateDevice(LocalDevicePtr local)
 #endif
 
         /* Only create a new sprite if it's a non-shared pointer */
-        InitSprite(dev, IsPointerDevice(dev) && dev->isMPDev);
+        if (IsPointerDevice(dev) && dev->isMPDev)
+            InitializeSprite(pDev, NullWindow);
+        else 
+            PairDevices(pairingClient, inputInfo.pointer, pDev);
+
         RegisterOtherDevice(dev);
 
         if (serverGeneration == 1) 
diff --git a/hw/xfree86/os-support/linux/lnx_agp.c b/hw/xfree86/os-support/linux/lnx_agp.c
index ded9e0f..300b08d 100644
--- a/hw/xfree86/os-support/linux/lnx_agp.c
+++ b/hw/xfree86/os-support/linux/lnx_agp.c
@@ -10,6 +10,7 @@
 
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
+#include <linux/types.h>
 #endif
 
 #include <X11/X.h>
diff --git a/include/inputstr.h b/include/inputstr.h
index c4a2d18..90a985b 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -355,7 +355,7 @@ typedef struct _DeviceIntRec {
     int			nPrivates;
     DeviceUnwrapProc    unwrapProc;
     Bool                isMPDev;           /* TRUE if multipointer device */
-    /* Each devices has a sprite. However, keyboards and shared pointers do
+    /* Each device has a sprite. However, keyboards and shared pointers do
        not in fact own a sprite but rather have their pointer set to the
        sprite of another device. pSprite always has to point to a valid
        sprite. spriteOwner indicates whether it is the device's sprite. */
commit 2a35d44b6d87f96a7ce90dc8f0142f48cc176e95
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Feb 28 15:43:06 2007 +1030

    Update device valuators on XTest motion event, otherwise the cursor jumps
    between coordinates stored in device and coordinates sent by the event.

diff --git a/Xext/xtest.c b/Xext/xtest.c
index c59adea..d46d6e7 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -316,7 +316,7 @@ ProcXTestFakeInput(client)
 #ifdef XINPUT
 	if (!extension)
 #endif /* XINPUT */
-	    dev = (DeviceIntPtr)LookupKeyboardDevice();
+	    dev = inputInfo.keyboard;
 	if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
 	    ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
 	{
@@ -360,7 +360,8 @@ ProcXTestFakeInput(client)
 	    break;
 	}
 #endif /* XINPUT */
-	dev = (DeviceIntPtr)LookupPointerDevice();
+        if (!dev)
+            dev = inputInfo.pointer;
 	if (ev->u.keyButtonPointer.root == None)
 	    root = GetCurrentRootWindow();
 	else
@@ -378,7 +379,7 @@ ProcXTestFakeInput(client)
 	if (ev->u.u.detail == xTrue)
 	{
 	    int x, y;
-	    GetSpritePosition(inputInfo.pointer, &x, &y);
+	    GetSpritePosition(dev, &x, &y);
 	    ev->u.keyButtonPointer.rootX += x;
 	    ev->u.keyButtonPointer.rootY += y;
 	}
@@ -442,13 +443,15 @@ ProcXTestFakeInput(client)
 	    (dev, root->drawable.pScreen,
 	     ev->u.keyButtonPointer.rootX,
 	     ev->u.keyButtonPointer.rootY, FALSE);
+        dev->valuator->lastx = ev->u.keyButtonPointer.rootX;
+        dev->valuator->lasty = ev->u.keyButtonPointer.rootY;
 	break;
     case ButtonPress:
     case ButtonRelease:
 #ifdef XINPUT
 	if (!extension)
 #endif /* XINPUT */
-	    dev = (DeviceIntPtr)LookupPointerDevice();
+	    dev = inputInfo.pointer;
 	if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
 	{
 	    client->errorValue = ev->u.u.detail;
commit bc4ae25433e38a25a2012f9f233d500665172a4b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Feb 23 12:06:51 2007 +1030

    xfree86: Don't initialize sprites for devices that don't own a sprite (stops
             keyboard hotplug segfaults)

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index c2ea108..608fa9b 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -421,7 +421,8 @@ NewInputDeviceRequest (InputOption *options)
         EnableDevice(dev);
 
     /* send enter/leave event, update sprite window */
-    InitializeSprite(dev, GetCurrentRootWindow());
+    if (dev->spriteOwner)
+        InitializeSprite(dev, GetCurrentRootWindow());
     CheckMotion(NULL, dev);
 
     return Success;
commit 4b8b0e377a27ec904b2028c89aed11c6416af26c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 22 20:00:59 2007 +1030

    Xi: 	Add access control request handling.
    
    dix:	New file access.c to handle all access control for devices.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 5d3417e..e77c8a3 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -20,7 +20,9 @@ libXi_la_SOURCES =	\
 	chgptr.c \
 	chgptr.h \
 	chpkpair.c \
-	chpkpair.h \ 
+	chpkpair.h \
+	chaccess.c \
+	chaccess.h \
 	closedev.c \
 	closedev.h \
 	devbell.c \
@@ -46,6 +48,8 @@ libXi_la_SOURCES =	\
 	getselev.h \
 	getvers.c \
 	getvers.h \
+        grabacc.c \
+        grabacc.h \
 	grabdev.c \
 	grabdev.h \
 	grabdevb.c \
@@ -62,6 +66,8 @@ libXi_la_SOURCES =	\
 	querydp.h \
 	queryst.c \
 	queryst.h \
+	qryacces.c \
+	qryacces.h \
 	regpair.c \
 	regpair.h \
 	selectev.c \
diff --git a/Xi/chaccess.c b/Xi/chaccess.c
new file mode 100644
index 0000000..5005e94
--- /dev/null
+++ b/Xi/chaccess.c
@@ -0,0 +1,177 @@
+/*
+
+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/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 "chaccess.h"
+
+/***********************************************************************
+ * This procedure allows a client to change window access control.
+ */
+
+int 
+SProcXChangeWindowAccess(ClientPtr client)
+{    
+    char n;
+    REQUEST(xChangeWindowAccessReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->win, n);
+    return ProcXChangeWindowAccess(client);
+}
+
+int 
+ProcXChangeWindowAccess(ClientPtr client)
+{
+    int padding, err, i;
+    CARD8* deviceids = NULL;
+    WindowPtr win;
+    DeviceIntPtr* perm_devices = NULL;
+    DeviceIntPtr* deny_devices = NULL;
+    REQUEST(xChangeWindowAccessReq);
+    REQUEST_AT_LEAST_SIZE(xChangeWindowAccessReq);
+    
+
+    padding = (4 - ((stuff->npermit + stuff->ndeny) % 4)) % 4;
+
+    if (stuff->length != ((sizeof(xChangeWindowAccessReq)  + 
+            (stuff->npermit + stuff->ndeny + padding)) >> 2))
+    {
+        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
+                0, BadLength);
+        return Success;
+    }
+
+
+    err = dixLookupWindow(&win, stuff->win, client, DixWriteAccess);
+    if (err != Success)
+    {
+        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
+                          stuff->win, err);
+        return Success;
+    }
+
+    /* Are we clearing? if so, ignore the rest */
+    if (stuff->clear)
+    {
+        err = ACClearWindowAccess(client, win, stuff->clear);
+        if (err != Success)
+            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, err);
+        return Success;
+    }
+
+    if (stuff->npermit || stuff->ndeny)
+        deviceids = (CARD8*)&stuff[1];
+
+    if (stuff->npermit)
+    {
+        perm_devices = 
+            (DeviceIntPtr*)xalloc(stuff->npermit * sizeof(DeviceIntPtr));
+        if (!perm_devices)
+        {
+            ErrorF("ProcXChangeWindowAccess: alloc failure.\n");
+            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, 
+                    BadImplementation);
+            return Success;
+        }
+
+        /* if one of the devices cannot be accessed, we don't do anything.*/
+        for (i = 0; i < stuff->npermit; i++)
+        {
+            perm_devices[i] = LookupDeviceIntRec(deviceids[i]);
+            if (!perm_devices[i])
+            {
+                xfree(perm_devices);
+                SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
+                        deviceids[i], BadDevice); 
+                return Success;
+            }
+        }
+    }
+
+    if (stuff->ndeny)
+    {
+        deny_devices = 
+            (DeviceIntPtr*)xalloc(stuff->ndeny * sizeof(DeviceIntPtr));
+        if (!deny_devices)
+        {
+            ErrorF("ProcXChangeWindowAccecss: alloc failure.\n");
+            SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 0, 
+                    BadImplementation);
+
+            xfree(perm_devices);
+            return Success;
+        }
+
+        for (i = 0; i < stuff->ndeny; i++)
+        {
+            deny_devices[i] = 
+                LookupDeviceIntRec(deviceids[i+stuff->npermit]);
+            
+            if (!deny_devices[i])
+            {
+                xfree(perm_devices);
+                xfree(deny_devices);
+                SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
+                        deviceids[i + stuff->npermit], BadDevice); 
+                return Success;
+            }
+        }
+    }
+
+    err = ACChangeWindowAccess(client, win, stuff->defaultRule,
+                               perm_devices, stuff->npermit,
+                               deny_devices, stuff->ndeny);
+    if (err != Success)
+    {
+        SendErrorToClient(client, IReqCode, X_ChangeWindowAccess, 
+                          stuff->win, err);
+        return Success;
+    }
+    
+    xfree(perm_devices);
+    xfree(deny_devices);
+    return Success;
+}
+
diff --git a/Xi/chaccess.h b/Xi/chaccess.h
new file mode 100644
index 0000000..8c2c600
--- /dev/null
+++ b/Xi/chaccess.h
@@ -0,0 +1,39 @@
+/*
+
+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 CHACCESS_H
+#define CHACCESS_H 1
+
+int SProcXChangeWindowAccess(ClientPtr /* client */);
+int ProcXChangeWindowAccess(ClientPtr /* client */);
+
+#endif /* CHACCESS_H */
diff --git a/Xi/extinit.c b/Xi/extinit.c
index cf4f509..598348e 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -74,6 +74,7 @@ SOFTWARE.
 
 /* modules local to Xi */
 #include "allowev.h"
+#include "chaccess.h"
 #include "chdevcur.h"
 #include "chgdctl.h"
 #include "chgfctl.h"
@@ -94,12 +95,14 @@ SOFTWARE.
 #include "getselev.h"
 #include "getvers.h"
 #include "getvers.h"
+#include "grabacc.h"
 #include "grabdev.h"
 #include "grabdevb.h"
 #include "grabdevk.h"
 #include "gtmotion.h"
 #include "listdev.h"
 #include "opendev.h"
+#include "qryacces.c"
 #include "querydp.h"
 #include "queryst.h"
 #include "regpair.h"
@@ -358,6 +361,12 @@ ProcIDispatch(register ClientPtr client)
         return (ProcXChangePointerKeyboardPairing(client));
     else if (stuff->data == X_RegisterPairingClient)
         return (ProcXRegisterPairingClient(client));
+    else if (stuff->data == X_GrabAccessControl)
+        return (ProcXGrabAccessControl(client));
+    else if (stuff->data == X_ChangeWindowAccess)
+        return (ProcXChangeWindowAccess(client));
+    else if (stuff->data == X_QueryWindowAccess)
+        return ProcXQueryWindowAccess(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -457,6 +466,12 @@ SProcIDispatch(register ClientPtr client)
         return (SProcXChangePointerKeyboardPairing(client));
     else if (stuff->data == X_RegisterPairingClient)
         return (SProcXRegisterPairingClient(client));
+    else if (stuff->data == X_GrabAccessControl)
+        return (SProcXGrabAccessControl(client));
+    else if (stuff->data == X_ChangeWindowAccess)
+        return (SProcXChangeWindowAccess(client));
+    else if (stuff->data == X_QueryWindowAccess)
+        return SProcXQueryWindowAccess(client);
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -531,10 +546,16 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
 				 (xChangeDeviceControlReply *) rep);
     else if (rep->RepType == X_QueryDevicePointer)
 	SRepXQueryDevicePointer(client, len,
-				 (xQueryDevicePointerReply *) rep);
+				(xQueryDevicePointerReply *) rep);
     else if (rep->RepType == X_RegisterPairingClient)
 	SRepXRegisterPairingClient(client, len,
-				 (xRegisterPairingClientReply *) rep);
+				  (xRegisterPairingClientReply *) rep);
+    else if (rep->RepType == X_GrabAccessControl)
+        SRepXGrabAccessControl(client, len,
+                                  (xGrabAccessControlReply*) rep);
+    else if (rep->RepType == X_QueryWindowAccess)
+        SRepXQueryWindowAccess(client, len,
+                               (xQueryWindowAccessReply*) rep);
     else {
 	FatalError("XINPUT confused sending swapped reply");
     }
diff --git a/Xi/grabacc.c b/Xi/grabacc.c
new file mode 100644
index 0000000..db9c9f2
--- /dev/null
+++ b/Xi/grabacc.c
@@ -0,0 +1,102 @@
+/*
+
+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/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 "grabacc.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to register as the global client to control
+ * any window access.
+ *
+ */
+int
+SProcXGrabAccessControl(ClientPtr client)
+{
+    char n;
+    REQUEST(xGrabAccessControlReq);
+
+    swaps(&stuff->length, n);
+    return ProcXGrabAccessControl(client);
+}
+
+int 
+ProcXGrabAccessControl(ClientPtr client)
+{
+    xGrabAccessControlReply rep;
+    REQUEST(xGrabAccessControlReq);
+    REQUEST_SIZE_MATCH(xGrabAccessControlReq);
+
+    if (stuff->ungrab)
+        ACUnregisterClient(client);
+
+    rep.repType = X_Reply;
+    rep.RepType = X_GrabAccessControl;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.success = stuff->ungrab || ACRegisterClient(client);
+
+    WriteReplyToClient(client, sizeof(xGrabAccessControlReply), &rep);
+    return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XGrabAccessControl function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void
+SRepXGrabAccessControl(ClientPtr client, int size, 
+        xGrabAccessControlReply* rep)
+{
+    register char n;
+
+    swaps(&rep->sequenceNumber, n);
+    swapl(&rep->length, n);
+    WriteToClient(client, size, (char *)rep);
+}
+
diff --git a/Xi/grabacc.h b/Xi/grabacc.h
new file mode 100644
index 0000000..6dcbcad
--- /dev/null
+++ b/Xi/grabacc.h
@@ -0,0 +1,41 @@
+/*
+
+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 GRABACC_H
+#define GRABACC_H 1
+
+int SProcXGrabAccessControl(ClientPtr /* client */);
+
+int ProcXGrabAccessControl(ClientPtr /* client */);
+void SRepXGrabAccessControl(ClientPtr client, int size, 
+        xGrabAccessControlReply* rep);
+#endif /* GRABACC_H */
diff --git a/Xi/qryacces.c b/Xi/qryacces.c
new file mode 100644
index 0000000..817bec8
--- /dev/null
+++ b/Xi/qryacces.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.
+
+*/
+
+#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 "qryacces.h"
+
+/***********************************************************************
+ * This procedure allows a client to query window access control.
+ */
+
+int
+SProcXQueryWindowAccess(ClientPtr client)
+{
+    char n;
+    REQUEST(xQueryWindowAccessReq);
+
+    swaps(&stuff->length, n);
+    swapl(&stuff->win, n);
+    return ProcXQueryWindowAccess(client);
+}
+
+int
+ProcXQueryWindowAccess(ClientPtr client)
+{
+    int err;
+    WindowPtr win;
+    DeviceIntPtr *perm, *deny;
+    int nperm, ndeny, i;
+    int defaultRule;
+    CARD8* deviceids;
+    xQueryWindowAccessReply rep;
+
+    REQUEST(xQueryWindowAccessReq);
+    REQUEST_SIZE_MATCH(xQueryWindowAccessReq);
+
+    err = dixLookupWindow(&win, stuff->win, client, DixReadAccess);
+    if (err != Success)
+    {
+        SendErrorToClient(client, IReqCode, X_QueryWindowAccess, 
+                          stuff->win, err); 
+        return Success;
+    }
+
+    ACQueryWindowAccess(win, &defaultRule, &perm, &nperm, &deny, &ndeny);
+
+    rep.repType = X_Reply;
+    rep.RepType = X_QueryWindowAccess;
+    rep.sequenceNumber = client->sequence;
+    rep.length = (nperm + ndeny + 3) >> 2;
+    rep.defaultRule = defaultRule;
+    rep.npermit = nperm;
+    rep.ndeny = ndeny;
+    WriteReplyToClient(client, sizeof(xQueryWindowAccessReply), &rep);
+
+    if (nperm + ndeny)
+    {
+        deviceids = (CARD8*)xalloc((nperm + ndeny) * sizeof(CARD8));
+        if (!deviceids)
+        {
+            ErrorF("ProcXQueryWindowAccess: xalloc failure.\n");
+            SendErrorToClient(client, IReqCode, X_QueryWindowAccess, 
+                    0, BadImplementation); 
+            return Success;
+        }
+
+        for (i = 0; i < nperm; i++)
+            deviceids[i] = perm[i]->id;
+        for (i = 0; i < ndeny; i++)
+            deviceids[i + nperm] = deny[i]->id;
+
+        WriteToClient(client, nperm + ndeny, (char*)deviceids);
+        xfree(deviceids);
+    }
+    return Success;
+}
+
+void
+SRepXQueryWindowAccess(ClientPtr client, 
+                      int size, 
+                      xQueryWindowAccessReply* rep)
+{
+    char n;
+    swaps(&rep->sequenceNumber, n);
+    swapl(&rep->length, n);
+    WriteToClient(client, size, (char*)rep);
+}
diff --git a/Xi/qryacces.h b/Xi/qryacces.h
new file mode 100644
index 0000000..5fce9ae
--- /dev/null
+++ b/Xi/qryacces.h
@@ -0,0 +1,41 @@
+/*
+
+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 QRYACCES_H
+#define QRYACCES_H 1
+
+int SProcXQueryWindowAccess(ClientPtr /* client */);
+int ProcXQueryWindowAccess(ClientPtr /* client */);
+void SRepXQueryWindowAccess(ClientPtr /* client */,
+                            int /* size */,
+                            xQueryWindowAccessReply* /* rep */);
+#endif
diff --git a/dix/Makefile.am b/dix/Makefile.am
index a1f02c1..d9083ea 100644
--- a/dix/Makefile.am
+++ b/dix/Makefile.am
@@ -5,6 +5,7 @@ AM_CFLAGS = $(DIX_CFLAGS) \
 	-DVENDOR_RELEASE="@VENDOR_RELEASE@"
 
 libdix_la_SOURCES = 	\
+        access.c        \
 	atom.c		\
 	colormap.c	\
 	cursor.c	\
diff --git a/dix/access.c b/dix/access.c
new file mode 100644
index 0000000..970d7c4
--- /dev/null
+++ b/dix/access.c
@@ -0,0 +1,287 @@
+/*
+
+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.
+
+*/
+
+/* This file controls the access control lists for each window. 
+ * Each device can be explicitely allowed or denied access to a given window.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XI.h>
+
+#include "input.h"
+#include "inputstr.h"
+#include "windowstr.h"
+
+
+/* Only one single client can be responsible for window access control. */
+static ClientPtr ACClient = NULL;
+
+
+/* Forward declarations */
+static void acReplaceList(DeviceIntPtr** list, 
+                          int* count, 
+                          DeviceIntPtr* devices, 
+                          int ndevices);
+
+/* Register global window access control client
+ * Return True on success or False otherwise.
+ */ 
+
+Bool
+ACRegisterClient(ClientPtr client)
+{
+    if (ACClient && ACClient != client)
+        return False;
+
+    ACClient = client;
+    return True;
+}
+
+
+/* Unregister global client. If client is not the registered client, nothing
+ * happens and False is returned. If no client is registered, return True.
+ * Returns True if client was registred and is now unregistered.
+ */ 
+
+Bool
+ACUnregisterClient(ClientPtr client)
+{
+    if (ACClient && ACClient != client)
+        return False;
+
+    ACClient = NULL;
+    return True;
+}
+
+/* Clears all access control for the window and remove the default rule,
+ * depending on what is set. */
+int ACClearWindowAccess(ClientPtr client,
+                        WindowPtr win,
+                        int what)
+{
+    if (client != ACClient && client != wClient(win))
+        return BadAccess;
+
+    if (!win->optional)
+    {
+        /* we shouldn't get here if programmers know what they're doing. 
+         * A client should not request to clear a window's access controls 
+         * if they've never been set before anyway. If they do, do nothing and
+         * let the client figure out what to do next.
+         */
+        return Success;
+    }
+
+    if (what & WindowAccessClearPerm)
+    {
+        xfree(win->optional->access.perm);
+        win->optional->access.perm = NULL;
+        win->optional->access.nperm = 0;
+    }
+
+    if (what & WindowAccessClearDeny)
+    {
+        xfree(win->optional->access.deny);
+        win->optional->access.deny = NULL;
+        win->optional->access.ndeny = 0;
+    }
+
+    if (what & WindowAccessClearRule)
+        win->optional->access.defaultRule = WindowAccessNoRule;
+
+    return Success;
+}
+
+/*
+ * Changes window access control.
+ *
+ * Returns Success or BadAccess if the client is not allowed to change
+ * anything.
+ */
+
+int
+ACChangeWindowAccess(ClientPtr client, 
+                     WindowPtr win, 
+                     int defaultRule,
+                     DeviceIntPtr* perm_devices,
+                     int nperm,
+                     DeviceIntPtr* deny_devices,
+                     int ndeny)
+{
+    if (client != ACClient && client != wClient(win))
+        return BadAccess;
+
+    if (!win->optional && !MakeWindowOptional(win))
+    {
+        ErrorF("ACChangeWindowAcccess: Failed to make window optional.\n");
+        return BadImplementation;
+    }
+
+    if (defaultRule != WindowAccessKeepRule)
+        win->optional->access.defaultRule = defaultRule;
+
+    if (nperm)
+    {
+        acReplaceList(&win->optional->access.perm, 
+                      &win->optional->access.nperm,
+                      perm_devices, nperm);
+    }
+
+    if (ndeny)
+    {
+        acReplaceList(&win->optional->access.deny, 
+                &win->optional->access.ndeny,
+                deny_devices, ndeny);
+    }
+
+    return Success;
+}
+
+static void
+acReplaceList(DeviceIntPtr** list, 
+              int* count, 
+              DeviceIntPtr* devices, 
+              int ndevices)
+{
+    xfree(*list);
+    *list = NULL;
+    *count = 0;
+
+    if (ndevices)
+    {
+        *list = 
+            xalloc(ndevices * sizeof(DeviceIntPtr*));
+        if (!*list)
+        {
+            ErrorF("ACChangeWindowAccess: out of memory\n");
+            return;
+        }
+        memcpy(*list,
+                devices, 
+                ndevices * sizeof(DeviceIntPtr));
+        *count = ndevices;
+    }
+    return;
+}
+
+/*
+ * Query the given window for the devices allowed to access a window.
+ * The caller is responsible for freeing perm and deny.
+ */
+void
+ACQueryWindowAccess(WindowPtr win, 
+                    int* defaultRule,
+                    DeviceIntPtr** perm,
+                    int* nperm,
+                    DeviceIntPtr** deny,
+                    int* ndeny)
+{
+    *defaultRule = WindowAccessNoRule;
+    *perm = NULL;
+    *nperm = 0;
+    *deny = NULL;
+    *ndeny = 0;
+
+    if (!win->optional)
+        return;
+
+    *defaultRule = win->optional->access.defaultRule;
+
+    if (win->optional->access.nperm)
+    {
+        *nperm = win->optional->access.nperm;
+        *perm = (DeviceIntPtr*)xalloc(*nperm * sizeof(DeviceIntPtr));
+        if (!*perm)
+        {
+            ErrorF("ACQuerywinAccess: xalloc failure\n");
+            return;
+        }
+        memcpy(*perm, 
+               win->optional->access.perm, 
+               *nperm * sizeof(DeviceIntPtr));
+    }
+
+    if (win->optional->access.ndeny)
+    {
+        *ndeny = win->optional->access.ndeny;
+        *deny = (DeviceIntPtr*)xalloc(*ndeny * sizeof(DeviceIntPtr));
+        if (!*deny)
+        {
+            ErrorF("ACQuerywinAccess: xalloc failure\n");
+            return;
+        }
+        memcpy(*deny, 
+               win->optional->access.deny, 
+               *ndeny * sizeof(DeviceIntPtr));
+    }
+}
+
+/*
+ * Check if the given device is allowed to send events to the window. Returns
+ * true if device is allowed or false otherwise.
+ *
+ * Checks are done in the following order until a result is found:
+ * If the device is explicitely permitted, allow.
+ * If the window has a default of DenyAll, do not allow.
+ * If the device is explicitely denied, do not allow.
+ * Check parent window. Rinse, wash, repeat.
+ * If no rule could be found, allow.
+ */
+Bool
+ACDeviceAllowed(WindowPtr win, DeviceIntPtr dev)
+{
+    int i;
+
+    if (!win) /* happens for parent of RootWindow */
+        return True;
+
+    if (!win->optional) /* no list, check parent */
+        return ACDeviceAllowed(win->parent, dev);
+
+    for (i = 0; i < win->optional->access.nperm; i++)
+    {
+        if (win->optional->access.perm[i]->id == dev->id)
+            return True;
+    }
+
+    if (win->optional->access.defaultRule == WindowAccessDenyAll)
+        return False;
+
+    for (i = 0; i < win->optional->access.ndeny; i++)
+    {
+        if (win->optional->access.deny[i]->id == dev->id)
+            return False;
+    }
+
+    return ACDeviceAllowed(win->parent, dev);
+}
+
diff --git a/dix/dispatch.c b/dix/dispatch.c
index a795d17..98183cc 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3568,6 +3568,7 @@ CloseDownClient(register ClientPtr client)
 	DeleteClientFromAnySelections(client);
 	ReleaseActiveGrabs(client);
 	DeleteClientFontStuff(client);
+        ACUnregisterClient(client);
         UnregisterPairingClient(client); /* other clients can pair devices */
 	if (!really_close_down)
 	{
diff --git a/dix/events.c b/dix/events.c
index 57a356d..5ea9a65 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1663,6 +1663,9 @@ DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
     Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
 		              this mask is the mask of the grab. */
     int type = pEvents->u.u.type;
+    
+    if (!ACDeviceAllowed(pWin, pDev))
+        return 0;
 
     /* CantBeFiltered means only window owner gets the event */
     if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
@@ -2748,16 +2751,20 @@ DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev,
     }
     if (!deliveries)
     {
-	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
+        if (ACDeviceAllowed(grab->window, thisDev))
+        {
+
+            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
+                        || xE->u.u.type == DeviceMotionNotify
 #endif
-			   ))
-	    thisDev->valuator->motionHintWindow = grab->window;
+                        ))
+                thisDev->valuator->motionHintWindow = grab->window;
+        }
     }
     if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
 #ifdef XINPUT
diff --git a/dix/window.c b/dix/window.c
index 604af38..3d79728 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -452,6 +452,13 @@ CreateRootWindow(ScreenPtr pScreen)
     pWin->optional->inputMasks = NULL;
     pWin->optional->deviceCursors = NULL;
 #endif
+
+    pWin->optional->access.perm = NULL;
+    pWin->optional->access.deny = NULL;
+    pWin->optional->access.nperm = 0;
+    pWin->optional->access.ndeny = 0;
+    pWin->optional->access.defaultRule = 0;
+
     pWin->optional->colormap = pScreen->defColormap;
     pWin->optional->visual = pScreen->rootVisual;
 
@@ -505,7 +512,6 @@ CreateRootWindow(ScreenPtr pScreen)
 		
     if (disableSaveUnders)
 	pScreen->saveUnderSupport = NotUseful;
-
     return TRUE;
 }
 
@@ -523,6 +529,7 @@ InitRootWindow(WindowPtr pWin)
     pWin->optional->cursor = rootCursor;
     rootCursor->refcnt++;
 
+
     if (!blackRoot && !whiteRoot) {
         MakeRootTile(pWin);
         backFlag |= CWBackPixmap;
@@ -3660,6 +3667,9 @@ CheckWindowOptionalNeed (register WindowPtr w)
             pNode = pNode->next;
         }
     }
+    if (optional->access.nperm != 0 ||
+            optional->access.ndeny != 0)
+        return;
 
     parentOptional = FindWindowWithOptional(w)->optional;
     if (optional->visual != parentOptional->visual)
@@ -3705,8 +3715,12 @@ MakeWindowOptional (register WindowPtr pWin)
 #endif
 #ifdef XINPUT
     optional->inputMasks = NULL;
-    optional->deviceCursors = NULL;
 #endif
+    optional->deviceCursors = NULL;
+    optional->access.nperm = 0;
+    optional->access.ndeny = 0;
+    optional->access.perm = NULL;
+    optional->access.deny = NULL;
     parentOptional = FindWindowWithOptional(pWin)->optional;
     optional->visual = parentOptional->visual;
     if (!pWin->cursorIsNone)
@@ -3771,6 +3785,9 @@ DisposeWindowOptional (register WindowPtr pWin)
         pWin->optional->deviceCursors = NULL;
     }
 
+    xfree(pWin->optional->access.perm);
+    xfree(pWin->optional->access.deny);
+
     xfree (pWin->optional);
     pWin->optional = NULL;
 }
diff --git a/include/input.h b/include/input.h
index d2e26ef..a7b1e84 100644
--- a/include/input.h
+++ b/include/input.h
@@ -445,6 +445,37 @@ extern void SwitchCorePointer(DeviceIntPtr pDev);
 extern DeviceIntPtr LookupDeviceIntRec(
     CARD8 deviceid);
 
+/* Pairing input devices */
+extern int PairDevices(ClientPtr client, 
+                       DeviceIntPtr pointer, 
+                       DeviceIntPtr keyboard);
+
+extern Bool RegisterPairingClient(ClientPtr client);
+extern Bool UnregisterPairingClient(ClientPtr client);
+
+/* Window/device based access control */
+extern Bool ACRegisterClient(ClientPtr client);
+extern Bool ACUnregisterClient(ClientPtr client);
+extern int ACClearWindowAccess(ClientPtr client,
+                        WindowPtr win,
+                        int what);
+extern int ACChangeWindowAccess(ClientPtr client, 
+                                WindowPtr win, 
+                                int defaultRule,
+                                DeviceIntPtr* perm_devices,
+                                int npermit,
+                                DeviceIntPtr* deny_devices,
+                                int ndeny);
+extern void ACQueryWindowAccess(WindowPtr win, 
+                                int* defaultRule,
+                                DeviceIntPtr** perm,
+                                int* nperm,
+                                DeviceIntPtr** deny,
+                                int* ndeny);
+
+extern Bool ACDeviceAllowed(WindowPtr win, 
+                            DeviceIntPtr dev);
+
 /* Implemented by the DDX. */
 extern int NewInputDeviceRequest(
     InputOption *options);
@@ -454,11 +485,4 @@ extern void DDXRingBell(
     int pitch,
     int duration);
 
-extern int PairDevices(ClientPtr client, 
-                       DeviceIntPtr pointer, 
-                       DeviceIntPtr keyboard);
-
-extern Bool RegisterPairingClient(ClientPtr client);
-extern Bool UnregisterPairingClient(ClientPtr client);
-
 #endif /* INPUT_H */
diff --git a/include/windowstr.h b/include/windowstr.h
index 4e9c82c..882f8a5 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -77,6 +77,14 @@ typedef struct _DevCursorNode {
     struct _DevCursorNode*      next;
 } DevCursNodeRec, *DevCursNodePtr, *DevCursorList;
 
+typedef struct _WindowAccessRec {
+    int                  defaultRule;      /* WindowAccessDenyAll */
+    DeviceIntPtr*        perm;
+    int                  nperm;
+    DeviceIntPtr*        deny;
+    int                  ndeny;
+} WindowAccessRec, *WindowAccessPtr;
+
 typedef struct _WindowOpt {
     VisualID		visual;		   /* default: same as parent */
     CursorPtr		cursor;		   /* default: window.cursorNone */
@@ -97,6 +105,7 @@ typedef struct _WindowOpt {
     struct _OtherInputMasks *inputMasks;   /* default: NULL */
 #endif
     DevCursorList       deviceCursors;     /* default: NULL */
+    WindowAccessRec     access;
 } WindowOptRec, *WindowOptPtr;
 
 #define BackgroundPixel	    2L
commit cd0af7a7856e8246e27acc5513d219a094211625
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Feb 21 10:08:41 2007 +1030

    Xi, dix: Only one client at a time can change the pointer-keyboard pairing,
             using xRegisterPairingClient request.

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 9000030..5d3417e 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -62,6 +62,8 @@ libXi_la_SOURCES =	\
 	querydp.h \
 	queryst.c \
 	queryst.h \
+	regpair.c \
+	regpair.h \
 	selectev.c \
 	selectev.h \
 	sendexev.c \
diff --git a/Xi/chpkpair.c b/Xi/chpkpair.c
index b862417..8e79a75 100644
--- a/Xi/chpkpair.c
+++ b/Xi/chpkpair.c
@@ -73,10 +73,13 @@ int
 ProcXChangePointerKeyboardPairing(register ClientPtr client)
 {
     DeviceIntPtr pPointer, pKeyboard;
+    int ret;
 
     REQUEST(xChangePointerKeyboardPairingReq);
     REQUEST_SIZE_MATCH(xChangePointerKeyboardPairingReq);
 
+    /* check if client is registered */
+
     pPointer = LookupDeviceIntRec(stuff->pointer);
     if (pPointer == NULL)
     {
@@ -93,7 +96,14 @@ ProcXChangePointerKeyboardPairing(register ClientPtr client)
         return Success;
     }
 
-    pKeyboard->pSprite = pPointer->pSprite;
+    ret = PairDevices(client, pPointer, pKeyboard);
+    if (ret != Success)
+    {
+        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing,
+                0, ret);
+        return Success;
+    }
+
 
     /* TODO: generate event here... */
     return Success;
diff --git a/Xi/extinit.c b/Xi/extinit.c
index a08ec77..cf4f509 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -102,6 +102,7 @@ SOFTWARE.
 #include "opendev.h"
 #include "querydp.h"
 #include "queryst.h"
+#include "regpair.h"
 #include "selectev.h"
 #include "sendexev.h"
 #include "chgkmap.h"
@@ -355,6 +356,8 @@ ProcIDispatch(register ClientPtr client)
         return (ProcXChangeDeviceCursor(client));
     else if (stuff->data == X_ChangePointerKeyboardPairing)
         return (ProcXChangePointerKeyboardPairing(client));
+    else if (stuff->data == X_RegisterPairingClient)
+        return (ProcXRegisterPairingClient(client));
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -452,6 +455,8 @@ SProcIDispatch(register ClientPtr client)
         return (SProcXChangeDeviceCursor(client));
     else if (stuff->data == X_ChangePointerKeyboardPairing)
         return (SProcXChangePointerKeyboardPairing(client));
+    else if (stuff->data == X_RegisterPairingClient)
+        return (SProcXRegisterPairingClient(client));
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -527,6 +532,9 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
     else if (rep->RepType == X_QueryDevicePointer)
 	SRepXQueryDevicePointer(client, len,
 				 (xQueryDevicePointerReply *) rep);
+    else if (rep->RepType == X_RegisterPairingClient)
+	SRepXRegisterPairingClient(client, len,
+				 (xRegisterPairingClientReply *) rep);
     else {
 	FatalError("XINPUT confused sending swapped reply");
     }
diff --git a/Xi/regpair.c b/Xi/regpair.c
new file mode 100644
index 0000000..cfaddb8
--- /dev/null
+++ b/Xi/regpair.c
@@ -0,0 +1,108 @@
+/*
+
+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 authenticate as pairing client
+ *
+ */
+
+#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 <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "exevents.h"
+#include "exglobals.h"
+
+#include "regpair.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to register the pairing of a pointer 
+ * with a keyboard.
+ *
+ */
+
+int 
+SProcXRegisterPairingClient(ClientPtr client)
+{
+    char n;
+    REQUEST(xRegisterPairingClientReq);
+    swaps(&stuff->length, n);
+    return ProcXRegisterPairingClient(client);
+}
+
+int 
+ProcXRegisterPairingClient(ClientPtr client)
+{
+    xRegisterPairingClientReply rep;
+
+    REQUEST(xRegisterPairingClientReq);
+    REQUEST_SIZE_MATCH(xRegisterPairingClientReq);
+
+    if (stuff->disable)
+        UnregisterPairingClient(client);
+
+    rep.repType = X_Reply;
+    rep.RepType = X_RegisterPairingClient;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.success = stuff->disable || RegisterPairingClient(client);
+
+    WriteReplyToClient(client, sizeof(xRegisterPairingClientReply), &rep);
+    return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XRegisterPairingClient function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void
+SRepXRegisterPairingClient(ClientPtr client, int size, 
+        xRegisterPairingClientReply* rep)
+{
+    register char n;
+
+    swaps(&rep->sequenceNumber, n);
+    swapl(&rep->length, n);
+    WriteToClient(client, size, (char *)rep);
+}
+
diff --git a/Xi/regpair.h b/Xi/regpair.h
new file mode 100644
index 0000000..b2bfaff
--- /dev/null
+++ b/Xi/regpair.h
@@ -0,0 +1,43 @@
+/*
+
+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 REGPAIR_H
+#define REGPAIR_H 1
+
+int SProcXRegisterPairingClient(ClientPtr /* client */);
+int ProcXRegisterPairingClient(ClientPtr /* client */);
+
+void SRepXRegisterPairingClient(ClientPtr /* client */, 
+                                int /* size */,
+                                xRegisterPairingClientReply* /* rep */);
+
+#endif /* REGPAIR_H */
diff --git a/dix/devices.c b/dix/devices.c
index bc7ca89..ad5cd50 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -81,6 +81,9 @@ SOFTWARE.
 
 int CoreDevicePrivatesIndex = 0, CoreDevicePrivatesGeneration = -1;
 
+/* The client that is allowed to change pointer-keyboard pairings. */
+static ClientPtr pairingClient = NULL;
+
 DeviceIntPtr
 AddInputDevice(DeviceProc deviceProc, Bool autoStart)
 {
@@ -1926,5 +1929,54 @@ ProcQueryKeymap(ClientPtr client)
 	bzero((char *)&rep.map[0], 32);
 
     WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
+ 
+   return Success;
+}
+
+/* Pair the keyboard to the pointer device. Keyboard events will follow the
+ * pointer sprite. 
+ */
+int 
+PairDevices(ClientPtr client, DeviceIntPtr pointer, DeviceIntPtr keyboard)
+{
+    if (!pairingClient)
+        RegisterPairingClient(client);
+    else if (pairingClient != client)
+        return BadAccess;
+
+    keyboard->pSprite = pointer->pSprite;
     return Success;
 }
+
+/*
+ * Register a client to be able to pair devices. 
+ */
+Bool
+RegisterPairingClient(ClientPtr client)
+{
+    if (!pairingClient)
+    {
+        pairingClient = client;
+    } else if (pairingClient != client)
+    {
+        return False;
+    }
+    return True;
+}
+
+/*
+ * Unregister pairing client;
+ */
+Bool 
+UnregisterPairingClient(ClientPtr client)
+{
+    if (pairingClient) 
+    {
+        if ( pairingClient == client)
+        {
+            pairingClient = NULL;
+        } else 
+            return False;
+    }
+    return True;
+}
diff --git a/dix/dispatch.c b/dix/dispatch.c
index d44687e..a795d17 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3568,6 +3568,7 @@ CloseDownClient(register ClientPtr client)
 	DeleteClientFromAnySelections(client);
 	ReleaseActiveGrabs(client);
 	DeleteClientFontStuff(client);
+        UnregisterPairingClient(client); /* other clients can pair devices */
 	if (!really_close_down)
 	{
 	    /*  This frees resources that should never be retained
diff --git a/include/input.h b/include/input.h
index 96a28a5..d2e26ef 100644
--- a/include/input.h
+++ b/include/input.h
@@ -454,4 +454,11 @@ extern void DDXRingBell(
     int pitch,
     int duration);
 
+extern int PairDevices(ClientPtr client, 
+                       DeviceIntPtr pointer, 
+                       DeviceIntPtr keyboard);
+
+extern Bool RegisterPairingClient(ClientPtr client);
+extern Bool UnregisterPairingClient(ClientPtr client);
+
 #endif /* INPUT_H */
commit f6c3b9fa97ccf85e96f15435d564a1c261e40532
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Feb 15 13:51:20 2007 +1030

    xfree86: mouse and keyboard hotplugging support. New mouse devices will get
             new cursors,  keyboard devices use VCP's focus until paired.

diff --git a/dix/events.c b/dix/events.c
index a931e41..57a356d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2043,7 +2043,7 @@ XYToWindow(int x, int y)
     return spriteTrace[spriteTraceGood-1];
 }
 
-static Bool
+Bool
 CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
     WindowPtr prevSpriteWin;
@@ -2190,61 +2190,65 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
 void
 DefineInitialRootWindow(register WindowPtr win)
 {
-    register ScreenPtr pScreen = win->drawable.pScreen;
-    SpritePtr pSprite;
     DeviceIntPtr pDev = inputInfo.devices;
 
+#ifdef XEVIE
+    xeviewin = win;
+#endif
+    ROOT = win;
+
     while (pDev)
     {
         if (DevHasCursor(pDev))
-        {
-            pSprite = pDev->pSprite;
+            InitializeSprite(pDev, win);
+        pDev = pDev->next;
+    }
+}
 
-            pSprite->hotPhys.pScreen = pScreen;
-            pSprite->hotPhys.x = pScreen->width / 2;
-            pSprite->hotPhys.y = pScreen->height / 2;
-            pSprite->hot = pSprite->hotPhys;
-            pSprite->hotLimits.x2 = pScreen->width;
-            pSprite->hotLimits.y2 = pScreen->height;
-#ifdef XEVIE
-            xeviewin =
-#endif
-                pSprite->win = win;
-            pSprite->current = wCursor (win);
-            pSprite->current->refcnt++;
-            spriteTraceGood = 1;
-            ROOT = win;
-            (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
-                                       &pSprite->hotLimits, &pSprite->physLimits);
-            pSprite->confined = FALSE;
-
-            (*pScreen->ConstrainCursor) (pDev, pScreen,
-                                         &pSprite->physLimits);
-            (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
-                                           pSprite->hot.y,
-                                           FALSE); 
-            (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
+void 
+InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
+{
+    SpritePtr pSprite;
+    ScreenPtr pScreen = pWin->drawable.pScreen;
 
+    pSprite = pDev->pSprite;
+    pSprite->hotPhys.pScreen = pScreen;
+    pSprite->hotPhys.x = pScreen->width / 2;
+    pSprite->hotPhys.y = pScreen->height / 2;
+    pSprite->hot = pSprite->hotPhys;
+    pSprite->hotLimits.x2 = pScreen->width;
+    pSprite->hotLimits.y2 = pScreen->height;
+    pSprite->win = pWin;
+    pSprite->current = wCursor (pWin);
+    pSprite->current->refcnt++;
+
+    (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
+                               &pSprite->hotLimits, &pSprite->physLimits);
+    pSprite->confined = FALSE;
+
+    (*pScreen->ConstrainCursor) (pDev, pScreen,
+                                 &pSprite->physLimits);
+    (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
+                                   pSprite->hot.y,
+                                   FALSE); 
+    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
 #ifdef PANORAMIX
-            if(!noPanoramiXExtension) {
-                pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
-                pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
-                pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
-                pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
-                pSprite->physLimits = pSprite->hotLimits;
-                pSprite->confineWin = NullWindow;
+    if(!noPanoramiXExtension) {
+        pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
+        pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
+        pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
+        pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
+        pSprite->physLimits = pSprite->hotLimits;
+        pSprite->confineWin = NullWindow;
 #ifdef SHAPE
-                pSprite->hotShape = NullRegion;
+        pSprite->hotShape = NullRegion;
 #endif
-                pSprite->screen = pScreen;
-                /* gotta UNINIT these someplace */
-                REGION_NULL(pScreen, &pSprite->Reg1);
-                REGION_NULL(pScreen, &pSprite->Reg2);
-            }
-#endif
-        }
-        pDev = pDev->next;
+        pSprite->screen = pScreen;
+        /* gotta UNINIT these someplace */
+        REGION_NULL(pScreen, &pSprite->Reg1);
+        REGION_NULL(pScreen, &pSprite->Reg2);
     }
+#endif
 }
 
 /*
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 6218b35..c2ea108 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -129,7 +129,6 @@ xf86ProcessCommonOptions(LocalDevicePtr local,
         xf86SetBoolOption(list, "CorePointer", 0) ||
         xf86SetBoolOption(list, "CoreKeyboard", 0)) {
         local->flags |= XI86_ALWAYS_CORE;
-        local->flags |= XI86_SHARED_POINTER;
         xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name);
     }
 
@@ -378,6 +377,16 @@ NewInputDeviceRequest (InputOption *options)
         }
     }
 
+    if (!drv) {
+        xf86Msg(X_ERROR, "No input driver specified (ignoring)\n");
+        return BadMatch;
+    }
+
+    if (!idev->identifier) {
+        xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n");
+        return BadMatch;
+    }
+
     if (!drv->PreInit) {
         xf86Msg(X_ERROR,
                 "Input driver `%s' has no PreInit function (ignoring)\n",
@@ -407,10 +416,14 @@ NewInputDeviceRequest (InputOption *options)
     xf86ActivateDevice(pInfo);
 
     dev = pInfo->dev;
-    dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success);
+    ActivateDevice(dev);
     if (dev->inited && dev->startup)
         EnableDevice(dev);
 
+    /* send enter/leave event, update sprite window */
+    InitializeSprite(dev, GetCurrentRootWindow());
+    CheckMotion(NULL, dev);
+
     return Success;
 }
 
diff --git a/include/dix.h b/include/dix.h
index 8e34211..1c6b163 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -494,6 +494,10 @@ extern int DeliverDeviceEvents(
 extern void DefineInitialRootWindow(
     WindowPtr /* win */);
 
+extern void InitializeSprite(
+    DeviceIntPtr /* pDev */,
+    WindowPtr    /* pWin */);
+
 extern void WindowHasNewCursor(
     WindowPtr /* pWin */);
 
@@ -578,6 +582,10 @@ extern int DeliverEvents(
     int /*count*/,
     WindowPtr /*otherParent*/);
 
+extern Bool
+CheckMotion(
+    xEvent* /* xE */, 
+    DeviceIntPtr /* pDev */);
 
 extern void WriteEventsToClient(
     ClientPtr /*pClient*/,
commit 25104ed2e6050f86691104b34eeaf3147eb83c4a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Feb 14 11:26:53 2007 +1030

    dix:    fix typo in condition.

diff --git a/dix/getevents.c b/dix/getevents.c
index ccaa232..a8d9ec3 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -515,7 +515,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     }
 
     /* Do we need to send a DeviceValuator event? */
-    if (!coreOnly & sendValuators) {
+    if (!coreOnly && sendValuators) {
         if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
             num_valuators = MAX_VALUATOR_EVENTS * 6;
         num_events += ((num_valuators - 1) / 6) + 1;
commit 33ef546b942977bb2573156eaba5269350d16f99
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Feb 14 11:18:43 2007 +1030

    dix:    Clean up GetPointerEvents. If pDev == inputInfo.pointer, assume that
            we do not want Xi events.
    
    mi:     Remove POINTER_CORE_ONLY flag.

diff --git a/dix/getevents.c b/dix/getevents.c
index f9e6962..ccaa232 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -482,8 +482,6 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
  * The DDX is responsible for allocating the event structure in the first
  * place via GetMaximumEventsNum(), and for freeing it.
  *
- * If flag has POINTER_CORE_ONLY set, no XI or valuator event will be
- * generated.
  */
 _X_EXPORT int
 GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
@@ -497,7 +495,8 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
     DeviceIntPtr pointer = NULL;
     int x = 0, y = 0;
-    Bool coreOnly = (flags & POINTER_CORE_ONLY);
+    /* The core pointer must not send Xi events. */
+    Bool coreOnly = (pDev == inputInfo.pointer);
 
     /* Sanity checks. */
     if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
@@ -530,10 +529,6 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
 
     ms = GetTimeInMillis();
 
-    kbp = (deviceKeyButtonPointer *) events;
-    kbp->time = ms;
-    kbp->deviceid = pDev->id;
-
     if (!pDev->coreEvents || pDev->isMPDev)
         pointer = pDev;
     else 
@@ -598,22 +593,27 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     pDev->valuator->lastx = x;
     pDev->valuator->lasty = y;
 
-    if (type == MotionNotify) {
-        kbp->type = DeviceMotionNotify;
-    }
-    else {
-        if (type == ButtonPress)
-            kbp->type = DeviceButtonPress;
-        else if (type == ButtonRelease)
-            kbp->type = DeviceButtonRelease;
-        kbp->detail = pDev->button->map[buttons];
-    }
-
-    kbp->root_x = x;
-    kbp->root_y = y;
-
+    /* create Xi event */
     if (!coreOnly)
     {
+        kbp = (deviceKeyButtonPointer *) events;
+        kbp->time = ms;
+        kbp->deviceid = pDev->id;
+
+        if (type == MotionNotify) {
+            kbp->type = DeviceMotionNotify;
+        }
+        else {
+            if (type == ButtonPress)
+                kbp->type = DeviceButtonPress;
+            else if (type == ButtonRelease)
+                kbp->type = DeviceButtonRelease;
+            kbp->detail = pDev->button->map[buttons];
+        }
+
+        kbp->root_x = x;
+        kbp->root_y = y;
+
         events++;
         if (sendValuators) {
             kbp->deviceid |= MORE_EVENTS;
diff --git a/include/input.h b/include/input.h
index f7d12cb..96a28a5 100644
--- a/include/input.h
+++ b/include/input.h
@@ -62,7 +62,6 @@ SOFTWARE.
 #define POINTER_RELATIVE (1 << 1)
 #define POINTER_ABSOLUTE (1 << 2)
 #define POINTER_ACCELERATE (1 << 3)
-#define POINTER_CORE_ONLY (1 << 4) /* do not generate XI event */
 
 #define MAP_LENGTH	256
 #define DOWN_LENGTH	32	/* 256/8 => number of bytes to hold 256 bits */
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 432333d..ed82fcd 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -543,7 +543,6 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
     xEvent* events;
     int i, nevents;
     int valuators[2];
-    int flags;
     miPointerPtr pPointer = MIPOINTER(pDev);
     SetupScreen(pScreen);
 
@@ -571,15 +570,8 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
 	return;
     }
 
-    flags = POINTER_ABSOLUTE;
-
-    /* If called from ProcWarpCursor, pDev is the VCP and we must not generate
-      an XI event. */
-    if (pDev == inputInfo.pointer)
-        flags |= POINTER_CORE_ONLY;
-
     nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
-                               flags, 0, 2, valuators);
+                               POINTER_ABSOLUTE, 0, 2, valuators);
 
     for (i = 0; i < nevents; i++)
         mieqEnqueue(pDev, &events[i]);
commit 7cd73b00a29469d37a7f526cc9b35cc927a13ae2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Feb 5 14:48:48 2007 +1030

    dix:    If POINTER_CORE_ONLY is set, GetPointerEvents() only creates a core event
    
    mi:	fix: Create motion event in miPointerMoved

diff --git a/dix/getevents.c b/dix/getevents.c
index 8eaacf1..f9e6962 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -481,6 +481,9 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
  * 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.
+ *
+ * If flag has POINTER_CORE_ONLY set, no XI or valuator event will be
+ * generated.
  */
 _X_EXPORT int
 GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
@@ -494,6 +497,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
     DeviceIntPtr pointer = NULL;
     int x = 0, y = 0;
+    Bool coreOnly = (flags & POINTER_CORE_ONLY);
 
     /* Sanity checks. */
     if (type != MotionNotify && type != ButtonPress && type != ButtonRelease)
@@ -502,7 +506,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
         return 0;
 
-    if (pDev->coreEvents || pDev->isMPDev)
+    if (!coreOnly && (pDev->coreEvents || pDev->isMPDev))
         num_events = 2;
     else
         num_events = 1;
@@ -512,7 +516,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     }
 
     /* Do we need to send a DeviceValuator event? */
-    if (sendValuators) {
+    if (!coreOnly & sendValuators) {
         if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS)
             num_valuators = MAX_VALUATOR_EVENTS * 6;
         num_events += ((num_valuators - 1) / 6) + 1;
@@ -608,16 +612,19 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     kbp->root_x = x;
     kbp->root_y = y;
 
-    events++;
-    if (sendValuators) {
-        kbp->deviceid |= MORE_EVENTS;
-        clipValuators(pDev, first_valuator, num_valuators, valuators);
-        events = getValuatorEvents(events, pDev, first_valuator,
-                                   num_valuators, valuators);
+    if (!coreOnly)
+    {
+        events++;
+        if (sendValuators) {
+            kbp->deviceid |= MORE_EVENTS;
+            clipValuators(pDev, first_valuator, num_valuators, valuators);
+            events = getValuatorEvents(events, pDev, first_valuator,
+                    num_valuators, valuators);
+        }
     }
 
     /* MPX devices always send core events */
-    if (pDev->coreEvents || pDev->isMPDev) {
+    if (coreOnly || pDev->coreEvents || pDev->isMPDev) {
         events->u.u.type = type;
         events->u.keyButtonPointer.time = ms;
         events->u.keyButtonPointer.rootX = x;
diff --git a/include/input.h b/include/input.h
index 96a28a5..f7d12cb 100644
--- a/include/input.h
+++ b/include/input.h
@@ -62,6 +62,7 @@ SOFTWARE.
 #define POINTER_RELATIVE (1 << 1)
 #define POINTER_ABSOLUTE (1 << 2)
 #define POINTER_ACCELERATE (1 << 3)
+#define POINTER_CORE_ONLY (1 << 4) /* do not generate XI event */
 
 #define MAP_LENGTH	256
 #define DOWN_LENGTH	32	/* 256/8 => number of bytes to hold 256 bits */
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 1474cb9..432333d 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -540,6 +540,10 @@ void
 miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
                      unsigned long time)
 {
+    xEvent* events;
+    int i, nevents;
+    int valuators[2];
+    int flags;
     miPointerPtr pPointer = MIPOINTER(pDev);
     SetupScreen(pScreen);
 
@@ -556,4 +560,29 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
     pPointer->x = x;
     pPointer->y = y;
     pPointer->pScreen = pScreen;
+
+    /* generate event here */
+    valuators[0] = x;
+    valuators[1] = y;
+    events = (xEvent*)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
+    if (!events)
+    {
+        FatalError("Could not allocate event store.\n");
+	return;
+    }
+
+    flags = POINTER_ABSOLUTE;
+
+    /* If called from ProcWarpCursor, pDev is the VCP and we must not generate
+      an XI event. */
+    if (pDev == inputInfo.pointer)
+        flags |= POINTER_CORE_ONLY;
+
+    nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
+                               flags, 0, 2, valuators);
+
+    for (i = 0; i < nevents; i++)
+        mieqEnqueue(pDev, &events[i]);
+
+    xfree(events);
 }
commit a309c936bb79e2fea04a96ce33c7da99ed902484
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Feb 5 11:38:44 2007 +1030

    xkb:	Daniel's patch to stop evdev keyboard segfaults.
    
    mi:	Remove quickfix from ba547d4f6a2707f51f0d826389d2d418fb62367a

diff --git a/mi/mieq.c b/mi/mieq.c
index 478b61e..6ed5ef3 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -244,14 +244,6 @@ mieqProcessInputEvents()
                 dev = e->pDev;
             }
 
-            /* FIXME: Keyboard extension devices do not have devPrivates
-             * initialized, resulting in a segfault in XkbHandleActions. */
-            if (e->event[0].u.u.type == DeviceKeyPress || 
-                    e->event[0].u.u.type == DeviceKeyRelease ||
-                    e->event[0].u.u.type == KeyPress ||
-                    e->event[0].u.u.type == KeyRelease)
-                e->pDev = dev = inputInfo.keyboard;
-
             /* 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 
diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
index 400306a..e24c1f0 100644
--- a/xkb/xkbUtils.c
+++ b/xkb/xkbUtils.c
@@ -1220,7 +1220,8 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies)
                     tmp = xalloc(src->max_key_code + 1);
                 if (!tmp)
                     return FALSE;
-                dst->map->syms = tmp;
+                /*dst->map->syms = tmp;*/
+                dst->map->modmap = tmp;
             }
             memcpy(dst->map->modmap, src->map->modmap, src->max_key_code + 1);
         }
commit 4aaaa70d1b52346213fad46777c006a93c4ece5d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jan 29 18:23:24 2007 +1030

    Xi:	Adding ChangePointerKeyboardPairing request
    	Adding PointerKeyboardPairingChanged event
    	Correct error values for XWarpDevicePointer
    
    dix:	Adding device argument to SendMappingNotify
    	Adding spriteOwner flag to devices

diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 9e7d1c4..9000030 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -19,6 +19,8 @@ libXi_la_SOURCES =	\
 	chgprop.h \
 	chgptr.c \
 	chgptr.h \
+	chpkpair.c \
+	chpkpair.h \ 
 	closedev.c \
 	closedev.h \
 	devbell.c \
diff --git a/Xi/chpkpair.c b/Xi/chpkpair.c
new file mode 100644
index 0000000..b862417
--- /dev/null
+++ b/Xi/chpkpair.c
@@ -0,0 +1,100 @@
+/*
+
+Copyright 2006 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 change pairing between pointer and keyboard 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 "chpkpair.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to change the pairing of a pointer with a
+ * a keyboard.
+ *
+ */
+
+int SProcXChangePointerKeyboardPairing(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(xChangePointerKeyboardPairingReq);
+    swaps(&stuff->length, n);
+    return (ProcXChangePointerKeyboardPairing(client));
+}
+
+int
+ProcXChangePointerKeyboardPairing(register ClientPtr client)
+{
+    DeviceIntPtr pPointer, pKeyboard;
+
+    REQUEST(xChangePointerKeyboardPairingReq);
+    REQUEST_SIZE_MATCH(xChangePointerKeyboardPairingReq);
+
+    pPointer = LookupDeviceIntRec(stuff->pointer);
+    if (pPointer == NULL)
+    {
+        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing, 
+                stuff->pointer, BadDevice); 
+        return Success;
+    }
+
+    pKeyboard = LookupDeviceIntRec(stuff->keyboard);
+    if (pKeyboard == NULL)
+    {
+        SendErrorToClient(client, IReqCode, X_ChangePointerKeyboardPairing, 
+                stuff->keyboard, BadDevice); 
+        return Success;
+    }
+
+    pKeyboard->pSprite = pPointer->pSprite;
+
+    /* TODO: generate event here... */
+    return Success;
+}
diff --git a/Xi/chpkpair.h b/Xi/chpkpair.h
new file mode 100644
index 0000000..1acf549
--- /dev/null
+++ b/Xi/chpkpair.h
@@ -0,0 +1,40 @@
+/************************************************************
+
+Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au>
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the above listed
+copyright holder(s) not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef CHPKPAIR_H
+#define CHPKPAIR_H 1
+
+int SProcXChangePointerKeyboardPairing(ClientPtr	/* client */
+    );
+
+int ProcXChangePointerKeyboardPairing(ClientPtr	/* client */
+    );
+
+#endif /* WARPDEVP_H */
+
diff --git a/Xi/exglobals.h b/Xi/exglobals.h
index bc4a60d..811375e 100644
--- a/Xi/exglobals.h
+++ b/Xi/exglobals.h
@@ -52,6 +52,9 @@ extern Mask DeviceOwnerGrabButtonMask;
 extern Mask DeviceButtonGrabMask;
 extern Mask DeviceButtonMotionMask;
 extern Mask DevicePresenceNotifyMask;
+extern Mask DeviceEnterWindowMask;
+extern Mask DeviceLeaveWindowMask;
+extern Mask PointerKeyboardPairingChangedNotifyMask;
 extern Mask PropagateMask[];
 
 extern int DeviceValuator;
@@ -72,6 +75,7 @@ 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 8948e6c..a08ec77 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -80,6 +80,7 @@ SOFTWARE.
 #include "chgkbd.h"
 #include "chgprop.h"
 #include "chgptr.h"
+#include "chpkpair.h"
 #include "closedev.h"
 #include "devbell.h"
 #include "getbmap.h"
@@ -172,6 +173,7 @@ Mask DeviceButtonMotionMask;
 Mask DevicePresenceNotifyMask;
 Mask DeviceEnterWindowMask;
 Mask DeviceLeaveWindowMask;
+Mask PointerKeyboardPairingChangedMask;
 
 int DeviceValuator;
 int DeviceKeyPress;
@@ -191,6 +193,7 @@ int ChangeDeviceNotify;
 int DevicePresenceNotify;
 int DeviceEnterNotify;
 int DeviceLeaveNotify;
+int PointerKeyboardPairingChangedNotify;
 
 int RT_INPUTCLIENT;
 
@@ -257,6 +260,7 @@ XInputExtensionInit(void)
 	EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
 	EventSwapVector[DeviceEnterNotify] = SEventIDispatch;
 	EventSwapVector[DeviceLeaveNotify] = SEventIDispatch;
+	EventSwapVector[PointerKeyboardPairingChangedNotify] = SEventIDispatch;
     } else {
 	FatalError("IExtensionInit: AddExtensions failed\n");
     }
@@ -349,6 +353,8 @@ ProcIDispatch(register ClientPtr client)
         return (ProcXWarpDevicePointer(client));
     else if (stuff->data == X_ChangeDeviceCursor)
         return (ProcXChangeDeviceCursor(client));
+    else if (stuff->data == X_ChangePointerKeyboardPairing)
+        return (ProcXChangePointerKeyboardPairing(client));
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -444,6 +450,8 @@ SProcIDispatch(register ClientPtr client)
 	return (SProcXWarpDevicePointer(client));
     else if (stuff->data == X_ChangeDeviceCursor)
         return (SProcXChangeDeviceCursor(client));
+    else if (stuff->data == X_ChangePointerKeyboardPairing)
+        return (SProcXChangePointerKeyboardPairing(client));
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -578,6 +586,8 @@ SEventIDispatch(xEvent * from, xEvent * to)
         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");
     }
@@ -708,6 +718,16 @@ void SDeviceLeaveNotifyEvent (deviceLeaveNotify *from, deviceLeaveNotify *to)
     swaps(&to->eventY, n);
 }
 
+void SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify *from, 
+                                                pairingChangedNotify *to)
+{
+    register char n;
+
+    *to = *from;
+    swaps(&to->sequenceNumber, n);
+    swapl(&to->time, n);
+}
+
 /************************************************************************
  *
  * This function sets up extension event types and masks.
@@ -737,6 +757,7 @@ FixExtensionEvents(ExtensionEntry * extEntry)
     DevicePresenceNotify = DeviceButtonStateNotify + 1;
     DeviceEnterNotify = DevicePresenceNotify + 1;
     DeviceLeaveNotify = DeviceEnterNotify + 1;
+    PointerKeyboardPairingChangedNotify = DeviceLeaveNotify + 1;
 
     event_base[KeyClass] = DeviceKeyPress;
     event_base[ButtonClass] = DeviceButtonPress;
@@ -821,6 +842,11 @@ FixExtensionEvents(ExtensionEntry * extEntry)
     SetMaskForExtEvent(DeviceLeaveWindowMask, DeviceLeaveNotify);
     AllowPropagateSuppress(DeviceLeaveWindowMask);
 
+    PointerKeyboardPairingChangedMask = GetNextExtEventMask();
+    SetMaskForExtEvent(PointerKeyboardPairingChangedMask, 
+            PointerKeyboardPairingChangedNotify);
+    AllowPropagateSuppress(PointerKeyboardPairingChangedMask);
+
     SetEventInfo(0, _noExtensionEvent);
 }
 
@@ -864,6 +890,7 @@ RestoreExtensionEvents(void)
     DevicePresenceNotify = 14;
     DeviceEnterNotify = 15;
     DeviceLeaveNotify = 16;
+    PointerKeyboardPairingChangedNotify = 17;
 
     BadDevice = 0;
     BadEvent = 1;
@@ -904,6 +931,7 @@ IResetProc(ExtensionEntry * unused)
     EventSwapVector[DevicePresenceNotify] = NotImplemented;
     EventSwapVector[DeviceEnterNotify] = NotImplemented;
     EventSwapVector[DeviceLeaveNotify] = NotImplemented;
+    EventSwapVector[PointerKeyboardPairingChangedNotify] = NotImplemented;
     RestoreExtensionEvents();
 }
 
@@ -923,17 +951,17 @@ AssignTypeAndName(DeviceIntPtr dev, Atom type, char *name)
 
 /***********************************************************************
  *
- * Returns true if a device may require a pointer (is not a keyboard).
+ * Returns true if a device may require a pointer (is a mouse).
+ * FIXME: Other devices should be able to get a pointer too...
  *
  */
 _X_EXPORT Bool
-MayNeedPointer(DeviceIntPtr dev)
+IsPointerDevice(DeviceIntPtr dev)
 {
-    /* return false if device is a keyboard */
-    if (dev_type[0].type == dev->type)
-        return FALSE;
+    if (dev_type[1].type == dev->type)
+        return TRUE;
   
-    return TRUE;
+    return FALSE;
 }
 
 /***********************************************************************
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
index 2b558d1..a9ddb0b 100644
--- a/Xi/warpdevp.c
+++ b/Xi/warpdevp.c
@@ -85,7 +85,8 @@ ProcXWarpDevicePointer(register ClientPtr client)
 
     pDev = LookupDeviceIntRec(stuff->deviceid);
     if (pDev == NULL) {
-        SendErrorToClient(client, IReqCode, X_WarpDevicePointer, 0,
+        SendErrorToClient(client, IReqCode, X_WarpDevicePointer,
+                stuff->deviceid,
                 BadDevice); 
         return Success;
     }
diff --git a/dix/devices.c b/dix/devices.c
index 41e8667..bc7ca89 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1072,8 +1072,8 @@ InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms,
 }
 
 _X_EXPORT void
-SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, 
-                  ClientPtr client)
+SendMappingNotify(DeviceIntPtr pDev, unsigned request, unsigned firstKeyCode,
+        unsigned count, ClientPtr client)
 {
     int i;
     xEvent event;
@@ -1088,8 +1088,7 @@ SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count,
 #ifdef XKB
     if (!noXkbExtension &&
 	((request == MappingKeyboard) || (request == MappingModifier))) {
-	XkbApplyMappingChange(inputInfo.keyboard,request,firstKeyCode,count,
-									client);
+	XkbApplyMappingChange(pDev,request,firstKeyCode,count, client);
     }
 #endif
 
@@ -1253,7 +1252,7 @@ ProcSetModifierMapping(ClientPtr client)
                                        stuff->numKeyPerModifier);
 
     /* FIXME: Send mapping notifies for all the extended devices as well. */
-    SendMappingNotify(MappingModifier, 0, 0, client);
+    SendMappingNotify(inputInfo.keyboard, MappingModifier, 0, 0, client);
     WriteReplyToClient(client, sizeof(xSetModifierMappingReply), &rep);
     return client->noClientException;
 }
@@ -1324,8 +1323,8 @@ ProcChangeKeyboardMapping(ClientPtr client)
     }
 
     /* FIXME: Send mapping notifies for all the extended devices as well. */
-    SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes,
-                      client);
+    SendMappingNotify(inputInfo.keyboard, MappingKeyboard,
+            stuff->firstKeyCode, stuff->keyCodes, client);
     return client->noClientException;
 }
 
@@ -1393,7 +1392,7 @@ ProcSetPointerMapping(ClientPtr client)
     }
 
     /* FIXME: Send mapping notifies for all the extended devices as well. */
-    SendMappingNotify(MappingPointer, 0, 0, client);
+    SendMappingNotify(inputInfo.pointer, MappingPointer, 0, 0, client);
     WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
     return Success;
 }
diff --git a/dix/events.c b/dix/events.c
index 0380ad1..a931e41 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -242,15 +242,13 @@ static int spriteTraceGood;
 
 
 /** 
- * True for the core pointer and any MPX device. 
- * False for any other device (including keyboards).
- * Does ID checking for sane range as well.
+ * True if device owns a cursor, false if device shares a cursor sprite with
+ * another device.
  */
 _X_EXPORT Bool
 DevHasCursor(DeviceIntPtr pDev) 
 {
-    return (pDev == inputInfo.pointer || 
-            (pDev->isMPDev && pDev->id < MAX_DEVICES)); 
+    return pDev->spriteOwner;
 }
 
 #ifdef XEVIE
@@ -4225,9 +4223,11 @@ InitSprite(DeviceIntPtr pDev, Bool hasCursor)
         pSprite->confined = FALSE;
 
         pDev->pSprite = pSprite;
+        pDev->spriteOwner = TRUE;
     } else
     {
         pDev->pSprite = inputInfo.pointer->pSprite;
+        pDev->spriteOwner = FALSE;
     }
 }
 
diff --git a/dix/getevents.c b/dix/getevents.c
index 7e0b63f..8eaacf1 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -724,7 +724,7 @@ SwitchCoreKeyboard(DeviceIntPtr pDev)
         }
 #endif
 
-        SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
+        SendMappingNotify(pDev, MappingKeyboard, ckeyc->curKeySyms.minKeyCode,
                           (ckeyc->curKeySyms.maxKeyCode -
                            ckeyc->curKeySyms.minKeyCode),
                           serverClient);
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index dc07b3f..6218b35 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -171,11 +171,24 @@ xf86ActivateDevice(LocalDevicePtr local)
         dev->public.devicePrivate = (pointer) local;
         local->dev = dev;      
         
-        dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
-        dev->isMPDev = 
-            MayNeedPointer(dev) && !(local->flags & XI86_SHARED_POINTER);
-        InitSprite(dev, dev->isMPDev);
+        dev->coreEvents = local->flags & XI86_ALWAYS_CORE; 
+        dev->isMPDev = !(local->flags & XI86_SHARED_POINTER);
+
+#ifdef XKB
+        if (!IsPointerDevice(dev))
+        {
+        /* FIXME: that's not the nice way to do it. XKB wraps the previously
+         * set procs, so if we don't have them here, our event will disappear
+         * in a black hole.*/
+            dev->public.processInputProc = CoreProcessKeyboardEvent;
+            dev->public.realInputProc = CoreProcessKeyboardEvent;
+            if (!noXkbExtension)
+                XkbSetExtension(dev, ProcessKeyboardEvent);
+        }
+#endif
 
+        /* Only create a new sprite if it's a non-shared pointer */
+        InitSprite(dev, IsPointerDevice(dev) && dev->isMPDev);
         RegisterOtherDevice(dev);
 
         if (serverGeneration == 1) 
diff --git a/include/extinit.h b/include/extinit.h
index 6cf7bf7..d7aa541 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -121,6 +121,12 @@ SDeviceLeaveNotifyEvent (
         deviceLeaveNotify * /* to */
         );
 
+void 
+SPointerKeyboardPairingChangedNotifyEvent (
+        pairingChangedNotify * /* from */,
+        pairingChangedNotify * /* to */
+        );
+
 void
 FixExtensionEvents (
 	ExtensionEntry 	*      /* extEntry */
@@ -143,7 +149,7 @@ AssignTypeAndName (
 	char *                 /* name */
 	);
 
-Bool MayNeedPointer(
+Bool IsPointerDevice(
         DeviceIntPtr            /* dev */
         );
 
diff --git a/include/input.h b/include/input.h
index a1c21f8..96a28a5 100644
--- a/include/input.h
+++ b/include/input.h
@@ -323,6 +323,7 @@ extern Bool InitKeyboardDeviceStruct(
     KbdCtrlProcPtr /*controlProc*/);
 
 extern void SendMappingNotify(
+    DeviceIntPtr /* pDev */,
     unsigned int /*request*/,
     unsigned int /*firstKeyCode*/,
     unsigned int /*count*/,
diff --git a/include/inputstr.h b/include/inputstr.h
index cc3280d..c4a2d18 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -178,7 +178,7 @@ typedef struct _ButtonClassRec {
 } ButtonClassRec, *ButtonClassPtr;
 
 typedef struct _FocusClassRec {
-    WindowPtr	win;
+    WindowPtr	win; /* May be set to a int constant (e.g. PointerRootWin)! */
     int		revert;
     TimeStamp	time;
     WindowPtr	*trace;
@@ -355,7 +355,12 @@ typedef struct _DeviceIntRec {
     int			nPrivates;
     DeviceUnwrapProc    unwrapProc;
     Bool                isMPDev;           /* TRUE if multipointer device */
+    /* Each devices has a sprite. However, keyboards and shared pointers do
+       not in fact own a sprite but rather have their pointer set to the
+       sprite of another device. pSprite always has to point to a valid
+       sprite. spriteOwner indicates whether it is the device's sprite. */
     SpritePtr           pSprite;        /* sprite information */
+    Bool                spriteOwner;    /* FALSE if shared sprite, see above*/
 } DeviceIntRec;
 
 typedef struct {
commit f3418b52dcf2ab4982504856ab9fae3e726ee6d2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jan 29 16:10:03 2007 +1030

    mi:     Fix cursor rendering issues.

diff --git a/mi/misprite.c b/mi/misprite.c
index 70dda1c..8639c56 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -137,6 +137,8 @@ _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
 
 static void miSpriteRemoveCursor(DeviceIntPtr pDev, 
                                  ScreenPtr pScreen); 
+static void miSpriteSaveUnderCursor(DeviceIntPtr pDev,
+                                 ScreenPtr pScreen);
 static void miSpriteRestoreCursor(DeviceIntPtr pDev,
                                  ScreenPtr pScreen);
 
@@ -524,6 +526,18 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
             if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
             {
                 SPRITE_DEBUG (("BlockHandler restore\n"));
+                miSpriteSaveUnderCursor (pDev, pScreen);
+            }
+        }
+    }
+    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+    {
+        if (DevHasCursor(pDev))
+        {
+            pCursorInfo = &pPriv->pDevCursors[pDev->id];
+            if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
+            {
+                SPRITE_DEBUG (("BlockHandler restore\n"));
                 miSpriteRestoreCursor (pDev, pScreen);
             }
         }
@@ -891,14 +905,15 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
 	else
 #endif
 	{
-	    SPRITE_DEBUG (("SetCursor remove\n"));
+	    SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id));
 	    miSpriteRemoveCursor (pDev, pScreen);
 	}
     }
 
     if (!pPointer->isUp && pPointer->pCursor)
     {
-	SPRITE_DEBUG (("SetCursor restore\n"));
+	SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id));
+        miSpriteSaveUnderCursor(pDev, pScreen);
 	miSpriteRestoreCursor (pDev, pScreen);
     }
 
@@ -944,6 +959,7 @@ miSpriteRemoveCursor (pDev, pScreen)
 
     miSpriteIsUpFALSE (pCursorInfo, pScreen, pScreenPriv);
     pCursorInfo->pCacheWin = NullWindow;
+    miSpriteDisableDamage(pScreen, pScreenPriv);
     if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDev,
                                          pScreen,
 					 pCursorInfo->saved.x1,
@@ -955,16 +971,17 @@ miSpriteRemoveCursor (pDev, pScreen)
     {
 	miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
     }
+    miSpriteEnableDamage(pScreen, pScreenPriv);
     DamageDrawInternal (pScreen, FALSE);
 }
 
 /*
- * Called from the block handler, restores the cursor
+ * Called from the block handler, saves area under cursor
  * before waiting for something to do.
  */
 
-static void
-miSpriteRestoreCursor (pDev, pScreen)
+static void 
+miSpriteSaveUnderCursor(pDev, pScreen)
     DeviceIntPtr pDev;
     ScreenPtr	pScreen;
 {
@@ -985,25 +1002,61 @@ miSpriteRestoreCursor (pDev, pScreen)
 
     x = pCursorInfo->x - (int)pCursor->bits->xhot;
     y = pCursorInfo->y - (int)pCursor->bits->yhot;
-    if ((*pScreenPriv->funcs->SaveUnderCursor) (pDev,
+    miSpriteDisableDamage(pScreen, pScreenPriv);
+
+    (*pScreenPriv->funcs->SaveUnderCursor) (pDev,
                                       pScreen,
 				      pCursorInfo->saved.x1,
 				      pCursorInfo->saved.y1,
                                       pCursorInfo->saved.x2 -
                                       pCursorInfo->saved.x1,
                                       pCursorInfo->saved.y2 -
-                                      pCursorInfo->saved.y1))
+                                      pCursorInfo->saved.y1);
+    SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
+    miSpriteEnableDamage(pScreen, pScreenPriv);
+    DamageDrawInternal (pScreen, FALSE);
+}
+
+
+/*
+ * Called from the block handler, restores the cursor
+ * before waiting for something to do.
+ */
+
+static void
+miSpriteRestoreCursor (pDev, pScreen)
+    DeviceIntPtr pDev;
+    ScreenPtr	pScreen;
+{
+    miSpriteScreenPtr   pScreenPriv;
+    int			x, y;
+    CursorPtr		pCursor;
+    miCursorInfoPtr     pCursorInfo;
+
+    DamageDrawInternal (pScreen, TRUE);
+    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+    pCursorInfo = pScreenPriv->cp;
+
+    if (DevHasCursor(pDev))
+        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+
+    miSpriteComputeSaved (pDev, pScreen);
+    pCursor = pCursorInfo->pCursor;
+
+    x = pCursorInfo->x - (int)pCursor->bits->xhot;
+    y = pCursorInfo->y - (int)pCursor->bits->yhot;
+    miSpriteDisableDamage(pScreen, pScreenPriv);
+    SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
+    if (pCursorInfo->checkPixels)
+        miSpriteFindColors (pCursorInfo, pScreen);
+    if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen, 
+                pCursor, x, y,
+                pCursorInfo->colors[SOURCE_COLOR].pixel,
+                pCursorInfo->colors[MASK_COLOR].pixel))
     {
-	if (pCursorInfo->checkPixels)
-	    miSpriteFindColors (pCursorInfo, pScreen);
-	if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen, 
-                                  pCursor, x, y,
-				  pCursorInfo->colors[SOURCE_COLOR].pixel,
-				  pCursorInfo->colors[MASK_COLOR].pixel))
-	{
-	    miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
-	}
+        miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
     }
+    miSpriteEnableDamage(pScreen, pScreenPriv);
     DamageDrawInternal (pScreen, FALSE);
 }
 
diff --git a/mi/mispritest.h b/mi/mispritest.h
index 39875e0..8c8cd53 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -95,31 +95,25 @@ typedef struct {
 #define MASK_COLOR	1
 
 static int damageRegister = 0;
-/*
- * FIXME: MPX uses a bug at the moment. The semaphore system in place will
- * call miSpriteIsUpTRUE multiple times and thus DamageUnregister() will never
- * be called in miSpriteIsUpFALSE. 
- * This gets rid of cursor rendering artefacts but I don't know how this
- * affects applications.
- * Without any semaphore system in place DamageRegister will be called twice
- * and segfault.
- */
-#define miSpriteIsUpTRUE(pDevCursor, pScreen, pScreenPriv) if (!pDevCursor->isUp) { \
-    pDevCursor->isUp = TRUE; \
-    if (!damageRegister ) { \
-        DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
-    } \
-    damageRegister++; \
-}
 
-#define miSpriteIsUpFALSE(pDevCursor, pScreen, pScreenPriv) if (pDevCursor->isUp) { \
-    damageRegister--; \
-    if (!damageRegister) { \
-        DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
-    } \
-    pDevCursor->isUp = FALSE; \
+#define miSpriteDisableDamage(pScreen, pScreenPriv) \
+    if (damageRegister) { \
+    DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage);  \
+    damageRegister = 0; \
 }
 
+#define miSpriteEnableDamage(pScreen, pScreenPriv) \
+    if (!damageRegister) {\
+    damageRegister = 1; \
+    DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
+    }
+
+#define miSpriteIsUpTRUE(pDevCursor, pScreen, pScreenPriv) if (!pDevCursor->isUp)  \
+    pDevCursor->isUp = TRUE; 
+
+#define miSpriteIsUpFALSE(pDevCursor, pScreen, pScreenPriv) if (pDevCursor->isUp)  \
+    pDevCursor->isUp = FALSE; 
+
 /*
  * Overlap BoxPtr and Box elements
  */
commit 15a81b6325d359990017b8e9f17ce18a7eff1354
Merge: 3759254... cc3d66d...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Jan 28 17:18:57 2007 +1030

    Merge branch 'master'

diff --cc dix/getevents.c
index f37737c,6f364ec..7e0b63f
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -549,11 -542,10 +549,7 @@@ GetPointerEvents(xEvent *events, Device
              y = valuators[1 - first_valuator];
          }
          else {
- <<<<<<< HEAD/dix/getevents.c
 -            if (pDev->coreEvents)
 -                y = cp->valuator->lasty;
 -            else
 -                y = pDev->valuator->lasty;
 +            y = pointer->valuator->lasty;
- =======
-                 y = pointer->valuator->lasty;
- >>>>>>> ca5ebe3971d8ebcfed00c5ebcd026cdd0ce0c6ba/dix/getevents.c
          }
      }
      else {
commit cc3d66d4a53fee8f1d940bb8c7f032c94b9c25f6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 15 17:50:02 2006 +1030

    o fix minor error in comment for GetPointerEvents()

diff --git a/dix/getevents.c b/dix/getevents.c
index 8b2a44d..6f364ec 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -470,7 +470,7 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
 
 
 /**
- * Generate a series of xEvents (returned in xE) representing pointer
+ * Generate a series of xEvents (returned in events) representing pointer
  * motion, or button presses.  Xi and XKB-aware.
  *
  * events is not NULL-terminated; the return value is the number of events.
commit 3759254c0967ae83bdcbf097d9e8a58733c8e6f9
Merge: ba547d4... ca5ebe3...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Sun Jan 28 17:05:55 2007 +1030

    Merge branch 'master'

diff --cc dix/getevents.c
index 7e0b63f,93fc232..f37737c
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -549,7 -544,7 +549,11 @@@ GetPointerEvents(xEvent *events, Device
              y = valuators[1 - first_valuator];
          }
          else {
++<<<<<<< HEAD/dix/getevents.c
 +            y = pointer->valuator->lasty;
++=======
+                 y = pointer->valuator->lasty;
++>>>>>>> ca5ebe3971d8ebcfed00c5ebcd026cdd0ce0c6ba/dix/getevents.c
          }
      }
      else {
commit ba547d4f6a2707f51f0d826389d2d418fb62367a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Jan 12 14:42:02 2007 +1030

    mi:     Quick fix to stop segfault on non-core keyboards.

diff --git a/dix/cursor.c b/dix/cursor.c
index b58a7bf..cf515c1 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -117,7 +117,6 @@ FreeCursor(pointer value, XID cid)
     ScreenPtr	pscr;
     DeviceIntPtr pDev; 
 
-    MPXDBG("freecursor refcount %d\n", pCurs->refcnt);
     if ( --pCurs->refcnt != 0)
 	return(Success);
 
diff --git a/mi/mieq.c b/mi/mieq.c
index 0744e6c..b336277 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -231,6 +231,14 @@ mieqProcessInputEvents()
                 dev = e->pDev;
             }
 
+            /* FIXME: Keyboard extension devices do not have devPrivates
+             * initialized, resulting in a segfault in XkbHandleActions. */
+            if (e->event[0].u.u.type == DeviceKeyPress || 
+                    e->event[0].u.u.type == DeviceKeyRelease ||
+                    e->event[0].u.u.type == KeyPress ||
+                    e->event[0].u.u.type == KeyRelease)
+                e->pDev = dev = inputInfo.keyboard;
+
             /* 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 
commit 5e2f8dee6331645fcbd2734c43698eb4f9c5b116
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Jan 11 14:05:39 2007 +1030

    mi:	remove core pointer special handling. No event has core pointer as
    	device now.
    
    dix:    zero pSprite memory, stop segfaults on server restart.

diff --git a/dix/events.c b/dix/events.c
index 23fb1ec..0380ad1 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2172,7 +2172,7 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
                 REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2,    xoff, yoff);
 
             /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
-            if ((grab = inputInfo.pointer->grab) && grab->confineTo) {
+            if ((grab = pDev->grab) && grab->confineTo) {
                 if (grab->confineTo->drawable.pScreen 
                         != pSprite->hotPhys.pScreen)
                     pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
@@ -3902,6 +3902,7 @@ ProcGrabPointer(ClientPtr client)
 	    oldCursor = grab->cursor;
 	}
 	tempGrab.cursor = cursor;
+        /* FIXME: refcnt?? */
 	tempGrab.resource = client->clientAsMask;
 	tempGrab.ownerEvents = stuff->ownerEvents;
 	tempGrab.eventMask = stuff->eventMask;
@@ -3958,7 +3959,7 @@ ProcChangeActivePointerGrab(ClientPtr client)
     grab->cursor = newCursor;
     if (newCursor)
 	newCursor->refcnt++;
-    PostNewCursor(inputInfo.pointer);
+    PostNewCursor(device);
     if (oldCursor)
 	FreeCursor(oldCursor, (Cursor)0);
     grab->eventMask = stuff->eventMask;
@@ -4213,6 +4214,7 @@ InitSprite(DeviceIntPtr pDev, Bool hasCursor)
         SpritePtr pSprite = (SpritePtr)xalloc(sizeof(SpriteRec));
         if (!pSprite)
             FatalError("failed to allocate sprite struct");
+        memset(pSprite, 0, sizeof(SpriteRec));
         pSprite->hot.pScreen = pSprite->hotPhys.pScreen = (ScreenPtr)NULL;
         pSprite->win = NullWindow;
         pSprite->current = NullCursor;
diff --git a/mi/mieq.c b/mi/mieq.c
index 49bf867..0744e6c 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -235,10 +235,7 @@ mieqProcessInputEvents()
              * Use dev to get the correct processing function but supply
              *  e->pDev to pass the correct device 
              */
-            if (e->pDev->isMPDev)
-                dev->public.processInputProc(e->event, e->pDev, e->nevents);
-            else
-                dev->public.processInputProc(e->event, dev, e->nevents);
+            dev->public.processInputProc(e->event, e->pDev, e->nevents);
         }
 
         /* Update the sprite now. Next event may be from different device. */
commit ea82333dc1799a7e013205adbc89874bc8d273cb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Jan 10 14:52:13 2007 +1030

    Xi:     add missing call for SProcXChangeDeviceCursor
    	add DeviceEnterNotify and DeviceLeaveNotify
    	fix: QueryDevicePointer crashed if called with keyboard device

diff --git a/Changelog b/Changelog
deleted file mode 100644
index 17ee9c5..0000000
--- a/Changelog
+++ /dev/null
@@ -1,575 +0,0 @@
-== 08.01.06 ==
-Xi:     Adding ChangeDeviceCursor request
-
-Files:
-	dix/window.c
-	dix/events.c
-	include/window.h
-	include/windowstr.h
-	Xi/extinit.c
-	Xi/chdevcur.c
-	Xi/chdevcur.h
-	Xi/Makefile.am
-
-____________________________________________________________
-
-xfree86:  fix XI86_SHARED_POINTER flag setting 
-
-File:
-	hw/xfree86/common/xf86Xinput.c
-
-== 20.12.06 ==
-xfree86: Changing "IsMPDevice" to "SharedPointer" option. Devices will default 
-	 to MP devices.
-
-Xi:	Adding QueryDevicePointer request/reply
-	Adding WarpDevicePointer request/reply
-
-Files: 
-	hw/xfree86/common/xf86Xinput.c
-	hw/xfree86/common/xf86Cursor.c
-	hw/xfree86/common/xf86Xinput.h
-	Xi/extinit.c
-	Xi/querydp.c
-	Xi/querydp.h
-	Xi/Makefile.am
-	Xi/warpdevp.c
-	Xi/warpdevp.h
-	dix/cursor.c
-	dix/events.c
-	dix/dix.h
-
-Note: This commit requires libXi additions to use the new functions.
-
-____________________________________________________________
-
-xfree86:  fix xf86ActivateDevice(): only set to MP device if not a keyboard
-
-Files:
-	hw/xfree86/common/xf86Xinput.c
-	include/extinit.h
-	Xi/extinit.c
-
-____________________________________________________________
-removing MPX extension files
-
-Files:
-	mpx/
-	include/mpxevents.h
-	include/mpxextinit.h
-
-____________________________________________________________
-xfree86: fix xf86ProcessCommonOptions() core and shared pointer assignment
-
-Files:
-	hw/xfree86/common/xf86Xinput.c
-
-TAG: mpx-0.3.0
-
-
-== 18.12.06 ==
-mi:     removing MPX ifdefs
-	global sprite renaming in mipointer and misprite
-	fixed: multiple remove cursor call in miSpriteInstallColormap
-	fixed: wrong core pointer usage in miSpriteStoreColors
-
-dix:    bugfix in CheckCursorConfinement
-	removing MPX ifdefs
-	removing MPX event generation (using Xi solely now)
-	bugfix GrabDevice: uninitialized field in grab struct caused segfault
-
-xfree86: removing MPX fdefs
-
-Xi:     removing MPX protocol events
-
-Files:
-	include/inputstr.h
-	mi/midispcur.c
-	mi/mieq.c
-	mi/mipointer.c
-	mi/misprite.c
-	dix/events.c
-	dix/cursor.c
-	dix/devices.c
-	hw/xfree86/common/xf86Events.c
-	hw/xfree86/common/xf86Input.h
-	Xi/exevents.c
-
-____________________________________________________________
-
-Cleaning up #ifdef MPX from remaining files, removing it from configure.ac.
-Removing building mpx extension from Makefile.am
-
-Files:
-	Makefile.am
-	configure.ac
-	hw/xfree86/ramdac/xf86HWCurs.c
-	include/dix-config.h.in
-	include/dix.h
-	include/globals.h
-	include/xorg-server.h.in
-	mi/mieq.c
-	mi/miinitext.c
-	mi/mipointer.c
-	os/utils.c
-
-== 12.12.06 ==
-dix:    Moving SpriteRec into DeviceIntRec
-	removing global sprite structure
-	beginning to remove MPX ifdefs
-
-xnest:  Fix to make xnest compile again 
-
-Files:
-	dix/getevents.c
-	dix/events.c
-	dix/devices.c
-	hw/xfree86/common/xf86Xinput.c
-	include/cursor.h
-	include/dix.h
-	include/dixevents.h
-	include/input.h
-	include/inputstr.h
-	XTrap/xtrapdi.c
-	Xext/xtest.c
-	hw/xnest/Events.c
-	record/record.c
-
-== 05.12.06 ==
-Xi:     adding MPX checks to ProcessOtherEvents
-
-mpx:    adding QueryPointer request and reply
-	adjusting names of requests to Xlib compatible naming (xMPX*** instead of
-	mpx***)
-
-
-Files:
-	Xi/exevents.c
-	mpx/Makefile.am
-	mpx/extinit.c
-	mpx/getevbase.c
-	mpx/getvers.c
-	mpx/queryptr.c
-	mpx/queryptr.h
-	mpx/selectev.c
-	mpx/listdev.h
-	mpx/listdev.c
-	include/mpxextinit.h
-
-____________________________________________________________
-
-Merging from master
-
-____________________________________________________________
-
-Ironing some glitches caused by the merge
-
-Files:
-	Xi/exevents.c
-	randr/rrpointer.c
-	dix/events.c
-
-
-== 01.12.06 ==
-
-mpx:    SelectEvents and GetEventBase requests. 
-	Some renaming and cleaning up in extinit.c
-	MPXLastEvent added 
-
-Xi:	ShouldFreeInputMask() from XI is not static any more, used in mpx
-
-dix:	GetPointerEvents() allocates MPX event for MPX devices.
-	DeliverDeviceEvents() caters for MPX devices.
-
-
-Files:
-	configure.ac
-	mpx/Makefile.am
-	mpx/extinit.c
-	mpx/getvers.c
-	mpx/getevbase.c
-	mpx/getevbase.h
-	mpx/listdev.c
-	mpx/listdev.h
-	mpx/mpxglobals.h
-	mpx/selectev.c
-	mpx/selectev.h
-	mpx/mpxevents.h
-	Xi/exevents.c
-	dix/events.c
-	dix/getevents.c
-	include/mpxevents.h
-	include/mpxextinit.h
-
-
-== 30.11.06
-mpx:    Adding ListDevices request. Minor changes, using
-	MPXRestoreExtensionEvents() when resetting.
-
-Files:
-	mpx/Makefile.am
-	mpx/extinit.c
-	mpx/listdev.c
-	mpx/listdev.h
-	mpx/mpxextinit.h
-
-
-== 29.11.06 ==
-mpx:    Infrastructure for MPX extension, GetExtensionVersion request works.
-
-Files:
-	mpx/
-	mpx/Makefile.am
-	mpx/extinit.c
-	mpx/getvers.c
-	mpx/getvers.h
-	mpxglobals.h
-	mpx/selectev.c
-	configure.ac
-	Makefile.am
-	os/utils.c
-	mi/miinitext.c
-	include/globals.h
-
-== 28.11.06 ==
-mi:     Bugfix: FreeCursor ignores negative refcounts.
-
-mieq:   Bugfix: Motion notifies did overwrite DeviceMotionNotifies
-
-Files:
-	dix/cursor.c
-	mi/mieq.c
-
-____________________________________________________________
-
-dix:	missing parameter to SetCursorPosition in CheckMotion ifndef MPX
-
-mi:	missing include in misprite.c ifndef MPX
-
-Files:
-	dix/events.c
-	mi/misprite.c
-
-
-== 27.11.06 ==
-mi:     free allocated memory in miDCCloseScreen and in miDCInitialize in case
-	of errors.
-	Some copyright notices.
-	misprite.c passes DeviceIntPtr around and down to DC (previously
-	miCursorInfoPtr and the plain device id).
-	Large cleanup in misprite.c to avoid code duplication.
-
-Files:
-	mi/midispcur.c
-	mi/misprite.c
-	mi/misprite.h
-
-____________________________________________________________
-
-mi:     mipointer.c cleanup, reducing code duplication, using MPHasCursor(),
-	removing IsMPDev()
-
-Files:
-	mi/mipointer.c
-
-____________________________________________________________
-
-mi:     malloc checks for misprite and midispcur, code cleanup
-	removed IsMPDev()
-
-Files:
-	mi/misprite.c
-	mi/mipointer.c
-	mi/midispcur.c
-	dix/events.c
-
-
-== 23.11.06 ==
-mi:	closing memory leak, miPointer is freed in miPointerCloseScreen
-	bugfix: uninitialized pPointer in miPointerGetPosition ifndef MPX
-	adding DeviceIntPtr parameter to ScreenRec's cursor functions.
-	cleanup of miPointer code to use same scheme in each function
-
-dix:	MPHasCursor() function determines checking whether to invoke
-	cursor rendering.
-
-animcur: adding DeviceIntPtr parameter to cursor functions but animcur relies
-	 on the core pointer right now.
-
-xfixes: adding DeviceIntPtr parameter to cursor functions but xfixes relies on
-	the core pointer right now.
-
-rac:	adding DeviceIntPtr parameter to cursor functions but RAC relies on
-	the core pointer right now.
-
-ramdac:	adding DeviceIntPtr parameter to cursor functions but ramdac relies on
-	the core pointer right now.
-
-Files:
-	mi/mipointer.c
-	mi/mipointer.h
-	mi/micursor.c
-	mi/mi.h
-	mi/mieq.c
-	include/cursor.h
-	include/inputstr.h
-	include/scrnintstr.h
-	include/dix.h
-	dix/events.c
-	dix/cursor.c
-	Xext/xtest.c
-	render/animcur.c
-	xfixes/cursor.c
-	XTrap/xtrapddmi.c
-	xkb/ddxFakeMtn.c
-	hw/xfree86/common/xf86Cursor.c
-	hw/xfree86/common/xf86RandR.c
-	hw/xfree86/rac/xf86RAC.c
-	hw/xfree86/ramdac/xf86Cursor.c
-	hw/xfree86/dri/dri.c
-
-
-== 22.11.06 ==
-
-mi:     added DevToSprite() conversion function
-        fixed miSpriteRealize to use passed pDev argument instead of looping.
-
-dix:    changed sprite dependency and added MPX functionality to parts of
-        events.c (XineramaChangeToCursor, XineramaCheckPhysLimits,
-        XineramaConstrainCursor)
-
-Xi:	fix: accessing other->buttons for keyboard segfaulted the server
-
-Files:
-        mi/misprite.c
-        mi/mipointer.c
-        dix/events.c
-        Xi/exevents.c
-
-____________________________________________________________
-
-dix	GetSpriteWindow() adjusted for MPX
-	added device dependency for MPX to DoEnterLeaveEvents,
-	EnterLeaveEvents, EnterNotifies, LeaveNotifies and
-	FixUpEventFromWindow.
-
-Files:
-        Xext/security.c
-        Xi/exevents.c
-        xkb/ddxFakeMtn.c
-        dix/events.c
-        include/dix.h
-
-____________________________________________________________
-
-dix:	DeliverEventsToWindow adjusted for MPX
-
-mi:     sprite debugging disabled
-
-Files:	
-        dix/events.c
-        Xi/exevents.c
-        mi/misprite.c
-        include/dix.h
-
-
-== 21.11.06 ==
-mi:     added MPX to miSpriteReportDamage
-        added id field to miCursorInfoPtr, required to pass through to miDC
-        core pointer uses mpCursors array as well.
-        added miDCBufferRec for future use with MPX
-
-Files:
-        mi/midispcur.c
-        mi/misprite.c
-        mi/mispritest.h
-
-TAG: MPX_BEFORE_MIDC_API_BREAK
-
-____________________________________________________________
-
-mi:     added device ID to miSpriteCursorFuncRec functions
-        added MPX code to midispcur.c
-
-
-Files:
-        mi/midispcur.c
-        mi/misprite.c
-        mi/mispritest.h
-
-BUG:   Core pointer changes whenever MPX cursor changes shape.
-
-____________________________________________________________
-
-mi:	constrain MPX cursors to screen 
-
-Files:
-	dix/events.c
-	mi/mipointer.c
-	include/scrnintstr.h
-
-TAG:   MPX_BEFORE_DIX_API_BREAK
-
-
-____________________________________________________________
-
-dix:    moved sprite from static to be pointer of type SpritePtr
-	added SpriteRecs for MPX devices
-	changed sprite dependency and added MPX functionality to parts 
-	of events.c (ConfineToShape, PostNewCursor, XineramaCheckMotion,
-	CheckMotion, XineramaChangeToCursor, ChangeToCursor, CheckPhysLimits,
-	PointerConfinedToScreen) 
-	added DeviceIntRec param to GetSpritePosition(). This required some
-	minor changes in ddx, xtest, xkb and xfixes.
-
-mi:	changed miPointer to pointer instead of static struct.
-
-Files:
-        dix/events.c
-        dix/exevents.c
-        Xext/xtest.c
-        ddx/ddxFakeBtn.c
-        ddx/ddxFakeMtn.c
-        ddx/ddxDevBtn.c
-        xkb/xkbActions.c
-        xfixes/cursor.c
-	mi/mieq.c
-
-____________________________________________________________
-
-dix:	WindowsRestructured() calls CheckMotion() on all devices
-
-mi:	core pointer was checked twice in miSpriteReportDamage,
-	miSpriteInstallColormap, miSpriteStoreColors, miSpriteSaveDoomedAreas
-	and miSpriteRealiseCursor 
-	using damage bug (see comment in file) to avoid artefacts
-
-Files:
-	dix/events.c
-	mi/misprite.c
-	mi/mispritest.h
-
-== 20.11.06 ==
-
-mi:     moved core pointer information from miSpriteScreenRec into a
-        miCursorInfoRec.
-        bugfix in mipointer, semicolon after preprocessor statement
-
-Files:
-        mi/mispritest.h
-        mi/misprite.c
-        mi/mipointer.c
-
-____________________________________________________________
-
-mi:     added MPX to miSprite functions. 
-
-Files:
-        mi/mispritest.h
-        mi/misprite.c
-        mi/mipointer.c
-        dix/events.c
-
-NOTE: This version will render multiple cursors but with an artefact each time
-when devices alternate.
-
-== 17.11.06 ==
-dix:    moved isMPdev field to end of _DeviceIntRec structure
-
-mi:     
-        added miMPPointers array to mipointer.c
-        added DeviceIntPtr to all miPointerSpriteFuncs. Coming from miPointer
-        we use inputInfo.pointer as standard value. ABI BREAK!
-
-ramdac: 
-        forcing failed HW Cursor initialisation. MPX needs software rendering.
-        changes to use new miPointerSpriteFunc (this required externing
-        inputInfo, should probably be fixed at a later point).
-
-
-RAC: changes to use new miPointerSpriteFuncs.
-
-Files: 
-        include/inputstr.h
-        mi/mipointer.c
-        mi/mipointer.h
-        mi/misprite.c
-        hw/xfree86/ramdac/xf86HWCurs.c
-        hw/xfree86/ramdac/xf86Cursor.c
-        hw/xfree86/rac/xf86RAC.c
-
-____________________________________________________________
-
-mi:
-        added miCursorInfoRec to contain info of the MPX cursors.
-        calling miUpdatePointerSprite() from event queue for MPX devices.
-        adding device-specific processing to miPointer*() functions.
-
-dix:    Call to SetCursorPosition in CheckMotion() temporarily disabled.
-
-xfree86/common: call to miPointerUpdateSprite() disabled, is done from the EQ 
-
-NOTE: This build will not display cursor images. 
-BUG: The second mouse does to take correct x coordinates.
-
-Files:
-        mi/mispritestr.h
-        mi/misprite.c
-        mi/mipointer.c
-        mi/mipointer.h
-        mi/mieq.c
-        dix/events.c
-        hw/xfree86/common/xf86Events.c
-
-
-== 16.11.06 ==
-dix: 
-        merge with code cleanup from master
-        GetPointerEvents treats events in the same way as XINPUT devices when flag
-        has POINTER_MULTIPOINTER set.
-
-xfree86/common:
-    added XI86_MP_DEVICE flag and parsing in xf86ProcessCommonOptions
-    added POINTER_MULTIPOINTER define. Is used in xf86PostMotionEvent and
-    xf86PostButtonEvent for the flags that are passed into GetPointerEvents()
-
-global:
-    added flags to configure.ac to enable/disable MPX define
-    added flags to dix-config.h.in to #define MPX
-
-Files:
-        dix/getevents.c
-        hw/xfree86/common/xf86Xinput.c
-        hw/xfree86/common/xf86Xinput.h
-        include/input.h
-        configure.ac
-        include/dix-config.h.in
-
-____________________________________________________________
-
-dix:    added isMPdev field to _DeviceIntRec, is used in GetPointerEvents()
-
-mieq:   avoid merging events from different devices in mieqEnqueue()
-
-xfree86/common
-        isMPdev field used from xf86ActivateDevice(), xf86PostMotionEvent()
-        and xf86PostButtonEvent()
-
-Files:
-        dix/getevents.c
-        hw/xfree86/common/xf86Xinput.c
-        include/inputstr.h
-        mi/mieq.c
-
-____________________________________________________________
-
-mieq:  EQ processing handles MP devices 
-
-global: MPX define added to xorg-server.h.in
-
-xfree86/common: small fix to avoid byte overflow
-
-Files:
-        mi/mieq.c
-        hw/xfree86/common/xf86Xinput.c
-        include/xserver-config.h.in
diff --git a/Xi/exglobals.h b/Xi/exglobals.h
index 3afd1bb..bc4a60d 100644
--- a/Xi/exglobals.h
+++ b/Xi/exglobals.h
@@ -70,6 +70,8 @@ extern int DeviceButtonStateNotify;
 extern int DeviceMappingNotify;
 extern int ChangeDeviceNotify;
 extern int DevicePresenceNotify;
+extern int DeviceEnterNotify;
+extern int DeviceLeaveNotify;
 
 extern int RT_INPUTCLIENT;
 
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 82bed50..8948e6c 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -170,6 +170,8 @@ Mask DeviceOwnerGrabButtonMask;
 Mask DeviceButtonGrabMask;
 Mask DeviceButtonMotionMask;
 Mask DevicePresenceNotifyMask;
+Mask DeviceEnterWindowMask;
+Mask DeviceLeaveWindowMask;
 
 int DeviceValuator;
 int DeviceKeyPress;
@@ -187,6 +189,8 @@ int DeviceButtonStateNotify;
 int DeviceMappingNotify;
 int ChangeDeviceNotify;
 int DevicePresenceNotify;
+int DeviceEnterNotify;
+int DeviceLeaveNotify;
 
 int RT_INPUTCLIENT;
 
@@ -251,6 +255,8 @@ XInputExtensionInit(void)
 	EventSwapVector[DeviceButtonStateNotify] = SEventIDispatch;
 	EventSwapVector[DeviceMappingNotify] = SEventIDispatch;
 	EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
+	EventSwapVector[DeviceEnterNotify] = SEventIDispatch;
+	EventSwapVector[DeviceLeaveNotify] = SEventIDispatch;
     } else {
 	FatalError("IExtensionInit: AddExtensions failed\n");
     }
@@ -436,6 +442,8 @@ SProcIDispatch(register ClientPtr client)
 	return (SProcXQueryDevicePointer(client));
     else if (stuff->data == X_WarpDevicePointer)
 	return (SProcXWarpDevicePointer(client));
+    else if (stuff->data == X_ChangeDeviceCursor)
+        return (SProcXChangeDeviceCursor(client));
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -566,6 +574,10 @@ SEventIDispatch(xEvent * from, xEvent * to)
 	DO_SWAP(SDeviceMappingNotifyEvent, deviceMappingNotify);
     else if (type == ChangeDeviceNotify)
 	DO_SWAP(SChangeDeviceNotifyEvent, changeDeviceNotify);
+    else if (type == DeviceEnterNotify)
+        DO_SWAP(SDeviceEnterNotifyEvent, deviceEnterNotify);
+    else if (type == DeviceLeaveNotify)
+        DO_SWAP(SDeviceLeaveNotifyEvent, deviceLeaveNotify);
     else {
 	FatalError("XInputExtension: Impossible event!\n");
     }
@@ -671,6 +683,31 @@ SDevicePresenceNotifyEvent (devicePresenceNotify *from, devicePresenceNotify *to
     swaps(&to->control, n);
 }
 
+void SDeviceEnterNotifyEvent (deviceEnterNotify *from, deviceEnterNotify *to)
+{
+    register char n;
+
+    *to = *from;
+    swaps(&to->sequenceNumber,n);
+    swapl(&to->time, n);
+}
+
+void SDeviceLeaveNotifyEvent (deviceLeaveNotify *from, deviceLeaveNotify *to)
+{
+    register char n;
+
+    *to = *from;
+    swaps(&to->sequenceNumber,n);
+    swapl(&to->time, n);
+    swapl(&to->root, n);
+    swapl(&to->event, n);
+    swapl(&to->child, n);
+    swaps(&to->rootX, n);
+    swaps(&to->rootY, n);
+    swaps(&to->eventX, n);
+    swaps(&to->eventY, n);
+}
+
 /************************************************************************
  *
  * This function sets up extension event types and masks.
@@ -698,6 +735,8 @@ FixExtensionEvents(ExtensionEntry * extEntry)
     DeviceKeyStateNotify = ChangeDeviceNotify + 1;
     DeviceButtonStateNotify = DeviceKeyStateNotify + 1;
     DevicePresenceNotify = DeviceButtonStateNotify + 1;
+    DeviceEnterNotify = DevicePresenceNotify + 1;
+    DeviceLeaveNotify = DeviceEnterNotify + 1;
 
     event_base[KeyClass] = DeviceKeyPress;
     event_base[ButtonClass] = DeviceButtonPress;
@@ -773,6 +812,15 @@ FixExtensionEvents(ExtensionEntry * extEntry)
 
     DevicePresenceNotifyMask = GetNextExtEventMask();
     SetEventInfo(DevicePresenceNotifyMask, _devicePresence);
+
+    DeviceEnterWindowMask = GetNextExtEventMask();
+    SetMaskForExtEvent(DeviceEnterWindowMask, DeviceEnterNotify);
+    AllowPropagateSuppress(DeviceEnterWindowMask);
+
+    DeviceLeaveWindowMask = GetNextExtEventMask();
+    SetMaskForExtEvent(DeviceLeaveWindowMask, DeviceLeaveNotify);
+    AllowPropagateSuppress(DeviceLeaveWindowMask);
+
     SetEventInfo(0, _noExtensionEvent);
 }
 
@@ -814,6 +862,8 @@ RestoreExtensionEvents(void)
     DeviceKeyStateNotify = 13;
     DeviceButtonStateNotify = 13;
     DevicePresenceNotify = 14;
+    DeviceEnterNotify = 15;
+    DeviceLeaveNotify = 16;
 
     BadDevice = 0;
     BadEvent = 1;
@@ -852,6 +902,8 @@ IResetProc(ExtensionEntry * unused)
     EventSwapVector[DeviceMappingNotify] = NotImplemented;
     EventSwapVector[ChangeDeviceNotify] = NotImplemented;
     EventSwapVector[DevicePresenceNotify] = NotImplemented;
+    EventSwapVector[DeviceEnterNotify] = NotImplemented;
+    EventSwapVector[DeviceLeaveNotify] = NotImplemented;
     RestoreExtensionEvents();
 }
 
diff --git a/Xi/querydp.c b/Xi/querydp.c
index 04323e4..c1ba2ee 100644
--- a/Xi/querydp.c
+++ b/Xi/querydp.c
@@ -84,7 +84,7 @@ ProcXQueryDevicePointer(register ClientPtr client)
     REQUEST_SIZE_MATCH(xQueryDevicePointerReq);
 
     pDev = LookupDeviceIntRec(stuff->deviceid);
-    if (pDev == NULL) {
+    if (pDev == NULL || pDev->valuator == NULL) {
         SendErrorToClient(client, IReqCode, X_QueryDevicePointer,
                 stuff->deviceid, BadDevice); 
         return Success;
diff --git a/dix/events.c b/dix/events.c
index 3c11723..23fb1ec 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -3322,13 +3322,17 @@ EnterLeaveEvent(
     register WindowPtr pWin,
     Window child)
 {
-    xEvent		event;
+    xEvent              event;
     register DeviceIntPtr keybd = inputInfo.keyboard;
     WindowPtr		focus;
     register DeviceIntPtr mouse = pDev;
     register GrabPtr	grab = mouse->grab;
     Mask		mask;
 
+    deviceEnterNotify   *devEnterLeave;
+    int                 mskidx;
+    OtherInputMasks     *inputMasks;
+
     if ((pWin == mouse->valuator->motionHintWindow) &&
 	(detail != NotifyInferior))
 	mouse->valuator->motionHintWindow = NullWindow;
@@ -3342,33 +3346,35 @@ EnterLeaveEvent(
     {
 	mask = pWin->eventMask | wOtherEventMasks(pWin);
     }
-    if (mask & filters[type])
-    {
-	event.u.u.type = type;
-	event.u.u.detail = detail;
-	event.u.enterLeave.time = currentTime.milliseconds;
-	event.u.enterLeave.rootX = pDev->pSprite->hot.x;
-	event.u.enterLeave.rootY = pDev->pSprite->hot.y;
-	/* Counts on the same initial structure of crossing & button events! */
-	FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
-	/* Enter/Leave events always set child */
-	event.u.enterLeave.child = child;
-	event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
-					    ELFlagSameScreen : 0;
+
+    event.u.u.type = type;
+    event.u.u.detail = detail;
+    event.u.enterLeave.time = currentTime.milliseconds;
+    event.u.enterLeave.rootX = pDev->pSprite->hot.x;
+    event.u.enterLeave.rootY = pDev->pSprite->hot.y;
+    /* Counts on the same initial structure of crossing & button events! */
+    FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
+    /* Enter/Leave events always set child */
+    event.u.enterLeave.child = child;
+    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
+        ELFlagSameScreen : 0;
 #ifdef XKB
-	if (!noXkbExtension) {
-	    event.u.enterLeave.state = mouse->button->state & 0x1f00;
-	    event.u.enterLeave.state |= 
-			XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
-	} else
+    if (!noXkbExtension) {
+        event.u.enterLeave.state = mouse->button->state & 0x1f00;
+        event.u.enterLeave.state |= 
+            XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
+    } else
 #endif
-	event.u.enterLeave.state = keybd->key->state | mouse->button->state;
-	event.u.enterLeave.mode = mode;
-	focus = keybd->focus->win;
-	if ((focus != NoneWin) &&
-	    ((pWin == focus) || (focus == PointerRootWin) ||
-	     IsParent(focus, pWin)))
-	    event.u.enterLeave.flags |= ELFlagFocus;
+        event.u.enterLeave.state = keybd->key->state | mouse->button->state;
+    event.u.enterLeave.mode = mode;
+    focus = keybd->focus->win;
+    if ((focus != NoneWin) &&
+            ((pWin == focus) || (focus == PointerRootWin) ||
+             IsParent(focus, pWin)))
+        event.u.enterLeave.flags |= ELFlagFocus;
+
+    if (mask & filters[type])
+    {
 	if (grab)
 	    (void)TryClientEvents(rClient(grab), &event, 1, mask,
 				  filters[type], grab);
@@ -3376,6 +3382,27 @@ EnterLeaveEvent(
 	    (void)DeliverEventsToWindow(pDev, pWin, &event, 1, filters[type],
 					NullGrab, 0);
     }
+
+    devEnterLeave = (deviceEnterNotify*)&event;
+    devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify :
+        DeviceLeaveNotify;
+    devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify :
+        DeviceLeaveNotify;
+    devEnterLeave->deviceid = pDev->id;
+    mskidx = pDev->id;
+    inputMasks = wOtherInputMasks(pWin);
+    if (inputMasks && 
+       (filters[devEnterLeave->type] & inputMasks->deliverableEvents[mskidx]))
+    {
+        if (grab)
+            (void)TryClientEvents(rClient(grab), (xEvent*)devEnterLeave, 1,
+                                  mask, filters[devEnterLeave->type], grab);
+	else
+	    (void)DeliverEventsToWindow(pDev, pWin, (xEvent*)devEnterLeave, 
+                                        1, filters[devEnterLeave->type], 
+                                        NullGrab, pDev->id);
+    }
+
     if ((type == EnterNotify) && (mask & KeymapStateMask))
     {
 	xKeymapEvent ke;
diff --git a/include/extinit.h b/include/extinit.h
index 5546b21..6cf7bf7 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -110,6 +110,18 @@ SDevicePresenceNotifyEvent (
        );
 
 void
+SDeviceEnterNotifyEvent (
+        deviceEnterNotify * /* from */,
+        deviceEnterNotify * /* to */
+        );
+
+void
+SDeviceLeaveNotifyEvent (
+        deviceLeaveNotify * /* from */,
+        deviceLeaveNotify * /* to */
+        );
+
+void
 FixExtensionEvents (
 	ExtensionEntry 	*      /* extEntry */
 	);
commit a7ab7932938820a795bb6fb8e0444e0824433b99
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jan 8 17:31:16 2007 +1030

    xfree86:  fix XI86_SHARED_POINTER flag setting

diff --git a/Changelog b/Changelog
index 431e008..17ee9c5 100644
--- a/Changelog
+++ b/Changelog
@@ -11,6 +11,12 @@ Files:
 	Xi/chdevcur.h
 	Xi/Makefile.am
 
+____________________________________________________________
+
+xfree86:  fix XI86_SHARED_POINTER flag setting 
+
+File:
+	hw/xfree86/common/xf86Xinput.c
 
 == 20.12.06 ==
 xfree86: Changing "IsMPDevice" to "SharedPointer" option. Devices will default 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index fd2a451..dc07b3f 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -134,7 +134,7 @@ xf86ProcessCommonOptions(LocalDevicePtr local,
     }
 
     if (xf86SetBoolOption(list, "SharedPointer", 0)) {
-        local->flags &= ~XI86_SHARED_POINTER;
+        local->flags |= XI86_SHARED_POINTER;
         xf86Msg(X_CONFIG, "%s: is shared device\n", local->name);
     } 
 
commit 95e1a88050dde61e9b2407428042a43e47b46e18
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Jan 8 12:31:18 2007 +1030

    Xi:     Adding ChangeDeviceCursor request

diff --git a/Changelog b/Changelog
index ef42159..431e008 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,17 @@
+== 08.01.06 ==
+Xi:     Adding ChangeDeviceCursor request
+
+Files:
+	dix/window.c
+	dix/events.c
+	include/window.h
+	include/windowstr.h
+	Xi/extinit.c
+	Xi/chdevcur.c
+	Xi/chdevcur.h
+	Xi/Makefile.am
+
+
 == 20.12.06 ==
 xfree86: Changing "IsMPDevice" to "SharedPointer" option. Devices will default 
 	 to MP devices.
diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index 0aa5844..9e7d1c4 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -5,6 +5,8 @@ AM_CFLAGS = $(DIX_CFLAGS)
 libXi_la_SOURCES =	\
 	allowev.c \
 	allowev.h \
+        chdevcur.c \
+        chdevcur.h \
 	chgdctl.c \
 	chgdctl.h \
 	chgfctl.c \
diff --git a/Xi/chdevcur.c b/Xi/chdevcur.c
new file mode 100644
index 0000000..fc4b0e0
--- /dev/null
+++ b/Xi/chdevcur.c
@@ -0,0 +1,123 @@
+/*
+
+Copyright 2006 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 change a given device pointer's cursor.
+ *
+ */
+
+#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 "chdevcur.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to set one pointer's cursor.
+ *
+ */
+
+int
+SProcXChangeDeviceCursor(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(xChangeDeviceCursorReq);
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
+    return (ProcXChangeDeviceCursor(client));
+}
+
+int ProcXChangeDeviceCursor(register ClientPtr client)
+{
+    int err;
+    WindowPtr pWin    = NULL;
+    DeviceIntPtr pDev = NULL;
+    CursorPtr pCursor = NULL;
+
+    REQUEST(xChangeDeviceCursorReq);
+    REQUEST_SIZE_MATCH(xChangeDeviceCursorReq);
+
+    pDev = LookupDeviceIntRec(stuff->deviceid);
+    if (pDev == NULL) {
+        SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 0,
+                BadDevice); 
+        return Success;
+    }
+
+    if (stuff->win != None)
+    {
+        err = dixLookupWindow(&pWin, stuff->win, client, DixReadWriteAccess);
+        if (err != Success)
+        {
+            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 
+                    stuff->win, err);
+            return Success;
+        }
+    }
+
+    if (stuff->cursor == None)
+    {
+        if (pWin == WindowTable[pWin->drawable.pScreen->myNum])
+            pCursor = rootCursor;
+        else
+            pCursor = (CursorPtr)None;
+    } 
+    else 
+    {
+        pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
+                                RT_CURSOR, DixReadAccess); 
+        if (!pCursor)
+        {
+            SendErrorToClient(client, IReqCode, X_ChangeDeviceCursor, 
+                    stuff->cursor, BadCursor);
+            return Success;
+        }
+    } 
+
+    ChangeWindowDeviceCursor(pWin, pDev, pCursor);
+
+    return Success;
+}
+
diff --git a/Xi/chdevcur.h b/Xi/chdevcur.h
new file mode 100644
index 0000000..92c8d4f
--- /dev/null
+++ b/Xi/chdevcur.h
@@ -0,0 +1,39 @@
+/************************************************************
+
+Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au>
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the above listed
+copyright holder(s) not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef CHDEVCUR_H
+#define CHDEVCUR_H 1
+
+int SProcXChangeDeviceCursor(ClientPtr	/* client */
+    );
+
+int ProcXChangeDeviceCursor(ClientPtr	/* client */
+    );
+
+#endif /* CHDEVCUR_H */
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 7c737a1..82bed50 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -74,6 +74,7 @@ SOFTWARE.
 
 /* modules local to Xi */
 #include "allowev.h"
+#include "chdevcur.h"
 #include "chgdctl.h"
 #include "chgfctl.h"
 #include "chgkbd.h"
@@ -340,6 +341,8 @@ ProcIDispatch(register ClientPtr client)
         return (ProcXQueryDevicePointer(client));
     else if (stuff->data == X_WarpDevicePointer)
         return (ProcXWarpDevicePointer(client));
+    else if (stuff->data == X_ChangeDeviceCursor)
+        return (ProcXChangeDeviceCursor(client));
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
diff --git a/dix/events.c b/dix/events.c
index 81efb70..3c11723 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -921,6 +921,7 @@ PostNewCursor(DeviceIntPtr pDev)
     register    WindowPtr win;
     register    GrabPtr grab = pDev->grab;
     SpritePtr   pSprite = pDev->pSprite;
+    CursorPtr   pCursor;
 
     if (syncEvents.playingEvents)
 	return;
@@ -939,11 +940,19 @@ PostNewCursor(DeviceIntPtr pDev)
     else
 	win = pSprite->win;
     for (; win; win = win->parent)
-	if (win->optional && win->optional->cursor != NullCursor)
-	{
-	    ChangeToCursor(pDev, win->optional->cursor);
-	    return;
+    {
+	if (win->optional) 
+        {
+            pCursor = WindowGetDeviceCursor(win, pDev);
+            if (!pCursor && win->optional->cursor != NullCursor)
+                pCursor = win->optional->cursor;
+            if (pCursor)
+            {
+                ChangeToCursor(pDev, pCursor);
+                return;
+            }
 	}
+    }
 }
 
 _X_EXPORT WindowPtr
diff --git a/dix/window.c b/dix/window.c
index e33140d..604af38 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -110,6 +110,7 @@ Equipment Corporation.
 #include "validate.h"
 #include "windowstr.h"
 #include "input.h"
+#include "inputstr.h"
 #include "resource.h"
 #include "colormapst.h"
 #include "cursorstr.h"
@@ -135,12 +136,21 @@ Equipment Corporation.
  *    GetWindowAttributes, DeleteWindow, DestroySubWindows,
  *    HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows,
  *    UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow,
- *
+ *    ChangeWindowDeviceCursor
  ******/
 
 static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11};
 static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88};
 
+static Bool WindowParentHasDeviceCursor(WindowPtr pWin, 
+                                        DeviceIntPtr pDev, 
+                                        CursorPtr pCurs);
+static Bool 
+WindowSeekDeviceCursor(WindowPtr pWin, 
+                       DeviceIntPtr pDev, 
+                       DevCursNodePtr* pNode, 
+                       DevCursNodePtr* pPrev);
+
 _X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF;
 
 _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
@@ -440,6 +450,7 @@ CreateRootWindow(ScreenPtr pScreen)
 #endif
 #ifdef XINPUT
     pWin->optional->inputMasks = NULL;
+    pWin->optional->deviceCursors = NULL;
 #endif
     pWin->optional->colormap = pScreen->defColormap;
     pWin->optional->visual = pScreen->rootVisual;
@@ -3639,6 +3650,17 @@ CheckWindowOptionalNeed (register WindowPtr w)
     if (optional->inputMasks != NULL)
 	return;
 #endif
+    if (optional->deviceCursors != NULL)
+    {
+        DevCursNodePtr pNode = optional->deviceCursors;
+        while(pNode)
+        {
+            if (pNode->cursor != None)
+                return;
+            pNode = pNode->next;
+        }
+    }
+
     parentOptional = FindWindowWithOptional(w)->optional;
     if (optional->visual != parentOptional->visual)
 	return;
@@ -3683,6 +3705,7 @@ MakeWindowOptional (register WindowPtr pWin)
 #endif
 #ifdef XINPUT
     optional->inputMasks = NULL;
+    optional->deviceCursors = NULL;
 #endif
     parentOptional = FindWindowWithOptional(pWin)->optional;
     optional->visual = parentOptional->visual;
@@ -3731,10 +3754,227 @@ DisposeWindowOptional (register WindowPtr pWin)
     }
     else
 	pWin->cursorIsNone = TRUE;
+
+    if (pWin->optional->deviceCursors)
+    {
+        DevCursorList pList;
+        DevCursorList pPrev;
+        pList = pWin->optional->deviceCursors;
+        while(pList)
+        {
+            if (pList->cursor)
+                FreeCursor(pList->cursor, (XID)0);
+            pPrev = pList;
+            pList = pList->next;
+            xfree(pPrev);
+        }
+        pWin->optional->deviceCursors = NULL;
+    }
+
     xfree (pWin->optional);
     pWin->optional = NULL;
 }
 
+/*
+ * Changes the cursor struct for the given device and the given window.
+ * A cursor that does not have a device cursor set will use whatever the
+ * standard cursor is for the window. If all devices have a cursor set,
+ * changing the window cursor (e.g. using XDefineCursor()) will not have any
+ * visible effect. Only when one of the device cursors is set to None again,
+ * this device's cursor will display the changed standard cursor.
+ * 
+ * CursorIsNone of the window struct is NOT modified if you set a device
+ * cursor. 
+ *
+ * Assumption: If there is a node for a device in the list, the device has a
+ * cursor. If the cursor is set to None, it is inherited by the parent.
+ */
+int ChangeWindowDeviceCursor(register WindowPtr pWin, 
+                              DeviceIntPtr pDev, 
+                              CursorPtr pCursor) 
+{
+    DevCursNodePtr pNode, pPrev;
+    CursorPtr pOldCursor = NULL;
+    ScreenPtr pScreen;
+    WindowPtr pChild;
+
+    if (!pWin->optional && !MakeWindowOptional(pWin))
+        return BadAlloc;
+
+    /* 1) Check if window has device cursor set
+     *  Yes: 1.1) swap cursor with given cursor if parent does not have same
+     *            cursor, free old cursor
+     *       1.2) free old cursor, use parent cursor
+     *  No: 1.1) add node to beginning of list.
+     *      1.2) add cursor to node if parent does not have same cursor
+     *      1.3) use parent cursor if parent does not have same cursor
+     *  2) Patch up children if child has a devcursor
+     *  2.1) if child has cursor None, it inherited from parent, set to old
+     *  cursor
+     *  2.2) if child has same cursor as new cursor, remove and set to None
+     */
+
+    pScreen = pWin->drawable.pScreen;
+
+    if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev))
+    {
+        /* has device cursor */
+
+        if (pNode->cursor == pCursor)
+            return Success;
+
+        pOldCursor = pNode->cursor;
+
+        if (!pCursor) /* remove from list */
+        {
+            pPrev->next = pNode->next;
+            xfree(pNode);
+        }
+
+    } else
+    {
+        /* no device cursor yet */
+        DevCursNodePtr pNewNode;
+
+        if (!pCursor)
+            return Success;
+
+        pNewNode = (DevCursNodePtr)xalloc(sizeof(DevCursNodeRec));
+        pNewNode->dev = pDev;
+        pNewNode->next = pWin->optional->deviceCursors;
+        pWin->optional->deviceCursors = pNewNode;
+        pNode = pNewNode;
+
+    }
+
+    if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor))
+        pNode->cursor = None;
+    else
+    {
+        pNode->cursor = pCursor;
+        pCursor->refcnt++;
+    }
+
+    pNode = pPrev = NULL;
+    /* fix up children */
+    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+    {
+        if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev))
+        {
+            if (pNode->cursor == None) /* inherited from parent */
+            {
+                pNode->cursor = pOldCursor;
+                pOldCursor->refcnt++;
+            } else if (pNode->cursor == pCursor)
+            {
+                pNode->cursor = None;
+                FreeCursor(pCursor, (Cursor)0); /* fix up refcnt */
+            }
+        }
+    }
+
+    if (pWin->realized)
+        WindowHasNewCursor(pWin);
+
+    if (pOldCursor)
+        FreeCursor(pOldCursor, (Cursor)0);
+
+    /* FIXME: We SHOULD check for an error value here XXX  
+       (comment taken from ChangeWindowAttributes) */
+    (*pScreen->ChangeWindowAttributes)(pWin, CWCursor);
+
+    return Success;
+}
+
+/* Get device cursor for given device or None if none is set */
+CursorPtr WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev)
+{
+    DevCursorList pList;
+
+    if (!pWin->optional || !pWin->optional->deviceCursors)
+        return NULL;
+
+    pList = pWin->optional->deviceCursors;
+
+    while(pList)
+    {
+        if (pList->dev == pDev)
+        {
+            if (pList->cursor == None) /* inherited from parent */
+                return WindowGetDeviceCursor(pWin->parent, pDev);
+            else
+                return pList->cursor;
+        }
+        pList = pList->next;
+    }
+    return NULL;
+}
+
+/* Searches for a DevCursorNode for the given window and device. If one is
+ * found, return True and set pNode and pPrev to the node and to the node
+ * before the node respectively. Otherwise return False.
+ */
+static Bool 
+WindowSeekDeviceCursor(WindowPtr pWin, 
+                       DeviceIntPtr pDev, 
+                       DevCursNodePtr* pNode, 
+                       DevCursNodePtr* pPrev)
+{
+    DevCursorList pList;
+
+    if (!pWin->optional)
+        return FALSE;
+
+    pList = pWin->optional->deviceCursors;
+    while(pList)
+    {
+        if (pList->next)
+        {
+            if (pList->next->dev == pDev)
+            {
+                *pNode = pList->next;
+                *pPrev = pList;
+                return TRUE;
+            }
+        }
+        pList = pList->next;
+    }
+    return FALSE;
+}
+
+/* Return True if a parent has the same device cursor set or False if
+ * otherwise 
+ */ 
+static Bool 
+WindowParentHasDeviceCursor(WindowPtr pWin, 
+                            DeviceIntPtr pDev, 
+                            CursorPtr pCursor)
+{
+    WindowPtr pParent;
+    DevCursNodePtr pParentNode, pParentPrev;
+
+    pParent = pWin->parent;
+    while(pParent)
+    {
+        if (WindowSeekDeviceCursor(pParent, pDev, 
+                    &pParentNode, &pParentPrev))
+        {
+            /* if there is a node in the list, the win has a dev cursor */
+            if (!pParentNode->cursor) /* inherited. loop needs to cont. */
+            {
+            } else if (pParentNode->cursor == pCursor) /* inherit */
+                return TRUE;
+            else  /* different cursor */
+                return FALSE;
+        } 
+        else 
+            /* parent does not have a device cursor for our device */
+            return FALSE;
+    }
+    return FALSE;
+}
+
+
 #ifndef NOLOGOHACK
 static void
 DrawLogo(WindowPtr pWin)
diff --git a/include/window.h b/include/window.h
index bddeb25..8f2522c 100644
--- a/include/window.h
+++ b/include/window.h
@@ -67,6 +67,10 @@ SOFTWARE.
 #define WT_NOMATCH 3
 #define NullWindow ((WindowPtr) 0)
 
+/* Forward declaration, we can't include input.h here */
+struct _DeviceIntRec;
+struct _Cursor;
+
 typedef struct _BackingStore *BackingStorePtr;
 typedef struct _Window *WindowPtr;
 
@@ -143,6 +147,15 @@ extern int ChangeWindowAttributes(
     XID* /*vlist*/,
     ClientPtr /*client*/);
 
+extern int ChangeWindowDeviceCursor(
+    WindowPtr /*pWin*/,
+    struct _DeviceIntRec* /*pDev*/,
+    struct _Cursor* /*pCursor*/);
+
+extern struct _Cursor* WindowGetDeviceCursor(
+    WindowPtr /*pWin*/,
+    struct _DeviceIntRec* /*pDev*/);
+
 /* Quartz support on Mac OS X uses the HIToolbox
    framework whose GetWindowAttributes function conflicts here. */
 #ifdef __DARWIN__
diff --git a/include/windowstr.h b/include/windowstr.h
index a37dc6b..4e9c82c 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -70,6 +70,13 @@ SOFTWARE.
 #define SameBorder(as, a, bs, b)				\
     EqualPixUnion(as, a, bs, b)
 
+/* used as NULL-terminated list */
+typedef struct _DevCursorNode {
+    CursorPtr                   cursor;
+    DeviceIntPtr                dev;
+    struct _DevCursorNode*      next;
+} DevCursNodeRec, *DevCursNodePtr, *DevCursorList;
+
 typedef struct _WindowOpt {
     VisualID		visual;		   /* default: same as parent */
     CursorPtr		cursor;		   /* default: window.cursorNone */
@@ -89,6 +96,7 @@ typedef struct _WindowOpt {
 #ifdef XINPUT
     struct _OtherInputMasks *inputMasks;   /* default: NULL */
 #endif
+    DevCursorList       deviceCursors;     /* default: NULL */
 } WindowOptRec, *WindowOptPtr;
 
 #define BackgroundPixel	    2L
commit 9fd2f167ec02ee170b87f02ddca89eba0b2e2389
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Dec 20 16:30:36 2006 +1030

    xfree86: fix xf86ProcessCommonOptions() core and shared pointer assignment
    
    TAG: mpx-0.3.0

diff --git a/Changelog b/Changelog
index 0cf051f..ef42159 100644
--- a/Changelog
+++ b/Changelog
@@ -38,6 +38,15 @@ Files:
 	include/mpxevents.h
 	include/mpxextinit.h
 
+____________________________________________________________
+xfree86: fix xf86ProcessCommonOptions() core and shared pointer assignment
+
+Files:
+	hw/xfree86/common/xf86Xinput.c
+
+TAG: mpx-0.3.0
+
+
 == 18.12.06 ==
 mi:     removing MPX ifdefs
 	global sprite renaming in mipointer and misprite
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index bf97112..fd2a451 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -124,11 +124,12 @@ _X_EXPORT void
 xf86ProcessCommonOptions(LocalDevicePtr local,
                          pointer	list)
 {
-    if (!xf86SetBoolOption(list, "AlwaysCore", 0) ||
+    if (xf86SetBoolOption(list, "AlwaysCore", 0) ||
         xf86SetBoolOption(list, "SendCoreEvents", 0) ||
         xf86SetBoolOption(list, "CorePointer", 0) ||
         xf86SetBoolOption(list, "CoreKeyboard", 0)) {
         local->flags |= XI86_ALWAYS_CORE;
+        local->flags |= XI86_SHARED_POINTER;
         xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name);
     }
 
commit 056c919d849a78c8d507bfcecfa74c0b0165751a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Dec 20 14:49:17 2006 +1030

    removing MPX extension files

diff --git a/Changelog b/Changelog
index 01bc1e8..0cf051f 100644
--- a/Changelog
+++ b/Changelog
@@ -30,6 +30,14 @@ Files:
 	include/extinit.h
 	Xi/extinit.c
 
+____________________________________________________________
+removing MPX extension files
+
+Files:
+	mpx/
+	include/mpxevents.h
+	include/mpxextinit.h
+
 == 18.12.06 ==
 mi:     removing MPX ifdefs
 	global sprite renaming in mipointer and misprite
diff --git a/include/mpxevents.h b/include/mpxevents.h
deleted file mode 100644
index 99bf2b0..0000000
--- a/include/mpxevents.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef MPXEVENTS_H
-#define MPXEVENTS_H 1
-
-#include <X11/X.h>	/* for inputstr.h    */
-#include <X11/Xproto.h>	/* Request macro     */
-#include "inputstr.h"	/* DeviceIntPtr      */
-
-extern int MPXSelectForWindow(
-	WindowPtr              /* pWin */,
-	ClientPtr              /* client */,
-        int                    /* mask */);
-
-#endif
diff --git a/include/mpxextinit.h b/include/mpxextinit.h
deleted file mode 100644
index 02be6c1..0000000
--- a/include/mpxextinit.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-/********************************************************************
- * Interface of mpx/extinit.c
- */
-
-#ifndef MPXEXTINIT_H
-#define MPXEXTINIT_H
-
-#include "extnsionst.h"
-
-void
-MPXExtensionInit(
-	void
-	);
-
-int
-ProcMPXDispatch (
-	ClientPtr              /* client */
-	);
-
-int
-SProcMPXDispatch(
-	ClientPtr              /* client */
-	);
-
-void
-SReplyMPXDispatch (
-	ClientPtr              /* client */,
-	int                    /* len */,
-	xMPXGetExtensionVersionReply *     /* rep */
-	);
-
-void
-SEventMPXDispatch (
-	xEvent *               /* from */,
-	xEvent *               /* to */
-	);
-
-void
-MPXFixExtensionEvents (
-	ExtensionEntry 	*      /* extEntry */
-	);
-
-void
-MPXResetProc(
-	ExtensionEntry *       /* unused */
-	);
-
-Mask
-MPXGetNextExtEventMask (
-	void
-);
-
-void
-MPXSetMaskForExtEvent(
-	Mask                   /* mask */,
-	int                    /* event */
-	);
-
-void
-MPXAllowPropagateSuppress (
-	Mask                   /* mask */
-	);
-
-void
-MPXRestoreExtensionEvents (
-	void
-	);
-#endif
-
-
diff --git a/mpx/Makefile.am b/mpx/Makefile.am
deleted file mode 100644
index b35d8e7..0000000
--- a/mpx/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-noinst_LTLIBRARIES = libmpx.la
-
-AM_CFLAGS = $(DIX_CFLAGS)
-
-libmpx_la_SOURCES =	\
-	extinit.c \
-        getvers.c \
-	getvers.h \
-        listdev.c \
-        listdev.h \
-        selectev.c \
-        selectev.h \
-        mpxglobals.h \
-	getevbase.c \
-	getevbase.h \
-        queryptr.h \
-        queryptr.c 
-
diff --git a/mpx/extinit.c b/mpx/extinit.c
deleted file mode 100644
index 4b4bd47..0000000
--- a/mpx/extinit.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "inputstr.h"
-#include "extnsionst.h"	/* extension entry   */
-#include <X11/extensions/MPX.h>
-#include <X11/extensions/MPXproto.h>
-#include <X11/extensions/MPXconst.h>
-
-#include "mpxglobals.h"
-#include "mpxextinit.h"
-#include "swaprep.h"
-
-#include "getvers.h"
-#include "listdev.h"
-#include "selectev.h"
-#include "getevbase.h"
-#include "queryptr.h"
-
-static Mask lastExtEventMask = 1;
-int MPXEventIndex;
-MPXExtEventInfo EventInfo[32];
-
-/**
- * MPX piggybacks on the X Input extension's event system. Each window has an
- * array of event masks, from 0 to MAX_DEVICES. In XI, each device can have
- * separate event masks. Before an event is delivered, the array at the index
- * of the device is checked.
- *
- * Two things:
- * -) core devices do not send input extension events
- * -) MPX events are not device specific.
- *
- * Since the mask of the core pointer (index 1) is thus not used by XI, MPX
- * can use it for the event mask. This also makes MPX less intrusive.  
- */
-int MPXmskidx = 1;
-
-
-/*****************************************************************
- *
- * Externs defined elsewhere in the X server.
- *
- */
-
-extern MPXExtensionVersion AllExtensionVersions[];
-
-Mask PropagateMask[MAX_DEVICES];
-
-/*****************************************************************
- *
- * Globals referenced elsewhere in the server.
- *
- */
-
-int MPXReqCode = 0;
-int MPXEventBase = 0;
-int MPXErrorBase = 0;
-
-int MPXButtonPress;
-int MPXButtonRelease;
-int MPXMotionNotify;
-int MPXLastEvent;
-
-/*****************************************************************
- *
- * Declarations of local routines.
- *
- */
-
-static MPXExtensionVersion thisversion = { 
-    MPX_Major,
-    MPX_Minor
-};
-
-/**********************************************************************
- *
- * MPXExtensionInit - initialize the input extension.
- *
- * Called from InitExtensions in main() or from QueryExtension() if the
- * extension is dynamically loaded.
- *
- * This extension has several events and errors.
- *
- */
-
-void
-MPXExtensionInit(void)
-{
-    ExtensionEntry *extEntry;
-
-    extEntry = AddExtension(MPXNAME, MPXEVENTS, MPXERRORS, 
-                            ProcMPXDispatch, SProcMPXDispatch, 
-                            MPXResetProc, StandardMinorOpcode);
-    if (extEntry) {
-	MPXReqCode = extEntry->base;
-        MPXEventBase = extEntry->eventBase;
-        MPXErrorBase = extEntry->errorBase;
-
-	AllExtensionVersions[MPXReqCode - 128] = thisversion;
-	MPXFixExtensionEvents(extEntry);
-	ReplySwapVector[MPXReqCode] = (ReplySwapPtr) SReplyMPXDispatch;
-	EventSwapVector[MPXButtonPress] = SEventMPXDispatch;
-	EventSwapVector[MPXButtonRelease] = SEventMPXDispatch;
-	EventSwapVector[MPXMotionNotify] = SEventMPXDispatch;
-    } else {
-	FatalError("MPXExtensionInit: AddExtensions failed\n");
-    }
-}
-
-/*************************************************************************
- *
- * ProcMPXDispatch - main dispatch routine for requests to this extension.
- * This routine is used if server and client have the same byte ordering.
- *
- */
-
-int 
-ProcMPXDispatch(register ClientPtr client)
-{
-    REQUEST(xReq);
-    if (stuff->data == X_MPXGetExtensionVersion)
-        return (ProcMPXGetExtensionVersion(client));
-    if (stuff->data == X_MPXListDevices)
-        return (ProcMPXListDevices(client));
-    if (stuff->data == X_MPXSelectEvents)
-        return (ProcMPXSelectEvents(client));
-    if (stuff->data == X_MPXGetEventBase)
-        return (ProcMPXGetEventBase(client));
-    if (stuff->data == X_MPXQueryPointer)
-        return (ProcMPXQueryPointer(client));
-    else {
-        SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
-    }
-
-    return (BadRequest);
-}
-
-/*******************************************************************************
- *
- * SProcMPXDispatch 
- *
- * Main swapped dispatch routine for requests to this extension.
- * This routine is used if server and client do not have the same byte ordering.
- *
- */
-
-int 
-SProcMPXDispatch(register ClientPtr client)
-{
-    REQUEST(xReq);
-    if (stuff->data == X_MPXGetExtensionVersion)
-        return (SProcMPXGetExtensionVersion(client));
-    if (stuff->data == X_MPXListDevices)
-        return (SProcMPXListDevices(client));
-    if (stuff->data == X_MPXSelectEvents)
-        return (SProcMPXSelectEvents(client));
-    if (stuff->data == X_MPXGetEventBase)
-        return (SProcMPXGetEventBase(client));
-    if (stuff->data == X_MPXQueryPointer)
-        return (SProcMPXQueryPointer(client));
-    else {
-        SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
-    }
-
-    return (BadRequest);
-}
-
-/***********************************************************************
- *
- * MPXResetProc.
- * Remove reply-swapping routine.
- * Remove event-swapping routine.
- *
- */
-
-void
-MPXResetProc(ExtensionEntry* unused)
-{
-    ReplySwapVector[MPXReqCode] = ReplyNotSwappd;
-    EventSwapVector[MPXButtonPress] = NotImplemented;
-    EventSwapVector[MPXButtonRelease] = NotImplemented;
-    EventSwapVector[MPXMotionNotify] = NotImplemented;
-
-    MPXRestoreExtensionEvents();
-
-}
-
-void SReplyMPXDispatch(ClientPtr client, int len, xMPXGetExtensionVersionReply* rep)
-{
-    if (rep->RepType ==  X_MPXGetExtensionVersion)
-        SRepMPXGetExtensionVersion(client, len, 
-                (xMPXGetExtensionVersionReply*) rep);
-    if (rep->RepType ==  X_MPXListDevices)
-        SRepMPXListDevices(client, len, 
-                (xMPXListDevicesReply*) rep);
-    else {
-	FatalError("MPX confused sending swapped reply");
-    }
-}
-
-void 
-SEventMPXDispatch(xEvent* from, xEvent* to)
-{
-    int type = from->u.u.type & 0177;
-    if (type == MPXButtonPress) {
-	SKeyButtonPtrEvent(from, to);
-	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
-    } else if (type == MPXButtonRelease) {
-	SKeyButtonPtrEvent(from, to);
-	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
-    } else if (type == MPXMotionNotify) {
-	SKeyButtonPtrEvent(from, to);
-	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
-    } else {
-	FatalError("XInputExtension: Impossible event!\n");
-    }
-}
-
-void 
-MPXFixExtensionEvents(ExtensionEntry* extEntry)
-{
-    MPXButtonPress = extEntry->eventBase;
-    MPXButtonRelease = MPXButtonPress + 1;
-    MPXMotionNotify = MPXButtonRelease + 1;
-    MPXLastEvent = MPXMotionNotify + 1;
-
-    MPXSetMaskForExtEvent(MPXButtonPressMask, MPXButtonPress);
-    MPXSetMaskForExtEvent(MPXButtonReleaseMask, MPXButtonRelease);
-    MPXSetMaskForExtEvent(MPXPointerMotionMask, MPXMotionNotify);
-}
-
-
-/**************************************************************************
- *
- * Assign the specified mask to the specified event.
- *
- */
-
-void
-MPXSetMaskForExtEvent(Mask mask, int event)
-{
-
-    EventInfo[MPXEventIndex].mask = mask;
-    EventInfo[MPXEventIndex++].type = event;
-
-    if ((event < LASTEvent) || (event >= 128))
-	FatalError("MaskForExtensionEvent: bogus event number");
-    SetMaskForEvent(mask, event);
-}
-
-/************************************************************************
- *
- * This function restores extension event types and masks to their 
- * initial state.
- *
- */
-
-void
-MPXRestoreExtensionEvents(void)
-{
-    int i;
-
-    MPXReqCode = 0;
-    for (i = 0; i < MPXEventIndex - 1; i++) {
-	if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
-	    SetMaskForEvent(0, EventInfo[i].type);
-	EventInfo[i].mask = 0;
-	EventInfo[i].type = 0;
-    }
-
-    MPXEventIndex = 0;
-    lastExtEventMask = 1;
-    MPXButtonPress = 0;
-    MPXButtonRelease = 1;
-    MPXMotionNotify = 2;
-}
-
-/**************************************************************************
- *
- * Allow the specified event to have its propagation suppressed.
- * The default is to not allow suppression of propagation.
- *
- */
-
-void
-MPXAllowPropagateSuppress(Mask mask)
-{
-    int i;
-
-    for (i = 0; i < MAX_DEVICES; i++)
-	PropagateMask[i] |= mask;
-}
-
diff --git a/mpx/getevbase.c b/mpx/getevbase.c
deleted file mode 100644
index 8b0f598..0000000
--- a/mpx/getevbase.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#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 <X11/extensions/MPX.h>
-#include <X11/extensions/MPXproto.h>
-
-#include "mpxglobals.h"
-#include "getevbase.h"
-
-/***********************************************************************
- *
- * This procedure writes the reply for the MPXGetEventBase function.
- */
-int
-ProcMPXGetEventBase(register ClientPtr client)
-{
-    xMPXGetEventBaseReply rep;
-
-    REQUEST(xMPXGetEventBaseReq);
-    REQUEST_SIZE_MATCH(xMPXGetEventBaseReq);
-
-    memset(&rep, 0, sizeof(xMPXGetEventBaseReply));
-    rep.repType = X_Reply;
-    rep.RepType = X_MPXGetEventBase;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-
-    rep.eventBase = MPXEventBase;
-
-    WriteReplyToClient(client, sizeof(xMPXGetEventBaseReply), &rep);
-
-    return Success;
-}
-
-/***********************************************************************
- *
- * This procedure writes the reply for the MPXGetEventBase function.
- */
-int
-SProcMPXGetEventBase(register ClientPtr client)
-{
-    register char n;
-
-    REQUEST(xMPXGetEventBaseReq);
-    swaps(&stuff->length, n);
-    REQUEST_SIZE_MATCH(xMPXGetEventBaseReq);
-    return (ProcMPXGetEventBase(client));
-}
-
diff --git a/mpx/getevbase.h b/mpx/getevbase.h
deleted file mode 100644
index 5ff8284..0000000
--- a/mpx/getevbase.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef GETEVBASE_H
-#define GETEVBASE_H 1
-
-int SProcMPXGetEventBase(ClientPtr	/* client */
-    );
-
-int ProcMPXGetEventBase(ClientPtr	/* client */
-    );
-
-#endif /* GETEVBASE_H */
diff --git a/mpx/getvers.c b/mpx/getvers.c
deleted file mode 100644
index fc3fc56..0000000
--- a/mpx/getvers.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#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 <X11/extensions/MPX.h>
-#include <X11/extensions/MPXproto.h>
-
-#include "mpxglobals.h"
-#include "getvers.h"
-
-MPXExtensionVersion AllExtensionVersions[128];
-
-/***********************************************************************
- *
- * Handle a request from a client with a different byte order than us.
- *
- */
-
-int
-SProcMPXGetExtensionVersion(register ClientPtr client)
-{
-    register char n;
-
-    REQUEST(xMPXGetExtensionVersionReq);
-    swaps(&stuff->length, n);
-    swaps(&stuff->major_version, n);
-    swaps(&stuff->minor_version, n);
-    REQUEST_AT_LEAST_SIZE(xMPXGetExtensionVersionReq);
-    return (ProcMPXGetExtensionVersion(client));
-}
-/***********************************************************************
- *
- * This procedure writes the reply for the XGetExtensionVersion function.
- */
-
-int
-ProcMPXGetExtensionVersion(register ClientPtr client)
-{
-    xMPXGetExtensionVersionReply rep;
-
-    REQUEST(xMPXGetExtensionVersionReq);
-    REQUEST_SIZE_MATCH(xMPXGetExtensionVersionReq);
-
-    rep.repType = X_Reply;
-    rep.RepType = X_MPXGetExtensionVersion;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-
-    rep.major_version = AllExtensionVersions[MPXReqCode - 128].major;
-    rep.minor_version = AllExtensionVersions[MPXReqCode - 128].minor;
-    WriteReplyToClient(client, sizeof(xMPXGetExtensionVersionReply), &rep);
-
-    return Success;
-}
-
-/***********************************************************************
- *
- * This procedure writes the reply for the MPXGetExtensionVersion function,
- * if the client and server have a different byte ordering.
- *
- */
-
-void
-SRepMPXGetExtensionVersion(ClientPtr client, int size,
-			 xMPXGetExtensionVersionReply * rep)
-{
-    register char n;
-
-    swaps(&rep->sequenceNumber, n);
-    swapl(&rep->length, n);
-    swaps(&rep->major_version, n);
-    swaps(&rep->minor_version, n);
-    WriteToClient(client, size, (char *)rep);
-}
-
-
diff --git a/mpx/getvers.h b/mpx/getvers.h
deleted file mode 100644
index 8800ac6..0000000
--- a/mpx/getvers.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef GETVERS_H
-#define GETVERS_H 1
-
-int SProcMPXGetExtensionVersion(ClientPtr	/* client */
-    );
-
-int ProcMPXGetExtensionVersion(ClientPtr	/* client */
-    );
-
-void SRepMPXGetExtensionVersion(ClientPtr /* client */ ,
-			      int /* size */ ,
-			      xMPXGetExtensionVersionReply *	/* rep */
-    );
-
-#endif
-
diff --git a/mpx/listdev.c b/mpx/listdev.c
deleted file mode 100644
index f977110..0000000
--- a/mpx/listdev.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "inputstr.h"
-
-#include <X11/extensions/MPX.h>
-#include <X11/extensions/MPXproto.h>
-
-#include "mpxextinit.h"
-#include "mpxglobals.h"
-
-#include "listdev.h"
-
-/***********************************************************************
- *
- * This procedure lists the MPX devices available to the server.
- *
- */
-int SProcMPXListDevices(register ClientPtr client)
-{
-    register char n;
-
-    REQUEST(xMPXListDevicesReq);
-    swaps(&stuff->length, n);
-    return (ProcMPXListDevices(client));
-}
-
-/***********************************************************************
- *
- * This procedure lists the MPX devices available to the server.
- *
- * Strongly based on ProcXListInputDevices
- */
-int ProcMPXListDevices(register ClientPtr client)
-{
-    xMPXListDevicesReply rep;
-    int numdevs = 0;
-    int namesize = 1;	/* need 1 extra byte for strcpy */
-    int size = 0;
-    int total_length; 
-    char* devbuf;
-    char* namebuf;
-    char *savbuf;
-    xMPXDeviceInfoPtr dev;
-    DeviceIntPtr d;
-
-    REQUEST_SIZE_MATCH(xMPXListDevicesReq);
-    memset(&rep, 0, sizeof(xMPXListDevicesReply));
-    rep.repType = X_Reply;
-    rep.RepType = X_MPXListDevices;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-
-    for (d = inputInfo.devices; d; d = d->next) {
-        if (d->isMPDev)
-        {
-            SizeMPXDeviceInfo(d, &namesize, &size);
-            numdevs++;
-        }
-    }
-
-    for (d = inputInfo.off_devices; d; d = d->next) {
-        if (d->isMPDev)
-        {
-            SizeMPXDeviceInfo(d, &namesize, &size);
-            numdevs++;
-        }
-    }
-
-    total_length = numdevs * sizeof(xMPXDeviceInfo) + size + namesize;
-    devbuf = (char *)xalloc(total_length);
-    namebuf = devbuf + (numdevs * sizeof(xMPXDeviceInfo));
-    savbuf = devbuf;
-
-    dev = (xMPXDeviceInfoPtr) devbuf;
-    for (d = inputInfo.devices; d; d = d->next, dev++)
-        if (d->isMPDev)
-            SetMPXDeviceInfo(client, d, dev, &devbuf, &namebuf);
-    for (d = inputInfo.off_devices; d; d = d->next, dev++)
-        if (d->isMPDev)
-            SetMPXDeviceInfo(client, d, dev, &devbuf, &namebuf);
-
-    rep.ndevices = numdevs;
-    rep.length = (total_length + 3) >> 2;
-    WriteReplyToClient(client, sizeof(xMPXListDevicesReply), &rep);
-    WriteToClient(client, total_length, savbuf);
-    xfree(savbuf);
-    return Success;
-}
-
-/***********************************************************************
- *
- * This procedure calculates the size of the information to be returned
- * for an input device.
- *
- */
-
-void
-SizeMPXDeviceInfo(DeviceIntPtr d, int *namesize, int *size)
-{
-    *namesize += 1;
-    if (d->name)
-	*namesize += strlen(d->name);
-}
-
-/***********************************************************************
- *
- * This procedure sets information to be returned for an input device.
- *
- */
-
-void
-SetMPXDeviceInfo(ClientPtr client, DeviceIntPtr d, xMPXDeviceInfoPtr dev,
-	       char **devbuf, char **namebuf)
-{
-    MPXCopyDeviceName(namebuf, d->name);
-    MPXCopySwapDevice(client, d, devbuf);
-}
-
-
-/***********************************************************************
- *
- * This procedure copies data to the DeviceInfo struct, swapping if necessary.
- *
- * We need the extra byte in the allocated buffer, because the trailing null
- * hammers one extra byte, which is overwritten by the next name except for
- * the last name copied.
- *
- */
-
-void
-MPXCopyDeviceName(char **namebuf, char *name)
-{
-    char *nameptr = (char *)*namebuf;
-
-    if (name) {
-	*nameptr++ = strlen(name);
-	strcpy(nameptr, name);
-	*namebuf += (strlen(name) + 1);
-    } else {
-	*nameptr++ = 0;
-	*namebuf += 1;
-    }
-}
-
-/***********************************************************************
- *
- * This procedure copies data to the DeviceInfo struct, swapping if necessary.
- *
- */
-void
-MPXCopySwapDevice(register ClientPtr client, DeviceIntPtr d, char **buf)
-{
-    register char n;
-    xMPXDeviceInfoPtr dev;
-
-    dev = (xMPXDeviceInfoPtr) * buf;
-    memset(dev, 0, sizeof(xMPXDeviceInfo));
-
-    dev->id = d->id;
-    dev->type = d->type;
-    if (client->swapped) {
-	swapl(&dev->type, n);	/* macro - braces are required */
-    }
-    *buf += sizeof(xMPXDeviceInfo);
-}
-
-/***********************************************************************
- *
- * This procedure writes the reply for the MPXListDevices function,
- * if the client and server have a different byte ordering.
- *
- */
-void
-SRepMPXListDevices(ClientPtr client, int size, xMPXListDevicesReply * rep)
-{
-    register char n;
-
-    swaps(&rep->sequenceNumber, n);
-    swapl(&rep->length, n);
-    WriteToClient(client, size, (char *)rep);
-}
diff --git a/mpx/listdev.h b/mpx/listdev.h
deleted file mode 100644
index 079fe8e..0000000
--- a/mpx/listdev.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef LISTDEV_H
-#define LISTDEV_H 1
-
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "inputstr.h"
-
-#include <X11/extensions/MPX.h>
-#include <X11/extensions/MPXproto.h>
-
-#include "mpxextinit.h"
-#include "mpxglobals.h"
-
-int SProcMPXListDevices(ClientPtr	/* client */
-    );
-
-int ProcMPXListDevices(ClientPtr	/* client */
-    );
-
-void SizeMPXDeviceInfo(DeviceIntPtr /* d */ ,
-		    int * /* namesize */ ,
-		    int *	/* size */
-    );
-
-void SetMPXDeviceInfo(ClientPtr /* client */ ,
-		    DeviceIntPtr /* d */ ,
-		    xMPXDeviceInfoPtr /* dev */ ,
-		    char ** /* devbuf */ ,
-		    char **	/* namebuf */
-    );
-
-
-void MPXCopyDeviceName(char ** /* namebuf */ ,
-		    char *	/* name */
-    );
-
-void MPXCopySwapDevice(ClientPtr /* client */ ,
-		    DeviceIntPtr /* d */ ,
-		    char **	/* buf */
-    );
-
-void SRepMPXListDevices(ClientPtr /* client */ ,
-			   int /* size */ ,
-			   xMPXListDevicesReply *	/* rep */
-    );
-#endif
diff --git a/mpx/mpxglobals.h b/mpx/mpxglobals.h
deleted file mode 100644
index 73f3990..0000000
--- a/mpx/mpxglobals.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef MPXGLOBALS_H
-#define MPXGLOBALS_H 1
-
-extern int MPXReqCode;
-extern int MPXEventBase;
-extern int MPXErrorBase;
-
-extern Mask PropagateMask[];
-
-extern int MPXmskidx;
-
-/* events */
-extern int MPXButtonPress;
-extern int MPXButtonRelease;
-extern int MPXMotionNotify;
-extern int MPXLastEvent;
-
-#define IsMPXEvent(xE) \
-    ((xE)->u.u.type >= MPXEventBase \
-     && (xE)->u.u.type < MPXLastEvent) 
-
-
-#endif
diff --git a/mpx/queryptr.c b/mpx/queryptr.c
deleted file mode 100644
index 7162074..0000000
--- a/mpx/queryptr.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "inputstr.h"
-#include "windowstr.h"
-#include <X11/extensions/MPX.h>
-#include <X11/extensions/MPXproto.h>
-
-#include "mpxglobals.h"
-
-#include "queryptr.h"
-
-/***********************************************************************
- *
- * This procedure writes the reply for the MPXQueryPointer function.
- */
-int
-ProcMPXQueryPointer(register ClientPtr client)
-{
-    xMPXQueryPointerReply rep;
-    DeviceIntPtr pDev;
-    WindowPtr root, win;
-    int x, y;
-
-    REQUEST(xMPXQueryPointerReq);
-    REQUEST_SIZE_MATCH(xMPXQueryPointerReq);
-
-    pDev = LookupDeviceIntRec(stuff->deviceid);
-    if (!pDev->isMPDev)
-    {
-        SendErrorToClient(client, MPXReqCode, X_MPXQueryPointer,
-                stuff->deviceid, BadValue);
-        return Success;
-    }
-
-
-    memset(&rep, 0, sizeof(xMPXQueryPointerReply));
-    rep.repType = X_Reply;
-    rep.RepType = X_MPXQueryPointer;
-    rep.length = 0;
-    rep.sequenceNumber = client->sequence;
-
-    root = GetCurrentRootWindow();
-    win = GetSpriteWindow(pDev);
-    GetSpritePosition(pDev, &x, &y);
-
-    rep.root = root->drawable.id;
-    rep.root_x = x;
-    rep.root_y = y;
-    if (win != root)
-    {
-        rep.child = win->drawable.id;
-        rep.win_x = x - win->drawable.x;
-        rep.win_y = y - win->drawable.y;
-    }
-    else
-    {
-        rep.child = None;
-        rep.win_x = x;
-        rep.win_y = y;
-    }
-
-
-    rep.mask = pDev->button->state | inputInfo.keyboard->key->state;
-
-    WriteReplyToClient(client, sizeof(xMPXQueryPointerReply), &rep);
-
-    return Success;
-}
-
-
-/***********************************************************************
- *
- * This procedure writes the reply for the MPXQueryPointer function.
- */
-int
-SProcMPXQueryPointer(register ClientPtr client)
-{
-    register char n;
-
-    REQUEST(xMPXQueryPointerReq);
-    swaps(&stuff->length, n);
-    REQUEST_SIZE_MATCH(xMPXQueryPointerReq);
-    return (ProcMPXQueryPointer(client));
-}
diff --git a/mpx/queryptr.h b/mpx/queryptr.h
deleted file mode 100644
index c89397c..0000000
--- a/mpx/queryptr.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef QUERYPTR_H
-#define QUERYPTR_H 1
-
-int SProcMPXQueryPointer(ClientPtr	/* client */
-    );
-
-int ProcMPXQueryPointer(ClientPtr	/* client */
-    );
-
-#endif /* QUERYPTR_H */
diff --git a/mpx/selectev.c b/mpx/selectev.c
deleted file mode 100644
index fc2ff9c..0000000
--- a/mpx/selectev.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-
-#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 <X11/extensions/MPX.h>
-#include <X11/extensions/MPXproto.h>
-#include "extnsionst.h"
-#include "mpxextinit.h"	/* LookupDeviceIntRec */
-#include "mpxglobals.h"
-#include "mpxevents.h"
-
-#include "selectev.h"
-
-/* functions borrowed from XI */
-extern void RecalculateDeviceDeliverableEvents(
-	WindowPtr              /* pWin */);
-
-extern int AddExtensionClient (
-	WindowPtr              /* pWin */,
-	ClientPtr              /* client */,
-	Mask                   /* mask */,
-	int                    /* mskidx */);
-extern Bool
-ShouldFreeInputMasks(WindowPtr /* pWin */, 
-                     Bool /* ignoreSelectedEvents */);
-
-/***********************************************************************
- *
- * Handle requests from clients with a different byte order.
- *
- */
-
-int
-SProcMPXSelectEvents(register ClientPtr client)
-{
-    register char n;
-
-    REQUEST(xMPXSelectEventsReq);
-    swaps(&stuff->length, n);
-    REQUEST_SIZE_MATCH(xMPXSelectEventsReq);
-    swapl(&stuff->window, n);
-    return (ProcMPXSelectEvents(client));
-}
-
-/***********************************************************************
- *
- * This procedure selects input from an extension device.
- *
- */
-
-int
-ProcMPXSelectEvents(register ClientPtr client)
-{
-    int ret;
-    WindowPtr pWin;
-
-    REQUEST(xMPXSelectEventsReq);
-    REQUEST_SIZE_MATCH(xMPXSelectEventsReq);
-
-    if (stuff->length != (sizeof(xMPXSelectEventsReq) >> 2))
-    { 
-        SendErrorToClient(client, MPXReqCode, X_MPXSelectEvents, 0,
-			  BadLength);
-	return Success;
-    }
-
-    pWin = (WindowPtr) LookupWindow(stuff->window, client);
-    if (!pWin) 
-    {
-	client->errorValue = stuff->window;
-	SendErrorToClient(client, MPXReqCode, X_MPXSelectEvents, 0,
-			  BadWindow);
-	return Success;
-    }
-
-    if (stuff->mask >= MPXHighestMask)
-    {
-        client->errorValue = stuff->mask;
-	SendErrorToClient(client, MPXReqCode, X_MPXSelectEvents, 0,
-			  BadValue);
-    }
-
-    if ((ret = MPXSelectForWindow(pWin, client, stuff->mask)) != Success) 
-    { 
-        SendErrorToClient(client, MPXReqCode, X_MPXSelectEvents, 0, ret);
-        return Success;
-    }
-
-    return Success;
-}
-
-/**
- * Selects a set of events for a given window. 
- * Different to XI, MPX is not device dependent. Either the client gets events
- * from all devices or none.
- *
- * This method borrows some functions from XI, due to the piggyback on the
- * core pointer (see comment in extinit.c)
- */
-int 
-MPXSelectForWindow(WindowPtr pWin, ClientPtr client, int mask)
-{
-    InputClientsPtr others;
-    int ret;
-
-    if (mask >= MPXHighestMask)
-    {
-        client->errorValue = mask;
-        return BadValue;
-    }
-
-    if (wOtherInputMasks(pWin))
-    {
-        for (others = wOtherInputMasks(pWin)->inputClients; others; 
-                others = others->next)
-        {
-            if (SameClient(others, client)) {
-                others->mask[MPXmskidx] = mask;
-                if (mask == 0)
-                {
-                    /* clean up stuff */
-                    RecalculateDeviceDeliverableEvents(pWin);
-                    if (ShouldFreeInputMasks(pWin, FALSE))
-                        FreeResource(others->resource, RT_NONE);
-                    return Success;
-                }
-                goto maskSet;
-            }
-        }
-    }
-    /* borrow from XI here */
-    if ((ret = AddExtensionClient(pWin, client, mask, MPXmskidx)) != Success)
-        return ret;
-maskSet:
-    RecalculateDeviceDeliverableEvents(pWin);
-    return Success;
-
-}
-
diff --git a/mpx/selectev.h b/mpx/selectev.h
deleted file mode 100644
index 7026199..0000000
--- a/mpx/selectev.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef SELECTEV_H
-#define SELECTEV_H 1
-
-int SProcMPXSelectEvents(ClientPtr	/* client */
-    );
-
-int ProcMPXSelectEvents(ClientPtr	/* client */
-    );
-
-#endif /* SELECTEV_H */
commit b55e1239ac3b2962a33d8af1f911cc0f01f40f23
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Dec 20 14:43:38 2006 +1030

    xfree86:  fix xf86ActivateDevice(): only set to MP device if not a keyboard

diff --git a/Changelog b/Changelog
index f698465..01bc1e8 100644
--- a/Changelog
+++ b/Changelog
@@ -21,6 +21,15 @@ Files:
 
 Note: This commit requires libXi additions to use the new functions.
 
+____________________________________________________________
+
+xfree86:  fix xf86ActivateDevice(): only set to MP device if not a keyboard
+
+Files:
+	hw/xfree86/common/xf86Xinput.c
+	include/extinit.h
+	Xi/extinit.c
+
 == 18.12.06 ==
 mi:     removing MPX ifdefs
 	global sprite renaming in mipointer and misprite
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 1619958..7c737a1 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -868,6 +868,21 @@ AssignTypeAndName(DeviceIntPtr dev, Atom type, char *name)
 
 /***********************************************************************
  *
+ * Returns true if a device may require a pointer (is not a keyboard).
+ *
+ */
+_X_EXPORT Bool
+MayNeedPointer(DeviceIntPtr dev)
+{
+    /* return false if device is a keyboard */
+    if (dev_type[0].type == dev->type)
+        return FALSE;
+  
+    return TRUE;
+}
+
+/***********************************************************************
+ *
  * Make device type atoms.
  *
  */
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 6f1ebf7..bf97112 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -171,7 +171,8 @@ xf86ActivateDevice(LocalDevicePtr local)
         local->dev = dev;      
         
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
-        dev->isMPDev = !(local->flags & XI86_SHARED_POINTER);
+        dev->isMPDev = 
+            MayNeedPointer(dev) && !(local->flags & XI86_SHARED_POINTER);
         InitSprite(dev, dev->isMPDev);
 
         RegisterOtherDevice(dev);
diff --git a/include/extinit.h b/include/extinit.h
index 2087d74..5546b21 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -131,6 +131,10 @@ AssignTypeAndName (
 	char *                 /* name */
 	);
 
+Bool MayNeedPointer(
+        DeviceIntPtr            /* dev */
+        );
+
 void
 MakeDeviceTypeAtoms (
 	void
commit 202b46eb6bf0d5f94973c2bf1e4ebe9d154eadbf
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Dec 20 13:05:53 2006 +1030

    xfree86: Changing "IsMPDevice" to "SharedPointer" option. Devices will default
    	 to MP devices.
    
    Xi:	Adding QueryDevicePointer request/reply
    	Adding WarpDevicePointer request/reply

diff --git a/Changelog b/Changelog
index 5890248..f698465 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,27 @@
-== 14.12.06 ==
+== 20.12.06 ==
+xfree86: Changing "IsMPDevice" to "SharedPointer" option. Devices will default 
+	 to MP devices.
+
+Xi:	Adding QueryDevicePointer request/reply
+	Adding WarpDevicePointer request/reply
+
+Files: 
+	hw/xfree86/common/xf86Xinput.c
+	hw/xfree86/common/xf86Cursor.c
+	hw/xfree86/common/xf86Xinput.h
+	Xi/extinit.c
+	Xi/querydp.c
+	Xi/querydp.h
+	Xi/Makefile.am
+	Xi/warpdevp.c
+	Xi/warpdevp.h
+	dix/cursor.c
+	dix/events.c
+	dix/dix.h
+
+Note: This commit requires libXi additions to use the new functions.
+
+== 18.12.06 ==
 mi:     removing MPX ifdefs
 	global sprite renaming in mipointer and misprite
 	fixed: multiple remove cursor call in miSpriteInstallColormap
diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index fbe4385..0aa5844 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -54,6 +54,8 @@ libXi_la_SOURCES =	\
 	listdev.h \
 	opendev.c \
 	opendev.h \
+	querydp.c \
+	querydp.h \
 	queryst.c \
 	queryst.h \
 	selectev.c \
@@ -75,6 +77,8 @@ libXi_la_SOURCES =	\
 	ungrdevb.c \
 	ungrdevb.h \
 	ungrdevk.c \
-	ungrdevk.h
+	ungrdevk.h \
+	warpdevp.c \
+	warpdevp.h 
 
 EXTRA_DIST = stubs.c
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 4548837..1619958 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -98,6 +98,7 @@ SOFTWARE.
 #include "gtmotion.h"
 #include "listdev.h"
 #include "opendev.h"
+#include "querydp.h"
 #include "queryst.h"
 #include "selectev.h"
 #include "sendexev.h"
@@ -110,6 +111,7 @@ SOFTWARE.
 #include "ungrdev.h"
 #include "ungrdevb.h"
 #include "ungrdevk.h"
+#include "warpdevp.h"
 
 static Mask lastExtEventMask = 1;
 int ExtEventIndex;
@@ -334,6 +336,10 @@ ProcIDispatch(register ClientPtr client)
 	return (ProcXGetDeviceControl(client));
     else if (stuff->data == X_ChangeDeviceControl)
 	return (ProcXChangeDeviceControl(client));
+    else if (stuff->data == X_QueryDevicePointer)
+        return (ProcXQueryDevicePointer(client));
+    else if (stuff->data == X_WarpDevicePointer)
+        return (ProcXWarpDevicePointer(client));
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -423,6 +429,10 @@ SProcIDispatch(register ClientPtr client)
 	return (SProcXGetDeviceControl(client));
     else if (stuff->data == X_ChangeDeviceControl)
 	return (SProcXChangeDeviceControl(client));
+    else if (stuff->data == X_QueryDevicePointer)
+	return (SProcXQueryDevicePointer(client));
+    else if (stuff->data == X_WarpDevicePointer)
+	return (SProcXWarpDevicePointer(client));
     else {
 	SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
     }
@@ -495,6 +505,9 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
     else if (rep->RepType == X_ChangeDeviceControl)
 	SRepXChangeDeviceControl(client, len,
 				 (xChangeDeviceControlReply *) rep);
+    else if (rep->RepType == X_QueryDevicePointer)
+	SRepXQueryDevicePointer(client, len,
+				 (xQueryDevicePointerReply *) rep);
     else {
 	FatalError("XINPUT confused sending swapped reply");
     }
diff --git a/Xi/querydp.c b/Xi/querydp.c
new file mode 100644
index 0000000..04323e4
--- /dev/null
+++ b/Xi/querydp.c
@@ -0,0 +1,166 @@
+/*
+
+Copyright 2006 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 query the pointer location of an extension input 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 <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "extnsionst.h"
+#include "extinit.h"	/* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+#endif
+
+#include "querydp.h"
+
+/***********************************************************************
+ *
+ * This procedure allows a client to query the pointer of a device.
+ *
+ */
+
+int
+SProcXQueryDevicePointer(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(xQueryDevicePointerReq);
+    swaps(&stuff->length, n);
+    return (ProcXQueryDevicePointer(client));
+}
+
+int
+ProcXQueryDevicePointer(register ClientPtr client)
+{
+    int rc;
+    xQueryDevicePointerReply rep;
+    DeviceIntPtr pDev;
+    WindowPtr pWin, t;
+    SpritePtr pSprite;
+
+    REQUEST(xQueryDevicePointerReq);
+    REQUEST_SIZE_MATCH(xQueryDevicePointerReq);
+
+    pDev = LookupDeviceIntRec(stuff->deviceid);
+    if (pDev == NULL) {
+        SendErrorToClient(client, IReqCode, X_QueryDevicePointer,
+                stuff->deviceid, BadDevice); 
+        return Success;
+    }
+
+    rc = dixLookupWindow(&pWin, stuff->win, client, DixReadAccess);
+    if (rc != Success)
+    {
+        SendErrorToClient(client, IReqCode, X_QueryDevicePointer, 
+                stuff->win, rc);
+        return Success;
+    }
+
+    if (pDev->valuator->motionHintWindow)
+        MaybeStopHint(pDev, client);
+
+    pSprite = pDev->pSprite;
+    rep.repType = X_Reply;
+    rep.RepType = X_QueryDevicePointer;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+    rep.mask = pDev->button->state | inputInfo.keyboard->key->state;
+    rep.root = (GetCurrentRootWindow())->drawable.id;
+    rep.rootX = pSprite->hot.x;
+    rep.rootY = pSprite->hot.y;
+    rep.child = None;
+    rep.shared = (pDev->isMPDev) ? xFalse : xTrue; 
+
+    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
+    {
+        rep.sameScreen = xTrue;
+        rep.winX = pSprite->hot.x - pWin->drawable.x;
+        rep.winY = pSprite->hot.y - pWin->drawable.y;
+        for (t = pSprite->win; t; t = t->parent)
+            if (t->parent == pWin)
+            {
+                rep.child = t->drawable.id;
+                break;
+            }
+    } else
+    {
+        rep.sameScreen = xFalse;
+        rep.winX = 0;
+        rep.winY = 0;
+    }
+
+#ifdef PANORAMIX
+    if(!noPanoramiXExtension) {
+        rep.rootX += panoramiXdataPtr[0].x;
+        rep.rootY += panoramiXdataPtr[0].y;
+        if (stuff->win == rep.root)
+        {
+            rep.winX += panoramiXdataPtr[0].x;
+            rep.winY += panoramiXdataPtr[0].y;
+        }
+    }
+#endif
+
+    WriteReplyToClient(client, sizeof(xQueryDevicePointerReply), &rep);
+    return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XQueryDevicePointer function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void
+SRepXQueryDevicePointer(ClientPtr client, int size, 
+        xQueryDevicePointerReply * rep)
+{
+    register char n;
+
+    swaps(&rep->sequenceNumber, n);
+    swapl(&rep->length, n);
+    WriteToClient(client, size, (char *)rep);
+}
diff --git a/Xi/querydp.h b/Xi/querydp.h
new file mode 100644
index 0000000..acad548
--- /dev/null
+++ b/Xi/querydp.h
@@ -0,0 +1,44 @@
+/************************************************************
+
+Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au>
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the above listed
+copyright holder(s) not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef QUERYDP_H
+#define QUERYDP_H 1
+
+int SProcXQueryDevicePointer(ClientPtr	/* client */
+    );
+
+int ProcXQueryDevicePointer(ClientPtr	/* client */
+    );
+
+void SRepXQueryDevicePointer(ClientPtr /* client */ ,
+			   int /* size */ ,
+			   xQueryDevicePointerReply *	/* rep */
+    );
+
+#endif /* QUERYDP_H */
diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c
new file mode 100644
index 0000000..2b558d1
--- /dev/null
+++ b/Xi/warpdevp.c
@@ -0,0 +1,186 @@
+/*
+
+Copyright 2006 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 Warp the pointer location of an extension input 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 "warpdevp.h"
+/***********************************************************************
+ *
+ * This procedure allows a client to warp the pointer of a device.
+ *
+ */
+
+int
+SProcXWarpDevicePointer(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(xWarpDevicePointerReq);
+    swaps(&stuff->length, n);
+    return (ProcXWarpDevicePointer(client));
+}
+
+int
+ProcXWarpDevicePointer(register ClientPtr client)
+{
+    int err;
+    int x, y;
+    WindowPtr dest = NULL;
+    DeviceIntPtr pDev;
+    SpritePtr pSprite;
+    ScreenPtr newScreen;
+
+    REQUEST(xWarpDevicePointerReq);
+    REQUEST_SIZE_MATCH(xWarpDevicePointerReq);
+
+    /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */
+
+    pDev = LookupDeviceIntRec(stuff->deviceid);
+    if (pDev == NULL) {
+        SendErrorToClient(client, IReqCode, X_WarpDevicePointer, 0,
+                BadDevice); 
+        return Success;
+    }
+
+    if (stuff->dst_win != None)
+    {
+        err = dixLookupWindow(&dest, stuff->dst_win, client, DixReadAccess);
+        if (err != Success)
+        {
+            SendErrorToClient(client, IReqCode, X_WarpDevicePointer, 
+                    stuff->dst_win, err);
+            return Success;
+        }
+    }
+
+    pSprite = pDev->pSprite;
+    x = pSprite->hotPhys.x;
+    y = pSprite->hotPhys.y;
+
+    if (stuff->src_win != None)
+    {
+        int winX, winY;
+        WindowPtr src;
+
+        err = dixLookupWindow(&src, stuff->src_win, client, DixReadAccess);
+        if (err != Success)
+        {
+            SendErrorToClient(client, IReqCode, X_WarpDevicePointer, 
+                    stuff->src_win, err);
+            return Success;
+        }
+
+        winX = src->drawable.x;
+        winY = src->drawable.y;
+        if (src->drawable.pScreen != pSprite->hotPhys.pScreen || 
+                x < winX + stuff->src_x ||
+                y < winY + stuff->src_y ||
+                (stuff->src_width != 0 &&
+                 winX + stuff->src_x + (int)stuff->src_width < 0) ||
+                (stuff->src_height != 0 &&
+                 winY + stuff->src_y + (int)stuff->src_height < y) ||
+                !PointInWindowIsVisible(src, x, y))
+            return Success;
+    }
+
+    if (dest)
+    {
+        x = dest->drawable.x;
+        y = dest->drawable.y;
+        newScreen = dest->drawable.pScreen;
+    } else
+        newScreen = pSprite->hotPhys.pScreen;
+
+    x += stuff->dst_x;
+    y += stuff->dst_y;
+
+    if (x < 0)
+        x = 0;
+    else if (x > newScreen->width)
+        x = newScreen->width - 1;
+
+    if (y < 0)
+        y = 0;
+    else if (y > newScreen->height)
+        y = newScreen->height - 1;
+
+    if (newScreen == pSprite->hotPhys.pScreen)
+    {
+        if (x < pSprite->physLimits.x1)
+            x = pSprite->physLimits.x1;
+        else if (x >= pSprite->physLimits.x2)
+            x = pSprite->physLimits.x2 - 1;
+
+        if (y < pSprite->physLimits.y1)
+            y = pSprite->physLimits.y1;
+        else if (y >= pSprite->physLimits.y2)
+            y = pSprite->physLimits.y2 - 1;
+
+#if defined(SHAPE)
+        if (pSprite->hotShape)
+            ConfineToShape(pDev, pSprite->hotShape, &x, &y);
+#endif
+        (*newScreen->SetCursorPosition)(pDev, newScreen, x, y, TRUE);
+    } else if (!PointerConfinedToScreen(pDev))
+    {
+        NewCurrentScreen(pDev, newScreen, x, y);
+    }
+
+    /* if we don't update the device, we get a jump next time it moves */
+    pDev->valuator->lastx = x;
+    pDev->valuator->lasty = x;
+    miPointerUpdateSprite(pDev);
+
+    /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it
+       here though. */
+    return Success;
+}
+
diff --git a/Xi/warpdevp.h b/Xi/warpdevp.h
new file mode 100644
index 0000000..8ce5b70
--- /dev/null
+++ b/Xi/warpdevp.h
@@ -0,0 +1,39 @@
+/************************************************************
+
+Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au>
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of the above listed
+copyright holder(s) not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission.
+
+THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE
+LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef WARPDEVP_H
+#define WARPDEVP_H 1
+
+int SProcXWarpDevicePointer(ClientPtr	/* client */
+    );
+
+int ProcXWarpDevicePointer(ClientPtr	/* client */
+    );
+
+#endif /* WARPDEVP_H */
diff --git a/dix/cursor.c b/dix/cursor.c
index f4e332f..b58a7bf 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -117,9 +117,6 @@ FreeCursor(pointer value, XID cid)
     ScreenPtr	pscr;
     DeviceIntPtr pDev; 
 
-    /* FIXME: MPX: When FreeClientRessources is called, it calls FreeCursor
-     * too often. Refcnt gots < 0 and FreeCursorBits segfaults because the
-     * memory is already freed. */
     MPXDBG("freecursor refcount %d\n", pCurs->refcnt);
     if ( --pCurs->refcnt != 0)
 	return(Success);
diff --git a/dix/events.c b/dix/events.c
index 73977c9..81efb70 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -324,7 +324,6 @@ static CARD8 criticalEvents[32] =
 };
 
 #ifdef PANORAMIX
-static void ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py);
 static void PostNewCursor(DeviceIntPtr pDev);
 
 #define SyntheticMotion(dev, x, y) \
@@ -700,7 +699,7 @@ SetCriticalEvent(int event)
 }
 
 #ifdef SHAPE
-static void
+void
 ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
 {
     BoxRec box;
diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c
index 27264a2..bbd6124 100644
--- a/hw/xfree86/common/xf86Cursor.c
+++ b/hw/xfree86/common/xf86Cursor.c
@@ -434,9 +434,9 @@ xf86WarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     int    sigstate;
     sigstate = xf86BlockSIGIO ();
-  miPointerWarpCursor(pDev, pScreen,x,y);
+    miPointerWarpCursor(pDev, pScreen, x, y);
 
-  xf86Info.currentScreen = pScreen;
+    xf86Info.currentScreen = pScreen;
     xf86UnblockSIGIO (sigstate);
 }
 
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index c262a95..6f1ebf7 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -132,10 +132,10 @@ xf86ProcessCommonOptions(LocalDevicePtr local,
         xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name);
     }
 
-    if (xf86SetBoolOption(list, "IsMPDevice", 0)) {
-        local->flags |= XI86_MP_DEVICE;
-        xf86Msg(X_CONFIG, "%s: is MP device\n", local->name);
-    }
+    if (xf86SetBoolOption(list, "SharedPointer", 0)) {
+        local->flags &= ~XI86_SHARED_POINTER;
+        xf86Msg(X_CONFIG, "%s: is shared device\n", local->name);
+    } 
 
     if (xf86SetBoolOption(list, "SendDragEvents", 1)) {
         local->flags |= XI86_SEND_DRAG_EVENTS;
@@ -171,7 +171,7 @@ xf86ActivateDevice(LocalDevicePtr local)
         local->dev = dev;      
         
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
-        dev->isMPDev = (local->flags & XI86_MP_DEVICE);
+        dev->isMPDev = !(local->flags & XI86_SHARED_POINTER);
         InitSprite(dev, dev->isMPDev);
 
         RegisterOtherDevice(dev);
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index e8abce7..4eaf8fc 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -82,7 +82,7 @@
 #define XI86_CORE_KEYBOARD	0x20 /* device is the core keyboard */
 #define XI86_POINTER_CAPABLE	0x40 /* capable of being a core pointer */
 #define XI86_KEYBOARD_CAPABLE	0x80 /* capable of being a core keyboard */
-#define XI86_MP_DEVICE 0x100 /* device is multipointer device */
+#define XI86_SHARED_POINTER     0x100 /* device shares core cursor */
 
 #define XI_PRIVATE(dev) \
 	(((LocalDevicePtr)((dev)->public.devicePrivate))->private)
diff --git a/include/dix.h b/include/dix.h
index 2662419..8e34211 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -416,6 +416,13 @@ extern void SetMaskForEvent(
     Mask /* mask */,
     int /* event */);
 
+#ifdef SHAPE
+extern void ConfineToShape(
+    DeviceIntPtr /* pDev */, 
+    RegionPtr /* shape */, 
+    int*      /* px */,
+    int*      /* py */);
+#endif
 
 extern Bool IsParent(
     WindowPtr /* maybeparent */,
commit ca5ebe3971d8ebcfed00c5ebcd026cdd0ce0c6ba
Merge: 4d07b50... 1b029fd...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 19 10:51:01 2006 +1030

    Merge branch 'master' of git://anongit.freedesktop.org/git/xorg/xserver

diff --cc dix/getevents.c
index 2077ce2,0150d66..93fc232
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -487,8 -484,10 +484,10 @@@ GetPointerEvents(xEvent *events, Device
      int num_events = 0, final_valuator = 0;
      CARD32 ms = 0;
      deviceKeyButtonPointer *kbp = NULL;
+     /* Thanks to a broken lib, we _always_ have to chase DeviceMotionNotifies
+      * with DeviceValuators. */
      Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
 -    DeviceIntPtr cp = inputInfo.pointer;
 +    DeviceIntPtr pointer = NULL;
      int x = 0, y = 0;
  
      /* Sanity checks. */
commit 2d0a63126b3d3a17005b7e122617ee0c5f44a55b
Merge: d8b5394... 1b029fd...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 19 10:31:40 2006 +1030

    Merge branch 'master' of git://anongit.freedesktop.org/git/xorg/xserver

diff --cc dix/cursor.c
index 090ad5e,7071d83..f4e332f
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@@ -299,12 -260,11 +299,12 @@@ AllocGlyphCursor(Font source, unsigned 
      int		nscr;
      ScreenPtr 	pscr;
      GlyphSharePtr pShare;
 +    DeviceIntPtr pDev;
  
      sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT,
- 						  SecurityReadAccess);
+ 						  DixReadAccess);
      maskfont = (FontPtr) SecurityLookupIDByType(client, mask, RT_FONT,
- 						SecurityReadAccess);
+ 						DixReadAccess);
  
      if (!sourcefont)
      {
diff --cc dix/events.c
index a6fcf4d,0053f42..73977c9
--- a/dix/events.c
+++ b/dix/events.c
@@@ -324,11 -324,12 +324,12 @@@ static CARD8 criticalEvents[32] 
  };
  
  #ifdef PANORAMIX
 -static void ConfineToShape(RegionPtr shape, int *px, int *py);
 -static void PostNewCursor(void);
 +static void ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py);
 +static void PostNewCursor(DeviceIntPtr pDev);
  
 -#define SyntheticMotion(x, y) \
 -    PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \
 -                              sprite.screen->myNum, \
 +#define SyntheticMotion(dev, x, y) \
-     PostSyntheticMotion(dev, x, y, dev->pSprite->screen, \
++    PostSyntheticMotion(dev, x, y, noPanoramiXExtension ? 0 : \
++                              dev->pSprite->screen->myNum, \
                          syncEvents.playingEvents ? \
                            syncEvents.time.milliseconds : \
                            currentTime.milliseconds);
@@@ -2342,20 -2228,18 +2343,19 @@@ static in
  XineramaWarpPointer(ClientPtr client)
  {
      WindowPtr	dest = NULL;
-     int		x, y;
+     int		x, y, rc;
 +    SpritePtr   pSprite = inputInfo.pointer->pSprite;
  
      REQUEST(xWarpPointerReq);
  
  
-     if (stuff->dstWid != None)
-     {
- 	dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess);
- 	if (!dest)
- 	    return BadWindow;
+     if (stuff->dstWid != None) {
+ 	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
+ 	if (rc != Success)
+ 	    return rc;
      }
 -    x = sprite.hotPhys.x;
 -    y = sprite.hotPhys.y;
 +    x = pSprite->hotPhys.x;
 +    y = pSprite->hotPhys.y;
  
      if (stuff->srcWid != None)
      {
@@@ -2416,9 -2301,8 +2417,9 @@@ in
  ProcWarpPointer(ClientPtr client)
  {
      WindowPtr	dest = NULL;
-     int		x, y;
+     int		x, y, rc;
      ScreenPtr	newScreen;
 +    SpritePtr   pSprite = inputInfo.pointer->pSprite;
  
      REQUEST(xWarpPointerReq);
  
@@@ -2429,14 -2313,13 +2430,13 @@@
  	return XineramaWarpPointer(client);
  #endif
  
-     if (stuff->dstWid != None)
-     {
- 	dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess);
- 	if (!dest)
- 	    return BadWindow;
+     if (stuff->dstWid != None) {
+ 	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
+ 	if (rc != Success)
+ 	    return rc;
      }
 -    x = sprite.hotPhys.x;
 -    y = sprite.hotPhys.y;
 +    x = pSprite->hotPhys.x;
 +    y = pSprite->hotPhys.y;
  
      if (stuff->srcWid != None)
      {
@@@ -4063,14 -3916,14 +4064,16 @@@ ProcQueryPointer(ClientPtr client
  {
      xQueryPointerReply rep;
      WindowPtr pWin, t;
--    REQUEST(xResourceReq);
      DeviceIntPtr mouse = inputInfo.pointer;
 +    SpritePtr pSprite = mouse->pSprite;
+     int rc;
+ 
++    REQUEST(xResourceReq);
 +
      REQUEST_SIZE_MATCH(xResourceReq);
-     pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess);
-     if (!pWin)
- 	return BadWindow;
+     rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
+     if (rc != Success)
+ 	return rc;
      if (mouse->valuator->motionHintWindow)
  	MaybeStopHint(mouse, client);
      rep.type = X_Reply;
diff --cc dix/getevents.c
index 87937f6,0150d66..7e0b63f
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@@ -489,8 -484,10 +489,10 @@@ GetPointerEvents(xEvent *events, Device
      int num_events = 0, final_valuator = 0;
      CARD32 ms = 0;
      deviceKeyButtonPointer *kbp = NULL;
+     /* Thanks to a broken lib, we _always_ have to chase DeviceMotionNotifies
+      * with DeviceValuators. */
      Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
 -    DeviceIntPtr cp = inputInfo.pointer;
 +    DeviceIntPtr pointer = NULL;
      int x = 0, y = 0;
  
      /* Sanity checks. */
@@@ -546,7 -542,10 +549,7 @@@
              y = valuators[1 - first_valuator];
          }
          else {
-                 y = pointer->valuator->lasty;
 -            if (pDev->coreEvents)
 -                y = cp->valuator->lasty;
 -            else
 -                y = pDev->valuator->lasty;
++            y = pointer->valuator->lasty;
          }
      }
      else {
@@@ -751,11 -761,7 +754,11 @@@ SwitchCorePointer(DeviceIntPtr pDev
   * to shift the pointer to get it inside the new bounds.
   */
  void
 -PostSyntheticMotion(int x, int y, ScreenPtr pScreen, unsigned long time)
 +PostSyntheticMotion(DeviceIntPtr pDev, 
 +                    int x, 
 +                    int y, 
-                     ScreenPtr pScreen,
++                    int screen,
 +                    unsigned long time) 
  {
      xEvent xE;
  
@@@ -764,8 -770,8 +767,8 @@@
         will translate from sprite screen to screen 0 upon reentry
         to the DIX layer. */
      if (!noPanoramiXExtension) {
--        x += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
--        y += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
++        x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
++        y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
      }
  #endif
  
diff --cc hw/xfree86/common/xf86Xinput.c
index 422d43d,16e330d..c262a95
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@@ -207,12 -156,7 +170,10 @@@ xf86ActivateDevice(LocalDevicePtr local
          dev->public.devicePrivate = (pointer) local;
          local->dev = dev;      
          
-         xf86XinputFinalizeInit(dev);
- 
          dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
 +        dev->isMPDev = (local->flags & XI86_MP_DEVICE);
 +        InitSprite(dev, dev->isMPDev);
 +
          RegisterOtherDevice(dev);
  
          if (serverGeneration == 1) 
diff --cc include/dixevents.h
index 821a7bf,c78fb0e..21d16a2
--- a/include/dixevents.h
+++ b/include/dixevents.h
@@@ -103,11 -103,7 +103,11 @@@ extern int ProcUngrabButton(ClientPtr /
  extern int ProcRecolorCursor(ClientPtr /* client */);
  
  #ifdef PANORAMIX
 -extern void PostSyntheticMotion(int x, int y, ScreenPtr pScreen, unsigned long time);
 +extern void PostSyntheticMotion(DeviceIntPtr pDev, 
 +                                int x, 
 +                                int y, 
-                                 ScreenPtr pScreen, 
++                                int screen,
 +                                unsigned long time);
  #endif
  
  #endif /* DIXEVENTS_H */
diff --cc include/input.h
index 357ba58,ebb0915..a1c21f8
--- a/include/input.h
+++ b/include/input.h
@@@ -419,10 -419,9 +419,10 @@@ extern int GetProximityEvents
      int *valuators);
  
  extern void PostSyntheticMotion(
 +    DeviceIntPtr pDev,
      int x,
      int y,
--    ScreenPtr pScreen,
++    int screen,
      unsigned long time);
  
  extern int GetMotionHistorySize(
commit d8b5394eda9d92b7193004931caa6c24a337b2e6
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Dec 18 17:35:34 2006 +1030

    Cleaning up ifdef MPX from remaining files, removing it from configure.ac.
    Removing building mpx extension from Makefile.am

diff --git a/Changelog b/Changelog
index 33f0313..5890248 100644
--- a/Changelog
+++ b/Changelog
@@ -26,6 +26,24 @@ Files:
 	hw/xfree86/common/xf86Input.h
 	Xi/exevents.c
 
+____________________________________________________________
+
+Cleaning up #ifdef MPX from remaining files, removing it from configure.ac.
+Removing building mpx extension from Makefile.am
+
+Files:
+	Makefile.am
+	configure.ac
+	hw/xfree86/ramdac/xf86HWCurs.c
+	include/dix-config.h.in
+	include/dix.h
+	include/globals.h
+	include/xorg-server.h.in
+	mi/mieq.c
+	mi/miinitext.c
+	mi/mipointer.c
+	os/utils.c
+
 == 12.12.06 ==
 dix:    Moving SpriteRec into DeviceIntRec
 	removing global sprite structure
diff --git a/Makefile.am b/Makefile.am
index 572d088..f35539e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,7 +42,6 @@ SUBDIRS = \
 	randr \
 	render  \
 	Xi \
-        mpx \
 	xkb \
 	$(DBE_DIR) \
 	$(MFB_DIR) \
@@ -79,7 +78,6 @@ DIST_SUBDIRS = \
 	randr \
 	render  \
 	Xi \
-        mpx \
 	xkb \
 	dbe \
 	mfb \
diff --git a/configure.ac b/configure.ac
index 43d53dc..cf6b3ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -421,8 +421,6 @@ AC_ARG_ENABLE(builtin-fonts,  AS_HELP_STRING([--enable-builtin-fonts], [Use only
 AC_ARG_ENABLE(null-root-cursor, AS_HELP_STRING([--enable-null-root-cursor], [Use an empty root cursor (default: use core cursor)]),
                                  [NULL_ROOT_CURSOR=$enableval],
                                  [NULL_ROOT_CURSOR=no])
-AC_ARG_ENABLE(mpx,            AS_HELP_STRING([--disable-mpx], [Disable MPX multipointer support (Default: enabled)]), [MPX=$enableval], [MPX=yes])
-
 dnl Extensions.
 AC_ARG_ENABLE(composite,      AS_HELP_STRING([--disable-composite], [Build Composite extension (default: enabled)]), [COMPOSITE=$enableval], [COMPOSITE=yes])
 AC_ARG_ENABLE(mitshm,         AS_HELP_STRING([--disable-shm], [Build SHM extension (default: enabled)]), [MITSHM=$enableval], [MITSHM=yes])
@@ -787,16 +785,6 @@ AC_DEFINE(XINPUT, 1, [Support X Input extension])
 XI_LIB='$(top_builddir)/Xi/libXi.la'
 XI_INC='-I$(top_srcdir)/Xi'
 
-dnl Enable MPX multipointer  extension
-AC_MSG_CHECKING([whether to use MPX extension])
-AC_MSG_RESULT([$MPX])
-AM_CONDITIONAL(MPX, [test "x$MPX" = xyes])
-
-if test "x$MPX" = xyes; then
-    AC_DEFINE(MPX, 1, [Support MPX multipointer extension])
-    MPX_LIB='$(top_builddir)/mpx/libmpx.la'
-    MPX_INC='-I$(top_srcdir)/mpx'
-fi
 AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes)
 
 AC_DEFINE(SHAPE, 1, [Support SHAPE extension])
@@ -1006,7 +994,7 @@ AC_EGREP_CPP([I_AM_SVR4],[
 AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4])
 AC_MSG_RESULT([yes])], AC_MSG_RESULT([no]))
 
-XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $MPX_INC"
+XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC" 
 AC_DEFINE_UNQUOTED(X_BYTE_ORDER,[$ENDIAN],[Endian order])
 
 AC_SUBST([XSERVER_LIBS])
@@ -1031,7 +1019,7 @@ if test "x$DMX" = xyes; then
 		              modules not found.])
 	fi
 	DMX_INCLUDES="$XEXT_INC $RENDER_INC $XTRAP_INC $RECORD_INC"
-	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $XTRAP_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB $CWRAP_LIB $MPX_LIB"
+	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $XTRAP_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB $CWRAP_LIB"
 	AC_SUBST([XDMX_LIBS])
 
 dnl USB sources in DMX require <linux/input.h>
@@ -1070,7 +1058,7 @@ AC_MSG_RESULT([$XVFB])
 AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
 
 if test "x$XVFB" = xyes; then
-	XVFB_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS $MPX_LIB"
+	XVFB_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS"
 	AC_SUBST([XVFB_LIBS])
 fi
 
@@ -1086,7 +1074,7 @@ AC_MSG_RESULT([$XNEST])
 AM_CONDITIONAL(XNEST, [test "x$XNEST" = xyes])
 
 if test "x$XNEST" = xyes; then
-	XNEST_LIBS="$XSERVER_LIBS $FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS $MPX_LIB"
+	XNEST_LIBS="$XSERVER_LIBS $FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS"
 	AC_SUBST([XNEST_LIBS])
 fi
 
@@ -1115,7 +1103,7 @@ AC_MSG_RESULT([$XGL])
 AM_CONDITIONAL(XGL, [test "x$XGL" = xyes])
 
 if test "x$XGL" = xyes; then
-	XGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
+	XGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
 	AC_SUBST([XGL_LIBS])
 	AC_DEFINE(XGL_MODULAR, 1, [Use loadable XGL modules])
 
@@ -1136,7 +1124,7 @@ AC_MSG_RESULT([$XEGL])
 AM_CONDITIONAL(XEGL, [test "x$XEGL" = xyes])
 
 if test "x$XEGL" = xyes; then
-	XEGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
+	XEGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
 	AC_SUBST([XEGL_LIBS])
 fi
 
@@ -1152,7 +1140,7 @@ AC_MSG_RESULT([$XGLX])
 AM_CONDITIONAL(XGLX, [test "x$XGLX" = xyes])
 
 if test "x$XGLX" = xyes; then
-	XGLX_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
+	XGLX_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
 	AC_SUBST([XGLX_LIBS])
 fi
 
@@ -1173,7 +1161,7 @@ if test "x$XORG" = xyes -o "x$XGL" = xyes; then
 	XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
 	XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
 	XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
-	XORG_LIBS="$COMPOSITE_LIB $MI_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XPSTUBS_LIB $OS_LIB $MPX_LIB"
+	XORG_LIBS="$COMPOSITE_LIB $MI_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XPSTUBS_LIB $OS_LIB"
 
 	if test "x$DGA" = xauto; then
 		PKG_CHECK_MODULES(DGA, xf86dgaproto, [DGA=yes], [DGA=no])
@@ -1639,7 +1627,7 @@ if test "$KDRIVE" = yes; then
     # dix os fb mi extension glx (NOTYET) damage shadow xpstubs
     #KDRIVE_PURE_LIBS="$DIX_LIB $OS_LIB $FB_LIB $XEXT_LIB $MIEXT_DAMAGE_LIB \
     #    $MIEXT_SHADOW_LIB $XPSTUBS_LIB"
-    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $OS_LIB $MPX_LIB"
+    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $OS_LIB"
     KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.a'
     case $host_os in
 	*linux*)
@@ -1830,7 +1818,6 @@ render/Makefile
 xkb/Makefile
 Xext/Makefile
 Xi/Makefile
-mpx/Makefile
 xfixes/Makefile
 exa/Makefile
 hw/Makefile
diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c
index b76b800..2dfc4b2 100644
--- a/hw/xfree86/ramdac/xf86HWCurs.c
+++ b/hw/xfree86/ramdac/xf86HWCurs.c
@@ -73,12 +73,9 @@ static unsigned char* RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
 Bool
 xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
 {
-
-#ifdef MPX
     /* Graphics cards cannot render multiple cursors in hardware. We have to
        software render them. */
     return FALSE;
-#endif
 
     if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
 	return FALSE;
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 29b044c..7aabae2 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -350,9 +350,6 @@
 /* Support X Input extension */
 #undef XINPUT
 
-/* Support MPX multipointer extension */
-#undef MPX
-
 /* Build XKB */
 #undef XKB
 
diff --git a/include/dix.h b/include/dix.h
index 959d5dc..aaefb0c 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -825,8 +825,6 @@ extern int xstrcasecmp(char *s1, char *s2);
 /* ffs.c */
 extern int ffs(int i);
 
-#ifdef MPX
-extern Bool MPHasCursor(DeviceIntPtr pDev);
-#endif
+extern Bool DevHasCursor(DeviceIntPtr pDev);
 
 #endif /* DIX_H */
diff --git a/include/globals.h b/include/globals.h
index ef22561..821b12b 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -63,10 +63,6 @@ extern Bool noCompositeExtension;
 extern Bool noDamageExtension;
 #endif
 
-#ifdef MPX
-extern Bool noMPXExtension;
-#endif
-
 #ifdef DBE
 extern Bool noDbeExtension;
 #endif
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index c58e2b3..48196d8 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -142,9 +142,6 @@
 /* Support X Input extension */
 #undef XINPUT
 
-/* Support MPX multipointer extension */
-#undef MPX
-
 /* Build XKB */
 #undef XKB
 
diff --git a/mi/mieq.c b/mi/mieq.c
index 42cacfd..49bf867 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -24,7 +24,6 @@ in this Software without prior written authorization from The Open Group.
  *
  * Author:  Keith Packard, MIT X Consortium
  */
-#ifdef MPX
  /* 
   * MPX additions:
   * Copyright © 2006 Peter Hutterer
@@ -32,7 +31,6 @@ in this Software without prior written authorization from The Open Group.
   * Author: Peter Hutterer <peter at cs.unisa.edu.au>
   *
   */
-#endif
 
 /*
  * mieq.c
@@ -110,13 +108,10 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
     deviceKeyButtonPointer *lastkbp = (deviceKeyButtonPointer *)
                                       &laste->event[0];
 
-#ifdef MPX
     /* avoid merging events from different devices */
     if (e->u.u.type == MotionNotify && pDev->isMPDev)
         isMotion = pDev->id;
-    else
-#endif
-    if (e->u.u.type == MotionNotify)
+    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 */
diff --git a/mi/miinitext.c b/mi/miinitext.c
index 3d9522d..cb34473 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -384,9 +384,6 @@ extern void DamageExtensionInit(INITARGS);
 #ifdef COMPOSITE
 extern void CompositeExtensionInit(INITARGS);
 #endif
-#ifdef MPX
-extern void MPXExtensionInit(INITARGS);
-#endif
 
 /* The following is only a small first step towards run-time
  * configurable extensions.
@@ -666,9 +663,6 @@ InitExtensions(argc, argv)
 #ifdef DAMAGE
     if (!noDamageExtension) DamageExtensionInit();
 #endif
-#ifdef MPX
-    if (!noMPXExtension) MPXExtensionInit();
-#endif
 }
 
 void
@@ -739,9 +733,6 @@ static ExtensionModule staticExtensions[] = {
 #ifdef XEVIE
     { XevieExtensionInit, "XEVIE", &noXevieExtension, NULL },
 #endif 
-#ifdef MPX
-    { MPXExtensionInit, "MPX", &noMPXExtension, NULL },
-#endif
     { NULL, NULL, NULL, NULL, NULL }
 };
     
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 85c5c8b..541e89b 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -189,9 +189,4 @@ extern void miPointerMoved(
 
 extern int miPointerScreenIndex;
 
-#ifdef MPX
-_X_EXPORT Bool IsMPDev(DeviceIntPtr pDev);
-#endif
-
-
 #endif /* MIPOINTER_H */
diff --git a/os/utils.c b/os/utils.c
index 42d41ce..9824501 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -252,9 +252,6 @@ _X_EXPORT Bool noXIdleExtension = FALSE;
 #ifdef XV
 _X_EXPORT Bool noXvExtension = FALSE;
 #endif
-#ifdef MPX
-_X_EXPORT Bool noMPXExtension = FALSE;
-#endif
 
 #define X_INCLUDE_NETDB_H
 #include <X11/Xos_r.h>
commit 03c554283e49e449fd1282cf32564d15d9fd2c77
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Dec 18 15:33:54 2006 +1030

    mi:     removing MPX ifdefs
    	global sprite renaming in mipointer and misprite
    	fixed: multiple remove cursor call in miSpriteInstallColormap
    	fixed: wrong core pointer usage in miSpriteStoreColors
    
    dix:    bugfix in CheckCursorConfinement
    	removing MPX ifdefs
    	removing MPX event generation (using Xi solely now)
    	bugfix GrabDevice: uninitialized field in grab struct caused segfault
    
    xfree86: removing MPX fdefs
    
    Xi:     removing MPX protocol events

diff --git a/Changelog b/Changelog
index 7efc82a..33f0313 100644
--- a/Changelog
+++ b/Changelog
@@ -7,15 +7,24 @@ mi:     removing MPX ifdefs
 dix:    bugfix in CheckCursorConfinement
 	removing MPX ifdefs
 	removing MPX event generation (using Xi solely now)
+	bugfix GrabDevice: uninitialized field in grab struct caused segfault
+
+xfree86: removing MPX fdefs
+
+Xi:     removing MPX protocol events
 
 Files:
+	include/inputstr.h
 	mi/midispcur.c
-	mi/misprite.c
-	mi/mispritest.h
+	mi/mieq.c
 	mi/mipointer.c
-	dix/getevents.c
+	mi/misprite.c
 	dix/events.c
 	dix/cursor.c
+	dix/devices.c
+	hw/xfree86/common/xf86Events.c
+	hw/xfree86/common/xf86Input.h
+	Xi/exevents.c
 
 == 12.12.06 ==
 dix:    Moving SpriteRec into DeviceIntRec
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 9c65193..f1cb647 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -73,12 +73,6 @@ SOFTWARE.
 #include "dixgrabs.h"	/* CreateGrab() */
 #include "scrnintstr.h"
 
-#ifdef MPX
-#include <X11/extensions/MPXconst.h>
-#include <X11/extensions/MPXproto.h>
-#include "mpxglobals.h"
-#endif
-
 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
 #define AllModifiersMask ( \
 	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
@@ -124,6 +118,7 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
     ValuatorClassPtr v = other->valuator;
     deviceValuator *xV = (deviceValuator *) xE;
 
+
     if (xE->u.u.type != DeviceValuator) {
 	GetSpritePosition(other, &rootX, &rootY);
 	xE->u.keyButtonPointer.rootX = rootX;
@@ -236,11 +231,7 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 
 	if (other->fromPassiveGrab && (key == other->activatingKey))
 	    deactivateDeviceGrab = TRUE;
-    } else if (xE->u.u.type == DeviceButtonPress
-#ifdef MPX
-            || xE->u.u.type == MPXButtonPress
-#endif
-            ) {
+    } else if (xE->u.u.type == DeviceButtonPress) {
         if (!b)
             return;
 
@@ -256,18 +247,11 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 	if (xE->u.u.detail <= 5)
 	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
-#ifdef MPX
-        if (xE->u.u.type == DeviceButtonPress)
-#endif
-            if (!grab)
-                if (CheckDeviceGrabs(other, xE, 0, count))
-                    return;
+        if (!grab)
+            if (CheckDeviceGrabs(other, xE, 0, count))
+                return;
 
-    } else if (xE->u.u.type == DeviceButtonRelease
-#ifdef MPX
-            || xE->u.u.type == MPXButtonRelease
-#endif
-            ) {
+    } else if (xE->u.u.type == DeviceButtonRelease) {
         if (!b)
             return;
 
@@ -283,11 +267,8 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 	if (xE->u.u.detail <= 5)
 	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
-#ifdef MPX
-        if (xE->u.u.type == DeviceButtonRelease)
-#endif
-            if (!b->state && other->fromPassiveGrab)
-                deactivateDeviceGrab = TRUE;
+        if (!b->state && other->fromPassiveGrab)
+            deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == ProximityIn)
 	other->valuator->mode &= ~OutOfProximity;
     else if (xE->u.u.type == ProximityOut)
diff --git a/dix/cursor.c b/dix/cursor.c
index 7df854c..090ad5e 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -120,22 +120,22 @@ FreeCursor(pointer value, XID cid)
     /* FIXME: MPX: When FreeClientRessources is called, it calls FreeCursor
      * too often. Refcnt gots < 0 and FreeCursorBits segfaults because the
      * memory is already freed. */
+    MPXDBG("freecursor refcount %d\n", pCurs->refcnt);
     if ( --pCurs->refcnt != 0)
 	return(Success);
 
-    pDev = inputInfo.pointer;
-
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
 	pscr = screenInfo.screens[nscr];
         for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
-            if (MPHasCursor(pDev))
+            if (DevHasCursor(pDev))
                 (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
         }
     }
     FreeCursorBits(pCurs->bits);
     xfree( pCurs);
+    MPXDBG("freeing memory for cursor\n");
     return(Success);
 }
 
@@ -219,7 +219,6 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
     pCurs->backGreen = backGreen;
     pCurs->backBlue = backBlue;
 
-    pDev = inputInfo.pointer;
     /*
      * realize the cursor for every screen
      */
@@ -228,7 +227,7 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
         pscr = screenInfo.screens[nscr];
         for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
-            if (MPHasCursor(pDev))
+            if (DevHasCursor(pDev))
             {
                 if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
                 {
@@ -241,7 +240,7 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
                     DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
                     while(pDevIt && pDevIt != pDev)
                     {
-                        if (MPHasCursor(pDevIt))
+                        if (DevHasCursor(pDevIt))
                             ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                         pDevIt = pDevIt->next;
                     }
@@ -252,7 +251,7 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
                         pDevIt = inputInfo.devices;
                         while (pDevIt)
                         {
-                            if (MPHasCursor(pDevIt))
+                            if (DevHasCursor(pDevIt))
                                 ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                             pDevIt = pDevIt->next;
                         }
@@ -439,7 +438,6 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     pCurs->backGreen = backGreen;
     pCurs->backBlue = backBlue;
 
-    pDev = inputInfo.pointer;
     /*
      * realize the cursor for every screen
      */
@@ -448,7 +446,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
         pscr = screenInfo.screens[nscr];
         for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
-            if (MPHasCursor(pDev))
+            if (DevHasCursor(pDev))
             {
                 if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
                 {
@@ -461,7 +459,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
                     DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
                     while(pDevIt && pDevIt != pDev)
                     {
-                        if (MPHasCursor(pDevIt))
+                        if (DevHasCursor(pDevIt))
                             ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                         pDevIt = pDevIt->next;
                     }
@@ -472,7 +470,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
                         pDevIt = inputInfo.devices;
                         while (pDevIt)
                         {
-                            if (MPHasCursor(pDevIt))
+                            if (DevHasCursor(pDevIt))
                                 ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                             pDevIt = pDevIt->next;
                         }
diff --git a/dix/devices.c b/dix/devices.c
index b4896ac..adf418c 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -497,6 +497,9 @@ CloseDevice(register DeviceIntPtr dev)
     while (dev->xkb_interest)
 	XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
 #endif
+    
+    if (DevHasCursor(dev))
+        xfree((pointer)dev->pSprite);
 
     xfree(dev->sync.event);
     xfree(dev);
diff --git a/dix/events.c b/dix/events.c
index 5ab0764..a6fcf4d 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -175,8 +175,6 @@ xEvent *xeviexE;
 #include "dixgrabs.h"
 #include "dispatch.h"
 
-#include "mpxglobals.h"
-
 #define EXTENSION_EVENT_BASE  64
 
 #define NoSuchEvent 0x80000000	/* so doesn't match NoEventMask */
@@ -243,15 +241,13 @@ static int spriteTraceSize = 0;
 static int spriteTraceGood;
 
 
-#define MPXDBG(...) fprintf (stderr, "MPX: " __VA_ARGS__)
-
 /** 
  * True for the core pointer and any MPX device. 
  * False for any other device (including keyboards).
  * Does ID checking for sane range as well.
  */
 _X_EXPORT Bool
-MPHasCursor(DeviceIntPtr pDev) 
+DevHasCursor(DeviceIntPtr pDev) 
 {
     return (pDev == inputInfo.pointer || 
             (pDev->isMPDev && pDev->id < MAX_DEVICES)); 
@@ -1210,7 +1206,7 @@ playmore:
     syncEvents.playingEvents = FALSE;
     for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-        if (MPHasCursor(dev))
+        if (DevHasCursor(dev))
         {
             /* the following may have been skipped during replay, 
               so do it now */
@@ -1315,7 +1311,7 @@ ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
     mouse->activeGrab = *grab;
     mouse->grab = &mouse->activeGrab;
     mouse->fromPassiveGrab = autoGrab;
-    PostNewCursor(inputInfo.pointer);
+    PostNewCursor(mouse);
     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
 }
 
@@ -1876,9 +1872,6 @@ DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
 	register OtherInputMasks *inputMasks;
 	int mskidx = dev->id;
 
-        if (IsMPXEvent(xE))
-            mskidx = MPXmskidx;
-
 	inputMasks = wOtherInputMasks(pWin);
 	if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
 	    return 0;
@@ -2082,7 +2075,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
         xeviehot.y = pSprite->hot.y;
 #endif
 	pSprite->hotPhys = pSprite->hot;
-#if !defined MPX
+
 	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
 	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
 	{
@@ -2090,7 +2083,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
                 pDev, pSprite->hotPhys.pScreen,
 		pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
 	}
-#endif
+
 	XE_KBPTR.rootX = pSprite->hot.x;
 	XE_KBPTR.rootY = pSprite->hot.y;
     }
@@ -2127,7 +2120,7 @@ WindowsRestructured()
     DeviceIntPtr pDev = inputInfo.devices;
     while(pDev)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
             CheckMotion((xEvent *)NULL, pDev);
         pDev = pDev->next;
     }
@@ -2150,7 +2143,7 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
     pDev = inputInfo.devices;
     while(pDev)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             pSprite = pDev->pSprite;
             pSprite->hot.x        -= xoff;
@@ -2196,7 +2189,7 @@ DefineInitialRootWindow(register WindowPtr win)
 
     while (pDev)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             pSprite = pDev->pSprite;
 
@@ -2257,7 +2250,11 @@ DefineInitialRootWindow(register WindowPtr win)
 void
 WindowHasNewCursor(WindowPtr pWin)
 {
-    PostNewCursor(inputInfo.pointer);
+    DeviceIntPtr pDev;
+
+    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+        if (DevHasCursor(pDev))
+            PostNewCursor(pDev);
 }
 
 _X_EXPORT void
@@ -2996,7 +2993,6 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
     register ButtonClassPtr butc = mouse->button;
     SpritePtr           pSprite = mouse->pSprite;
 
-
 #ifdef XKB
     XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
 #endif
@@ -3997,6 +3993,9 @@ GrabDevice(register ClientPtr client, register DeviceIntPtr dev,
     {
 	GrabRec tempGrab;
 
+        /* Otherwise segfaults happen on grabbed MPX devices */
+        memset(&tempGrab, 0, sizeof(GrabRec));
+
 	tempGrab.window = pWin;
 	tempGrab.resource = client->clientAsMask;
 	tempGrab.ownerEvents = ownerEvents;
@@ -4004,6 +4003,8 @@ GrabDevice(register ClientPtr client, register DeviceIntPtr dev,
 	tempGrab.pointerMode = other_mode;
 	tempGrab.eventMask = mask;
 	tempGrab.device = dev;
+        tempGrab.cursor = NULL;
+
 	(*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
 	*status = GrabSuccess;
     }
@@ -4589,7 +4590,7 @@ CheckCursorConfinement(WindowPtr pWin)
 
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             grab = pDev->grab;
             if (grab && (confineTo = grab->confineTo))
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index a552491..acadc48 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -246,11 +246,8 @@ ProcessInputEvents ()
   xf86Info.inputPending = FALSE;
 
   mieqProcessInputEvents();
-#ifndef MPX
-  /* For MPX, this is done inside the mieqProcessInputEvents() */
-  miPointerUpdateSprite(inputInfo.pointer);
-#endif
 
+  /* FIXME: This is a problem if we have multiple pointers */
   miPointerGetPosition(inputInfo.pointer, &x, &y);
   xf86SetViewport(xf86Info.currentScreen, x, y);
 }
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 4c752cd..e8abce7 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -82,10 +82,7 @@
 #define XI86_CORE_KEYBOARD	0x20 /* device is the core keyboard */
 #define XI86_POINTER_CAPABLE	0x40 /* capable of being a core pointer */
 #define XI86_KEYBOARD_CAPABLE	0x80 /* capable of being a core keyboard */
-
-#ifdef MPX
 #define XI86_MP_DEVICE 0x100 /* device is multipointer device */
-#endif
 
 #define XI_PRIVATE(dev) \
 	(((LocalDevicePtr)((dev)->public.devicePrivate))->private)
diff --git a/include/inputstr.h b/include/inputstr.h
index 048a34a..cc3280d 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -379,4 +379,5 @@ typedef struct _QdEvent {
     int			evcount;
 } QdEventRec;    
 
+#define MPXDBG(...) ErrorF("MPX: " __VA_ARGS__ )
 #endif /* INPUTSTRUCT_H */
diff --git a/mi/midispcur.c b/mi/midispcur.c
index 38772f6..35f0fba 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -538,7 +538,7 @@ miDCPutUpCursor (pDev, pScreen, pCursor, x, y, source, mask)
     pWin = WindowTable[pScreen->myNum];
     pBuffer = pScreenPriv->pCoreBuffer;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
 
 #ifdef ARGB_CURSOR
@@ -589,7 +589,7 @@ miDCSaveUnderCursor (pDev, pScreen, x, y, w, h)
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
 
     pSave = pBuffer->pSave;
@@ -628,7 +628,7 @@ miDCRestoreUnderCursor (pDev, pScreen, x, y, w, h)
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
 
     pSave = pBuffer->pSave;
@@ -661,7 +661,7 @@ miDCChangeSave (pDev, pScreen, x, y, w, h, dx, dy)
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
 
     pSave = pBuffer->pSave;
@@ -812,7 +812,7 @@ miDCMoveCursor (pDev, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
     pWin = WindowTable[pScreen->myNum];
     pBuffer = pScreenPriv->pCoreBuffer;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
 
     pTemp = pBuffer->pTemp;
diff --git a/mi/mieq.c b/mi/mieq.c
index b40944e..42cacfd 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -227,9 +227,7 @@ mieqProcessInputEvents()
             else if (e->event[0].u.u.type == MotionNotify ||
                      e->event[0].u.u.type == ButtonPress ||
                      e->event[0].u.u.type == ButtonRelease) {
-#ifdef MPX
                 if (!e->pDev->isMPDev)
-#endif
                     SwitchCorePointer(e->pDev);
                 dev = inputInfo.pointer;
 
@@ -238,7 +236,6 @@ mieqProcessInputEvents()
                 dev = e->pDev;
             }
 
-#ifdef MPX
             /* 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 
@@ -246,16 +243,14 @@ mieqProcessInputEvents()
             if (e->pDev->isMPDev)
                 dev->public.processInputProc(e->event, e->pDev, e->nevents);
             else
-#endif
-            dev->public.processInputProc(e->event, dev, e->nevents);
+                dev->public.processInputProc(e->event, dev, e->nevents);
         }
-#ifdef MPX
-        /* Update the sprite now. Next event may be from different device.  */
+
+        /* Update the sprite now. Next event may be from different device. */
         if (e->event[0].u.u.type == MotionNotify && 
                 (e->pDev->isMPDev || e->pDev->coreEvents))
         {
             miPointerUpdateSprite(e->pDev);
         }
-#endif
     }
 }
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 10e6f3e..1474cb9 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -70,7 +70,7 @@ static miPointerPtr miCorePointer;
  */
 static miPointerRec miPointers[MAX_DEVICES];
 #define MIPOINTER(dev) \
-    (MPHasCursor((dev))) ? &miPointers[(dev)->id] : miCorePointer
+    (DevHasCursor((dev))) ? &miPointers[(dev)->id] : miCorePointer
 
 static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                    CursorPtr pCursor);
diff --git a/mi/misprite.c b/mi/misprite.c
index 2e3b376..70dda1c 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -152,7 +152,7 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
 
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
@@ -318,7 +318,7 @@ miSpriteCloseScreen (i, pScreen)
     pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             miCursorInfoPtr pCursor;
             pCursor = &pScreenPriv->pDevCursors[pDev->id];
@@ -352,7 +352,7 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
 
     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
              pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
              if (pDrawable->type == DRAWABLE_WINDOW &&
@@ -392,7 +392,7 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
 
     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
@@ -444,7 +444,7 @@ miSpriteSourceValidate (pDrawable, x, y, width, height)
 
     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
             if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp &&
@@ -477,7 +477,7 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 
     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
             /*
@@ -518,7 +518,7 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
 
     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             pCursorInfo = &pPriv->pDevCursors[pDev->id];
             if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
@@ -612,7 +612,7 @@ miSpriteStoreColors (pMap, ndef, pdef)
 
     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if (MPHasCursor(pDev))
+        if (DevHasCursor(pDev))
         {
             pCursorInfo = &pPriv->pDevCursors[pDev->id];
             if (pCursorInfo->pColormap == pMap)
@@ -721,7 +721,7 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
 
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        if(MPHasCursor(pDev))
+        if(DevHasCursor(pDev))
         {
             pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
             if (pCursorInfo->isUp)
@@ -765,7 +765,7 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = pScreenPriv->cp;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
     if (pCursor == pCursorInfo->pCursor)
@@ -799,7 +799,7 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     miCursorInfoPtr pPointer = pScreenPriv->cp;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pPointer = &pScreenPriv->pDevCursors[pDev->id];
 
     if (!pCursor)
@@ -916,7 +916,7 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursor = pScreenPriv->cp->pCursor;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pCursor = pScreenPriv->pDevCursors[pDev->id].pCursor;
 
     miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
@@ -939,7 +939,7 @@ miSpriteRemoveCursor (pDev, pScreen)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = pScreenPriv->cp;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
     miSpriteIsUpFALSE (pCursorInfo, pScreen, pScreenPriv);
@@ -977,7 +977,7 @@ miSpriteRestoreCursor (pDev, pScreen)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = pScreenPriv->cp;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
     miSpriteComputeSaved (pDev, pScreen);
@@ -1025,7 +1025,7 @@ miSpriteComputeSaved (pDev, pScreen)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = pScreenPriv->cp;
 
-    if (MPHasCursor(pDev))
+    if (DevHasCursor(pDev))
         pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
     pCursor = pCursorInfo->pCursor;
commit a96788058e48f3e97c66da6dafd58828f0c2ce53
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Dec 14 10:50:18 2006 +1030

    mi:     removing MPX ifdefs
    	global sprite renaming in mipointer and misprite
    	fixed: multiple remove cursor call in miSpriteInstallColormap
    	fixed: wrong core pointer usage in miSpriteStoreColors
    
    dix:    bugfix in CheckCursorConfinement
    	removing MPX ifdefs
    	removing MPX event generation (using Xi solely now)

diff --git a/Changelog b/Changelog
index 463d028..7efc82a 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,22 @@
-MPX Changelog file
+== 14.12.06 ==
+mi:     removing MPX ifdefs
+	global sprite renaming in mipointer and misprite
+	fixed: multiple remove cursor call in miSpriteInstallColormap
+	fixed: wrong core pointer usage in miSpriteStoreColors
+
+dix:    bugfix in CheckCursorConfinement
+	removing MPX ifdefs
+	removing MPX event generation (using Xi solely now)
+
+Files:
+	mi/midispcur.c
+	mi/misprite.c
+	mi/mispritest.h
+	mi/mipointer.c
+	dix/getevents.c
+	dix/events.c
+	dix/cursor.c
+
 == 12.12.06 ==
 dix:    Moving SpriteRec into DeviceIntRec
 	removing global sprite structure
diff --git a/dix/cursor.c b/dix/cursor.c
index 6da763b..7df854c 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -128,16 +128,11 @@ FreeCursor(pointer value, XID cid)
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
 	pscr = screenInfo.screens[nscr];
-#ifdef MPX
-        pDev = inputInfo.devices;
-        while(pDev)
+        for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
-#endif
-            (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
-#ifdef MPX
-            pDev = pDev->next;
+            if (MPHasCursor(pDev))
+                (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
         }
-#endif
     }
     FreeCursorBits(pCurs->bits);
     xfree( pCurs);
@@ -231,16 +226,12 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
         pscr = screenInfo.screens[nscr];
-#ifdef MPX
-        pDev = inputInfo.devices;
-        while(pDev)
+        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
             if (MPHasCursor(pDev))
             {
-#endif
                 if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
                 {
-#ifdef MPX
                     /* Realize failed for device pDev on screen pscr.
                      * We have to assume that for all devices before, realize
                      * worked. We need to rollback all devices so far on the
@@ -254,11 +245,9 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
                             ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                         pDevIt = pDevIt->next;
                     }
-#endif
                     while (--nscr >= 0)
                     {
                         pscr = screenInfo.screens[nscr];
-#ifdef MPX
                         /* now unrealize all devices on previous screens */
                         pDevIt = inputInfo.devices;
                         while (pDevIt)
@@ -267,19 +256,14 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
                                 ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                             pDevIt = pDevIt->next;
                         }
-#else
                         ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
-#endif
                     }
                     FreeCursorBits(bits);
                     xfree(pCurs);
                     return (CursorPtr)NULL;
                 }
-#ifdef MPX
             }
-            pDev = pDev->next;
         }
-#endif
     }
     return pCurs;
 }
@@ -462,16 +446,12 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
         pscr = screenInfo.screens[nscr];
-#ifdef MPX
-        pDev = inputInfo.devices;
-        while(pDev)
+        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
         {
             if (MPHasCursor(pDev))
             {
-#endif
                 if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
                 {
-#ifdef MPX
                     /* Realize failed for device pDev on screen pscr.
                      * We have to assume that for all devices before, realize
                      * worked. We need to rollback all devices so far on the
@@ -485,11 +465,9 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
                             ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                         pDevIt = pDevIt->next;
                     }
-#endif
                     while (--nscr >= 0)
                     {
                         pscr = screenInfo.screens[nscr];
-#ifdef MPX
                         /* now unrealize all devices on previous screens */
                         pDevIt = inputInfo.devices;
                         while (pDevIt)
@@ -498,19 +476,14 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
                                 ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
                             pDevIt = pDevIt->next;
                         }
-#else
                         ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
-#endif
                     }
                     FreeCursorBits(bits);
                     xfree(pCurs);
                     return BadAlloc;
                 }
-#ifdef MPX
             }
-            pDev = pDev->next;
         }
-#endif
     }
     *ppCurs = pCurs;
     return Success;
diff --git a/dix/events.c b/dix/events.c
index f438b07..5ab0764 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4589,13 +4589,16 @@ CheckCursorConfinement(WindowPtr pWin)
 
     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-        grab = pDev->grab;
-        if (grab && (confineTo = grab->confineTo))
+        if (MPHasCursor(pDev))
         {
-            if (!BorderSizeNotEmpty(pDev, confineTo))
-                (*inputInfo.pointer->DeactivateGrab)(pDev);
-            else if ((pWin == confineTo) || IsParent(pWin, confineTo))
-                ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
+            grab = pDev->grab;
+            if (grab && (confineTo = grab->confineTo))
+            {
+                if (!BorderSizeNotEmpty(pDev, confineTo))
+                    (*inputInfo.pointer->DeactivateGrab)(pDev);
+                else if ((pWin == confineTo) || IsParent(pWin, confineTo))
+                    ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
+            }
         }
     }
 }
diff --git a/dix/getevents.c b/dix/getevents.c
index f223f29..87937f6 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -66,12 +66,6 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
 #include "exglobals.h"
 #include "extnsionst.h"
 
-#ifdef MPX
-#include <X11/extensions/MPXconst.h>
-#include <X11/extensions/MPXproto.h>
-#include "mpxglobals.h"
-#endif
-
 /* Maximum number of valuators, divided by six, rounded up, to get number
  * of events. */
 #define MAX_VALUATOR_EVENTS 6
@@ -505,12 +499,8 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
 
     if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
         return 0;
-#ifdef MPX
-    if (pDev->isMPDev)
-        num_events = 3;
-    else
-#endif
-    if (pDev->coreEvents)
+
+    if (pDev->coreEvents || pDev->isMPDev)
         num_events = 2;
     else
         num_events = 1;
@@ -537,15 +527,10 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     kbp->time = ms;
     kbp->deviceid = pDev->id;
 
-#ifdef MPX
-    if (pDev->isMPDev)
+    if (!pDev->coreEvents || pDev->isMPDev)
         pointer = pDev;
-    else
-#endif
-    if (pDev->coreEvents)
+    else 
         pointer = inputInfo.pointer;
-    else
-        pointer = pDev;
 
     /* Set x and y based on whether this is absolute or relative, and
      * accelerate if we need to. */
@@ -598,16 +583,10 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
-#ifdef MPX
-    if (pDev->isMPDev)
-    {
-        // noop, just less intrusive to fit MPX in like that
-    } else
-#endif
-    if (pDev->coreEvents) {
+    if (pDev->coreEvents && !pDev->isMPDev) {
         /* set the virtual core pointer's coordinates */
-        pointer->valuator->lastx = x;
-        pointer->valuator->lasty = y;
+        inputInfo.pointer->valuator->lastx = x;
+        inputInfo.pointer->valuator->lasty = y;
     }
     pDev->valuator->lastx = x;
     pDev->valuator->lasty = y;
@@ -634,31 +613,8 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
                                    num_valuators, valuators);
     }
 
-#ifdef MPX
-    if (pDev->isMPDev)
-    {
-        /* MPX events are the same as XI events but without valuators. */
-        memcpy(events, kbp, sizeof(deviceKeyButtonPointer));
-        switch(type)
-        {
-            case ButtonPress:
-                events->u.u.type = MPXButtonPress;
-                break;
-            case ButtonRelease:
-                events->u.u.type = MPXButtonRelease;
-                break;
-            case MotionNotify:
-                events->u.u.type = MPXMotionNotify;
-                break;
-        }
-        events++;
-    }
-
     /* MPX devices always send core events */
     if (pDev->coreEvents || pDev->isMPDev) {
-#else
-    if (pDev->coreEvents) {
-#endif
         events->u.u.type = type;
         events->u.keyButtonPointer.time = ms;
         events->u.keyButtonPointer.rootX = x;
diff --git a/mi/midispcur.c b/mi/midispcur.c
index 0b4ef49..38772f6 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -58,11 +58,7 @@ in this Software without prior written authorization from The Open Group.
 # include   "picturestr.h"
 #endif
 
-#ifdef MPX
-# include "inputstr.h"
-
-#define SaneID(a) (a >= 0 && a < MAX_DEVICES)
-#endif
+# include "inputstr.h" /* for MAX_DEVICES */
 
 /* per-screen private data */
 
@@ -83,11 +79,13 @@ typedef struct {
 #endif
 } miDCBufferRec, *miDCBufferPtr;
 
+/* 
+ * The core pointer buffer will point to the index of the virtual core pointer
+ * in the pCursorBuffers array. 
+ */
 typedef struct {
     miDCBufferPtr pCoreBuffer; /* for core pointer */
-#ifdef MPX
-    miDCBufferPtr pMPBuffers;   /* for MPX pointers */
-#endif
+    miDCBufferPtr pCursorBuffers;   /* one for each device */
     CloseScreenProcPtr CloseScreen;
 } miDCScreenRec, *miDCScreenPtr;
 
@@ -140,6 +138,7 @@ miDCInitialize (pScreen, screenFuncs)
 {
     miDCScreenPtr   pScreenPriv;
     miDCBufferPtr   pBuffer;
+    int mpBufferIdx;
 
     if (miDCGeneration != serverGeneration)
     {
@@ -155,52 +154,37 @@ miDCInitialize (pScreen, screenFuncs)
     /*
      * initialize the entire private structure to zeros
      */
-#if !defined MPX
-    pScreenPriv->pCoreBuffer = (miDCBufferPtr)xalloc(sizeof(miDCBufferRec));
-    if (!pScreenPriv->pCoreBuffer)
+
+    pScreenPriv->pCursorBuffers = (miDCBufferPtr)xalloc(MAX_DEVICES *
+            sizeof(miDCBufferRec));
+    if (!pScreenPriv->pCursorBuffers)
     {
         xfree((pointer)pScreenPriv);
         return FALSE;
     }
-    pBuffer = pScreenPriv->pCoreBuffer;
-#else /* ifdef MPX */
-    {
-        int mpBufferIdx = 0;
-
-        pScreenPriv->pMPBuffers = (miDCBufferPtr)xalloc(MAX_DEVICES *
-                                sizeof(miDCBufferRec));
-        if (!pScreenPriv->pMPBuffers)
-        {
-            xfree((pointer)pScreenPriv);
-            return FALSE;
-        }
- 
-        /* virtual core pointer ID is 1 */
-        pScreenPriv->pCoreBuffer = &pScreenPriv->pMPBuffers[1];
-
-        while(mpBufferIdx < MAX_DEVICES)
-        {
-            pBuffer = &pScreenPriv->pMPBuffers[mpBufferIdx];
-#endif
-            pBuffer->pSourceGC =
-                pBuffer->pMaskGC =
-                pBuffer->pSaveGC =
-                pBuffer->pRestoreGC =
-                pBuffer->pMoveGC =
-                pBuffer->pPixSourceGC =
-                pBuffer->pPixMaskGC = NULL;
+
+    /* virtual core pointer ID is 1 */
+    pScreenPriv->pCoreBuffer = &pScreenPriv->pCursorBuffers[1];
+
+    mpBufferIdx = 0;
+    while(mpBufferIdx < MAX_DEVICES)
+    {
+        pBuffer = &pScreenPriv->pCursorBuffers[mpBufferIdx];
+        pBuffer->pSourceGC =
+            pBuffer->pMaskGC =
+            pBuffer->pSaveGC =
+            pBuffer->pRestoreGC =
+            pBuffer->pMoveGC =
+            pBuffer->pPixSourceGC =
+            pBuffer->pPixMaskGC = NULL;
 #ifdef ARGB_CURSOR
             pBuffer->pRootPicture = NULL;
             pBuffer->pTempPicture = NULL;
 #endif
+        pBuffer->pSave = pBuffer->pTemp = NULL;
 
-            pBuffer->pSave = pBuffer->pTemp = NULL;
-
-#ifdef MPX
-            mpBufferIdx++;
-        }
+        mpBufferIdx++;
     }
-#endif
 
 
     pScreenPriv->CloseScreen = pScreen->CloseScreen;
@@ -210,11 +194,7 @@ miDCInitialize (pScreen, screenFuncs)
 
     if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
     {
-#ifdef MPX
-        xfree((pointer)pScreenPriv->pMPBuffers);
-#else
-        xfree((pointer)pScreenPriv->pCoreBuffer);
-#endif
+        xfree ((pointer) pScreenPriv->pCursorBuffers);
 	xfree ((pointer) pScreenPriv);
 	return FALSE;
     }
@@ -232,28 +212,25 @@ miDCCloseScreen (index, pScreen)
 {
     miDCScreenPtr   pScreenPriv;
     miDCBufferPtr   pBuffer;
+    int mpBufferIdx;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
-    pBuffer = pScreenPriv->pCoreBuffer;
 
-#ifdef MPX
+    mpBufferIdx = 0;
+    while (mpBufferIdx < MAX_DEVICES) 
     {
-        int mpBufferIdx = 0;
-        while (mpBufferIdx < MAX_DEVICES) 
-        {
-            pBuffer = &pScreenPriv->pMPBuffers[mpBufferIdx];
+        pBuffer = &pScreenPriv->pCursorBuffers[mpBufferIdx];
 
-#endif
-            tossGC (pBuffer->pSourceGC);
-            tossGC (pBuffer->pMaskGC);
-            tossGC (pBuffer->pSaveGC);
-            tossGC (pBuffer->pRestoreGC);
-            tossGC (pBuffer->pMoveGC);
-            tossGC (pBuffer->pPixSourceGC);
-            tossGC (pBuffer->pPixMaskGC);
-            tossPix (pBuffer->pSave);
-            tossPix (pBuffer->pTemp);
+        tossGC (pBuffer->pSourceGC);
+        tossGC (pBuffer->pMaskGC);
+        tossGC (pBuffer->pSaveGC);
+        tossGC (pBuffer->pRestoreGC);
+        tossGC (pBuffer->pMoveGC);
+        tossGC (pBuffer->pPixSourceGC);
+        tossGC (pBuffer->pPixMaskGC);
+        tossPix (pBuffer->pSave);
+        tossPix (pBuffer->pTemp);
 #ifdef ARGB_CURSOR
 #if 0				/* This has been free()d before */
             tossPict (pScreenPriv->pRootPicture);
@@ -261,16 +238,10 @@ miDCCloseScreen (index, pScreen)
             tossPict (pBuffer->pTempPicture);
 #endif
 
-#ifdef MPX
             mpBufferIdx++;
-        }
     }
 
-    xfree((pointer) pScreenPriv->pMPBuffers);
-#else
-
-    xfree((pointer) pScreenPriv->pCoreBuffer);
-#endif
+    xfree((pointer) pScreenPriv->pCursorBuffers);
 
     xfree ((pointer) pScreenPriv);
     return (*pScreen->CloseScreen) (index, pScreen);
@@ -567,10 +538,8 @@ miDCPutUpCursor (pDev, pScreen, pCursor, x, y, source, mask)
     pWin = WindowTable[pScreen->myNum];
     pBuffer = pScreenPriv->pCoreBuffer;
 
-#ifdef MPX
     if (MPHasCursor(pDev))
-            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
-#endif
+        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
 
 #ifdef ARGB_CURSOR
     if (pPriv->pPicture)
@@ -619,10 +588,10 @@ miDCSaveUnderCursor (pDev, pScreen, x, y, w, h)
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
-#ifdef MPX
+
     if (MPHasCursor(pDev))
-            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
-#endif
+        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
@@ -658,10 +627,10 @@ miDCRestoreUnderCursor (pDev, pScreen, x, y, w, h)
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
-#ifdef MPX
+
     if (MPHasCursor(pDev))
-            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
-#endif
+        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     if (!pSave)
@@ -691,10 +660,10 @@ miDCChangeSave (pDev, pScreen, x, y, w, h, dx, dy)
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
-#ifdef MPX
+
     if (MPHasCursor(pDev))
-            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
-#endif
+        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     /*
@@ -842,10 +811,10 @@ miDCMoveCursor (pDev, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pWin = WindowTable[pScreen->myNum];
     pBuffer = pScreenPriv->pCoreBuffer;
-#ifdef MPX
+
     if (MPHasCursor(pDev))
-            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
-#endif
+        pBuffer = &pScreenPriv->pCursorBuffers[pDev->id];
+
     pTemp = pBuffer->pTemp;
     if (!pTemp ||
 	pTemp->drawable.width != pBuffer->pSave->drawable.width ||
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 6ccc729..10e6f3e 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -1,5 +1,5 @@
 /*
- * miPointer->c
+ * mipointer.c
  */
 
 
@@ -63,15 +63,14 @@ static unsigned long miPointerGeneration = 0;
  * until more than one pointer device exists.
  */
 
-static miPointerPtr miPointer;
+static miPointerPtr miCorePointer;
 
-#ifdef MPX
 /* Multipointers 
  * ID of a device == index in this array.
  */
-static miPointerRec miMPPointers[MAX_DEVICES];
-
-#endif
+static miPointerRec miPointers[MAX_DEVICES];
+#define MIPOINTER(dev) \
+    (MPHasCursor((dev))) ? &miPointers[(dev)->id] : miCorePointer
 
 static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                    CursorPtr pCursor);
@@ -103,6 +102,7 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
 {
     miPointerScreenPtr	pScreenPriv;
     miPointerPtr        pPointer;
+    int                 ptrIdx;
 
     if (miPointerGeneration != serverGeneration)
     {
@@ -139,29 +139,16 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     pScreen->SetCursorPosition = miPointerSetCursorPosition;
     pScreen->RecolorCursor = miRecolorCursor;
     pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
+
     /*
      * set up the pointer object
+     * virtual core pointer ID is always 1, so we let it point to the matching
+     * index in the array.
      */
-#if !defined MPX
-    miPointer = (miPointerPtr)xalloc(sizeof(miPointerRec));
-    if (!miPointer)
-    {
-        xfree((pointer)pScreenPriv);
-        return FALSE;
-    }
-    pPointer = miPointer;
-#else /* ifdef MPX */
-    miPointer = &miMPPointers[1];
+    miCorePointer = &miPointers[1];
+    for(ptrIdx = 0; ptrIdx < MAX_DEVICES; ptrIdx++)
     {
-        int mpPtrIdx = 0; /* loop counter */
-        /*
-         * Set up pointer objects for multipointer devices.
-         */
-        while(mpPtrIdx < MAX_DEVICES)
-        {
-            pPointer = &miMPPointers[mpPtrIdx];
-#endif
-
+            pPointer = &miPointers[ptrIdx];
             pPointer->pScreen = NULL;
             pPointer->pSpriteScreen = NULL;
             pPointer->pCursor = NULL;
@@ -173,11 +160,7 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
             pPointer->confined = FALSE;
             pPointer->x = 0;
             pPointer->y = 0;
-#ifdef MPX
-            mpPtrIdx++;
-        }
     }
-#endif
 
     return TRUE;
 }
@@ -187,28 +170,21 @@ miPointerCloseScreen (index, pScreen)
     int		index;
     ScreenPtr	pScreen;
 {
-    SetupScreen(pScreen);
-    miPointerPtr pPointer = miPointer;
+    miPointerPtr pPointer;
+    int ptrIdx;
 
-#ifdef MPX
-    int mpPointerIdx = 0;
+    SetupScreen(pScreen);
 
-    while(mpPointerIdx < MAX_DEVICES)
+    for(ptrIdx = 0; ptrIdx < MAX_DEVICES; ptrIdx++)
     {
-        pPointer = &miMPPointers[mpPointerIdx];
-#endif
+        pPointer = &miPointers[ptrIdx];
+
         if (pScreen == pPointer->pScreen)
             pPointer->pScreen = 0;
         if (pScreen == pPointer->pSpriteScreen)
             pPointer->pSpriteScreen = 0;
-#ifdef MPX
-        mpPointerIdx++;
     }
-#endif
 
-#if !defined MPX
-    xfree((pointer)miPointer);
-#endif
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
     xfree ((pointer) pScreenPriv);
     return (*pScreen->CloseScreen) (index, pScreen);
@@ -244,12 +220,8 @@ miPointerDisplayCursor (pDev, pScreen, pCursor)
     ScreenPtr 	 pScreen;
     CursorPtr	 pCursor;
 {
-    miPointerPtr pPointer = miPointer;
-#ifdef MPX
-    /* use core pointer for non MPX devices */
-    if (MPHasCursor(pDev))
-        pPointer = &miMPPointers[pDev->id];
-#endif
+    miPointerPtr pPointer = MIPOINTER(pDev);
+
     pPointer->pCursor = pCursor;
     pPointer->pScreen = pScreen;
     miPointerUpdateSprite(pDev);
@@ -262,11 +234,8 @@ miPointerConstrainCursor (pDev, pScreen, pBox)
     ScreenPtr	pScreen;
     BoxPtr	pBox;
 {
-    miPointerPtr pPointer = miPointer;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pPointer = &miMPPointers[pDev->id];
-#endif
+    miPointerPtr pPointer = MIPOINTER(pDev);
+
     pPointer->limits = *pBox;
     pPointer->confined = PointerConfinedToScreen(pDev);
 }
@@ -320,15 +289,9 @@ miPointerWarpCursor (pDev, pScreen, x, y)
     ScreenPtr	 pScreen;
     int	   	 x, y;
 {
-    miPointerPtr pPointer = miPointer;
+    miPointerPtr pPointer = MIPOINTER(pDev);
     SetupScreen (pScreen);
 
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pPointer = &miMPPointers[pDev->id];
-#endif
-
-
     if (pPointer->pScreen != pScreen)
 	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
 
@@ -376,20 +339,13 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     miPointerScreenPtr	pScreenPriv;
     CursorPtr		pCursor;
     int			x, y, devx, devy;
-    miPointerPtr        pPointer = miPointer;
+    miPointerPtr        pPointer;
 
     if (!pDev || 
-            !(pDev->coreEvents || pDev == inputInfo.pointer 
-#ifdef MPX
-                || pDev->isMPDev
-#endif
-             ))
+            !(pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev))
         return;
 
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pPointer = &miMPPointers[pDev->id];
-#endif
+    pPointer = MIPOINTER(pDev);
 
     pScreen = pPointer->pScreen;
     if (!pScreen)
@@ -458,7 +414,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
 void
 miPointerDeltaCursor (int dx, int dy, unsigned long time)
 {
-    int x = miPointer->x + dx, y = miPointer->y + dy;
+    int x = miCorePointer->x + dx, y = miCorePointer->y + dy;
 
     miPointerSetPosition(inputInfo.pointer, &x, &y, time);
 }
@@ -474,16 +430,13 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
 {
 	miPointerScreenPtr pScreenPriv;
 	ScreenPtr pScreen;
-        miPointerPtr pPointer = miPointer;
+        miPointerPtr pPointer = MIPOINTER(pDev);
 
 	pScreen = screenInfo.screens[screen_no];
 	pScreenPriv = GetScreenPrivate (pScreen);
 	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
 	NewCurrentScreen (pDev, pScreen, x, y);
-#ifdef MPX
-        if (MPHasCursor(pDev))
-            pPointer = &miMPPointers[pDev->id];
-#endif
+
         pPointer->limits.x2 = pScreen->width;
         pPointer->limits.y2 = pScreen->height;
 }
@@ -497,11 +450,7 @@ miPointerCurrentScreen ()
 _X_EXPORT ScreenPtr
 miPointerGetScreen(DeviceIntPtr pDev)
 {
-    miPointerPtr pPointer;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pPointer = &miMPPointers[pDev->id];
-#endif
+    miPointerPtr pPointer = MIPOINTER(pDev);
     return pPointer->pScreen;
 }
 
@@ -521,22 +470,14 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     ScreenPtr		pScreen;
     ScreenPtr		newScreen;
 
-    miPointerPtr        pPointer = miPointer;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pPointer = &(miMPPointers[pDev->id]);
-#endif
+    miPointerPtr        pPointer = MIPOINTER(pDev);
 
     pScreen = pPointer->pScreen;
     if (!pScreen)
 	return;	    /* called before ready */
 
     if (!pDev || 
-            !(pDev->coreEvents || pDev == inputInfo.pointer 
-#ifdef MPX
-                || pDev->isMPDev
-#endif
-                ))
+            !(pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev))
         return;
 
     if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
@@ -583,11 +524,7 @@ miPointerPosition (int *x, int *y)
 _X_EXPORT void
 miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
 {
-    miPointerPtr pPointer = miPointer;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pPointer = &miMPPointers[pDev->id];
-#endif
+    miPointerPtr pPointer = MIPOINTER(pDev);
     *x = pPointer->x;
     *y = pPointer->y;
 }
@@ -603,20 +540,12 @@ void
 miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
                      unsigned long time)
 {
-    miPointerPtr pPointer = miPointer;
+    miPointerPtr pPointer = MIPOINTER(pDev);
     SetupScreen(pScreen);
 
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pPointer = &miMPPointers[pDev->id];
-#endif
 
-    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer
-#ifdef MPX
-                || pDev->isMPDev
-#endif
-                ) &&
-        !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
+    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev)
+        && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
     {
 	pPointer->devx = x;
 	pPointer->devy = y;
diff --git a/mi/misprite.c b/mi/misprite.c
index e55032b..2e3b376 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -146,31 +146,25 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
     ScreenPtr		    pScreen = closure;
     miSpriteScreenPtr	    pScreenPriv;
     miCursorInfoPtr         pCursorInfo;
-    DeviceIntPtr            pDev = inputInfo.pointer;
+    DeviceIntPtr            pDev;
     
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
+    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (MPHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
+
             if (pCursorInfo->isUp &&
-                    RECT_IN_REGION (pScreen, pRegion, &pCursorInfo->saved) 
+                RECT_IN_REGION (pScreen, pRegion, &pCursorInfo->saved) 
                          != rgnOUT) 
             {
                 SPRITE_DEBUG(("Damage remove\n"));
                 miSpriteRemoveCursor (pDev, pScreen);
             }
-#ifdef MPX
         }
-        pDev = pDev->next;
     }
-#endif
 }
 
 /*
@@ -188,6 +182,7 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     miSpriteScreenPtr	pScreenPriv;
     VisualPtr		pVisual;
     miCursorInfoPtr     pCursorInfo;
+    int cursorIdx;
     
     if (!DamageSetup (pScreen))
 	return FALSE;
@@ -235,54 +230,41 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     
     pScreenPriv->BlockHandler = pScreen->BlockHandler;
     
-#if !defined MPX
-    pScreenPriv->cp = (miCursorInfoPtr)xalloc(sizeof(miCursorInfoRec));
-    if (!pScreenPriv->cp)
-    {
-        xfree((pointer)pScreenPriv);
-        return FALSE;
-    }
-    pCursorInfo = pScreenPriv->cp;
-#else
-    /* alloc and zero memory for all MPX cursors */
-    pScreenPriv->mpCursors = (miCursorInfoPtr)xalloc(MAX_DEVICES * sizeof(miCursorInfoRec));
-    if (!pScreenPriv->mpCursors)
+    /* alloc and zero memory for all cursors */
+    pScreenPriv->pDevCursors = 
+        (miCursorInfoPtr)xalloc(MAX_DEVICES * sizeof(miCursorInfoRec));
+
+    if (!pScreenPriv->pDevCursors)
     {
-        xfree((pointer)pScreenPriv->cp);
         xfree((pointer)pScreenPriv);
         return FALSE;
     }
-    pScreenPriv->cp = &(pScreenPriv->mpCursors[1]);
+    /* virtual core pointer's ID is 1 */
+    pScreenPriv->cp = &(pScreenPriv->pDevCursors[1]);
 
+    cursorIdx = 0;
+    while (cursorIdx < MAX_DEVICES)
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
-        {
-            pCursorInfo = &(pScreenPriv->mpCursors[mpCursorIdx]);
-#endif
+        pCursorInfo = &(pScreenPriv->pDevCursors[cursorIdx]);
+        pCursorInfo->pCursor = NULL;
+        pCursorInfo->x = 0;
+        pCursorInfo->y = 0;
+        pCursorInfo->isUp = FALSE;
+        pCursorInfo->shouldBeUp = FALSE;
+        pCursorInfo->pCacheWin = NullWindow;
+        pCursorInfo->isInCacheWin = FALSE;
+        pCursorInfo->checkPixels = TRUE;
+        pCursorInfo->pInstalledMap = NULL;
+        pCursorInfo->pColormap = NULL;
+        pCursorInfo->colors[SOURCE_COLOR].red = 0;
+        pCursorInfo->colors[SOURCE_COLOR].green = 0;
+        pCursorInfo->colors[SOURCE_COLOR].blue = 0;
+        pCursorInfo->colors[MASK_COLOR].red = 0;
+        pCursorInfo->colors[MASK_COLOR].green = 0;
+        pCursorInfo->colors[MASK_COLOR].blue = 0;
 
-            pCursorInfo->pCursor = NULL;
-            pCursorInfo->x = 0;
-            pCursorInfo->y = 0;
-            pCursorInfo->isUp = FALSE;
-            pCursorInfo->shouldBeUp = FALSE;
-            pCursorInfo->pCacheWin = NullWindow;
-            pCursorInfo->isInCacheWin = FALSE;
-            pCursorInfo->checkPixels = TRUE;
-            pCursorInfo->pInstalledMap = NULL;
-            pCursorInfo->pColormap = NULL;
-            pCursorInfo->colors[SOURCE_COLOR].red = 0;
-            pCursorInfo->colors[SOURCE_COLOR].green = 0;
-            pCursorInfo->colors[SOURCE_COLOR].blue = 0;
-            pCursorInfo->colors[MASK_COLOR].red = 0;
-            pCursorInfo->colors[MASK_COLOR].green = 0;
-            pCursorInfo->colors[MASK_COLOR].blue = 0;
-
-#ifdef MPX
-            mpCursorIdx++;
-        }
+        cursorIdx++;
     }
-#endif
 
     pScreenPriv->funcs = cursorFuncs;
     pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv;
@@ -321,6 +303,7 @@ miSpriteCloseScreen (i, pScreen)
     ScreenPtr	pScreen;
 {
     miSpriteScreenPtr   pScreenPriv;
+    DeviceIntPtr        pDev;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
@@ -333,15 +316,18 @@ miSpriteCloseScreen (i, pScreen)
     pScreen->StoreColors = pScreenPriv->StoreColors;
 
     pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
-    miSpriteIsUpFALSE (pScreenPriv->cp, pScreen, pScreenPriv);
+    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+    {
+        if (MPHasCursor(pDev))
+        {
+            miCursorInfoPtr pCursor;
+            pCursor = &pScreenPriv->pDevCursors[pDev->id];
+            miSpriteIsUpFALSE (pCursor, pScreen, pScreenPriv);
+        }
+    }
     DamageDestroy (pScreenPriv->pDamage);
 
-#ifdef MPX
-    xfree((pointer)(pScreenPriv->mpCursors));
-#else
-    xfree((pointer)(pScreenPriv->cp));
-#endif
-    
+    xfree ((pointer)(pScreenPriv->pDevCursors));
     xfree ((pointer) pScreenPriv);
 
     return (*pScreen->CloseScreen) (i, pScreen);
@@ -363,16 +349,12 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
     SCREEN_PROLOGUE (pScreen, GetImage);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while (pDev)
+    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (MPHasCursor(pDev))
         {
-             pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+             pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
              if (pDrawable->type == DRAWABLE_WINDOW &&
                      pCursorInfo->isUp &&
                      ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, 
@@ -381,11 +363,8 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
                  SPRITE_DEBUG (("GetImage remove\n"));
                  miSpriteRemoveCursor (pDev, pScreen);
              }
-#ifdef MPX
         }
-        pDev = pDev->next;
     }
-#endif
 
     (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
 			  format, planemask, pdstLine);
@@ -410,16 +389,12 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
     SCREEN_PROLOGUE (pScreen, GetSpans);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
+    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (MPHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
             if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp)
             {
@@ -445,11 +420,8 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
                     }
                 }
             }
-#ifdef MPX
         }
-        pDev = pDev->next;
     }
-#endif
 
     (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
 
@@ -469,16 +441,12 @@ miSpriteSourceValidate (pDrawable, x, y, width, height)
     SCREEN_PROLOGUE (pScreen, SourceValidate);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
+    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (MPHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
             if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp &&
                     ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
                         x, y, width, height))
@@ -486,12 +454,8 @@ miSpriteSourceValidate (pDrawable, x, y, width, height)
                 SPRITE_DEBUG (("SourceValidate remove\n"));
                 miSpriteRemoveCursor (pDev, pScreen);
             }
-#ifdef MPX
         }
-        pDev = pDev->next;
     }
-#endif
-
 
     if (pScreen->SourceValidate)
 	(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
@@ -510,16 +474,12 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
     SCREEN_PROLOGUE (pScreen, CopyWindow);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
+    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (MPHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
             /*
              * Damage will take care of destination check
              */
@@ -529,11 +489,8 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
                 SPRITE_DEBUG (("CopyWindow remove\n"));
                 miSpriteRemoveCursor (pDev, pScreen);
             }
-#ifdef MPX
         }
-        pDev = pDev->next;
     }
-#endif
 
     (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
     SCREEN_EPILOGUE (pScreen, CopyWindow);
@@ -552,7 +509,6 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
     miCursorInfoPtr         pCursorInfo;
 
     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pPriv->cp;
 
     SCREEN_PROLOGUE(pScreen, BlockHandler);
     
@@ -560,25 +516,18 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
 
     SCREEN_EPILOGUE(pScreen, BlockHandler);
 
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
+    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (MPHasCursor(pDev))
         {
-            pCursorInfo = &pPriv->mpCursors[pDev->id];
-#endif
+            pCursorInfo = &pPriv->pDevCursors[pDev->id];
             if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
             {
                 SPRITE_DEBUG (("BlockHandler restore\n"));
                 miSpriteRestoreCursor (pDev, pScreen);
             }
-#ifdef MPX
         }
-        pDev = pDev->next;
     }
-#endif
-
 }
 
 static void
@@ -592,7 +541,6 @@ miSpriteInstallColormap (pMap)
     int                     cursorIdx;
 
     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pPriv->cp;
 
     SCREEN_PROLOGUE(pScreen, InstallColormap);
     
@@ -600,37 +548,30 @@ miSpriteInstallColormap (pMap)
 
     SCREEN_EPILOGUE(pScreen, InstallColormap);
 
-#ifdef MPX
     /* InstallColormap is called before devices are initialized. We cannot
      * just run through the device list, we need to go through all possible
      * sprite structs.*/
-    cursorIdx = 0;
-    while(cursorIdx < MAX_DEVICES)
+    for (cursorIdx = 0; cursorIdx < MAX_DEVICES; cursorIdx++)
     {
-        pCursorInfo = &pPriv->mpCursors[cursorIdx];
-#endif
+        pCursorInfo = &pPriv->pDevCursors[cursorIdx];
         pCursorInfo->pInstalledMap = pMap;
         if (pCursorInfo->pColormap != pMap)
         {
             pCursorInfo->checkPixels = TRUE;
             if (pCursorInfo->isUp)
             {
-#ifdef MPX
                 /* find matching device */
-                pDev = inputInfo.devices;
-                while(pDev && pDev->id != cursorIdx)
-                    pDev = pDev->next;
-                if (!pDev)
-                    pDev = inputInfo.pointer;
-#endif
-                miSpriteRemoveCursor (pDev, pScreen);
-            }
-        }
-#ifdef MPX
-        cursorIdx++;
+                for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
+                {
+                    if (pDev->id == cursorIdx)
+                    {
+                        miSpriteRemoveCursor(pDev, pScreen);
+                        break;
+                    }
+                }
+            } 
+        } 
     }
-#endif
-
 }
 
 static void
@@ -650,7 +591,6 @@ miSpriteStoreColors (pMap, ndef, pdef)
     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
     SCREEN_PROLOGUE(pScreen, StoreColors);
-    pCursorInfo = pPriv->cp;
     
     (*pScreen->StoreColors) (pMap, ndef, pdef);
 
@@ -670,14 +610,11 @@ miSpriteStoreColors (pMap, ndef, pdef)
 	    UpdateDAC(dev, plane,green,greenMask) \
 	    UpdateDAC(dev, plane,blue,blueMask)
 
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
+    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if (MPHasCursor(pDev))
         {
-            pCursorInfo = &pPriv->mpCursors[pDev->id];
-#endif
+            pCursorInfo = &pPriv->pDevCursors[pDev->id];
             if (pCursorInfo->pColormap == pMap)
             {
                 updated = 0;
@@ -688,8 +625,8 @@ miSpriteStoreColors (pMap, ndef, pdef)
 
                     for (i = 0; i < ndef; i++)
                     {
-                        CheckDirect (pPriv->cp, SOURCE_COLOR)
-                            CheckDirect (pPriv->cp, MASK_COLOR)
+                        CheckDirect (pCursorInfo, SOURCE_COLOR)
+                            CheckDirect (pCursorInfo, MASK_COLOR)
                     }
                 }
                 else
@@ -720,11 +657,8 @@ miSpriteStoreColors (pMap, ndef, pdef)
                         miSpriteRemoveCursor (pDev, pScreen);
                 }
             }
-#ifdef MPX
         }
-        pDev = pDev->next;
     }
-#endif
 
 }
 
@@ -784,16 +718,12 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
     SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
+    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
         if(MPHasCursor(pDev))
         {
-            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+            pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
             if (pCursorInfo->isUp)
             {
                 cursorBox = pCursorInfo->saved;
@@ -809,11 +739,8 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
                     miSpriteRemoveCursor (pDev, pScreen);
             }
 
-#ifdef MPX
         }
-        pDev = pDev->next;
     }
-#endif
 
     (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
 
@@ -838,10 +765,8 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
     if (MPHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
     if (pCursor == pCursorInfo->pCursor)
 	pCursorInfo->checkPixels = TRUE;
@@ -873,10 +798,9 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     miCursorInfoPtr pPointer = pScreenPriv->cp;
-#ifdef MPX
+
     if (MPHasCursor(pDev))
-        pPointer = &pScreenPriv->mpCursors[pDev->id];
-#endif
+        pPointer = &pScreenPriv->pDevCursors[pDev->id];
 
     if (!pCursor)
     {
@@ -992,10 +916,9 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursor = pScreenPriv->cp->pCursor;
 
-#ifdef MPX
     if (MPHasCursor(pDev))
-        pCursor = pScreenPriv->mpCursors[pDev->id].pCursor;
-#endif
+        pCursor = pScreenPriv->pDevCursors[pDev->id].pCursor;
+
     miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
 }
 
@@ -1016,10 +939,8 @@ miSpriteRemoveCursor (pDev, pScreen)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
     if (MPHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
     miSpriteIsUpFALSE (pCursorInfo, pScreen, pScreenPriv);
     pCursorInfo->pCacheWin = NullWindow;
@@ -1056,10 +977,8 @@ miSpriteRestoreCursor (pDev, pScreen)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
     if (MPHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
+        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
     miSpriteComputeSaved (pDev, pScreen);
     pCursor = pCursorInfo->pCursor;
@@ -1106,11 +1025,8 @@ miSpriteComputeSaved (pDev, pScreen)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursorInfo = pScreenPriv->cp;
 
-#ifdef MPX
     if (MPHasCursor(pDev))
-        pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
-#endif
-
+        pCursorInfo = &pScreenPriv->pDevCursors[pDev->id];
 
     pCursor = pCursorInfo->pCursor;
     x = pCursorInfo->x - (int)pCursor->bits->xhot;
diff --git a/mi/mispritest.h b/mi/mispritest.h
index 0ba5365..39875e0 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -88,9 +88,7 @@ typedef struct {
     VisualPtr	    pVisual;
     miSpriteCursorFuncPtr    funcs;
     DamagePtr	    pDamage;		/* damage tracking structure */
-#ifdef MPX
-    miCursorInfoPtr mpCursors;         /* all cursor's info */
-#endif
+    miCursorInfoPtr pDevCursors;         /* all cursors' info */
 } miSpriteScreenRec, *miSpriteScreenPtr;
 
 #define SOURCE_COLOR	0
commit ae3c24da34cd8eeb77a6389861856fd51e0841f5
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Dec 11 18:09:59 2006 +1030

    dix:    Moving SpriteRec into DeviceIntRec
    	removing global sprite structure
    	beginning to remove MPX ifdefs
    
    xnest:  Fix to make xnest compile again

diff --git a/Changelog b/Changelog
index 5a264ab..463d028 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,26 @@
 MPX Changelog file
+== 12.12.06 ==
+dix:    Moving SpriteRec into DeviceIntRec
+	removing global sprite structure
+	beginning to remove MPX ifdefs
+
+xnest:  Fix to make xnest compile again 
+
+Files:
+	dix/getevents.c
+	dix/events.c
+	dix/devices.c
+	hw/xfree86/common/xf86Xinput.c
+	include/cursor.h
+	include/dix.h
+	include/dixevents.h
+	include/input.h
+	include/inputstr.h
+	XTrap/xtrapdi.c
+	Xext/xtest.c
+	hw/xnest/Events.c
+	record/record.c
+
 == 05.12.06 ==
 Xi:     adding MPX checks to ProcessOtherEvents
 
diff --git a/XTrap/xtrapdi.c b/XTrap/xtrapdi.c
index c5d640d..ec85518 100644
--- a/XTrap/xtrapdi.c
+++ b/XTrap/xtrapdi.c
@@ -71,6 +71,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #endif
 #include "pixmapstr.h"          /* DrawableRec */
 #include "windowstr.h"          /* Drawable Lookup structures */
+#include "inputstr.h"
 #include <X11/extensions/xtrapdi.h>
 #include <X11/extensions/xtrapddmi.h>
 #include <X11/extensions/xtrapproto.h>
@@ -1564,7 +1565,7 @@ void XETrapStampAndMail(xEvent *x_event)
                 data.u.event.u.u.type == ButtonRelease ||
                 data.u.event.u.u.type == KeyPress ||
                 data.u.event.u.u.type == KeyRelease)) {
-		    int scr = XineramaGetCursorScreen();
+		    int scr = XineramaGetCursorScreen(inputInfo.pointer);
 		    data.u.event.u.keyButtonPointer.rootX +=
 			panoramiXdataPtr[scr].x - panoramiXdataPtr[0].x;
 		    data.u.event.u.keyButtonPointer.rootY +=
diff --git a/Xext/xtest.c b/Xext/xtest.c
index 66c84d7..7b2aa75 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -148,7 +148,7 @@ ProcXTestCompareCursor(client)
     if (stuff->cursor == None)
 	pCursor = NullCursor;
     else if (stuff->cursor == XTestCurrentCursor)
-	pCursor = GetSpriteCursor();
+	pCursor = GetSpriteCursor(inputInfo.pointer);
     else {
 	pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
 	if (!pCursor) 
@@ -426,7 +426,8 @@ ProcXTestFakeInput(client)
 
 #ifdef PANORAMIX
 	if ((!noPanoramiXExtension
-	     && root->drawable.pScreen->myNum != XineramaGetCursorScreen())
+	     && root->drawable.pScreen->myNum 
+                != XineramaGetCursorScreen(inputInfo.pointer))
 	    || (noPanoramiXExtension && root != GetCurrentRootWindow()))
 
 #else
diff --git a/dix/devices.c b/dix/devices.c
index e6a5049..b4896ac 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -366,8 +366,12 @@ InitCoreDevices()
         if (!AllocateDevicePrivate(dev, CoreDevicePrivatesIndex))
             FatalError("Couldn't allocate pointer devPrivates\n");
         dev->devPrivates[CoreDevicePrivatesIndex].ptr = NULL;
+        InitSprite(dev, TRUE);
         (void)ActivateDevice(dev);
         inputInfo.pointer = dev;
+        /* the core keyboard is initialised by now. set the keyboard's sprite
+         * to the core pointer's sprite. */
+        InitSprite(inputInfo.keyboard, FALSE);
     }
 }
 
diff --git a/dix/events.c b/dix/events.c
index 8d7167e..f438b07 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -175,9 +175,7 @@ xEvent *xeviexE;
 #include "dixgrabs.h"
 #include "dispatch.h"
 
-#ifdef MPX
 #include "mpxglobals.h"
-#endif
 
 #define EXTENSION_EVENT_BASE  64
 
@@ -244,33 +242,9 @@ static WindowPtr *spriteTrace = (WindowPtr *)NULL;
 static int spriteTraceSize = 0;
 static int spriteTraceGood;
 
-typedef struct {
-    CursorPtr	current;
-    BoxRec	hotLimits;	/* logical constraints of hot spot */
-    Bool	confined;	/* confined to screen */
-#if defined(SHAPE) || defined(PANORAMIX)
-    RegionPtr	hotShape;	/* additional logical shape constraint */
-#endif
-    BoxRec	physLimits;	/* physical constraints of hot spot */
-    WindowPtr	win;		/* window of logical position */
-    HotSpot	hot;		/* logical pointer position */
-    HotSpot	hotPhys;	/* physical pointer position */
-#ifdef PANORAMIX
-    ScreenPtr	screen;		/* all others are in Screen 0 coordinates */
-    RegionRec   Reg1;	        /* Region 1 for confining motion */
-    RegionRec   Reg2;		/* Region 2 for confining virtual motion */
-    WindowPtr   windows[MAXSCREENS];
-    WindowPtr	confineWin;	/* confine window */ 
-#endif
-} SpriteRec, *SpritePtr;
-
-static SpritePtr sprite;		/* info about the cursor sprite */
 
-#ifdef MPX
 #define MPXDBG(...) fprintf (stderr, "MPX: " __VA_ARGS__)
 
-static SpritePtr mpsprites;             /* info about the MPX sprites */
-
 /** 
  * True for the core pointer and any MPX device. 
  * False for any other device (including keyboards).
@@ -283,8 +257,6 @@ MPHasCursor(DeviceIntPtr pDev)
             (pDev->isMPDev && pDev->id < MAX_DEVICES)); 
 }
 
-#endif
-
 #ifdef XEVIE
 _X_EXPORT WindowPtr xeviewin;
 _X_EXPORT HotSpot xeviehot;
@@ -359,8 +331,8 @@ static CARD8 criticalEvents[32] =
 static void ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py);
 static void PostNewCursor(DeviceIntPtr pDev);
 
-#define SyntheticMotion(x, y) \
-    PostSyntheticMotion(x, y, sprite->screen, \
+#define SyntheticMotion(dev, x, y) \
+    PostSyntheticMotion(dev, x, y, dev->pSprite->screen, \
                         syncEvents.playingEvents ? \
                           syncEvents.time.milliseconds : \
                           currentTime.milliseconds);
@@ -375,12 +347,7 @@ XineramaSetCursorPosition(
     ScreenPtr pScreen;
     BoxRec box;
     int i;
-    SpritePtr pSprite = sprite;
-
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
 
     /* x,y are in Screen 0 coordinates.  We need to decide what Screen
        to send the message too and what the coordinates relative to 
@@ -418,15 +385,10 @@ XineramaSetCursorPosition(
 static void
 XineramaConstrainCursor(DeviceIntPtr pDev)
 {
-    SpritePtr pSprite = sprite;
+    SpritePtr pSprite = pDev->pSprite;
     ScreenPtr pScreen;
     BoxRec newBox;
 
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
-
     pScreen = pSprite->screen;
     newBox = pSprite->physLimits;
 
@@ -447,14 +409,10 @@ XineramaCheckPhysLimits(
     Bool generateEvents
 ){
     HotSpot new;
-    SpritePtr pSprite = sprite;
+    SpritePtr pSprite = pDev->pSprite;
 
     if (!cursor)
 	return;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
  
     new = pSprite->hotPhys;
 
@@ -480,7 +438,7 @@ XineramaCheckPhysLimits(
     {
 	XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
 	if (!generateEvents)
-	    SyntheticMotion(new.x, new.y);
+	    SyntheticMotion(pDev, new.x, new.y);
     }
 
     /* Tell DDX what the limits are */
@@ -489,10 +447,12 @@ XineramaCheckPhysLimits(
 
 
 static Bool
-XineramaSetWindowPntrs(WindowPtr pWin)
+XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
 {
+    SpritePtr pSprite = pDev->pSprite;
+
     if(pWin == WindowTable[0]) {
-	    memcpy(sprite->windows, WindowTable, 
+	    memcpy(pSprite->windows, WindowTable, 
 				PanoramiXNumScreens*sizeof(WindowPtr));
     } else {
 	PanoramiXRes *win;
@@ -504,8 +464,8 @@ XineramaSetWindowPntrs(WindowPtr pWin)
 	    return FALSE;
 
 	for(i = 0; i < PanoramiXNumScreens; i++) {
-	   sprite->windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
-	   if(!sprite->windows[i])  /* window is being unmapped */
+	   pSprite->windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
+	   if(!pSprite->windows[i])  /* window is being unmapped */
 		return FALSE;
 	}
     }
@@ -514,16 +474,18 @@ XineramaSetWindowPntrs(WindowPtr pWin)
 
 static void
 XineramaCheckVirtualMotion(
+   DeviceIntPtr pDev,
    QdEventPtr qe,
-   WindowPtr pWin
-){
+   WindowPtr pWin) 
+{
+    SpritePtr pSprite = pDev->pSprite;
 
     if (qe)
     {
-	sprite->hot.pScreen = qe->pScreen;  /* should always be Screen 0 */
-	sprite->hot.x = qe->event->u.keyButtonPointer.rootX;
-	sprite->hot.y = qe->event->u.keyButtonPointer.rootY;
-	pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
+	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->grab ? pDev->grab->confineTo :
 					 NullWindow;
     }
     if (pWin)
@@ -531,13 +493,13 @@ XineramaCheckVirtualMotion(
 	int x, y, off_x, off_y, i;
 	BoxRec lims;
 
-	if(!XineramaSetWindowPntrs(pWin))
+	if(!XineramaSetWindowPntrs(pDev, pWin))
 	    return;
 
 	i = PanoramiXNumScreens - 1;
 	
-	REGION_COPY(sprite->screen, &sprite->Reg2, 
-					&sprite->windows[i]->borderSize); 
+	REGION_COPY(pSprite->screen, &pSprite->Reg2, 
+					&pSprite->windows[i]->borderSize); 
 	off_x = panoramiXdataPtr[i].x;
 	off_y = panoramiXdataPtr[i].y;
 
@@ -546,39 +508,40 @@ XineramaCheckVirtualMotion(
 	    y = off_y - panoramiXdataPtr[i].y;
 
 	    if(x || y)
-		REGION_TRANSLATE(sprite->screen, &sprite->Reg2, x, y);
+		REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, x, y);
 		
-	    REGION_UNION(sprite->screen, &sprite->Reg2, &sprite->Reg2, 
-					&sprite->windows[i]->borderSize);
+	    REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2, 
+					&pSprite->windows[i]->borderSize);
 
 	    off_x = panoramiXdataPtr[i].x;
 	    off_y = panoramiXdataPtr[i].y;
 	}
 
-	lims = *REGION_EXTENTS(sprite->screen, &sprite->Reg2);
+	lims = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg2);
 
-        if (sprite->hot.x < lims.x1)
-            sprite->hot.x = lims.x1;
-        else if (sprite->hot.x >= lims.x2)
-            sprite->hot.x = lims.x2 - 1;
-        if (sprite->hot.y < lims.y1)
-            sprite->hot.y = lims.y1;
-        else if (sprite->hot.y >= lims.y2)
-            sprite->hot.y = lims.y2 - 1;
+        if (pSprite->hot.x < lims.x1)
+            pSprite->hot.x = lims.x1;
+        else if (pSprite->hot.x >= lims.x2)
+            pSprite->hot.x = lims.x2 - 1;
+        if (pSprite->hot.y < lims.y1)
+            pSprite->hot.y = lims.y1;
+        else if (pSprite->hot.y >= lims.y2)
+            pSprite->hot.y = lims.y2 - 1;
 
-	if (REGION_NUM_RECTS(&sprite->Reg2) > 1) 
-	    ConfineToShape(inputInfo.pointer, &sprite->Reg2, &sprite->hot.x, &sprite->hot.y);
+	if (REGION_NUM_RECTS(&pSprite->Reg2) > 1) 
+	    ConfineToShape(pDev, &pSprite->Reg2, 
+                    &pSprite->hot.x, &pSprite->hot.y);
 
 	if (qe)
 	{
-	    qe->pScreen = sprite->hot.pScreen;
-	    qe->event->u.keyButtonPointer.rootX = sprite->hot.x;
-	    qe->event->u.keyButtonPointer.rootY = sprite->hot.y;
+	    qe->pScreen = pSprite->hot.pScreen;
+	    qe->event->u.keyButtonPointer.rootX = pSprite->hot.x;
+	    qe->event->u.keyButtonPointer.rootY = pSprite->hot.y;
 	}
     }
 #ifdef XEVIE
-    xeviehot.x = sprite->hot.x;
-    xeviehot.y = sprite->hot.y;
+    xeviehot.x = pSprite->hot.x;
+    xeviehot.y = pSprite->hot.y;
 #endif
 }
 
@@ -587,12 +550,7 @@ static Bool
 XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
     WindowPtr prevSpriteWin;
-    SpritePtr pSprite = sprite;
-
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
 
     prevSpriteWin = pSprite->win;
 
@@ -653,25 +611,28 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 
 
 static void
-XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
+XineramaConfineCursorToWindow(DeviceIntPtr pDev, 
+                              WindowPtr pWin, 
+                              Bool generateEvents)
 {
+    SpritePtr pSprite = pDev->pSprite;
 
     if (syncEvents.playingEvents)
     {
-	XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin);
-	SyntheticMotion(sprite->hot.x, sprite->hot.y);
+	XineramaCheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
+	SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
     }
     else
     {
 	int x, y, off_x, off_y, i;
 
-	if(!XineramaSetWindowPntrs(pWin))
+	if(!XineramaSetWindowPntrs(pDev, pWin))
 	    return;
 
 	i = PanoramiXNumScreens - 1;
 	
-	REGION_COPY(sprite->screen, &sprite->Reg1, 
-					&sprite->windows[i]->borderSize); 
+	REGION_COPY(pSprite->screen, &pSprite->Reg1, 
+					&pSprite->windows[i]->borderSize); 
 	off_x = panoramiXdataPtr[i].x;
 	off_y = panoramiXdataPtr[i].y;
 
@@ -680,26 +641,26 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
 	    y = off_y - panoramiXdataPtr[i].y;
 
 	    if(x || y)
-		REGION_TRANSLATE(sprite->screen, &sprite->Reg1, x, y);
+		REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, x, y);
 		
-	    REGION_UNION(sprite->screen, &sprite->Reg1, &sprite->Reg1, 
-					&sprite->windows[i]->borderSize);
+	    REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1, 
+					&pSprite->windows[i]->borderSize);
 
 	    off_x = panoramiXdataPtr[i].x;
 	    off_y = panoramiXdataPtr[i].y;
 	}
 
-	sprite->hotLimits = *REGION_EXTENTS(sprite->screen, &sprite->Reg1);
+	pSprite->hotLimits = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg1);
 
-	if(REGION_NUM_RECTS(&sprite->Reg1) > 1)
-	   sprite->hotShape = &sprite->Reg1;
+	if(REGION_NUM_RECTS(&pSprite->Reg1) > 1)
+	   pSprite->hotShape = &pSprite->Reg1;
 	else
-	   sprite->hotShape = NullRegion;
+	   pSprite->hotShape = NullRegion;
 	
-	sprite->confined = FALSE;
-	sprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
+	pSprite->confined = FALSE;
+	pSprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
 
-        XineramaCheckPhysLimits(inputInfo.pointer, sprite->current,
+        XineramaCheckPhysLimits(pDev, pSprite->current,
                                 generateEvents); 
     }
 }
@@ -708,12 +669,7 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
 static void
 XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 {
-    SpritePtr pSprite = sprite;
-
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
 
     if (cursor != pSprite->current)
     {
@@ -753,11 +709,7 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
     BoxRec box;
     int x = *px, y = *py;
     int incx = 1, incy = 1;
-    SpritePtr pSprite = sprite;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
 
     if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box))
 	return;
@@ -798,12 +750,7 @@ CheckPhysLimits(
     ScreenPtr pScreen)
 {
     HotSpot new;
-    SpritePtr pSprite = sprite;
-
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
 
     if (!cursor)
 	return;
@@ -838,90 +785,94 @@ CheckPhysLimits(
         (*pScreen->SetCursorPosition) 
             (pDev, pScreen, new.x, new.y, generateEvents); 
         if (!generateEvents)
-	    SyntheticMotion(new.x, new.y);
+	    SyntheticMotion(pDev, new.x, new.y);
     }
 }
 
 static void
 CheckVirtualMotion(
+    register DeviceIntPtr pDev,
     register QdEventPtr qe,
     register WindowPtr pWin)
 {
+    SpritePtr pSprite = pDev->pSprite;
+
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
-	XineramaCheckVirtualMotion(qe, pWin);
+	XineramaCheckVirtualMotion(pDev, qe, pWin);
 	return;
     }
 #endif
     if (qe)
     {
-	sprite->hot.pScreen = qe->pScreen;
-	sprite->hot.x = qe->event->u.keyButtonPointer.rootX;
-	sprite->hot.y = qe->event->u.keyButtonPointer.rootY;
-	pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
-					 NullWindow;
+	pSprite->hot.pScreen = qe->pScreen;
+	pSprite->hot.x = qe->event->u.keyButtonPointer.rootX;
+	pSprite->hot.y = qe->event->u.keyButtonPointer.rootY;
+	pWin = pDev->grab ? pDev->grab->confineTo : NullWindow;
     }
     if (pWin)
     {
 	BoxRec lims;
 
-	if (sprite->hot.pScreen != pWin->drawable.pScreen)
+	if (pSprite->hot.pScreen != pWin->drawable.pScreen)
 	{
-	    sprite->hot.pScreen = pWin->drawable.pScreen;
-	    sprite->hot.x = sprite->hot.y = 0;
+	    pSprite->hot.pScreen = pWin->drawable.pScreen;
+	    pSprite->hot.x = pSprite->hot.y = 0;
 	}
 	lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
-	if (sprite->hot.x < lims.x1)
-	    sprite->hot.x = lims.x1;
-	else if (sprite->hot.x >= lims.x2)
-	    sprite->hot.x = lims.x2 - 1;
-	if (sprite->hot.y < lims.y1)
-	    sprite->hot.y = lims.y1;
-	else if (sprite->hot.y >= lims.y2)
-	    sprite->hot.y = lims.y2 - 1;
+	if (pSprite->hot.x < lims.x1)
+	    pSprite->hot.x = lims.x1;
+	else if (pSprite->hot.x >= lims.x2)
+	    pSprite->hot.x = lims.x2 - 1;
+	if (pSprite->hot.y < lims.y1)
+	    pSprite->hot.y = lims.y1;
+	else if (pSprite->hot.y >= lims.y2)
+	    pSprite->hot.y = lims.y2 - 1;
 #ifdef SHAPE
 	if (wBoundingShape(pWin))
-	    ConfineToShape(inputInfo.pointer, &pWin->borderSize, &sprite->hot.x, &sprite->hot.y);
+	    ConfineToShape(pDev, &pWin->borderSize, 
+                    &pSprite->hot.x, &pSprite->hot.y);
 #endif
 	if (qe)
 	{
-	    qe->pScreen = sprite->hot.pScreen;
-	    qe->event->u.keyButtonPointer.rootX = sprite->hot.x;
-	    qe->event->u.keyButtonPointer.rootY = sprite->hot.y;
+	    qe->pScreen = pSprite->hot.pScreen;
+	    qe->event->u.keyButtonPointer.rootX = pSprite->hot.x;
+	    qe->event->u.keyButtonPointer.rootY = pSprite->hot.y;
 	}
     }
 #ifdef XEVIE
-    xeviehot.x = sprite->hot.x;
-    xeviehot.y = sprite->hot.y;
+    xeviehot.x = pSprite->hot.x;
+    xeviehot.y = pSprite->hot.y;
 #endif
-    ROOT = WindowTable[sprite->hot.pScreen->myNum];
+    ROOT = WindowTable[pSprite->hot.pScreen->myNum];
 }
 
 static void
-ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
+ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
 {
     ScreenPtr pScreen = pWin->drawable.pScreen;
+    SpritePtr pSprite = pDev->pSprite;
 
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
-	XineramaConfineCursorToWindow(pWin, generateEvents);
+	XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
 	return;
     }	
 #endif
 
     if (syncEvents.playingEvents)
     {
-	CheckVirtualMotion((QdEventPtr)NULL, pWin);
-	SyntheticMotion(sprite->hot.x, sprite->hot.y);
+	CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
+	SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
     }
     else
     {
-	sprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
+	pSprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
 #ifdef SHAPE
-	sprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
+	pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
 					       : NullRegion;
 #endif
-        CheckPhysLimits(inputInfo.pointer, sprite->current, generateEvents,
+        CheckPhysLimits(pDev, pSprite->current, generateEvents,
                         confineToScreen, pScreen);
     }
 }
@@ -929,23 +880,13 @@ ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
 _X_EXPORT Bool
 PointerConfinedToScreen(DeviceIntPtr pDev)
 {
-    SpritePtr pSprite = sprite;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
-    return pSprite->confined;
+    return pDev->pSprite->confined;
 }
 
 static void
 ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 {
-    SpritePtr pSprite = sprite;
-
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
 
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
@@ -960,7 +901,7 @@ ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 		(pSprite->current->bits->yhot != cursor->bits->yhot))
 	    CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
 			    (ScreenPtr)NULL);
-        (*sprite->hotPhys.pScreen->DisplayCursor) (pDev,
+        (*pSprite->hotPhys.pScreen->DisplayCursor) (pDev,
                                                    pSprite->hotPhys.pScreen,
                                                    cursor);
 	FreeCursor(pSprite->current, (Cursor)0);
@@ -983,13 +924,7 @@ PostNewCursor(DeviceIntPtr pDev)
 {
     register    WindowPtr win;
     register    GrabPtr grab = pDev->grab;
-    SpritePtr   pSprite = sprite;
-
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
-
+    SpritePtr   pSprite = pDev->pSprite;
 
     if (syncEvents.playingEvents)
 	return;
@@ -1024,38 +959,29 @@ GetCurrentRootWindow()
 _X_EXPORT WindowPtr
 GetSpriteWindow(DeviceIntPtr pDev)
 {
-#ifdef MPX
-    if(MPHasCursor(pDev))
-        return mpsprites[pDev->id].win;
-#endif
-
-    return sprite->win;
+    return pDev->pSprite->win;
 }
 
 _X_EXPORT CursorPtr
-GetSpriteCursor()
+GetSpriteCursor(DeviceIntPtr pDev)
 {
-    return sprite->current;
+    return pDev->pSprite->current;
 }
 
 _X_EXPORT void
 GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
 {
-    SpritePtr pSprite = sprite;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
     *px = pSprite->hotPhys.x;
     *py = pSprite->hotPhys.y;
 }
 
 #ifdef PANORAMIX
 _X_EXPORT int
-XineramaGetCursorScreen()
+XineramaGetCursorScreen(DeviceIntPtr pDev)
 {
     if(!noPanoramiXExtension) {
-	return sprite->screen->myNum;
+	return pDev->pSprite->screen->myNum;
     } else {
 	return 0;
     }
@@ -1100,6 +1026,7 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
     register QdEventPtr tail = *syncEvents.pendtail;
     register QdEventPtr qe;
     xEvent		*qxE;
+    SpritePtr pSprite = device->pSprite;
 
     NoticeTime(xE);
 
@@ -1124,7 +1051,7 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 	 */
 	if (xE->u.u.type == MotionNotify)
 	    XE_KBPTR.root =
-		WindowTable[sprite->hotPhys.pScreen->myNum]->drawable.id;
+		WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id;
 	eventinfo.events = xE;
 	eventinfo.count = count;
 	CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
@@ -1133,21 +1060,21 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
     {
 #ifdef PANORAMIX
 	if(!noPanoramiXExtension) {
-	    XE_KBPTR.rootX += panoramiXdataPtr[sprite->screen->myNum].x -
+	    XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
 			      panoramiXdataPtr[0].x;
-	    XE_KBPTR.rootY += panoramiXdataPtr[sprite->screen->myNum].y -
+	    XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y -
 			      panoramiXdataPtr[0].y;
 	}
 #endif
-	sprite->hotPhys.x = XE_KBPTR.rootX;
-	sprite->hotPhys.y = XE_KBPTR.rootY;
+	pSprite->hotPhys.x = XE_KBPTR.rootX;
+	pSprite->hotPhys.y = XE_KBPTR.rootY;
 	/* do motion compression */
 	if (tail &&
 	    (tail->event->u.u.type == MotionNotify) &&
-	    (tail->pScreen == sprite->hotPhys.pScreen))
+	    (tail->pScreen == pSprite->hotPhys.pScreen))
 	{
-	    tail->event->u.keyButtonPointer.rootX = sprite->hotPhys.x;
-	    tail->event->u.keyButtonPointer.rootY = sprite->hotPhys.y;
+	    tail->event->u.keyButtonPointer.rootX = pSprite->hotPhys.x;
+	    tail->event->u.keyButtonPointer.rootY = pSprite->hotPhys.y;
 	    tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
 	    tail->months = currentTime.months;
 	    return;
@@ -1158,7 +1085,7 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 	return;
     qe->next = (QdEventPtr)NULL;
     qe->device = device;
-    qe->pScreen = sprite->hotPhys.pScreen;
+    qe->pScreen = pSprite->hotPhys.pScreen;
     qe->months = currentTime.months;
     qe->event = (xEvent *)(qe + 1);
     qe->evcount = count;
@@ -1174,6 +1101,7 @@ PlayReleasedEvents(void)
 {
     register QdEventPtr *prev, qe;
     register DeviceIntPtr dev;
+    DeviceIntPtr pDev;
 
     prev = &syncEvents.pending;
     while ( (qe = *prev) )
@@ -1181,10 +1109,11 @@ PlayReleasedEvents(void)
 	if (!qe->device->sync.frozen)
 	{
 	    *prev = qe->next;
+            pDev = qe->device;
 	    if (*syncEvents.pendtail == *prev)
 		syncEvents.pendtail = prev;
 	    if (qe->event->u.u.type == MotionNotify)
-		CheckVirtualMotion(qe, NullWindow);
+		CheckVirtualMotion(pDev, qe, NullWindow);
 	    syncEvents.time.months = qe->months;
 	    syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
 #ifdef PANORAMIX
@@ -1194,10 +1123,10 @@ PlayReleasedEvents(void)
 	    if(!noPanoramiXExtension) {
 		qe->event->u.keyButtonPointer.rootX += 
 			panoramiXdataPtr[0].x - 
-			panoramiXdataPtr[sprite->screen->myNum].x;
+			panoramiXdataPtr[pDev->pSprite->screen->myNum].x;
 		qe->event->u.keyButtonPointer.rootY += 
 			panoramiXdataPtr[0].y - 
-			panoramiXdataPtr[sprite->screen->myNum].y;
+			panoramiXdataPtr[pDev->pSprite->screen->myNum].y;
 	    }
 #endif
 	    (*qe->device->public.processInputProc)(qe->event, qe->device,
@@ -1279,17 +1208,27 @@ playmore:
 	}
     }
     syncEvents.playingEvents = FALSE;
-    /* the following may have been skipped during replay, so do it now */
-    if ((grab = inputInfo.pointer->grab) && grab->confineTo)
+    for (dev = inputInfo.devices; dev; dev = dev->next)
     {
-	if (grab->confineTo->drawable.pScreen != sprite->hotPhys.pScreen)
-	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
-	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
+        if (MPHasCursor(dev))
+        {
+            /* the following may have been skipped during replay, 
+              so do it now */
+            if ((grab = dev->grab) && grab->confineTo)
+            {
+                if (grab->confineTo->drawable.pScreen !=
+                        dev->pSprite->hotPhys.pScreen) 
+                    dev->pSprite->hotPhys.x =
+                        dev->pSprite->hotPhys.y = 0;
+                ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
+            }
+            else
+                ConfineCursorToWindow(dev,
+                        WindowTable[dev->pSprite->hotPhys.pScreen->myNum],
+                        TRUE, FALSE);
+            PostNewCursor(dev);
+        }
     }
-    else
-	ConfineCursorToWindow(WindowTable[sprite->hotPhys.pScreen->myNum],
-			      TRUE, FALSE);
-    PostNewCursor(inputInfo.pointer);
 }
 
 #ifdef RANDR
@@ -1297,16 +1236,23 @@ void
 ScreenRestructured (ScreenPtr pScreen)
 {
     GrabPtr grab;
+    DeviceIntPtr pDev;
 
-    if ((grab = inputInfo.pointer->grab) && grab->confineTo)
+    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-	if (grab->confineTo->drawable.pScreen != sprite->hotPhys.pScreen)
-	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
-	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
+
+        if ((grab = pDev->grab) && grab->confineTo)
+        {
+            if (grab->confineTo->drawable.pScreen 
+                    != pDev->pSprite->hotPhys.pScreen)
+                pDev->pSprite->hotPhys.x = pDev->pSprite->hotPhys.y = 0;
+            ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
+        }
+        else
+            ConfineCursorToWindow(pDev, 
+                    WindowTable[pDev->pSprite->hotPhys.pScreen->myNum],
+                    TRUE, FALSE);
     }
-    else
-	ConfineCursorToWindow(WindowTable[sprite->hotPhys.pScreen->myNum],
-			      TRUE, FALSE);
 }
 #endif
 
@@ -1349,13 +1295,14 @@ ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
                     TimeStamp time, Bool autoGrab)
 {
     WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
-				     : sprite->win;
+				     : mouse->pSprite->win;
 
     if (grab->confineTo)
     {
-	if (grab->confineTo->drawable.pScreen != sprite->hotPhys.pScreen)
-	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
-	ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
+	if (grab->confineTo->drawable.pScreen 
+                != mouse->pSprite->hotPhys.pScreen)
+	    mouse->pSprite->hotPhys.x = mouse->pSprite->hotPhys.y = 0;
+	ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
     }
     DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
     mouse->valuator->motionHintWindow = NullWindow;
@@ -1387,10 +1334,11 @@ DeactivatePointerGrab(register DeviceIntPtr mouse)
 	if (dev->sync.other == grab)
 	    dev->sync.other = NullGrab;
     }
-    DoEnterLeaveEvents(mouse, grab->window, sprite->win, NotifyUngrab);
+    DoEnterLeaveEvents(mouse, grab->window, 
+                       mouse->pSprite->win, NotifyUngrab);
     if (grab->confineTo)
-	ConfineCursorToWindow(ROOT, FALSE, FALSE);
-    PostNewCursor(inputInfo.pointer);
+	ConfineCursorToWindow(mouse, ROOT, FALSE, FALSE);
+    PostNewCursor(mouse);
     if (grab->cursor)
 	FreeCursor(grab->cursor, (Cursor)0);
     ComputeFreezes();
@@ -1406,7 +1354,7 @@ ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
     else if (keybd->focus)
 	oldWin = keybd->focus->win;
     else
-	oldWin = sprite->win;
+	oldWin = keybd->pSprite->win;
     if (oldWin == FollowKeyboardWin)
 	oldWin = inputInfo.keyboard->focus->win;
     if (keybd->valuator)
@@ -1428,7 +1376,7 @@ DeactivateKeyboardGrab(register DeviceIntPtr keybd)
     register GrabPtr grab = keybd->grab;
     register DeviceIntPtr dev;
     register WindowPtr focusWin = keybd->focus ? keybd->focus->win
-					       : sprite->win;
+					       : keybd->pSprite->win;
 
     if (focusWin == FollowKeyboardWin)
 	focusWin = inputInfo.keyboard->focus->win;
@@ -1865,11 +1813,7 @@ FixUpEventFromWindow(
     Window child,
     Bool calcChild)
 {
-    SpritePtr pSprite = sprite;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
 
     if (calcChild)
     {
@@ -1931,10 +1875,9 @@ DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
     {
 	register OtherInputMasks *inputMasks;
 	int mskidx = dev->id;
-#ifdef MPX
+
         if (IsMPXEvent(xE))
             mskidx = MPXmskidx;
-#endif
 
 	inputMasks = wOtherInputMasks(pWin);
 	if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
@@ -2029,17 +1972,19 @@ static Bool
 PointInBorderSize(WindowPtr pWin, int x, int y)
 {
     BoxRec box;
+    SpritePtr pSprite = inputInfo.pointer->pSprite;
 
     if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box))
 	return TRUE;
 
 #ifdef PANORAMIX
-    if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) {
+    if(!noPanoramiXExtension && 
+            XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
 	int i;
 
 	for(i = 1; i < PanoramiXNumScreens; i++) {
-	   if(POINT_IN_REGION(sprite->screen, 
-			&sprite->windows[i]->borderSize, 
+	   if(POINT_IN_REGION(pSprite->screen, 
+			&pSprite->windows[i]->borderSize, 
 			x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, 
 			y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, 
 			&box))
@@ -2102,12 +2047,7 @@ static Bool
 CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
     WindowPtr prevSpriteWin;
-    SpritePtr pSprite = sprite;
-        
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
         
     prevSpriteWin = pSprite->win;
 
@@ -2184,7 +2124,6 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 _X_EXPORT void
 WindowsRestructured()
 {
-#ifdef MPX
     DeviceIntPtr pDev = inputInfo.devices;
     while(pDev)
     {
@@ -2192,9 +2131,6 @@ WindowsRestructured()
             CheckMotion((xEvent *)NULL, pDev);
         pDev = pDev->next;
     }
-#else
-    (void) CheckMotion((xEvent *)NULL, inputInfo.pointer);
-#endif
 }
 
 #ifdef PANORAMIX
@@ -2206,33 +2142,48 @@ WindowsRestructured()
 void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
 {
     GrabPtr   grab;
+    DeviceIntPtr pDev;
+    SpritePtr pSprite;
 
     if (noPanoramiXExtension) return;
-    
-    sprite->hot.x        -= xoff;
-    sprite->hot.y        -= yoff;
-
-    sprite->hotPhys.x    -= xoff;
-    sprite->hotPhys.y    -= yoff;
-
-    sprite->hotLimits.x1 -= xoff; 
-    sprite->hotLimits.y1 -= yoff;
-    sprite->hotLimits.x2 -= xoff;
-    sprite->hotLimits.y2 -= yoff;
-
-    if (REGION_NOTEMPTY(sprite->screen, &sprite->Reg1))
-        REGION_TRANSLATE(sprite->screen, &sprite->Reg1,    xoff, yoff);
-    if (REGION_NOTEMPTY(sprite->screen, &sprite->Reg2))
-        REGION_TRANSLATE(sprite->screen, &sprite->Reg2,    xoff, yoff);
-
-    /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
-    if ((grab = inputInfo.pointer->grab) && grab->confineTo) {
-	if (grab->confineTo->drawable.pScreen != sprite->hotPhys.pScreen)
-	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
-	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
-    } else
-	ConfineCursorToWindow(WindowTable[sprite->hotPhys.pScreen->myNum],
-			      TRUE, FALSE);
+
+    pDev = inputInfo.devices;
+    while(pDev)
+    {
+        if (MPHasCursor(pDev))
+        {
+            pSprite = pDev->pSprite;
+            pSprite->hot.x        -= xoff;
+            pSprite->hot.y        -= yoff;
+
+            pSprite->hotPhys.x    -= xoff;
+            pSprite->hotPhys.y    -= yoff;
+
+            pSprite->hotLimits.x1 -= xoff; 
+            pSprite->hotLimits.y1 -= yoff;
+            pSprite->hotLimits.x2 -= xoff;
+            pSprite->hotLimits.y2 -= yoff;
+
+            if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg1))
+                REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1,    xoff, yoff);
+            if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg2))
+                REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2,    xoff, yoff);
+
+            /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
+            if ((grab = inputInfo.pointer->grab) && grab->confineTo) {
+                if (grab->confineTo->drawable.pScreen 
+                        != pSprite->hotPhys.pScreen)
+                    pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
+                ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
+            } else
+                ConfineCursorToWindow(
+                        pDev,
+                        WindowTable[pSprite->hotPhys.pScreen->myNum],
+                        TRUE, FALSE);
+
+        }
+        pDev = pDev->next;
+    }
 }
 #endif
 
@@ -2240,75 +2191,60 @@ void
 DefineInitialRootWindow(register WindowPtr win)
 {
     register ScreenPtr pScreen = win->drawable.pScreen;
-    SpritePtr pSprite = sprite;
-    DeviceIntPtr pDev = inputInfo.pointer;
-#ifdef MPX
-    int mpSpriteIdx = 0;
+    SpritePtr pSprite;
+    DeviceIntPtr pDev = inputInfo.devices;
 
-    while (mpSpriteIdx < MAX_DEVICES)
+    while (pDev)
     {
-        pSprite = &mpsprites[mpSpriteIdx];
-#endif
-
-        pSprite->hotPhys.pScreen = pScreen;
-        pSprite->hotPhys.x = pScreen->width / 2;
-        pSprite->hotPhys.y = pScreen->height / 2;
-        pSprite->hot = pSprite->hotPhys;
-        pSprite->hotLimits.x2 = pScreen->width;
-        pSprite->hotLimits.y2 = pScreen->height;
+        if (MPHasCursor(pDev))
+        {
+            pSprite = pDev->pSprite;
+
+            pSprite->hotPhys.pScreen = pScreen;
+            pSprite->hotPhys.x = pScreen->width / 2;
+            pSprite->hotPhys.y = pScreen->height / 2;
+            pSprite->hot = pSprite->hotPhys;
+            pSprite->hotLimits.x2 = pScreen->width;
+            pSprite->hotLimits.y2 = pScreen->height;
 #ifdef XEVIE
-        xeviewin =
+            xeviewin =
 #endif
-            pSprite->win = win;
-        pSprite->current = wCursor (win);
-        pSprite->current->refcnt++;
-        spriteTraceGood = 1;
-        ROOT = win;
-        (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
-                                   &pSprite->hotLimits, &pSprite->physLimits);
-        pSprite->confined = FALSE;
+                pSprite->win = win;
+            pSprite->current = wCursor (win);
+            pSprite->current->refcnt++;
+            spriteTraceGood = 1;
+            ROOT = win;
+            (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
+                                       &pSprite->hotLimits, &pSprite->physLimits);
+            pSprite->confined = FALSE;
 
-#ifdef MPX
-        /* this is ugly */
-        pDev = inputInfo.devices;
-        while(pDev)
-        {
-            if (pDev->id == mpSpriteIdx && MPHasCursor(pDev))
-            {
-#endif
-                (*pScreen->ConstrainCursor) (pDev, pScreen,
-                                             &pSprite->physLimits);
-                (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
-                                               pSprite->hot.y,
-                                               FALSE); 
-                (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
-#ifdef MPX
-            }
-            pDev = pDev->next;
-        }
-#endif
+            (*pScreen->ConstrainCursor) (pDev, pScreen,
+                                         &pSprite->physLimits);
+            (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
+                                           pSprite->hot.y,
+                                           FALSE); 
+            (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
 
 #ifdef PANORAMIX
-        if(!noPanoramiXExtension) {
-            pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
-            pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
-            pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
-            pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
-            pSprite->physLimits = pSprite->hotLimits;
-            pSprite->confineWin = NullWindow;
+            if(!noPanoramiXExtension) {
+                pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
+                pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
+                pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
+                pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
+                pSprite->physLimits = pSprite->hotLimits;
+                pSprite->confineWin = NullWindow;
 #ifdef SHAPE
-            pSprite->hotShape = NullRegion;
+                pSprite->hotShape = NullRegion;
 #endif
-            pSprite->screen = pScreen;
-            /* gotta UNINIT these someplace */
-            REGION_NULL(pScreen, &pSprite->Reg1);
-            REGION_NULL(pScreen, &pSprite->Reg2);
-        }
+                pSprite->screen = pScreen;
+                /* gotta UNINIT these someplace */
+                REGION_NULL(pScreen, &pSprite->Reg1);
+                REGION_NULL(pScreen, &pSprite->Reg2);
+            }
 #endif
-#ifdef MPX
-        mpSpriteIdx++;
+        }
+        pDev = pDev->next;
     }
-#endif
 }
 
 /*
@@ -2327,11 +2263,7 @@ WindowHasNewCursor(WindowPtr pWin)
 _X_EXPORT void
 NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
 {
-    SpritePtr pSprite = sprite;
-#ifdef MPX
-    if (MPHasCursor(pDev))
-        pSprite = &mpsprites[pDev->id];
-#endif
+    SpritePtr pSprite = pDev->pSprite;
 
     pSprite->hotPhys.x = x;
     pSprite->hotPhys.y = y;
@@ -2345,9 +2277,10 @@ NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
 	    pSprite->screen = newScreen;
 	    /* Make sure we tell the DDX to update its copy of the screen */
 	    if(pSprite->confineWin)
-		XineramaConfineCursorToWindow(pSprite->confineWin, TRUE);
+		XineramaConfineCursorToWindow(pDev, 
+                        pSprite->confineWin, TRUE);
 	    else
-		XineramaConfineCursorToWindow(WindowTable[0], TRUE);
+		XineramaConfineCursorToWindow(pDev, WindowTable[0], TRUE);
 	    /* if the pointer wasn't confined, the DDX won't get 
 	       told of the pointer warp so we reposition it here */
 	    if(!syncEvents.playingEvents)
@@ -2362,7 +2295,8 @@ NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
     } else 
 #endif
     if (newScreen != pSprite->hotPhys.pScreen)
-	ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE);
+	ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum], 
+                TRUE, FALSE);
 }
 
 #ifdef PANORAMIX
@@ -2383,13 +2317,13 @@ XineramaPointInWindowIsVisible(
     if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
         return TRUE;
     
-    if(!XineramaSetWindowPntrs(pWin)) return FALSE;
+    if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
 
     xoff = x + panoramiXdataPtr[0].x;  
     yoff = y + panoramiXdataPtr[0].y;  
 
     for(i = 1; i < PanoramiXNumScreens; i++) {
-	pWin = sprite->windows[i];
+	pWin = inputInfo.pointer->pSprite->windows[i];
 	pScreen = pWin->drawable.pScreen;
 	x = xoff - panoramiXdataPtr[i].x;
 	y = yoff - panoramiXdataPtr[i].y;
@@ -2412,6 +2346,7 @@ XineramaWarpPointer(ClientPtr client)
 {
     WindowPtr	dest = NULL;
     int		x, y;
+    SpritePtr   pSprite = inputInfo.pointer->pSprite;
 
     REQUEST(xWarpPointerReq);
 
@@ -2422,8 +2357,8 @@ XineramaWarpPointer(ClientPtr client)
 	if (!dest)
 	    return BadWindow;
     }
-    x = sprite->hotPhys.x;
-    y = sprite->hotPhys.y;
+    x = pSprite->hotPhys.x;
+    y = pSprite->hotPhys.y;
 
     if (stuff->srcWid != None)
     {
@@ -2461,16 +2396,16 @@ XineramaWarpPointer(ClientPtr client)
     x += stuff->dstX;
     y += stuff->dstY;
 
-    if (x < sprite->physLimits.x1)
-	x = sprite->physLimits.x1;
-    else if (x >= sprite->physLimits.x2)
-	x = sprite->physLimits.x2 - 1;
-    if (y < sprite->physLimits.y1)
-	y = sprite->physLimits.y1;
-    else if (y >= sprite->physLimits.y2)
-	y = sprite->physLimits.y2 - 1;
-    if (sprite->hotShape)
-	ConfineToShape(inputInfo.pointer, sprite->hotShape, &x, &y);
+    if (x < pSprite->physLimits.x1)
+	x = pSprite->physLimits.x1;
+    else if (x >= pSprite->physLimits.x2)
+	x = pSprite->physLimits.x2 - 1;
+    if (y < pSprite->physLimits.y1)
+	y = pSprite->physLimits.y1;
+    else if (y >= pSprite->physLimits.y2)
+	y = pSprite->physLimits.y2 - 1;
+    if (pSprite->hotShape)
+	ConfineToShape(inputInfo.pointer, pSprite->hotShape, &x, &y);
 
     XineramaSetCursorPosition(inputInfo.pointer, x, y, TRUE);
 
@@ -2486,6 +2421,7 @@ ProcWarpPointer(ClientPtr client)
     WindowPtr	dest = NULL;
     int		x, y;
     ScreenPtr	newScreen;
+    SpritePtr   pSprite = inputInfo.pointer->pSprite;
 
     REQUEST(xWarpPointerReq);
 
@@ -2502,8 +2438,8 @@ ProcWarpPointer(ClientPtr client)
 	if (!dest)
 	    return BadWindow;
     }
-    x = sprite->hotPhys.x;
-    y = sprite->hotPhys.y;
+    x = pSprite->hotPhys.x;
+    y = pSprite->hotPhys.y;
 
     if (stuff->srcWid != None)
     {
@@ -2516,7 +2452,7 @@ ProcWarpPointer(ClientPtr client)
 
 	winX = source->drawable.x;
 	winY = source->drawable.y;
-	if (source->drawable.pScreen != sprite->hotPhys.pScreen ||
+	if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
 	    x < winX + stuff->srcX ||
 	    y < winY + stuff->srcY ||
 	    (stuff->srcWidth != 0 &&
@@ -2532,7 +2468,7 @@ ProcWarpPointer(ClientPtr client)
 	y = dest->drawable.y;
 	newScreen = dest->drawable.pScreen;
     } else 
-	newScreen = sprite->hotPhys.pScreen;
+	newScreen = pSprite->hotPhys.pScreen;
 
     x += stuff->dstX;
     y += stuff->dstY;
@@ -2546,19 +2482,19 @@ ProcWarpPointer(ClientPtr client)
     else if (y >= newScreen->height)
 	y = newScreen->height - 1;
 
-    if (newScreen == sprite->hotPhys.pScreen)
+    if (newScreen == pSprite->hotPhys.pScreen)
     {
-	if (x < sprite->physLimits.x1)
-	    x = sprite->physLimits.x1;
-	else if (x >= sprite->physLimits.x2)
-	    x = sprite->physLimits.x2 - 1;
-	if (y < sprite->physLimits.y1)
-	    y = sprite->physLimits.y1;
-	else if (y >= sprite->physLimits.y2)
-	    y = sprite->physLimits.y2 - 1;
+	if (x < pSprite->physLimits.x1)
+	    x = pSprite->physLimits.x1;
+	else if (x >= pSprite->physLimits.x2)
+	    x = pSprite->physLimits.x2 - 1;
+	if (y < pSprite->physLimits.y1)
+	    y = pSprite->physLimits.y1;
+	else if (y >= pSprite->physLimits.y2)
+	    y = pSprite->physLimits.y2 - 1;
 #if defined(SHAPE)
-	if (sprite->hotShape)
-	    ConfineToShape(inputInfo.pointer, sprite->hotShape, &x, &y);
+	if (pSprite->hotShape)
+	    ConfineToShape(inputInfo.pointer, pSprite->hotShape, &x, &y);
 #endif
         (*newScreen->SetCursorPosition)(inputInfo.pointer, newScreen, x, y,
                                         TRUE); 
@@ -2571,17 +2507,18 @@ ProcWarpPointer(ClientPtr client)
 }
 
 static Bool 
-BorderSizeNotEmpty(WindowPtr pWin)
+BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
 {
-     if(REGION_NOTEMPTY(sprite->hotPhys.pScreen, &pWin->borderSize))
+     if(REGION_NOTEMPTY(pDev->pSprite->hotPhys.pScreen, &pWin->borderSize))
 	return TRUE;
 
 #ifdef PANORAMIX
-     if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) {
+     if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
 	int i;
 
 	for(i = 1; i < PanoramiXNumScreens; i++) {
-	    if(REGION_NOTEMPTY(sprite->screen, &sprite->windows[i]->borderSize))
+	    if(REGION_NOTEMPTY(pDev->pSprite->screen, 
+                        &pDev->pSprite->windows[i]->borderSize))
 		return TRUE;
 	}
      }
@@ -2643,7 +2580,7 @@ CheckPassiveGrabsOnWindow(
 	if (GrabMatchesSecond(&tempGrab, grab) &&
 	    (!grab->confineTo ||
 	     (grab->confineTo->realized && 
-				BorderSizeNotEmpty(grab->confineTo))))
+				BorderSizeNotEmpty(device, grab->confineTo))))
 	{
 	    if (!XaceHook(XACE_DEVICE_ACCESS, wClient(pWin), device, FALSE))
 		return FALSE;
@@ -2776,6 +2713,7 @@ DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev,
     int deliveries = 0;
     register DeviceIntPtr dev;
     register xEvent *dxE;
+    SpritePtr pSprite = thisDev->pSprite;
 
     if (grab->ownerEvents)
     {
@@ -2790,10 +2728,11 @@ DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev,
 	else
 	    focus = PointerRootWin;
 	if (focus == PointerRootWin)
-	    deliveries = DeliverDeviceEvents(sprite->win, xE, grab, NullWindow,
-					     thisDev, count);
-	else if (focus && (focus == sprite->win || IsParent(focus, sprite->win)))
-	    deliveries = DeliverDeviceEvents(sprite->win, xE, grab, focus,
+	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, 
+                                             NullWindow, thisDev, count);
+	else if (focus && (focus == pSprite->win || 
+                    IsParent(focus, pSprite->win)))
+	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, focus,
 					     thisDev, count);
 	else if (focus)
 	    deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
@@ -2926,8 +2865,8 @@ drawable.id:0;
     )))
 #endif
     XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state);
-    XE_KBPTR.rootX = sprite->hot.x;
-    XE_KBPTR.rootY = sprite->hot.y;
+    XE_KBPTR.rootX = keybd->pSprite->hot.x;
+    XE_KBPTR.rootY = keybd->pSprite->hot.y;
     key = xE->u.u.detail;
     kptr = &keyc->down[key >> 3];
     bit = 1 << (key & 7);
@@ -3003,7 +2942,7 @@ drawable.id:0;
     if (grab)
 	DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
     else
-	DeliverFocusedEvent(keybd, xE, sprite->win, count);
+	DeliverFocusedEvent(keybd, xE, keybd->pSprite->win, count);
     if (deactivateGrab)
         (*keybd->DeactivateGrab)(keybd);
 
@@ -3055,12 +2994,8 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
     register GrabPtr	grab = mouse->grab;
     Bool                deactivateGrab = FALSE;
     register ButtonClassPtr butc = mouse->button;
-    SpritePtr           pSprite = sprite;
+    SpritePtr           pSprite = mouse->pSprite;
 
-#ifdef MPX
-    if (MPHasCursor(mouse))
-        pSprite = &mpsprites[mouse->id];
-#endif
 
 #ifdef XKB
     XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
@@ -3407,8 +3342,8 @@ EnterLeaveEvent(
 	event.u.u.type = type;
 	event.u.u.detail = detail;
 	event.u.enterLeave.time = currentTime.milliseconds;
-	event.u.enterLeave.rootX = sprite->hot.x;
-	event.u.enterLeave.rootY = sprite->hot.y;
+	event.u.enterLeave.rootX = pDev->pSprite->hot.x;
+	event.u.enterLeave.rootY = pDev->pSprite->hot.y;
 	/* Counts on the same initial structure of crossing & button events! */
 	FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
 	/* Enter/Leave events always set child */
@@ -3611,6 +3546,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
     int     out, in;		       /* for holding details for to/from
 				          PointerRoot/None */
     int     i;
+    SpritePtr pSprite = dev->pSprite;
 
     if (fromWin == toWin)
 	return;
@@ -3623,8 +3559,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
    	{
 	    if (fromWin == PointerRootWin)
-		FocusOutEvents(dev, sprite->win, ROOT, mode, NotifyPointer,
-			       TRUE);
+                FocusOutEvents(dev, pSprite->win, ROOT, mode,
+                        NotifyPointer, TRUE);
 	    /* Notify all the roots */
 #ifdef PANORAMIX
  	    if ( !noPanoramiXExtension )
@@ -3636,8 +3572,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	}
 	else
 	{
-	    if (IsParent(fromWin, sprite->win))
-	      FocusOutEvents(dev, sprite->win, fromWin, mode, NotifyPointer,
+	    if (IsParent(fromWin, pSprite->win))
+	      FocusOutEvents(dev, pSprite->win, fromWin, mode, NotifyPointer,
 			     FALSE);
 	    FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
 	    /* next call catches the root too, if the screen changed */
@@ -3653,7 +3589,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	    for (i=0; i<screenInfo.numScreens; i++)
 	        FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
 	if (toWin == PointerRootWin)
-	    (void)FocusInEvents(dev, ROOT, sprite->win, NullWindow, mode,
+	    (void)FocusInEvents(dev, ROOT, pSprite->win, NullWindow, mode,
 				NotifyPointer, TRUE);
     }
     else
@@ -3661,7 +3597,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
 	{
 	    if (fromWin == PointerRootWin)
-		FocusOutEvents(dev, sprite->win, ROOT, mode, NotifyPointer,
+		FocusOutEvents(dev, pSprite->win, ROOT, mode, NotifyPointer,
 			       TRUE);
 #ifdef PANORAMIX
  	    if ( !noPanoramiXExtension )
@@ -3674,8 +3610,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	      (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
 				  NotifyNonlinearVirtual, TRUE);
 	    FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
-	    if (IsParent(toWin, sprite->win))
-    	       (void)FocusInEvents(dev, toWin, sprite->win, NullWindow, mode,
+	    if (IsParent(toWin, pSprite->win))
+    	       (void)FocusInEvents(dev, toWin, pSprite->win, NullWindow, mode,
 				   NotifyPointer, FALSE);
 	}
 	else
@@ -3686,21 +3622,21 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 		FocusOutEvents(dev, fromWin->parent, toWin, mode,
 			       NotifyVirtual, FALSE);
 		FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
-		if ((IsParent(toWin, sprite->win)) &&
-			(sprite->win != fromWin) &&
-			(!IsParent(fromWin, sprite->win)) &&
-			(!IsParent(sprite->win, fromWin)))
-		    (void)FocusInEvents(dev, toWin, sprite->win, NullWindow,
+		if ((IsParent(toWin, pSprite->win)) &&
+			(pSprite->win != fromWin) &&
+			(!IsParent(fromWin, pSprite->win)) &&
+			(!IsParent(pSprite->win, fromWin)))
+		    (void)FocusInEvents(dev, toWin, pSprite->win, NullWindow,
 					mode, NotifyPointer, FALSE);
 	    }
 	    else
 		if (IsParent(fromWin, toWin))
 		{
-		    if ((IsParent(fromWin, sprite->win)) &&
-			    (sprite->win != fromWin) &&
-			    (!IsParent(toWin, sprite->win)) &&
-			    (!IsParent(sprite->win, toWin)))
-			FocusOutEvents(dev, sprite->win, fromWin, mode,
+		    if ((IsParent(fromWin, pSprite->win)) &&
+			    (pSprite->win != fromWin) &&
+			    (!IsParent(toWin, pSprite->win)) &&
+			    (!IsParent(pSprite->win, toWin)))
+			FocusOutEvents(dev, pSprite->win, fromWin, mode,
 				       NotifyPointer, FALSE);
 		    FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
 		    (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
@@ -3712,8 +3648,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 		/* neither fromWin or toWin is child of other */
 		    WindowPtr common = CommonAncestor(toWin, fromWin);
 		/* common == NullWindow ==> different screens */
-		    if (IsParent(fromWin, sprite->win))
-			FocusOutEvents(dev, sprite->win, fromWin, mode,
+		    if (IsParent(fromWin, pSprite->win))
+			FocusOutEvents(dev, pSprite->win, fromWin, mode,
 				       NotifyPointer, FALSE);
 		    FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
 		    if (fromWin->parent != NullWindow)
@@ -3723,8 +3659,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 		      (void)FocusInEvents(dev, common, toWin, toWin, mode,
 					  NotifyNonlinearVirtual, FALSE);
 		    FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
-		    if (IsParent(toWin, sprite->win))
-			(void)FocusInEvents(dev, toWin, sprite->win, NullWindow,
+		    if (IsParent(toWin, pSprite->win))
+			(void)FocusInEvents(dev, toWin, pSprite->win, NullWindow,
 					    mode, NotifyPointer, FALSE);
 		}
 	}
@@ -3914,7 +3850,8 @@ ProcGrabPointer(ClientPtr client)
 	rep.status = AlreadyGrabbed;
     else if ((!pWin->realized) ||
              (confineTo &&
-                !(confineTo->realized && BorderSizeNotEmpty(confineTo))))
+                !(confineTo->realized 
+                    && BorderSizeNotEmpty(device, confineTo))))
 	rep.status = GrabNotViewable;
     else if (device->sync.frozen &&
 	     device->sync.other && !SameClient(device->sync.other, client))
@@ -3930,7 +3867,7 @@ ProcGrabPointer(ClientPtr client)
 	if (grab)
  	{
 	    if (grab->confineTo && !confineTo)
-		ConfineCursorToWindow(ROOT, FALSE, FALSE);
+		ConfineCursorToWindow(device, ROOT, FALSE, FALSE);
 	    oldCursor = grab->cursor;
 	}
 	tempGrab.cursor = cursor;
@@ -4127,6 +4064,7 @@ ProcQueryPointer(ClientPtr client)
     WindowPtr pWin, t;
     REQUEST(xResourceReq);
     DeviceIntPtr mouse = inputInfo.pointer;
+    SpritePtr pSprite = mouse->pSprite;
 
     REQUEST_SIZE_MATCH(xResourceReq);
     pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess);
@@ -4139,15 +4077,15 @@ ProcQueryPointer(ClientPtr client)
     rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
     rep.length = 0;
     rep.root = (ROOT)->drawable.id;
-    rep.rootX = sprite->hot.x;
-    rep.rootY = sprite->hot.y;
+    rep.rootX = pSprite->hot.x;
+    rep.rootY = pSprite->hot.y;
     rep.child = None;
-    if (sprite->hot.pScreen == pWin->drawable.pScreen)
+    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
     {
 	rep.sameScreen = xTrue;
-	rep.winX = sprite->hot.x - pWin->drawable.x;
-	rep.winY = sprite->hot.y - pWin->drawable.y;
-	for (t = sprite->win; t; t = t->parent)
+	rep.winX = pSprite->hot.x - pWin->drawable.x;
+	rep.winY = pSprite->hot.y - pWin->drawable.y;
+	for (t = pSprite->win; t; t = t->parent)
 	    if (t->parent == pWin)
 	    {
 		rep.child = t->drawable.id;
@@ -4182,19 +4120,6 @@ InitEvents()
 {
     int i;
 
-    sprite = (SpritePtr)xalloc(sizeof(SpriteRec));
-    if (!sprite)
-        FatalError("failed to allocate sprite struct");
-
-#ifdef MPX
-    mpsprites = (SpritePtr)xalloc(MAX_DEVICES * sizeof(SpriteRec));
-    if (!mpsprites)
-        FatalError("failed to allocate MPX sprite structs");
-    xfree(sprite);
-    sprite = &mpsprites[1];
-#endif
-
-    sprite->hot.pScreen = sprite->hotPhys.pScreen = (ScreenPtr)NULL;
     inputInfo.numDevices = 0;
     inputInfo.devices = (DeviceIntPtr)NULL;
     inputInfo.off_devices = (DeviceIntPtr)NULL;
@@ -4211,34 +4136,7 @@ InitEvents()
     lastEventMask = OwnerGrabButtonMask;
     filters[MotionNotify] = PointerMotionMask;
 #ifdef XEVIE
-    xeviewin =
-#endif
-    sprite->win = NullWindow;
-    sprite->current = NullCursor;
-    sprite->hotLimits.x1 = 0;
-    sprite->hotLimits.y1 = 0;
-    sprite->hotLimits.x2 = 0;
-    sprite->hotLimits.y2 = 0;
-    sprite->confined = FALSE;
-
-#ifdef MPX
-    {
-        int mpSpriteIdx = 0;
-        while(mpSpriteIdx < MAX_DEVICES)
-        {
-            SpritePtr pSprite = &mpsprites[mpSpriteIdx];
-            pSprite->hot.pScreen = pSprite->hotPhys.pScreen = (ScreenPtr)NULL;
-            pSprite->win = NullWindow;
-            pSprite->current = NullCursor;
-            pSprite->hotLimits.x1 = 0;
-            pSprite->hotLimits.y1 = 0;
-            pSprite->hotLimits.x2 = 0;
-            pSprite->hotLimits.y2 = 0;
-            pSprite->confined = FALSE;
-
-            mpSpriteIdx++;
-        }
-    }
+    xeviewin = NULL;
 #endif
 
     syncEvents.replayDev = (DeviceIntPtr)NULL;
@@ -4263,19 +4161,41 @@ InitEvents()
     }
 }
 
+
+/**
+ * Initialize a sprite structure for the given device. If hasCursor is False,
+ * let the device use the core pointer's sprite structure.
+ */
+void 
+InitSprite(DeviceIntPtr pDev, Bool hasCursor)
+{
+    if (hasCursor)
+    {
+        SpritePtr pSprite = (SpritePtr)xalloc(sizeof(SpriteRec));
+        if (!pSprite)
+            FatalError("failed to allocate sprite struct");
+        pSprite->hot.pScreen = pSprite->hotPhys.pScreen = (ScreenPtr)NULL;
+        pSprite->win = NullWindow;
+        pSprite->current = NullCursor;
+        pSprite->hotLimits.x1 = 0;
+        pSprite->hotLimits.y1 = 0;
+        pSprite->hotLimits.x2 = 0;
+        pSprite->hotLimits.y2 = 0;
+        pSprite->confined = FALSE;
+
+        pDev->pSprite = pSprite;
+    } else
+    {
+        pDev->pSprite = inputInfo.pointer->pSprite;
+    }
+}
+
 void
 CloseDownEvents(void)
 {
   xfree(spriteTrace);
   spriteTrace = NULL;
   spriteTraceSize = 0;
-
-#ifdef MPX
-  /* sprite points to mpsprites[1] in MPX, don't free it separately */
-  xfree(mpsprites);
-#else
-  xfree(sprite);
-#endif
 }
 
 int
@@ -4283,6 +4203,7 @@ ProcSendEvent(ClientPtr client)
 {
     WindowPtr pWin;
     WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
+    SpritePtr pSprite = inputInfo.pointer->pSprite;
     REQUEST(xSendEventReq);
 
     REQUEST_SIZE_MATCH(xSendEventReq);
@@ -4313,7 +4234,7 @@ ProcSendEvent(ClientPtr client)
     }
 
     if (stuff->destination == PointerWindow)
-	pWin = sprite->win;
+	pWin = pSprite->win;
     else if (stuff->destination == InputFocus)
     {
 	WindowPtr inputFocus = inputInfo.keyboard->focus->win;
@@ -4326,10 +4247,10 @@ ProcSendEvent(ClientPtr client)
    	if (inputFocus == PointerRootWin)
 	    inputFocus = ROOT;
 
-	if (IsParent(inputFocus, sprite->win))
+	if (IsParent(inputFocus, pSprite->win))
 	{
 	    effectiveFocus = inputFocus;
-	    pWin = sprite->win;
+	    pWin = pSprite->win;
 	}
 	else
 	    effectiveFocus = pWin = inputFocus;
@@ -4658,19 +4579,24 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
 _X_EXPORT void
 CheckCursorConfinement(WindowPtr pWin)
 {
-    GrabPtr grab = inputInfo.pointer->grab;
+    GrabPtr grab;
     WindowPtr confineTo;
+    DeviceIntPtr pDev;
 
 #ifdef PANORAMIX
     if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
 #endif
 
-    if (grab && (confineTo = grab->confineTo))
+    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
     {
-	if (!BorderSizeNotEmpty(confineTo))
-	    (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer);
-	else if ((pWin == confineTo) || IsParent(pWin, confineTo))
-	    ConfineCursorToWindow(confineTo, TRUE, TRUE);
+        grab = pDev->grab;
+        if (grab && (confineTo = grab->confineTo))
+        {
+            if (!BorderSizeNotEmpty(pDev, confineTo))
+                (*inputInfo.pointer->DeactivateGrab)(pDev);
+            else if ((pWin == confineTo) || IsParent(pWin, confineTo))
+                ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
+        }
     }
 }
 
@@ -4696,6 +4622,7 @@ ProcRecolorCursor(ClientPtr client)
     int		nscr;
     ScreenPtr	pscr;
     Bool 	displayed;
+    SpritePtr   pSprite = inputInfo.pointer->pSprite;
     REQUEST(xRecolorCursorReq);
 
     REQUEST_SIZE_MATCH(xRecolorCursorReq);
@@ -4720,12 +4647,12 @@ ProcRecolorCursor(ClientPtr client)
 	pscr = screenInfo.screens[nscr];
 #ifdef PANORAMIX
 	if(!noPanoramiXExtension)
-	    displayed = (pscr == sprite->screen);
+	    displayed = (pscr == pSprite->screen);
 	else
 #endif
-	    displayed = (pscr == sprite->hotPhys.pScreen);
+	    displayed = (pscr == pSprite->hotPhys.pScreen);
 	( *pscr->RecolorCursor)(inputInfo.pointer, pscr, pCursor,
-				(pCursor == sprite->current) && displayed);
+				(pCursor == pSprite->current) && displayed);
     }
     return (Success);
 }
diff --git a/dix/getevents.c b/dix/getevents.c
index 0932a1a..f223f29 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -488,11 +488,6 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
  * The DDX is responsible for allocating the event structure in the first
  * place via GetMaximumEventsNum(), and for freeing it.
  */
-#ifdef MPX
- /* In MPX, flags can be set to POINTER_MULTIPOINTER to indicate that the
-  * device is a multipointer device. MP devices always send core events.
-  */
-#endif
 _X_EXPORT int
 GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
                  int flags, int first_valuator, int num_valuators,
@@ -543,7 +538,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     kbp->deviceid = pDev->id;
 
 #ifdef MPX
-    if (flags & POINTER_MULTIPOINTER)
+    if (pDev->isMPDev)
         pointer = pDev;
     else
 #endif
@@ -604,7 +599,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
 #ifdef MPX
-    if (flags & POINTER_MULTIPOINTER)
+    if (pDev->isMPDev)
     {
         // noop, just less intrusive to fit MPX in like that
     } else
@@ -800,7 +795,11 @@ SwitchCorePointer(DeviceIntPtr pDev)
  * to shift the pointer to get it inside the new bounds.
  */
 void
-PostSyntheticMotion(int x, int y, ScreenPtr pScreen, unsigned long time)
+PostSyntheticMotion(DeviceIntPtr pDev, 
+                    int x, 
+                    int y, 
+                    ScreenPtr pScreen,
+                    unsigned long time) 
 {
     xEvent xE;
 
@@ -820,5 +819,5 @@ PostSyntheticMotion(int x, int y, ScreenPtr pScreen, unsigned long time)
     xE.u.keyButtonPointer.rootY = y;
     xE.u.keyButtonPointer.time = time;
 
-    (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);
+    (*pDev->public.processInputProc)(&xE, pDev, 1);
 }
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 2cb1441..422d43d 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -47,7 +47,6 @@
  */
 /* $XConsortium: xf86Xinput.c /main/14 1996/10/27 11:05:25 kaleb $ */
 
-#ifdef MPX
  /* 
   * MPX additions:
   * Copyright © 2006 Peter Hutterer
@@ -55,7 +54,6 @@
   * Author: Peter Hutterer <peter at cs.unisa.edu.au>
   *
   */
-#endif
 
 
 #ifdef HAVE_XORG_CONFIG_H
@@ -144,12 +142,10 @@ xf86ProcessCommonOptions(LocalDevicePtr local,
         xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name);
     }
 
-#ifdef MPX
     if (xf86SetBoolOption(list, "IsMPDevice", 0)) {
         local->flags |= XI86_MP_DEVICE;
         xf86Msg(X_CONFIG, "%s: is MP device\n", local->name);
     }
-#endif
 
     if (xf86SetBoolOption(list, "SendDragEvents", 1)) {
         local->flags |= XI86_SEND_DRAG_EVENTS;
@@ -214,12 +210,9 @@ xf86ActivateDevice(LocalDevicePtr local)
         xf86XinputFinalizeInit(dev);
 
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
-#ifdef MPX
-        if (local->flags & XI86_MP_DEVICE)
-            dev->isMPDev = TRUE;
-        else
-            dev->isMPDev = FALSE;
-#endif
+        dev->isMPDev = (local->flags & XI86_MP_DEVICE);
+        InitSprite(dev, dev->isMPDev);
+
         RegisterOtherDevice(dev);
 
         if (serverGeneration == 1) 
@@ -466,11 +459,6 @@ xf86PostMotionEvent(DeviceIntPtr	device,
     else
         flags = POINTER_RELATIVE | POINTER_ACCELERATE;
 
-#ifdef MPX
-    if (device->isMPDev)
-        flags |= POINTER_MULTIPOINTER;
-#endif
-    
     valuators = xcalloc(sizeof(int), num_valuators);
 
     va_start(var, num_valuators);
@@ -543,11 +531,6 @@ xf86PostButtonEvent(DeviceIntPtr	device,
     else
         flags = POINTER_RELATIVE;
 
-#ifdef MPX
-    if (device->isMPDev)
-        flags |= POINTER_MULTIPOINTER;
-#endif
-    
     valuators = xcalloc(sizeof(int), num_valuators);
 
     va_start(var, num_valuators);
diff --git a/hw/xnest/Events.c b/hw/xnest/Events.c
index a209241..8f794ed 100644
--- a/hw/xnest/Events.c
+++ b/hw/xnest/Events.c
@@ -25,6 +25,7 @@ is" without express or implied warranty.
 #include "scrnintstr.h"
 #include "windowstr.h"
 #include "servermd.h"
+#include "inputstr.h"
 
 #include "mi.h"
 
@@ -183,7 +184,7 @@ xnestCollectEvents()
       if (X.xcrossing.detail != NotifyInferior) {
 	pScreen = xnestScreen(X.xcrossing.window);
 	if (pScreen) {
-	  NewCurrentScreen(pScreen, X.xcrossing.x, X.xcrossing.y);
+	  NewCurrentScreen(inputInfo.pointer, pScreen, X.xcrossing.x, X.xcrossing.y);
           valuators[0] = X.xcrossing.x;
           valuators[1] = X.xcrossing.y;
           lastEventTime = GetTimeInMillis();
diff --git a/include/cursor.h b/include/cursor.h
index 7aacf23..e51394c 100644
--- a/include/cursor.h
+++ b/include/cursor.h
@@ -144,7 +144,7 @@ extern void GetSpritePosition(
     int * /*py*/);
 
 #ifdef PANORAMIX
-extern int XineramaGetCursorScreen(void);
+extern int XineramaGetCursorScreen(struct _DeviceIntRec* pDev);
 #endif /* PANORAMIX */
 
 #endif /* CURSOR_H */
diff --git a/include/dix.h b/include/dix.h
index 6f2e43a..959d5dc 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -649,6 +649,10 @@ extern int GrabDevice(
     CARD8 * /* status */);
 
 extern void InitEvents(void);
+extern void InitSprite(
+        DeviceIntPtr /* pDev */, 
+        Bool /* hasCursor */
+        );
 
 extern void CloseDownEvents(void);
 
diff --git a/include/dixevents.h b/include/dixevents.h
index c78fb0e..821a7bf 100644
--- a/include/dixevents.h
+++ b/include/dixevents.h
@@ -28,7 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 extern void SetCriticalEvent(int /* event */);
 
-extern CursorPtr GetSpriteCursor(void);
+extern CursorPtr GetSpriteCursor(DeviceIntPtr /*pDev*/);
 
 extern int ProcAllowEvents(ClientPtr /* client */);
 
@@ -103,7 +103,11 @@ extern int ProcUngrabButton(ClientPtr /* client */);
 extern int ProcRecolorCursor(ClientPtr /* client */);
 
 #ifdef PANORAMIX
-extern void PostSyntheticMotion(int x, int y, ScreenPtr pScreen, unsigned long time);
+extern void PostSyntheticMotion(DeviceIntPtr pDev, 
+                                int x, 
+                                int y, 
+                                ScreenPtr pScreen, 
+                                unsigned long time);
 #endif
 
 #endif /* DIXEVENTS_H */
diff --git a/include/input.h b/include/input.h
index 73da42f..357ba58 100644
--- a/include/input.h
+++ b/include/input.h
@@ -62,9 +62,6 @@ SOFTWARE.
 #define POINTER_RELATIVE (1 << 1)
 #define POINTER_ABSOLUTE (1 << 2)
 #define POINTER_ACCELERATE (1 << 3)
-#ifdef MPX
-#define POINTER_MULTIPOINTER (1 << 4)
-#endif
 
 #define MAP_LENGTH	256
 #define DOWN_LENGTH	32	/* 256/8 => number of bytes to hold 256 bits */
@@ -422,6 +419,7 @@ extern int GetProximityEvents(
     int *valuators);
 
 extern void PostSyntheticMotion(
+    DeviceIntPtr pDev,
     int x,
     int y,
     ScreenPtr pScreen,
diff --git a/include/inputstr.h b/include/inputstr.h
index 5128293..048a34a 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -52,6 +52,7 @@ SOFTWARE.
 #include "input.h"
 #include "window.h"
 #include "dixstruct.h"
+#include "cursorstr.h"
 
 #define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7)))
 
@@ -264,6 +265,30 @@ typedef struct _LedFeedbackClassRec {
 #endif
 } LedFeedbackClassRec;
 
+
+/**
+ * Sprite information for a device.
+ */
+typedef struct {
+    CursorPtr	current;
+    BoxRec	hotLimits;	/* logical constraints of hot spot */
+    Bool	confined;	/* confined to screen */
+#if defined(SHAPE) || defined(PANORAMIX)
+    RegionPtr	hotShape;	/* additional logical shape constraint */
+#endif
+    BoxRec	physLimits;	/* physical constraints of hot spot */
+    WindowPtr	win;		/* window of logical position */
+    HotSpot	hot;		/* logical pointer position */
+    HotSpot	hotPhys;	/* physical pointer position */
+#ifdef PANORAMIX
+    ScreenPtr	screen;		/* all others are in Screen 0 coordinates */
+    RegionRec   Reg1;	        /* Region 1 for confining motion */
+    RegionRec   Reg2;		/* Region 2 for confining virtual motion */
+    WindowPtr   windows[MAXSCREENS];
+    WindowPtr	confineWin;	/* confine window */ 
+#endif
+} SpriteRec, *SpritePtr;
+
 /* states for devices */
 
 #define NOT_GRABBED		0
@@ -329,9 +354,8 @@ typedef struct _DeviceIntRec {
     DevUnion		*devPrivates;
     int			nPrivates;
     DeviceUnwrapProc    unwrapProc;
-#ifdef MPX
     Bool                isMPDev;           /* TRUE if multipointer device */
-#endif
+    SpritePtr           pSprite;        /* sprite information */
 } DeviceIntRec;
 
 typedef struct {
diff --git a/record/record.c b/record/record.c
index 0ed8f84..4e7f92a 100644
--- a/record/record.c
+++ b/record/record.c
@@ -43,6 +43,7 @@ and Jim Haggerty of Metheus.
 #include <X11/extensions/recordstr.h>
 #include "set.h"
 #include "swaprep.h"
+#include "inputstr.h"
 
 #include <stdio.h>
 #include <assert.h>
@@ -861,7 +862,7 @@ RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
 			     pev->u.u.type == ButtonRelease ||
 			     pev->u.u.type == KeyPress ||
 			     pev->u.u.type == KeyRelease)) {
-				int scr = XineramaGetCursorScreen();
+				int scr = XineramaGetCursorScreen(inputInfo.pointer);
 				memcpy(&shiftedEvent, pev, sizeof(xEvent));
 				shiftedEvent.u.keyButtonPointer.rootX +=
 				    panoramiXdataPtr[scr].x - 
commit eb1d9f51af19dab20a95c2830ca1c508d8ee66bb
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 5 18:50:19 2006 +1030

    Ironing some glitches caused by the merge

diff --git a/Changelog b/Changelog
index 54c2f9e..5a264ab 100644
--- a/Changelog
+++ b/Changelog
@@ -24,6 +24,15 @@ ____________________________________________________________
 
 Merging from master
 
+____________________________________________________________
+
+Ironing some glitches caused by the merge
+
+Files:
+	Xi/exevents.c
+	randr/rrpointer.c
+	dix/events.c
+
 
 == 01.12.06 ==
 
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 8150b1e..9c65193 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -266,7 +266,8 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
     } else if (xE->u.u.type == DeviceButtonRelease
 #ifdef MPX
             || xE->u.u.type == MPXButtonRelease
-#endif) {
+#endif
+            ) {
         if (!b)
             return;
 
diff --git a/dix/events.c b/dix/events.c
index 3d7abd8..8d7167e 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -360,7 +360,7 @@ static void ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
 static void PostNewCursor(DeviceIntPtr pDev);
 
 #define SyntheticMotion(x, y) \
-    PostSyntheticMotion(x, y, sprite.screen, \
+    PostSyntheticMotion(x, y, sprite->screen, \
                         syncEvents.playingEvents ? \
                           syncEvents.time.milliseconds : \
                           currentTime.milliseconds);
diff --git a/randr/rrpointer.c b/randr/rrpointer.c
index c092e49..b9ee3bc 100644
--- a/randr/rrpointer.c
+++ b/randr/rrpointer.c
@@ -21,6 +21,7 @@
  */
 
 #include "randrstr.h"
+#include "inputstr.h"
 
 /*
  * When the pointer moves, check to see if the specified position is outside
@@ -87,7 +88,7 @@ RRPointerToNearestCrtc (ScreenPtr pScreen, int x, int y, RRCrtcPtr skip)
 	}
     }
     if (best_dx || best_dy)
-	(*pScreen->SetCursorPosition) (pScreen, x + best_dx, y + best_dy, TRUE);
+	(*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, x + best_dx, y + best_dy, TRUE);
     pScrPriv->pointerCrtc = nearest;
 }
 
@@ -132,6 +133,6 @@ RRPointerScreenConfigured (ScreenPtr pScreen)
 
     if (pScreen != pCurrentScreen)
 	return;
-    GetSpritePosition (&x, &y);
+    GetSpritePosition(inputInfo.pointer, &x, &y);
     RRPointerToNearestCrtc (pScreen, x, y, NULL);
 }
commit 3c8f166022a2d19af14eb670fa382503ba1451cd
Merge: 2a51149... f9f7d7f...
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 5 18:28:33 2006 +1030

    Merge branch 'master' of git://anongit.freedesktop.org/git/xorg/xserver into mpx
    
    Conflicts:
    
    	dix/events.c

diff --cc Changelog
index fbf1360,0000000..54c2f9e
mode 100644,000000..100644
--- a/Changelog
+++ b/Changelog
@@@ -1,426 -1,0 +1,430 @@@
 +MPX Changelog file
 +== 05.12.06 ==
 +Xi:     adding MPX checks to ProcessOtherEvents
 +
 +mpx:    adding QueryPointer request and reply
 +	adjusting names of requests to Xlib compatible naming (xMPX*** instead of
 +	mpx***)
 +
 +
 +Files:
 +	Xi/exevents.c
 +	mpx/Makefile.am
 +	mpx/extinit.c
 +	mpx/getevbase.c
 +	mpx/getvers.c
 +	mpx/queryptr.c
 +	mpx/queryptr.h
 +	mpx/selectev.c
 +	mpx/listdev.h
 +	mpx/listdev.c
 +	include/mpxextinit.h
 +
++____________________________________________________________
++
++Merging from master
++
 +
 +== 01.12.06 ==
 +
 +mpx:    SelectEvents and GetEventBase requests. 
 +	Some renaming and cleaning up in extinit.c
 +	MPXLastEvent added 
 +
 +Xi:	ShouldFreeInputMask() from XI is not static any more, used in mpx
 +
 +dix:	GetPointerEvents() allocates MPX event for MPX devices.
 +	DeliverDeviceEvents() caters for MPX devices.
 +
 +
 +Files:
 +	configure.ac
 +	mpx/Makefile.am
 +	mpx/extinit.c
 +	mpx/getvers.c
 +	mpx/getevbase.c
 +	mpx/getevbase.h
 +	mpx/listdev.c
 +	mpx/listdev.h
 +	mpx/mpxglobals.h
 +	mpx/selectev.c
 +	mpx/selectev.h
 +	mpx/mpxevents.h
 +	Xi/exevents.c
 +	dix/events.c
 +	dix/getevents.c
 +	include/mpxevents.h
 +	include/mpxextinit.h
 +
 +
 +== 30.11.06
 +mpx:    Adding ListDevices request. Minor changes, using
 +	MPXRestoreExtensionEvents() when resetting.
 +
 +Files:
 +	mpx/Makefile.am
 +	mpx/extinit.c
 +	mpx/listdev.c
 +	mpx/listdev.h
 +	mpx/mpxextinit.h
 +
 +
 +== 29.11.06 ==
 +mpx:    Infrastructure for MPX extension, GetExtensionVersion request works.
 +
 +Files:
 +	mpx/
 +	mpx/Makefile.am
 +	mpx/extinit.c
 +	mpx/getvers.c
 +	mpx/getvers.h
 +	mpxglobals.h
 +	mpx/selectev.c
 +	configure.ac
 +	Makefile.am
 +	os/utils.c
 +	mi/miinitext.c
 +	include/globals.h
 +
 +== 28.11.06 ==
 +mi:     Bugfix: FreeCursor ignores negative refcounts.
 +
 +mieq:   Bugfix: Motion notifies did overwrite DeviceMotionNotifies
 +
 +Files:
 +	dix/cursor.c
 +	mi/mieq.c
 +
 +____________________________________________________________
 +
 +dix:	missing parameter to SetCursorPosition in CheckMotion ifndef MPX
 +
 +mi:	missing include in misprite.c ifndef MPX
 +
 +Files:
 +	dix/events.c
 +	mi/misprite.c
 +
 +
 +== 27.11.06 ==
 +mi:     free allocated memory in miDCCloseScreen and in miDCInitialize in case
 +	of errors.
 +	Some copyright notices.
 +	misprite.c passes DeviceIntPtr around and down to DC (previously
 +	miCursorInfoPtr and the plain device id).
 +	Large cleanup in misprite.c to avoid code duplication.
 +
 +Files:
 +	mi/midispcur.c
 +	mi/misprite.c
 +	mi/misprite.h
 +
 +____________________________________________________________
 +
 +mi:     mipointer.c cleanup, reducing code duplication, using MPHasCursor(),
 +	removing IsMPDev()
 +
 +Files:
 +	mi/mipointer.c
 +
 +____________________________________________________________
 +
 +mi:     malloc checks for misprite and midispcur, code cleanup
 +	removed IsMPDev()
 +
 +Files:
 +	mi/misprite.c
 +	mi/mipointer.c
 +	mi/midispcur.c
 +	dix/events.c
 +
 +
 +== 23.11.06 ==
 +mi:	closing memory leak, miPointer is freed in miPointerCloseScreen
 +	bugfix: uninitialized pPointer in miPointerGetPosition ifndef MPX
 +	adding DeviceIntPtr parameter to ScreenRec's cursor functions.
 +	cleanup of miPointer code to use same scheme in each function
 +
 +dix:	MPHasCursor() function determines checking whether to invoke
 +	cursor rendering.
 +
 +animcur: adding DeviceIntPtr parameter to cursor functions but animcur relies
 +	 on the core pointer right now.
 +
 +xfixes: adding DeviceIntPtr parameter to cursor functions but xfixes relies on
 +	the core pointer right now.
 +
 +rac:	adding DeviceIntPtr parameter to cursor functions but RAC relies on
 +	the core pointer right now.
 +
 +ramdac:	adding DeviceIntPtr parameter to cursor functions but ramdac relies on
 +	the core pointer right now.
 +
 +Files:
 +	mi/mipointer.c
 +	mi/mipointer.h
 +	mi/micursor.c
 +	mi/mi.h
 +	mi/mieq.c
 +	include/cursor.h
 +	include/inputstr.h
 +	include/scrnintstr.h
 +	include/dix.h
 +	dix/events.c
 +	dix/cursor.c
 +	Xext/xtest.c
 +	render/animcur.c
 +	xfixes/cursor.c
 +	XTrap/xtrapddmi.c
 +	xkb/ddxFakeMtn.c
 +	hw/xfree86/common/xf86Cursor.c
 +	hw/xfree86/common/xf86RandR.c
 +	hw/xfree86/rac/xf86RAC.c
 +	hw/xfree86/ramdac/xf86Cursor.c
 +	hw/xfree86/dri/dri.c
 +
 +
 +== 22.11.06 ==
 +
 +mi:     added DevToSprite() conversion function
 +        fixed miSpriteRealize to use passed pDev argument instead of looping.
 +
 +dix:    changed sprite dependency and added MPX functionality to parts of
 +        events.c (XineramaChangeToCursor, XineramaCheckPhysLimits,
 +        XineramaConstrainCursor)
 +
 +Xi:	fix: accessing other->buttons for keyboard segfaulted the server
 +
 +Files:
 +        mi/misprite.c
 +        mi/mipointer.c
 +        dix/events.c
 +        Xi/exevents.c
 +
 +____________________________________________________________
 +
 +dix	GetSpriteWindow() adjusted for MPX
 +	added device dependency for MPX to DoEnterLeaveEvents,
 +	EnterLeaveEvents, EnterNotifies, LeaveNotifies and
 +	FixUpEventFromWindow.
 +
 +Files:
 +        Xext/security.c
 +        Xi/exevents.c
 +        xkb/ddxFakeMtn.c
 +        dix/events.c
 +        include/dix.h
 +
 +____________________________________________________________
 +
 +dix:	DeliverEventsToWindow adjusted for MPX
 +
 +mi:     sprite debugging disabled
 +
 +Files:	
 +        dix/events.c
 +        Xi/exevents.c
 +        mi/misprite.c
 +        include/dix.h
 +
 +
 +== 21.11.06 ==
 +mi:     added MPX to miSpriteReportDamage
 +        added id field to miCursorInfoPtr, required to pass through to miDC
 +        core pointer uses mpCursors array as well.
 +        added miDCBufferRec for future use with MPX
 +
 +Files:
 +        mi/midispcur.c
 +        mi/misprite.c
 +        mi/mispritest.h
 +
 +TAG: MPX_BEFORE_MIDC_API_BREAK
 +
 +____________________________________________________________
 +
 +mi:     added device ID to miSpriteCursorFuncRec functions
 +        added MPX code to midispcur.c
 +
 +
 +Files:
 +        mi/midispcur.c
 +        mi/misprite.c
 +        mi/mispritest.h
 +
 +BUG:   Core pointer changes whenever MPX cursor changes shape.
 +
 +____________________________________________________________
 +
 +mi:	constrain MPX cursors to screen 
 +
 +Files:
 +	dix/events.c
 +	mi/mipointer.c
 +	include/scrnintstr.h
 +
 +TAG:   MPX_BEFORE_DIX_API_BREAK
 +
 +
 +____________________________________________________________
 +
 +dix:    moved sprite from static to be pointer of type SpritePtr
 +	added SpriteRecs for MPX devices
 +	changed sprite dependency and added MPX functionality to parts 
 +	of events.c (ConfineToShape, PostNewCursor, XineramaCheckMotion,
 +	CheckMotion, XineramaChangeToCursor, ChangeToCursor, CheckPhysLimits,
 +	PointerConfinedToScreen) 
 +	added DeviceIntRec param to GetSpritePosition(). This required some
 +	minor changes in ddx, xtest, xkb and xfixes.
 +
 +mi:	changed miPointer to pointer instead of static struct.
 +
 +Files:
 +        dix/events.c
 +        dix/exevents.c
 +        Xext/xtest.c
 +        ddx/ddxFakeBtn.c
 +        ddx/ddxFakeMtn.c
 +        ddx/ddxDevBtn.c
 +        xkb/xkbActions.c
 +        xfixes/cursor.c
 +	mi/mieq.c
 +
 +____________________________________________________________
 +
 +dix:	WindowsRestructured() calls CheckMotion() on all devices
 +
 +mi:	core pointer was checked twice in miSpriteReportDamage,
 +	miSpriteInstallColormap, miSpriteStoreColors, miSpriteSaveDoomedAreas
 +	and miSpriteRealiseCursor 
 +	using damage bug (see comment in file) to avoid artefacts
 +
 +Files:
 +	dix/events.c
 +	mi/misprite.c
 +	mi/mispritest.h
 +
 +== 20.11.06 ==
 +
 +mi:     moved core pointer information from miSpriteScreenRec into a
 +        miCursorInfoRec.
 +        bugfix in mipointer, semicolon after preprocessor statement
 +
 +Files:
 +        mi/mispritest.h
 +        mi/misprite.c
 +        mi/mipointer.c
 +
 +____________________________________________________________
 +
 +mi:     added MPX to miSprite functions. 
 +
 +Files:
 +        mi/mispritest.h
 +        mi/misprite.c
 +        mi/mipointer.c
 +        dix/events.c
 +
 +NOTE: This version will render multiple cursors but with an artefact each time
 +when devices alternate.
 +
 +== 17.11.06 ==
 +dix:    moved isMPdev field to end of _DeviceIntRec structure
 +
 +mi:     
 +        added miMPPointers array to mipointer.c
 +        added DeviceIntPtr to all miPointerSpriteFuncs. Coming from miPointer
 +        we use inputInfo.pointer as standard value. ABI BREAK!
 +
 +ramdac: 
 +        forcing failed HW Cursor initialisation. MPX needs software rendering.
 +        changes to use new miPointerSpriteFunc (this required externing
 +        inputInfo, should probably be fixed at a later point).
 +
 +
 +RAC: changes to use new miPointerSpriteFuncs.
 +
 +Files: 
 +        include/inputstr.h
 +        mi/mipointer.c
 +        mi/mipointer.h
 +        mi/misprite.c
 +        hw/xfree86/ramdac/xf86HWCurs.c
 +        hw/xfree86/ramdac/xf86Cursor.c
 +        hw/xfree86/rac/xf86RAC.c
 +
 +____________________________________________________________
 +
 +mi:
 +        added miCursorInfoRec to contain info of the MPX cursors.
 +        calling miUpdatePointerSprite() from event queue for MPX devices.
 +        adding device-specific processing to miPointer*() functions.
 +
 +dix:    Call to SetCursorPosition in CheckMotion() temporarily disabled.
 +
 +xfree86/common: call to miPointerUpdateSprite() disabled, is done from the EQ 
 +
 +NOTE: This build will not display cursor images. 
 +BUG: The second mouse does to take correct x coordinates.
 +
 +Files:
 +        mi/mispritestr.h
 +        mi/misprite.c
 +        mi/mipointer.c
 +        mi/mipointer.h
 +        mi/mieq.c
 +        dix/events.c
 +        hw/xfree86/common/xf86Events.c
 +
 +
 +== 16.11.06 ==
 +dix: 
 +        merge with code cleanup from master
 +        GetPointerEvents treats events in the same way as XINPUT devices when flag
 +        has POINTER_MULTIPOINTER set.
 +
 +xfree86/common:
 +    added XI86_MP_DEVICE flag and parsing in xf86ProcessCommonOptions
 +    added POINTER_MULTIPOINTER define. Is used in xf86PostMotionEvent and
 +    xf86PostButtonEvent for the flags that are passed into GetPointerEvents()
 +
 +global:
 +    added flags to configure.ac to enable/disable MPX define
 +    added flags to dix-config.h.in to #define MPX
 +
 +Files:
 +        dix/getevents.c
 +        hw/xfree86/common/xf86Xinput.c
 +        hw/xfree86/common/xf86Xinput.h
 +        include/input.h
 +        configure.ac
 +        include/dix-config.h.in
 +
 +____________________________________________________________
 +
 +dix:    added isMPdev field to _DeviceIntRec, is used in GetPointerEvents()
 +
 +mieq:   avoid merging events from different devices in mieqEnqueue()
 +
 +xfree86/common
 +        isMPdev field used from xf86ActivateDevice(), xf86PostMotionEvent()
 +        and xf86PostButtonEvent()
 +
 +Files:
 +        dix/getevents.c
 +        hw/xfree86/common/xf86Xinput.c
 +        include/inputstr.h
 +        mi/mieq.c
 +
 +____________________________________________________________
 +
 +mieq:  EQ processing handles MP devices 
 +
 +global: MPX define added to xorg-server.h.in
 +
 +xfree86/common: small fix to avoid byte overflow
 +
 +Files:
 +        mi/mieq.c
 +        hw/xfree86/common/xf86Xinput.c
 +        include/xserver-config.h.in
diff --cc dix/events.c
index c7d4df0,7cfe0ad..3d7abd8
--- a/dix/events.c
+++ b/dix/events.c
@@@ -358,12 -324,11 +356,11 @@@ static CARD8 criticalEvents[32] 
  };
  
  #ifdef PANORAMIX
 -static void ConfineToShape(RegionPtr shape, int *px, int *py);
 -static void PostNewCursor(void);
 +static void ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py);
 +static void PostNewCursor(DeviceIntPtr pDev);
  
  #define SyntheticMotion(x, y) \
-     PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \
-                               sprite->screen->myNum, \
+     PostSyntheticMotion(x, y, sprite.screen, \
                          syncEvents.playingEvents ? \
                            syncEvents.time.milliseconds : \
                            currentTime.milliseconds);
@@@ -3559,17 -3338,14 +3548,14 @@@ FocusEvent(DeviceIntPtr dev, int type, 
  	((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
      {
  	xKeymapEvent ke;
- #ifdef XACE
  	ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
- 	if (!XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
- 	{
- 	    bzero((char *)&ke.map[0], 31);
- 	}
+ 	if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
+ 	    memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
  	else
- #endif
- 	memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
+ 	    bzero((char *)&ke.map[0], 31);
+ 
  	ke.type = KeymapNotify;
 -	(void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
 +	(void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
  				    KeymapStateMask, NullGrab, 0);
      }
  }
commit 2a511492f9a235d3f5390ab87b6c643cbea92d88
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Dec 5 15:45:18 2006 +1030

    Xi:     adding MPX checks to ProcessOtherEvents
    
    mpx:    adding QueryPointer request and reply
    	adjusting names of requests to Xlib compatible naming (xMPX*** instead of
    	mpx***)

diff --git a/Changelog b/Changelog
index a63021c..fbf1360 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,26 @@
 MPX Changelog file
+== 05.12.06 ==
+Xi:     adding MPX checks to ProcessOtherEvents
+
+mpx:    adding QueryPointer request and reply
+	adjusting names of requests to Xlib compatible naming (xMPX*** instead of
+	mpx***)
+
+
+Files:
+	Xi/exevents.c
+	mpx/Makefile.am
+	mpx/extinit.c
+	mpx/getevbase.c
+	mpx/getvers.c
+	mpx/queryptr.c
+	mpx/queryptr.h
+	mpx/selectev.c
+	mpx/listdev.h
+	mpx/listdev.c
+	include/mpxextinit.h
+
+
 == 01.12.06 ==
 
 mpx:    SelectEvents and GetEventBase requests. 
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 26c3f4b..8150b1e 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -73,6 +73,12 @@ SOFTWARE.
 #include "dixgrabs.h"	/* CreateGrab() */
 #include "scrnintstr.h"
 
+#ifdef MPX
+#include <X11/extensions/MPXconst.h>
+#include <X11/extensions/MPXproto.h>
+#include "mpxglobals.h"
+#endif
+
 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
 #define AllModifiersMask ( \
 	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
@@ -230,7 +236,11 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 
 	if (other->fromPassiveGrab && (key == other->activatingKey))
 	    deactivateDeviceGrab = TRUE;
-    } else if (xE->u.u.type == DeviceButtonPress) {
+    } else if (xE->u.u.type == DeviceButtonPress
+#ifdef MPX
+            || xE->u.u.type == MPXButtonPress
+#endif
+            ) {
         if (!b)
             return;
 
@@ -246,11 +256,17 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 	if (xE->u.u.detail <= 5)
 	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
-	if (!grab)
-	    if (CheckDeviceGrabs(other, xE, 0, count))
-		return;
-
-    } else if (xE->u.u.type == DeviceButtonRelease) {
+#ifdef MPX
+        if (xE->u.u.type == DeviceButtonPress)
+#endif
+            if (!grab)
+                if (CheckDeviceGrabs(other, xE, 0, count))
+                    return;
+
+    } else if (xE->u.u.type == DeviceButtonRelease
+#ifdef MPX
+            || xE->u.u.type == MPXButtonRelease
+#endif) {
         if (!b)
             return;
 
@@ -266,8 +282,11 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 	if (xE->u.u.detail <= 5)
 	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
 	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
-	if (!b->state && other->fromPassiveGrab)
-	    deactivateDeviceGrab = TRUE;
+#ifdef MPX
+        if (xE->u.u.type == DeviceButtonRelease)
+#endif
+            if (!b->state && other->fromPassiveGrab)
+                deactivateDeviceGrab = TRUE;
     } else if (xE->u.u.type == ProximityIn)
 	other->valuator->mode &= ~OutOfProximity;
     else if (xE->u.u.type == ProximityOut)
diff --git a/include/mpxextinit.h b/include/mpxextinit.h
index 7fbb4c4..02be6c1 100644
--- a/include/mpxextinit.h
+++ b/include/mpxextinit.h
@@ -28,7 +28,7 @@ void
 SReplyMPXDispatch (
 	ClientPtr              /* client */,
 	int                    /* len */,
-	mpxGetExtensionVersionReply *     /* rep */
+	xMPXGetExtensionVersionReply *     /* rep */
 	);
 
 void
diff --git a/mpx/Makefile.am b/mpx/Makefile.am
index 63c384f..b35d8e7 100644
--- a/mpx/Makefile.am
+++ b/mpx/Makefile.am
@@ -12,5 +12,7 @@ libmpx_la_SOURCES =	\
         selectev.h \
         mpxglobals.h \
 	getevbase.c \
-	getevbase.h
+	getevbase.h \
+        queryptr.h \
+        queryptr.c 
 
diff --git a/mpx/extinit.c b/mpx/extinit.c
index 89a9dc7..4b4bd47 100644
--- a/mpx/extinit.c
+++ b/mpx/extinit.c
@@ -7,7 +7,6 @@
 #include <X11/X.h>
 #include <X11/Xproto.h>
 #include "inputstr.h"
-//#include "gcstruct.h"	/* pointer for extnsionst.h */
 #include "extnsionst.h"	/* extension entry   */
 #include <X11/extensions/MPX.h>
 #include <X11/extensions/MPXproto.h>
@@ -21,6 +20,7 @@
 #include "listdev.h"
 #include "selectev.h"
 #include "getevbase.h"
+#include "queryptr.h"
 
 static Mask lastExtEventMask = 1;
 int MPXEventIndex;
@@ -74,7 +74,6 @@ int MPXLastEvent;
  */
 
 static MPXExtensionVersion thisversion = { 
-    MPX_Present,
     MPX_Major,
     MPX_Minor
 };
@@ -125,14 +124,16 @@ int
 ProcMPXDispatch(register ClientPtr client)
 {
     REQUEST(xReq);
-    if (stuff->data == MPX_GetExtensionVersion)
+    if (stuff->data == X_MPXGetExtensionVersion)
         return (ProcMPXGetExtensionVersion(client));
-    if (stuff->data == MPX_ListDevices)
+    if (stuff->data == X_MPXListDevices)
         return (ProcMPXListDevices(client));
-    if (stuff->data == MPX_SelectEvents)
+    if (stuff->data == X_MPXSelectEvents)
         return (ProcMPXSelectEvents(client));
-    if (stuff->data == MPX_GetEventBase)
+    if (stuff->data == X_MPXGetEventBase)
         return (ProcMPXGetEventBase(client));
+    if (stuff->data == X_MPXQueryPointer)
+        return (ProcMPXQueryPointer(client));
     else {
         SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
     }
@@ -153,14 +154,16 @@ int
 SProcMPXDispatch(register ClientPtr client)
 {
     REQUEST(xReq);
-    if (stuff->data == MPX_GetExtensionVersion)
+    if (stuff->data == X_MPXGetExtensionVersion)
         return (SProcMPXGetExtensionVersion(client));
-    if (stuff->data == MPX_ListDevices)
+    if (stuff->data == X_MPXListDevices)
         return (SProcMPXListDevices(client));
-    if (stuff->data == MPX_SelectEvents)
+    if (stuff->data == X_MPXSelectEvents)
         return (SProcMPXSelectEvents(client));
-    if (stuff->data == MPX_GetEventBase)
+    if (stuff->data == X_MPXGetEventBase)
         return (SProcMPXGetEventBase(client));
+    if (stuff->data == X_MPXQueryPointer)
+        return (SProcMPXQueryPointer(client));
     else {
         SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
     }
@@ -188,14 +191,14 @@ MPXResetProc(ExtensionEntry* unused)
 
 }
 
-void SReplyMPXDispatch(ClientPtr client, int len, mpxGetExtensionVersionReply* rep)
+void SReplyMPXDispatch(ClientPtr client, int len, xMPXGetExtensionVersionReply* rep)
 {
-    if (rep->RepType ==  MPX_GetExtensionVersion)
+    if (rep->RepType ==  X_MPXGetExtensionVersion)
         SRepMPXGetExtensionVersion(client, len, 
-                (mpxGetExtensionVersionReply*) rep);
-    if (rep->RepType ==  MPX_ListDevices)
+                (xMPXGetExtensionVersionReply*) rep);
+    if (rep->RepType ==  X_MPXListDevices)
         SRepMPXListDevices(client, len, 
-                (mpxListDevicesReply*) rep);
+                (xMPXListDevicesReply*) rep);
     else {
 	FatalError("MPX confused sending swapped reply");
     }
diff --git a/mpx/getevbase.c b/mpx/getevbase.c
index 7ec82f6..8b0f598 100644
--- a/mpx/getevbase.c
+++ b/mpx/getevbase.c
@@ -20,20 +20,20 @@
 int
 ProcMPXGetEventBase(register ClientPtr client)
 {
-    mpxGetEventBaseReply rep;
+    xMPXGetEventBaseReply rep;
 
-    REQUEST(mpxGetEventBaseReq);
-    REQUEST_SIZE_MATCH(mpxGetEventBaseReq);
+    REQUEST(xMPXGetEventBaseReq);
+    REQUEST_SIZE_MATCH(xMPXGetEventBaseReq);
 
-    memset(&rep, 0, sizeof(mpxGetEventBaseReply));
+    memset(&rep, 0, sizeof(xMPXGetEventBaseReply));
     rep.repType = X_Reply;
-    rep.RepType = MPX_GetEventBase;
+    rep.RepType = X_MPXGetEventBase;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
 
     rep.eventBase = MPXEventBase;
 
-    WriteReplyToClient(client, sizeof(mpxGetEventBaseReply), &rep);
+    WriteReplyToClient(client, sizeof(xMPXGetEventBaseReply), &rep);
 
     return Success;
 }
@@ -47,9 +47,9 @@ SProcMPXGetEventBase(register ClientPtr client)
 {
     register char n;
 
-    REQUEST(mpxGetEventBaseReq);
+    REQUEST(xMPXGetEventBaseReq);
     swaps(&stuff->length, n);
-    REQUEST_SIZE_MATCH(mpxGetEventBaseReq);
+    REQUEST_SIZE_MATCH(xMPXGetEventBaseReq);
     return (ProcMPXGetEventBase(client));
 }
 
diff --git a/mpx/getvers.c b/mpx/getvers.c
index 7297a1f..fc3fc56 100644
--- a/mpx/getvers.c
+++ b/mpx/getvers.c
@@ -26,11 +26,11 @@ SProcMPXGetExtensionVersion(register ClientPtr client)
 {
     register char n;
 
-    REQUEST(mpxGetExtensionVersionReq);
+    REQUEST(xMPXGetExtensionVersionReq);
     swaps(&stuff->length, n);
     swaps(&stuff->major_version, n);
     swaps(&stuff->minor_version, n);
-    REQUEST_AT_LEAST_SIZE(mpxGetExtensionVersionReq);
+    REQUEST_AT_LEAST_SIZE(xMPXGetExtensionVersionReq);
     return (ProcMPXGetExtensionVersion(client));
 }
 /***********************************************************************
@@ -41,19 +41,19 @@ SProcMPXGetExtensionVersion(register ClientPtr client)
 int
 ProcMPXGetExtensionVersion(register ClientPtr client)
 {
-    mpxGetExtensionVersionReply rep;
+    xMPXGetExtensionVersionReply rep;
 
-    REQUEST(mpxGetExtensionVersionReq);
-    REQUEST_SIZE_MATCH(mpxGetExtensionVersionReq);
+    REQUEST(xMPXGetExtensionVersionReq);
+    REQUEST_SIZE_MATCH(xMPXGetExtensionVersionReq);
 
     rep.repType = X_Reply;
-    rep.RepType = MPX_GetExtensionVersion;
+    rep.RepType = X_MPXGetExtensionVersion;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
 
-    rep.major_version = AllExtensionVersions[MPXReqCode - 128].major_version;
-    rep.minor_version = AllExtensionVersions[MPXReqCode - 128].minor_version;
-    WriteReplyToClient(client, sizeof(mpxGetExtensionVersionReply), &rep);
+    rep.major_version = AllExtensionVersions[MPXReqCode - 128].major;
+    rep.minor_version = AllExtensionVersions[MPXReqCode - 128].minor;
+    WriteReplyToClient(client, sizeof(xMPXGetExtensionVersionReply), &rep);
 
     return Success;
 }
@@ -67,7 +67,7 @@ ProcMPXGetExtensionVersion(register ClientPtr client)
 
 void
 SRepMPXGetExtensionVersion(ClientPtr client, int size,
-			 mpxGetExtensionVersionReply * rep)
+			 xMPXGetExtensionVersionReply * rep)
 {
     register char n;
 
diff --git a/mpx/getvers.h b/mpx/getvers.h
index da24018..8800ac6 100644
--- a/mpx/getvers.h
+++ b/mpx/getvers.h
@@ -15,7 +15,7 @@ int ProcMPXGetExtensionVersion(ClientPtr	/* client */
 
 void SRepMPXGetExtensionVersion(ClientPtr /* client */ ,
 			      int /* size */ ,
-			      mpxGetExtensionVersionReply *	/* rep */
+			      xMPXGetExtensionVersionReply *	/* rep */
     );
 
 #endif
diff --git a/mpx/listdev.c b/mpx/listdev.c
index 8bb27b3..f977110 100644
--- a/mpx/listdev.c
+++ b/mpx/listdev.c
@@ -25,7 +25,7 @@ int SProcMPXListDevices(register ClientPtr client)
 {
     register char n;
 
-    REQUEST(mpxListDevicesReq);
+    REQUEST(xMPXListDevicesReq);
     swaps(&stuff->length, n);
     return (ProcMPXListDevices(client));
 }
@@ -38,7 +38,7 @@ int SProcMPXListDevices(register ClientPtr client)
  */
 int ProcMPXListDevices(register ClientPtr client)
 {
-    mpxListDevicesReply rep;
+    xMPXListDevicesReply rep;
     int numdevs = 0;
     int namesize = 1;	/* need 1 extra byte for strcpy */
     int size = 0;
@@ -46,13 +46,13 @@ int ProcMPXListDevices(register ClientPtr client)
     char* devbuf;
     char* namebuf;
     char *savbuf;
-    mpxDeviceInfoPtr dev;
+    xMPXDeviceInfoPtr dev;
     DeviceIntPtr d;
 
-    REQUEST_SIZE_MATCH(mpxListDevicesReq);
-    memset(&rep, 0, sizeof(mpxListDevicesReply));
+    REQUEST_SIZE_MATCH(xMPXListDevicesReq);
+    memset(&rep, 0, sizeof(xMPXListDevicesReply));
     rep.repType = X_Reply;
-    rep.RepType = MPX_ListDevices;
+    rep.RepType = X_MPXListDevices;
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
 
@@ -72,12 +72,12 @@ int ProcMPXListDevices(register ClientPtr client)
         }
     }
 
-    total_length = numdevs * sizeof(mpxDeviceInfo) + size + namesize;
+    total_length = numdevs * sizeof(xMPXDeviceInfo) + size + namesize;
     devbuf = (char *)xalloc(total_length);
-    namebuf = devbuf + (numdevs * sizeof(mpxDeviceInfo));
+    namebuf = devbuf + (numdevs * sizeof(xMPXDeviceInfo));
     savbuf = devbuf;
 
-    dev = (mpxDeviceInfoPtr) devbuf;
+    dev = (xMPXDeviceInfoPtr) devbuf;
     for (d = inputInfo.devices; d; d = d->next, dev++)
         if (d->isMPDev)
             SetMPXDeviceInfo(client, d, dev, &devbuf, &namebuf);
@@ -87,7 +87,7 @@ int ProcMPXListDevices(register ClientPtr client)
 
     rep.ndevices = numdevs;
     rep.length = (total_length + 3) >> 2;
-    WriteReplyToClient(client, sizeof(mpxListDevicesReply), &rep);
+    WriteReplyToClient(client, sizeof(xMPXListDevicesReply), &rep);
     WriteToClient(client, total_length, savbuf);
     xfree(savbuf);
     return Success;
@@ -115,7 +115,7 @@ SizeMPXDeviceInfo(DeviceIntPtr d, int *namesize, int *size)
  */
 
 void
-SetMPXDeviceInfo(ClientPtr client, DeviceIntPtr d, mpxDeviceInfoPtr dev,
+SetMPXDeviceInfo(ClientPtr client, DeviceIntPtr d, xMPXDeviceInfoPtr dev,
 	       char **devbuf, char **namebuf)
 {
     MPXCopyDeviceName(namebuf, d->name);
@@ -157,17 +157,17 @@ void
 MPXCopySwapDevice(register ClientPtr client, DeviceIntPtr d, char **buf)
 {
     register char n;
-    mpxDeviceInfoPtr dev;
+    xMPXDeviceInfoPtr dev;
 
-    dev = (mpxDeviceInfoPtr) * buf;
-    memset(dev, 0, sizeof(mpxDeviceInfo));
+    dev = (xMPXDeviceInfoPtr) * buf;
+    memset(dev, 0, sizeof(xMPXDeviceInfo));
 
     dev->id = d->id;
     dev->type = d->type;
     if (client->swapped) {
 	swapl(&dev->type, n);	/* macro - braces are required */
     }
-    *buf += sizeof(mpxDeviceInfo);
+    *buf += sizeof(xMPXDeviceInfo);
 }
 
 /***********************************************************************
@@ -177,7 +177,7 @@ MPXCopySwapDevice(register ClientPtr client, DeviceIntPtr d, char **buf)
  *
  */
 void
-SRepMPXListDevices(ClientPtr client, int size, mpxListDevicesReply * rep)
+SRepMPXListDevices(ClientPtr client, int size, xMPXListDevicesReply * rep)
 {
     register char n;
 
diff --git a/mpx/listdev.h b/mpx/listdev.h
index 0d2e0dc..079fe8e 100644
--- a/mpx/listdev.h
+++ b/mpx/listdev.h
@@ -31,7 +31,7 @@ void SizeMPXDeviceInfo(DeviceIntPtr /* d */ ,
 
 void SetMPXDeviceInfo(ClientPtr /* client */ ,
 		    DeviceIntPtr /* d */ ,
-		    mpxDeviceInfoPtr /* dev */ ,
+		    xMPXDeviceInfoPtr /* dev */ ,
 		    char ** /* devbuf */ ,
 		    char **	/* namebuf */
     );
@@ -48,6 +48,6 @@ void MPXCopySwapDevice(ClientPtr /* client */ ,
 
 void SRepMPXListDevices(ClientPtr /* client */ ,
 			   int /* size */ ,
-			   mpxListDevicesReply *	/* rep */
+			   xMPXListDevicesReply *	/* rep */
     );
 #endif
diff --git a/mpx/queryptr.c b/mpx/queryptr.c
new file mode 100644
index 0000000..7162074
--- /dev/null
+++ b/mpx/queryptr.c
@@ -0,0 +1,90 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "inputstr.h"
+#include "windowstr.h"
+#include <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+
+#include "mpxglobals.h"
+
+#include "queryptr.h"
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the MPXQueryPointer function.
+ */
+int
+ProcMPXQueryPointer(register ClientPtr client)
+{
+    xMPXQueryPointerReply rep;
+    DeviceIntPtr pDev;
+    WindowPtr root, win;
+    int x, y;
+
+    REQUEST(xMPXQueryPointerReq);
+    REQUEST_SIZE_MATCH(xMPXQueryPointerReq);
+
+    pDev = LookupDeviceIntRec(stuff->deviceid);
+    if (!pDev->isMPDev)
+    {
+        SendErrorToClient(client, MPXReqCode, X_MPXQueryPointer,
+                stuff->deviceid, BadValue);
+        return Success;
+    }
+
+
+    memset(&rep, 0, sizeof(xMPXQueryPointerReply));
+    rep.repType = X_Reply;
+    rep.RepType = X_MPXQueryPointer;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+
+    root = GetCurrentRootWindow();
+    win = GetSpriteWindow(pDev);
+    GetSpritePosition(pDev, &x, &y);
+
+    rep.root = root->drawable.id;
+    rep.root_x = x;
+    rep.root_y = y;
+    if (win != root)
+    {
+        rep.child = win->drawable.id;
+        rep.win_x = x - win->drawable.x;
+        rep.win_y = y - win->drawable.y;
+    }
+    else
+    {
+        rep.child = None;
+        rep.win_x = x;
+        rep.win_y = y;
+    }
+
+
+    rep.mask = pDev->button->state | inputInfo.keyboard->key->state;
+
+    WriteReplyToClient(client, sizeof(xMPXQueryPointerReply), &rep);
+
+    return Success;
+}
+
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the MPXQueryPointer function.
+ */
+int
+SProcMPXQueryPointer(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(xMPXQueryPointerReq);
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(xMPXQueryPointerReq);
+    return (ProcMPXQueryPointer(client));
+}
diff --git a/mpx/queryptr.h b/mpx/queryptr.h
new file mode 100644
index 0000000..c89397c
--- /dev/null
+++ b/mpx/queryptr.h
@@ -0,0 +1,16 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef QUERYPTR_H
+#define QUERYPTR_H 1
+
+int SProcMPXQueryPointer(ClientPtr	/* client */
+    );
+
+int ProcMPXQueryPointer(ClientPtr	/* client */
+    );
+
+#endif /* QUERYPTR_H */
diff --git a/mpx/selectev.c b/mpx/selectev.c
index 1e75a51..fc2ff9c 100644
--- a/mpx/selectev.c
+++ b/mpx/selectev.c
@@ -42,9 +42,9 @@ SProcMPXSelectEvents(register ClientPtr client)
 {
     register char n;
 
-    REQUEST(mpxSelectEventsReq);
+    REQUEST(xMPXSelectEventsReq);
     swaps(&stuff->length, n);
-    REQUEST_SIZE_MATCH(mpxSelectEventsReq);
+    REQUEST_SIZE_MATCH(xMPXSelectEventsReq);
     swapl(&stuff->window, n);
     return (ProcMPXSelectEvents(client));
 }
@@ -61,12 +61,12 @@ ProcMPXSelectEvents(register ClientPtr client)
     int ret;
     WindowPtr pWin;
 
-    REQUEST(mpxSelectEventsReq);
-    REQUEST_SIZE_MATCH(mpxSelectEventsReq);
+    REQUEST(xMPXSelectEventsReq);
+    REQUEST_SIZE_MATCH(xMPXSelectEventsReq);
 
-    if (stuff->length != (sizeof(mpxSelectEventsReq) >> 2))
+    if (stuff->length != (sizeof(xMPXSelectEventsReq) >> 2))
     { 
-        SendErrorToClient(client, MPXReqCode, MPX_SelectEvents, 0,
+        SendErrorToClient(client, MPXReqCode, X_MPXSelectEvents, 0,
 			  BadLength);
 	return Success;
     }
@@ -75,7 +75,7 @@ ProcMPXSelectEvents(register ClientPtr client)
     if (!pWin) 
     {
 	client->errorValue = stuff->window;
-	SendErrorToClient(client, MPXReqCode, MPX_SelectEvents, 0,
+	SendErrorToClient(client, MPXReqCode, X_MPXSelectEvents, 0,
 			  BadWindow);
 	return Success;
     }
@@ -83,13 +83,13 @@ ProcMPXSelectEvents(register ClientPtr client)
     if (stuff->mask >= MPXHighestMask)
     {
         client->errorValue = stuff->mask;
-	SendErrorToClient(client, MPXReqCode, MPX_SelectEvents, 0,
+	SendErrorToClient(client, MPXReqCode, X_MPXSelectEvents, 0,
 			  BadValue);
     }
 
     if ((ret = MPXSelectForWindow(pWin, client, stuff->mask)) != Success) 
     { 
-        SendErrorToClient(client, MPXReqCode, MPX_SelectEvents, 0, ret);
+        SendErrorToClient(client, MPXReqCode, X_MPXSelectEvents, 0, ret);
         return Success;
     }
 
commit 416f1bb99a6d4557f2863ae941868e47e11bbb3b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Dec 1 15:56:52 2006 +1030

    mpx:    SelectEvents and GetEventBase requests.
    	Some renaming and cleaning up in extinit.c
    	MPXLastEvent added
    
    Xi:	ShouldFreeInputMask() from XI is not static any more, used in mpx
    
    dix:	GetPointerEvents() allocates MPX event for MPX devices.
    	DeliverDeviceEvents() caters for MPX devices.

diff --git a/Changelog b/Changelog
index c818bce..a63021c 100644
--- a/Changelog
+++ b/Changelog
@@ -1,5 +1,49 @@
 MPX Changelog file
-== 29.11.206 ==
+== 01.12.06 ==
+
+mpx:    SelectEvents and GetEventBase requests. 
+	Some renaming and cleaning up in extinit.c
+	MPXLastEvent added 
+
+Xi:	ShouldFreeInputMask() from XI is not static any more, used in mpx
+
+dix:	GetPointerEvents() allocates MPX event for MPX devices.
+	DeliverDeviceEvents() caters for MPX devices.
+
+
+Files:
+	configure.ac
+	mpx/Makefile.am
+	mpx/extinit.c
+	mpx/getvers.c
+	mpx/getevbase.c
+	mpx/getevbase.h
+	mpx/listdev.c
+	mpx/listdev.h
+	mpx/mpxglobals.h
+	mpx/selectev.c
+	mpx/selectev.h
+	mpx/mpxevents.h
+	Xi/exevents.c
+	dix/events.c
+	dix/getevents.c
+	include/mpxevents.h
+	include/mpxextinit.h
+
+
+== 30.11.06
+mpx:    Adding ListDevices request. Minor changes, using
+	MPXRestoreExtensionEvents() when resetting.
+
+Files:
+	mpx/Makefile.am
+	mpx/extinit.c
+	mpx/listdev.c
+	mpx/listdev.h
+	mpx/mpxextinit.h
+
+
+== 29.11.06 ==
 mpx:    Infrastructure for MPX extension, GetExtensionVersion request works.
 
 Files:
diff --git a/Xi/exevents.c b/Xi/exevents.c
index ecbb199..26c3f4b 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -82,7 +82,7 @@ SOFTWARE.
 #define Motion_Filter(class) (DevicePointerMotionMask | \
 			      (class)->state | (class)->motionMask)
 
-static Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
+Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
 				 Bool	/* ignoreSelectedEvents */
     );
 static Bool MakeInputMasks(WindowPtr	/* pWin */
@@ -1196,7 +1196,7 @@ DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
     return Success;
 }
 
-static Bool
+Bool
 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
 {
     int i;
diff --git a/configure.ac b/configure.ac
index e5d2f5e..fa1a5c8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1003,7 +1003,7 @@ AC_EGREP_CPP([I_AM_SVR4],[
 AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4])
 AC_MSG_RESULT([yes])], AC_MSG_RESULT([no]))
 
-XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC"
+XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $MPX_INC"
 AC_DEFINE_UNQUOTED(X_BYTE_ORDER,[$ENDIAN],[Endian order])
 
 AC_SUBST([XSERVER_LIBS])
diff --git a/dix/events.c b/dix/events.c
index 8ef318a..c7d4df0 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -107,6 +107,12 @@ of the copyright holder.
 
 ******************************************************************/
 
+/* 
+ * MPX additions
+ * Copyright 2006 by Peter Hutterer
+ * Author: Peter Hutterer <peter at cs.unisa.edu.au>
+ */
+
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -171,6 +177,10 @@ xEvent *xeviexE;
 #include "dixgrabs.h"
 #include "dispatch.h"
 
+#ifdef MPX
+#include "mpxglobals.h"
+#endif
+
 #define EXTENSION_EVENT_BASE  64
 
 #define NoSuchEvent 0x80000000	/* so doesn't match NoEventMask */
@@ -1924,6 +1934,10 @@ DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
     {
 	register OtherInputMasks *inputMasks;
 	int mskidx = dev->id;
+#ifdef MPX
+        if (IsMPXEvent(xE))
+            mskidx = MPXmskidx;
+#endif
 
 	inputMasks = wOtherInputMasks(pWin);
 	if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
diff --git a/dix/getevents.c b/dix/getevents.c
index 9c7b723..7c121a5 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -21,15 +21,12 @@
  *
  * Author: Daniel Stone <daniel at fooishbar.org>
  */
-#ifdef MPX
  /* 
   * MPX additions:
   * Copyright © 2006 Peter Hutterer
-  * License see above.
   * Author: Peter Hutterer <peter at cs.unisa.edu.au>
   *
   */
-#endif
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -72,6 +69,11 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
 #include "exglobals.h"
 #include "extnsionst.h"
 
+#ifdef MPX
+#include <X11/extensions/MPXconst.h>
+#include <X11/extensions/MPXproto.h>
+#include "mpxglobals.h"
+#endif
 
 /* Maximum number of valuators, divided by six, rounded up, to get number
  * of events. */
@@ -511,7 +513,11 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
 
     if ((type == ButtonPress || type == ButtonRelease) && !pDev->button)
         return 0;
-
+#ifdef MPX
+    if (pDev->isMPDev)
+        num_events = 3;
+    else
+#endif
     if (pDev->coreEvents)
         num_events = 2;
     else
@@ -603,7 +609,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
 #ifdef MPX
     if (flags & POINTER_MULTIPOINTER)
     {
-        // noop, just to fit MPX in easier with the following if
+        // noop, just less intrusive to fit MPX in like that
     } else
 #endif
     if (pDev->coreEvents) {
@@ -637,6 +643,25 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     }
 
 #ifdef MPX
+    if (pDev->isMPDev)
+    {
+        /* MPX events are the same as XI events but without valuators. */
+        memcpy(events, kbp, sizeof(deviceKeyButtonPointer));
+        switch(type)
+        {
+            case ButtonPress:
+                events->u.u.type = MPXButtonPress;
+                break;
+            case ButtonRelease:
+                events->u.u.type = MPXButtonRelease;
+                break;
+            case MotionNotify:
+                events->u.u.type = MPXMotionNotify;
+                break;
+        }
+        events++;
+    }
+
     /* MPX devices always send core events */
     if (pDev->coreEvents || pDev->isMPDev) {
 #else
diff --git a/include/mpxevents.h b/include/mpxevents.h
new file mode 100644
index 0000000..99bf2b0
--- /dev/null
+++ b/include/mpxevents.h
@@ -0,0 +1,19 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef MPXEVENTS_H
+#define MPXEVENTS_H 1
+
+#include <X11/X.h>	/* for inputstr.h    */
+#include <X11/Xproto.h>	/* Request macro     */
+#include "inputstr.h"	/* DeviceIntPtr      */
+
+extern int MPXSelectForWindow(
+	WindowPtr              /* pWin */,
+	ClientPtr              /* client */,
+        int                    /* mask */);
+
+#endif
diff --git a/include/mpxextinit.h b/include/mpxextinit.h
new file mode 100644
index 0000000..7fbb4c4
--- /dev/null
+++ b/include/mpxextinit.h
@@ -0,0 +1,72 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+/********************************************************************
+ * Interface of mpx/extinit.c
+ */
+
+#ifndef MPXEXTINIT_H
+#define MPXEXTINIT_H
+
+#include "extnsionst.h"
+
+void
+MPXExtensionInit(
+	void
+	);
+
+int
+ProcMPXDispatch (
+	ClientPtr              /* client */
+	);
+
+int
+SProcMPXDispatch(
+	ClientPtr              /* client */
+	);
+
+void
+SReplyMPXDispatch (
+	ClientPtr              /* client */,
+	int                    /* len */,
+	mpxGetExtensionVersionReply *     /* rep */
+	);
+
+void
+SEventMPXDispatch (
+	xEvent *               /* from */,
+	xEvent *               /* to */
+	);
+
+void
+MPXFixExtensionEvents (
+	ExtensionEntry 	*      /* extEntry */
+	);
+
+void
+MPXResetProc(
+	ExtensionEntry *       /* unused */
+	);
+
+Mask
+MPXGetNextExtEventMask (
+	void
+);
+
+void
+MPXSetMaskForExtEvent(
+	Mask                   /* mask */,
+	int                    /* event */
+	);
+
+void
+MPXAllowPropagateSuppress (
+	Mask                   /* mask */
+	);
+
+void
+MPXRestoreExtensionEvents (
+	void
+	);
+#endif
+
+
diff --git a/mpx/Makefile.am b/mpx/Makefile.am
index db75eb5..63c384f 100644
--- a/mpx/Makefile.am
+++ b/mpx/Makefile.am
@@ -5,5 +5,12 @@ AM_CFLAGS = $(DIX_CFLAGS)
 libmpx_la_SOURCES =	\
 	extinit.c \
         getvers.c \
-	getvers.h
+	getvers.h \
+        listdev.c \
+        listdev.h \
+        selectev.c \
+        selectev.h \
+        mpxglobals.h \
+	getevbase.c \
+	getevbase.h
 
diff --git a/mpx/extinit.c b/mpx/extinit.c
index 59bc494..89a9dc7 100644
--- a/mpx/extinit.c
+++ b/mpx/extinit.c
@@ -11,17 +11,36 @@
 #include "extnsionst.h"	/* extension entry   */
 #include <X11/extensions/MPX.h>
 #include <X11/extensions/MPXproto.h>
+#include <X11/extensions/MPXconst.h>
 
+#include "mpxglobals.h"
 #include "mpxextinit.h"
 #include "swaprep.h"
 
 #include "getvers.h"
+#include "listdev.h"
+#include "selectev.h"
+#include "getevbase.h"
 
 static Mask lastExtEventMask = 1;
-int ExtEventIndex;
-Mask ExtValidMasks[EMASKSIZE];
+int MPXEventIndex;
+MPXExtEventInfo EventInfo[32];
+
+/**
+ * MPX piggybacks on the X Input extension's event system. Each window has an
+ * array of event masks, from 0 to MAX_DEVICES. In XI, each device can have
+ * separate event masks. Before an event is delivered, the array at the index
+ * of the device is checked.
+ *
+ * Two things:
+ * -) core devices do not send input extension events
+ * -) MPX events are not device specific.
+ *
+ * Since the mask of the core pointer (index 1) is thus not used by XI, MPX
+ * can use it for the event mask. This also makes MPX less intrusive.  
+ */
+int MPXmskidx = 1;
 
-XExtEventInfo EventInfo[32];
 
 /*****************************************************************
  *
@@ -29,7 +48,7 @@ XExtEventInfo EventInfo[32];
  *
  */
 
-extern XExtensionVersion AllExtensionVersions[];
+extern MPXExtensionVersion AllExtensionVersions[];
 
 Mask PropagateMask[MAX_DEVICES];
 
@@ -46,6 +65,7 @@ int MPXErrorBase = 0;
 int MPXButtonPress;
 int MPXButtonRelease;
 int MPXMotionNotify;
+int MPXLastEvent;
 
 /*****************************************************************
  *
@@ -53,7 +73,8 @@ int MPXMotionNotify;
  *
  */
 
-static XExtensionVersion thisversion = { MPX_Present,
+static MPXExtensionVersion thisversion = { 
+    MPX_Present,
     MPX_Major,
     MPX_Minor
 };
@@ -106,6 +127,12 @@ ProcMPXDispatch(register ClientPtr client)
     REQUEST(xReq);
     if (stuff->data == MPX_GetExtensionVersion)
         return (ProcMPXGetExtensionVersion(client));
+    if (stuff->data == MPX_ListDevices)
+        return (ProcMPXListDevices(client));
+    if (stuff->data == MPX_SelectEvents)
+        return (ProcMPXSelectEvents(client));
+    if (stuff->data == MPX_GetEventBase)
+        return (ProcMPXGetEventBase(client));
     else {
         SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
     }
@@ -128,6 +155,12 @@ SProcMPXDispatch(register ClientPtr client)
     REQUEST(xReq);
     if (stuff->data == MPX_GetExtensionVersion)
         return (SProcMPXGetExtensionVersion(client));
+    if (stuff->data == MPX_ListDevices)
+        return (SProcMPXListDevices(client));
+    if (stuff->data == MPX_SelectEvents)
+        return (SProcMPXSelectEvents(client));
+    if (stuff->data == MPX_GetEventBase)
+        return (SProcMPXGetEventBase(client));
     else {
         SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
     }
@@ -151,6 +184,8 @@ MPXResetProc(ExtensionEntry* unused)
     EventSwapVector[MPXButtonRelease] = NotImplemented;
     EventSwapVector[MPXMotionNotify] = NotImplemented;
 
+    MPXRestoreExtensionEvents();
+
 }
 
 void SReplyMPXDispatch(ClientPtr client, int len, mpxGetExtensionVersionReply* rep)
@@ -158,6 +193,9 @@ void SReplyMPXDispatch(ClientPtr client, int len, mpxGetExtensionVersionReply* r
     if (rep->RepType ==  MPX_GetExtensionVersion)
         SRepMPXGetExtensionVersion(client, len, 
                 (mpxGetExtensionVersionReply*) rep);
+    if (rep->RepType ==  MPX_ListDevices)
+        SRepMPXListDevices(client, len, 
+                (mpxListDevicesReply*) rep);
     else {
 	FatalError("MPX confused sending swapped reply");
     }
@@ -184,46 +222,16 @@ SEventMPXDispatch(xEvent* from, xEvent* to)
 void 
 MPXFixExtensionEvents(ExtensionEntry* extEntry)
 {
-    Mask mask;
-
     MPXButtonPress = extEntry->eventBase;
     MPXButtonRelease = MPXButtonPress + 1;
     MPXMotionNotify = MPXButtonRelease + 1;
+    MPXLastEvent = MPXMotionNotify + 1;
 
-    mask = MPXGetNextExtEventMask();
-    MPXSetMaskForExtEvent(mask, MPXButtonPress);
-    MPXAllowPropagateSuppress(mask);
-
-    mask = MPXGetNextExtEventMask();
-    MPXSetMaskForExtEvent(mask, MPXButtonRelease);
-    MPXAllowPropagateSuppress(mask);
-
-    mask = MPXGetNextExtEventMask();
-    MPXSetMaskForExtEvent(mask, MPXMotionNotify);
-    MPXAllowPropagateSuppress(mask);
-
+    MPXSetMaskForExtEvent(MPXButtonPressMask, MPXButtonPress);
+    MPXSetMaskForExtEvent(MPXButtonReleaseMask, MPXButtonRelease);
+    MPXSetMaskForExtEvent(MPXPointerMotionMask, MPXMotionNotify);
 }
 
-/**************************************************************************
- *
- * Return the next available extension event mask.
- *
- */
-Mask
-MPXGetNextExtEventMask(void)
-{
-    int i;
-    Mask mask = lastExtEventMask;
-
-    if (lastExtEventMask == 0) {
-	FatalError("MPXGetNextExtEventMask: no more events are available.");
-    }
-    lastExtEventMask <<= 1;
-
-    for (i = 0; i < MAX_DEVICES; i++)
-	ExtValidMasks[i] |= mask;
-    return mask;
-}
 
 /**************************************************************************
  *
@@ -235,8 +243,8 @@ void
 MPXSetMaskForExtEvent(Mask mask, int event)
 {
 
-    EventInfo[ExtEventIndex].mask = mask;
-    EventInfo[ExtEventIndex++].type = event;
+    EventInfo[MPXEventIndex].mask = mask;
+    EventInfo[MPXEventIndex++].type = event;
 
     if ((event < LASTEvent) || (event >= 128))
 	FatalError("MaskForExtensionEvent: bogus event number");
@@ -256,14 +264,14 @@ MPXRestoreExtensionEvents(void)
     int i;
 
     MPXReqCode = 0;
-    for (i = 0; i < ExtEventIndex - 1; i++) {
+    for (i = 0; i < MPXEventIndex - 1; i++) {
 	if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
 	    SetMaskForEvent(0, EventInfo[i].type);
 	EventInfo[i].mask = 0;
 	EventInfo[i].type = 0;
     }
 
-    ExtEventIndex = 0;
+    MPXEventIndex = 0;
     lastExtEventMask = 1;
     MPXButtonPress = 0;
     MPXButtonRelease = 1;
@@ -285,3 +293,4 @@ MPXAllowPropagateSuppress(Mask mask)
     for (i = 0; i < MAX_DEVICES; i++)
 	PropagateMask[i] |= mask;
 }
+
diff --git a/mpx/getevbase.c b/mpx/getevbase.c
new file mode 100644
index 0000000..7ec82f6
--- /dev/null
+++ b/mpx/getevbase.c
@@ -0,0 +1,55 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#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 <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+
+#include "mpxglobals.h"
+#include "getevbase.h"
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the MPXGetEventBase function.
+ */
+int
+ProcMPXGetEventBase(register ClientPtr client)
+{
+    mpxGetEventBaseReply rep;
+
+    REQUEST(mpxGetEventBaseReq);
+    REQUEST_SIZE_MATCH(mpxGetEventBaseReq);
+
+    memset(&rep, 0, sizeof(mpxGetEventBaseReply));
+    rep.repType = X_Reply;
+    rep.RepType = MPX_GetEventBase;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+
+    rep.eventBase = MPXEventBase;
+
+    WriteReplyToClient(client, sizeof(mpxGetEventBaseReply), &rep);
+
+    return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the MPXGetEventBase function.
+ */
+int
+SProcMPXGetEventBase(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(mpxGetEventBaseReq);
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(mpxGetEventBaseReq);
+    return (ProcMPXGetEventBase(client));
+}
+
diff --git a/mpx/getevbase.h b/mpx/getevbase.h
new file mode 100644
index 0000000..5ff8284
--- /dev/null
+++ b/mpx/getevbase.h
@@ -0,0 +1,16 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef GETEVBASE_H
+#define GETEVBASE_H 1
+
+int SProcMPXGetEventBase(ClientPtr	/* client */
+    );
+
+int ProcMPXGetEventBase(ClientPtr	/* client */
+    );
+
+#endif /* GETEVBASE_H */
diff --git a/mpx/getvers.c b/mpx/getvers.c
index 4663c54..7297a1f 100644
--- a/mpx/getvers.c
+++ b/mpx/getvers.c
@@ -13,7 +13,7 @@
 #include "mpxglobals.h"
 #include "getvers.h"
 
-XExtensionVersion AllExtensionVersions[128];
+MPXExtensionVersion AllExtensionVersions[128];
 
 /***********************************************************************
  *
@@ -33,7 +33,6 @@ SProcMPXGetExtensionVersion(register ClientPtr client)
     REQUEST_AT_LEAST_SIZE(mpxGetExtensionVersionReq);
     return (ProcMPXGetExtensionVersion(client));
 }
-
 /***********************************************************************
  *
  * This procedure writes the reply for the XGetExtensionVersion function.
@@ -78,3 +77,5 @@ SRepMPXGetExtensionVersion(ClientPtr client, int size,
     swaps(&rep->minor_version, n);
     WriteToClient(client, size, (char *)rep);
 }
+
+
diff --git a/mpx/listdev.c b/mpx/listdev.c
new file mode 100644
index 0000000..8bb27b3
--- /dev/null
+++ b/mpx/listdev.c
@@ -0,0 +1,187 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "inputstr.h"
+
+#include <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+
+#include "mpxextinit.h"
+#include "mpxglobals.h"
+
+#include "listdev.h"
+
+/***********************************************************************
+ *
+ * This procedure lists the MPX devices available to the server.
+ *
+ */
+int SProcMPXListDevices(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(mpxListDevicesReq);
+    swaps(&stuff->length, n);
+    return (ProcMPXListDevices(client));
+}
+
+/***********************************************************************
+ *
+ * This procedure lists the MPX devices available to the server.
+ *
+ * Strongly based on ProcXListInputDevices
+ */
+int ProcMPXListDevices(register ClientPtr client)
+{
+    mpxListDevicesReply rep;
+    int numdevs = 0;
+    int namesize = 1;	/* need 1 extra byte for strcpy */
+    int size = 0;
+    int total_length; 
+    char* devbuf;
+    char* namebuf;
+    char *savbuf;
+    mpxDeviceInfoPtr dev;
+    DeviceIntPtr d;
+
+    REQUEST_SIZE_MATCH(mpxListDevicesReq);
+    memset(&rep, 0, sizeof(mpxListDevicesReply));
+    rep.repType = X_Reply;
+    rep.RepType = MPX_ListDevices;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+
+    for (d = inputInfo.devices; d; d = d->next) {
+        if (d->isMPDev)
+        {
+            SizeMPXDeviceInfo(d, &namesize, &size);
+            numdevs++;
+        }
+    }
+
+    for (d = inputInfo.off_devices; d; d = d->next) {
+        if (d->isMPDev)
+        {
+            SizeMPXDeviceInfo(d, &namesize, &size);
+            numdevs++;
+        }
+    }
+
+    total_length = numdevs * sizeof(mpxDeviceInfo) + size + namesize;
+    devbuf = (char *)xalloc(total_length);
+    namebuf = devbuf + (numdevs * sizeof(mpxDeviceInfo));
+    savbuf = devbuf;
+
+    dev = (mpxDeviceInfoPtr) devbuf;
+    for (d = inputInfo.devices; d; d = d->next, dev++)
+        if (d->isMPDev)
+            SetMPXDeviceInfo(client, d, dev, &devbuf, &namebuf);
+    for (d = inputInfo.off_devices; d; d = d->next, dev++)
+        if (d->isMPDev)
+            SetMPXDeviceInfo(client, d, dev, &devbuf, &namebuf);
+
+    rep.ndevices = numdevs;
+    rep.length = (total_length + 3) >> 2;
+    WriteReplyToClient(client, sizeof(mpxListDevicesReply), &rep);
+    WriteToClient(client, total_length, savbuf);
+    xfree(savbuf);
+    return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure calculates the size of the information to be returned
+ * for an input device.
+ *
+ */
+
+void
+SizeMPXDeviceInfo(DeviceIntPtr d, int *namesize, int *size)
+{
+    *namesize += 1;
+    if (d->name)
+	*namesize += strlen(d->name);
+}
+
+/***********************************************************************
+ *
+ * This procedure sets information to be returned for an input device.
+ *
+ */
+
+void
+SetMPXDeviceInfo(ClientPtr client, DeviceIntPtr d, mpxDeviceInfoPtr dev,
+	       char **devbuf, char **namebuf)
+{
+    MPXCopyDeviceName(namebuf, d->name);
+    MPXCopySwapDevice(client, d, devbuf);
+}
+
+
+/***********************************************************************
+ *
+ * This procedure copies data to the DeviceInfo struct, swapping if necessary.
+ *
+ * We need the extra byte in the allocated buffer, because the trailing null
+ * hammers one extra byte, which is overwritten by the next name except for
+ * the last name copied.
+ *
+ */
+
+void
+MPXCopyDeviceName(char **namebuf, char *name)
+{
+    char *nameptr = (char *)*namebuf;
+
+    if (name) {
+	*nameptr++ = strlen(name);
+	strcpy(nameptr, name);
+	*namebuf += (strlen(name) + 1);
+    } else {
+	*nameptr++ = 0;
+	*namebuf += 1;
+    }
+}
+
+/***********************************************************************
+ *
+ * This procedure copies data to the DeviceInfo struct, swapping if necessary.
+ *
+ */
+void
+MPXCopySwapDevice(register ClientPtr client, DeviceIntPtr d, char **buf)
+{
+    register char n;
+    mpxDeviceInfoPtr dev;
+
+    dev = (mpxDeviceInfoPtr) * buf;
+    memset(dev, 0, sizeof(mpxDeviceInfo));
+
+    dev->id = d->id;
+    dev->type = d->type;
+    if (client->swapped) {
+	swapl(&dev->type, n);	/* macro - braces are required */
+    }
+    *buf += sizeof(mpxDeviceInfo);
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the MPXListDevices function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+void
+SRepMPXListDevices(ClientPtr client, int size, mpxListDevicesReply * rep)
+{
+    register char n;
+
+    swaps(&rep->sequenceNumber, n);
+    swapl(&rep->length, n);
+    WriteToClient(client, size, (char *)rep);
+}
diff --git a/mpx/listdev.h b/mpx/listdev.h
new file mode 100644
index 0000000..0d2e0dc
--- /dev/null
+++ b/mpx/listdev.h
@@ -0,0 +1,53 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef LISTDEV_H
+#define LISTDEV_H 1
+
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "inputstr.h"
+
+#include <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+
+#include "mpxextinit.h"
+#include "mpxglobals.h"
+
+int SProcMPXListDevices(ClientPtr	/* client */
+    );
+
+int ProcMPXListDevices(ClientPtr	/* client */
+    );
+
+void SizeMPXDeviceInfo(DeviceIntPtr /* d */ ,
+		    int * /* namesize */ ,
+		    int *	/* size */
+    );
+
+void SetMPXDeviceInfo(ClientPtr /* client */ ,
+		    DeviceIntPtr /* d */ ,
+		    mpxDeviceInfoPtr /* dev */ ,
+		    char ** /* devbuf */ ,
+		    char **	/* namebuf */
+    );
+
+
+void MPXCopyDeviceName(char ** /* namebuf */ ,
+		    char *	/* name */
+    );
+
+void MPXCopySwapDevice(ClientPtr /* client */ ,
+		    DeviceIntPtr /* d */ ,
+		    char **	/* buf */
+    );
+
+void SRepMPXListDevices(ClientPtr /* client */ ,
+			   int /* size */ ,
+			   mpxListDevicesReply *	/* rep */
+    );
+#endif
diff --git a/mpx/mpxglobals.h b/mpx/mpxglobals.h
index d74710c..73f3990 100644
--- a/mpx/mpxglobals.h
+++ b/mpx/mpxglobals.h
@@ -4,12 +4,26 @@
 #include <dix-config.h>
 #endif
 
+#ifndef MPXGLOBALS_H
+#define MPXGLOBALS_H 1
+
 extern int MPXReqCode;
 extern int MPXEventBase;
 extern int MPXErrorBase;
 
+extern Mask PropagateMask[];
+
+extern int MPXmskidx;
+
+/* events */
 extern int MPXButtonPress;
 extern int MPXButtonRelease;
 extern int MPXMotionNotify;
+extern int MPXLastEvent;
 
-extern Mask PropagateMask[];
+#define IsMPXEvent(xE) \
+    ((xE)->u.u.type >= MPXEventBase \
+     && (xE)->u.u.type < MPXLastEvent) 
+
+
+#endif
diff --git a/mpx/selectev.c b/mpx/selectev.c
index d29d3f1..1e75a51 100644
--- a/mpx/selectev.c
+++ b/mpx/selectev.c
@@ -12,5 +12,135 @@
 #include <X11/extensions/MPX.h>
 #include <X11/extensions/MPXproto.h>
 #include "extnsionst.h"
-#include "extinit.h"	/* LookupDeviceIntRec */
+#include "mpxextinit.h"	/* LookupDeviceIntRec */
+#include "mpxglobals.h"
+#include "mpxevents.h"
+
+#include "selectev.h"
+
+/* functions borrowed from XI */
+extern void RecalculateDeviceDeliverableEvents(
+	WindowPtr              /* pWin */);
+
+extern int AddExtensionClient (
+	WindowPtr              /* pWin */,
+	ClientPtr              /* client */,
+	Mask                   /* mask */,
+	int                    /* mskidx */);
+extern Bool
+ShouldFreeInputMasks(WindowPtr /* pWin */, 
+                     Bool /* ignoreSelectedEvents */);
+
+/***********************************************************************
+ *
+ * Handle requests from clients with a different byte order.
+ *
+ */
+
+int
+SProcMPXSelectEvents(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(mpxSelectEventsReq);
+    swaps(&stuff->length, n);
+    REQUEST_SIZE_MATCH(mpxSelectEventsReq);
+    swapl(&stuff->window, n);
+    return (ProcMPXSelectEvents(client));
+}
+
+/***********************************************************************
+ *
+ * This procedure selects input from an extension device.
+ *
+ */
+
+int
+ProcMPXSelectEvents(register ClientPtr client)
+{
+    int ret;
+    WindowPtr pWin;
+
+    REQUEST(mpxSelectEventsReq);
+    REQUEST_SIZE_MATCH(mpxSelectEventsReq);
+
+    if (stuff->length != (sizeof(mpxSelectEventsReq) >> 2))
+    { 
+        SendErrorToClient(client, MPXReqCode, MPX_SelectEvents, 0,
+			  BadLength);
+	return Success;
+    }
+
+    pWin = (WindowPtr) LookupWindow(stuff->window, client);
+    if (!pWin) 
+    {
+	client->errorValue = stuff->window;
+	SendErrorToClient(client, MPXReqCode, MPX_SelectEvents, 0,
+			  BadWindow);
+	return Success;
+    }
+
+    if (stuff->mask >= MPXHighestMask)
+    {
+        client->errorValue = stuff->mask;
+	SendErrorToClient(client, MPXReqCode, MPX_SelectEvents, 0,
+			  BadValue);
+    }
+
+    if ((ret = MPXSelectForWindow(pWin, client, stuff->mask)) != Success) 
+    { 
+        SendErrorToClient(client, MPXReqCode, MPX_SelectEvents, 0, ret);
+        return Success;
+    }
+
+    return Success;
+}
+
+/**
+ * Selects a set of events for a given window. 
+ * Different to XI, MPX is not device dependent. Either the client gets events
+ * from all devices or none.
+ *
+ * This method borrows some functions from XI, due to the piggyback on the
+ * core pointer (see comment in extinit.c)
+ */
+int 
+MPXSelectForWindow(WindowPtr pWin, ClientPtr client, int mask)
+{
+    InputClientsPtr others;
+    int ret;
+
+    if (mask >= MPXHighestMask)
+    {
+        client->errorValue = mask;
+        return BadValue;
+    }
+
+    if (wOtherInputMasks(pWin))
+    {
+        for (others = wOtherInputMasks(pWin)->inputClients; others; 
+                others = others->next)
+        {
+            if (SameClient(others, client)) {
+                others->mask[MPXmskidx] = mask;
+                if (mask == 0)
+                {
+                    /* clean up stuff */
+                    RecalculateDeviceDeliverableEvents(pWin);
+                    if (ShouldFreeInputMasks(pWin, FALSE))
+                        FreeResource(others->resource, RT_NONE);
+                    return Success;
+                }
+                goto maskSet;
+            }
+        }
+    }
+    /* borrow from XI here */
+    if ((ret = AddExtensionClient(pWin, client, mask, MPXmskidx)) != Success)
+        return ret;
+maskSet:
+    RecalculateDeviceDeliverableEvents(pWin);
+    return Success;
+
+}
 
diff --git a/mpx/selectev.h b/mpx/selectev.h
new file mode 100644
index 0000000..7026199
--- /dev/null
+++ b/mpx/selectev.h
@@ -0,0 +1,17 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef SELECTEV_H
+#define SELECTEV_H 1
+
+int SProcMPXSelectEvents(ClientPtr	/* client */
+    );
+
+int ProcMPXSelectEvents(ClientPtr	/* client */
+    );
+
+#endif /* SELECTEV_H */
commit afd6af65510b0147f16f08314045b3506bfa9d89
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 29 17:55:15 2006 +1030

    mpx:    Infrastructure for MPX extension, GetExtensionVersion request works.

diff --git a/Changelog b/Changelog
index 7d0d80c..c818bce 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,21 @@
 MPX Changelog file
+== 29.11.206 ==
+mpx:    Infrastructure for MPX extension, GetExtensionVersion request works.
+
+Files:
+	mpx/
+	mpx/Makefile.am
+	mpx/extinit.c
+	mpx/getvers.c
+	mpx/getvers.h
+	mpxglobals.h
+	mpx/selectev.c
+	configure.ac
+	Makefile.am
+	os/utils.c
+	mi/miinitext.c
+	include/globals.h
+
 == 28.11.06 ==
 mi:     Bugfix: FreeCursor ignores negative refcounts.
 
diff --git a/Makefile.am b/Makefile.am
index f35539e..572d088 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,6 +42,7 @@ SUBDIRS = \
 	randr \
 	render  \
 	Xi \
+        mpx \
 	xkb \
 	$(DBE_DIR) \
 	$(MFB_DIR) \
@@ -78,6 +79,7 @@ DIST_SUBDIRS = \
 	randr \
 	render  \
 	Xi \
+        mpx \
 	xkb \
 	dbe \
 	mfb \
diff --git a/configure.ac b/configure.ac
index 706df91..e5d2f5e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -791,6 +791,8 @@ AM_CONDITIONAL(MPX, [test "x$MPX" = xyes])
 
 if test "x$MPX" = xyes; then
     AC_DEFINE(MPX, 1, [Support MPX multipointer extension])
+    MPX_LIB='$(top_builddir)/mpx/libmpx.la'
+    MPX_INC='-I$(top_srcdir)/mpx'
 fi
 AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes)
 
@@ -1026,7 +1028,7 @@ if test "x$DMX" = xyes; then
 		              modules not found.])
 	fi
 	DMX_INCLUDES="$XEXT_INC $RENDER_INC $XTRAP_INC $RECORD_INC"
-	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $XTRAP_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB $CWRAP_LIB"
+	XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $XTRAP_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $OS_LIB $CWRAP_LIB $MPX_LIB"
 	AC_SUBST([XDMX_LIBS])
 
 dnl USB sources in DMX require <linux/input.h>
@@ -1065,7 +1067,7 @@ AC_MSG_RESULT([$XVFB])
 AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
 
 if test "x$XVFB" = xyes; then
-	XVFB_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS"
+	XVFB_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS $MPX_LIB"
 	AC_SUBST([XVFB_LIBS])
 fi
 
@@ -1081,7 +1083,7 @@ AC_MSG_RESULT([$XNEST])
 AM_CONDITIONAL(XNEST, [test "x$XNEST" = xyes])
 
 if test "x$XNEST" = xyes; then
-	XNEST_LIBS="$XSERVER_LIBS $FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS"
+	XNEST_LIBS="$XSERVER_LIBS $FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS $MPX_LIB"
 	AC_SUBST([XNEST_LIBS])
 fi
 
@@ -1110,7 +1112,7 @@ AC_MSG_RESULT([$XGL])
 AM_CONDITIONAL(XGL, [test "x$XGL" = xyes])
 
 if test "x$XGL" = xyes; then
-	XGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
+	XGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
 	AC_SUBST([XGL_LIBS])
 	AC_DEFINE(XGL_MODULAR, 1, [Use loadable XGL modules])
 
@@ -1131,7 +1133,7 @@ AC_MSG_RESULT([$XEGL])
 AM_CONDITIONAL(XEGL, [test "x$XEGL" = xyes])
 
 if test "x$XEGL" = xyes; then
-	XEGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
+	XEGL_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
 	AC_SUBST([XEGL_LIBS])
 fi
 
@@ -1147,7 +1149,7 @@ AC_MSG_RESULT([$XGLX])
 AM_CONDITIONAL(XGLX, [test "x$XGLX" = xyes])
 
 if test "x$XGLX" = xyes; then
-	XGLX_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB"
+	XGLX_LIBS="$FB_LIB $MI_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $MIEXT_LAYER_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $MPX_LIB"
 	AC_SUBST([XGLX_LIBS])
 fi
 
@@ -1168,7 +1170,7 @@ if test "x$XORG" = xyes -o "x$XGL" = xyes; then
 	XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
 	XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
 	XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
-	XORG_LIBS="$COMPOSITE_LIB $MI_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XPSTUBS_LIB $OS_LIB"
+	XORG_LIBS="$COMPOSITE_LIB $MI_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XPSTUBS_LIB $OS_LIB $MPX_LIB"
 
 	if test "x$DGA" = xauto; then
 		PKG_CHECK_MODULES(DGA, xf86dgaproto, [DGA=yes], [DGA=no])
@@ -1633,7 +1635,7 @@ if test "$KDRIVE" = yes; then
     # dix os fb mi extension glx (NOTYET) damage shadow xpstubs
     #KDRIVE_PURE_LIBS="$DIX_LIB $OS_LIB $FB_LIB $XEXT_LIB $MIEXT_DAMAGE_LIB \
     #    $MIEXT_SHADOW_LIB $XPSTUBS_LIB"
-    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $OS_LIB"
+    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $OS_LIB $MPX_LIB"
     KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.a'
     case $host_os in
 	*linux*)
@@ -1826,6 +1828,7 @@ render/Makefile
 xkb/Makefile
 Xext/Makefile
 Xi/Makefile
+mpx/Makefile
 xfixes/Makefile
 exa/Makefile
 hw/Makefile
diff --git a/include/globals.h b/include/globals.h
index 821b12b..ef22561 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -63,6 +63,10 @@ extern Bool noCompositeExtension;
 extern Bool noDamageExtension;
 #endif
 
+#ifdef MPX
+extern Bool noMPXExtension;
+#endif
+
 #ifdef DBE
 extern Bool noDbeExtension;
 #endif
diff --git a/mi/miinitext.c b/mi/miinitext.c
index cb34473..3d9522d 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -384,6 +384,9 @@ extern void DamageExtensionInit(INITARGS);
 #ifdef COMPOSITE
 extern void CompositeExtensionInit(INITARGS);
 #endif
+#ifdef MPX
+extern void MPXExtensionInit(INITARGS);
+#endif
 
 /* The following is only a small first step towards run-time
  * configurable extensions.
@@ -663,6 +666,9 @@ InitExtensions(argc, argv)
 #ifdef DAMAGE
     if (!noDamageExtension) DamageExtensionInit();
 #endif
+#ifdef MPX
+    if (!noMPXExtension) MPXExtensionInit();
+#endif
 }
 
 void
@@ -733,6 +739,9 @@ static ExtensionModule staticExtensions[] = {
 #ifdef XEVIE
     { XevieExtensionInit, "XEVIE", &noXevieExtension, NULL },
 #endif 
+#ifdef MPX
+    { MPXExtensionInit, "MPX", &noMPXExtension, NULL },
+#endif
     { NULL, NULL, NULL, NULL, NULL }
 };
     
diff --git a/mpx/Makefile.am b/mpx/Makefile.am
new file mode 100644
index 0000000..db75eb5
--- /dev/null
+++ b/mpx/Makefile.am
@@ -0,0 +1,9 @@
+noinst_LTLIBRARIES = libmpx.la
+
+AM_CFLAGS = $(DIX_CFLAGS)
+
+libmpx_la_SOURCES =	\
+	extinit.c \
+        getvers.c \
+	getvers.h
+
diff --git a/mpx/extinit.c b/mpx/extinit.c
new file mode 100644
index 0000000..59bc494
--- /dev/null
+++ b/mpx/extinit.c
@@ -0,0 +1,287 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "inputstr.h"
+//#include "gcstruct.h"	/* pointer for extnsionst.h */
+#include "extnsionst.h"	/* extension entry   */
+#include <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+
+#include "mpxextinit.h"
+#include "swaprep.h"
+
+#include "getvers.h"
+
+static Mask lastExtEventMask = 1;
+int ExtEventIndex;
+Mask ExtValidMasks[EMASKSIZE];
+
+XExtEventInfo EventInfo[32];
+
+/*****************************************************************
+ *
+ * Externs defined elsewhere in the X server.
+ *
+ */
+
+extern XExtensionVersion AllExtensionVersions[];
+
+Mask PropagateMask[MAX_DEVICES];
+
+/*****************************************************************
+ *
+ * Globals referenced elsewhere in the server.
+ *
+ */
+
+int MPXReqCode = 0;
+int MPXEventBase = 0;
+int MPXErrorBase = 0;
+
+int MPXButtonPress;
+int MPXButtonRelease;
+int MPXMotionNotify;
+
+/*****************************************************************
+ *
+ * Declarations of local routines.
+ *
+ */
+
+static XExtensionVersion thisversion = { MPX_Present,
+    MPX_Major,
+    MPX_Minor
+};
+
+/**********************************************************************
+ *
+ * MPXExtensionInit - initialize the input extension.
+ *
+ * Called from InitExtensions in main() or from QueryExtension() if the
+ * extension is dynamically loaded.
+ *
+ * This extension has several events and errors.
+ *
+ */
+
+void
+MPXExtensionInit(void)
+{
+    ExtensionEntry *extEntry;
+
+    extEntry = AddExtension(MPXNAME, MPXEVENTS, MPXERRORS, 
+                            ProcMPXDispatch, SProcMPXDispatch, 
+                            MPXResetProc, StandardMinorOpcode);
+    if (extEntry) {
+	MPXReqCode = extEntry->base;
+        MPXEventBase = extEntry->eventBase;
+        MPXErrorBase = extEntry->errorBase;
+
+	AllExtensionVersions[MPXReqCode - 128] = thisversion;
+	MPXFixExtensionEvents(extEntry);
+	ReplySwapVector[MPXReqCode] = (ReplySwapPtr) SReplyMPXDispatch;
+	EventSwapVector[MPXButtonPress] = SEventMPXDispatch;
+	EventSwapVector[MPXButtonRelease] = SEventMPXDispatch;
+	EventSwapVector[MPXMotionNotify] = SEventMPXDispatch;
+    } else {
+	FatalError("MPXExtensionInit: AddExtensions failed\n");
+    }
+}
+
+/*************************************************************************
+ *
+ * ProcMPXDispatch - main dispatch routine for requests to this extension.
+ * This routine is used if server and client have the same byte ordering.
+ *
+ */
+
+int 
+ProcMPXDispatch(register ClientPtr client)
+{
+    REQUEST(xReq);
+    if (stuff->data == MPX_GetExtensionVersion)
+        return (ProcMPXGetExtensionVersion(client));
+    else {
+        SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
+    }
+
+    return (BadRequest);
+}
+
+/*******************************************************************************
+ *
+ * SProcMPXDispatch 
+ *
+ * Main swapped dispatch routine for requests to this extension.
+ * This routine is used if server and client do not have the same byte ordering.
+ *
+ */
+
+int 
+SProcMPXDispatch(register ClientPtr client)
+{
+    REQUEST(xReq);
+    if (stuff->data == MPX_GetExtensionVersion)
+        return (SProcMPXGetExtensionVersion(client));
+    else {
+        SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest);
+    }
+
+    return (BadRequest);
+}
+
+/***********************************************************************
+ *
+ * MPXResetProc.
+ * Remove reply-swapping routine.
+ * Remove event-swapping routine.
+ *
+ */
+
+void
+MPXResetProc(ExtensionEntry* unused)
+{
+    ReplySwapVector[MPXReqCode] = ReplyNotSwappd;
+    EventSwapVector[MPXButtonPress] = NotImplemented;
+    EventSwapVector[MPXButtonRelease] = NotImplemented;
+    EventSwapVector[MPXMotionNotify] = NotImplemented;
+
+}
+
+void SReplyMPXDispatch(ClientPtr client, int len, mpxGetExtensionVersionReply* rep)
+{
+    if (rep->RepType ==  MPX_GetExtensionVersion)
+        SRepMPXGetExtensionVersion(client, len, 
+                (mpxGetExtensionVersionReply*) rep);
+    else {
+	FatalError("MPX confused sending swapped reply");
+    }
+}
+
+void 
+SEventMPXDispatch(xEvent* from, xEvent* to)
+{
+    int type = from->u.u.type & 0177;
+    if (type == MPXButtonPress) {
+	SKeyButtonPtrEvent(from, to);
+	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+    } else if (type == MPXButtonRelease) {
+	SKeyButtonPtrEvent(from, to);
+	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+    } else if (type == MPXMotionNotify) {
+	SKeyButtonPtrEvent(from, to);
+	to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+    } else {
+	FatalError("XInputExtension: Impossible event!\n");
+    }
+}
+
+void 
+MPXFixExtensionEvents(ExtensionEntry* extEntry)
+{
+    Mask mask;
+
+    MPXButtonPress = extEntry->eventBase;
+    MPXButtonRelease = MPXButtonPress + 1;
+    MPXMotionNotify = MPXButtonRelease + 1;
+
+    mask = MPXGetNextExtEventMask();
+    MPXSetMaskForExtEvent(mask, MPXButtonPress);
+    MPXAllowPropagateSuppress(mask);
+
+    mask = MPXGetNextExtEventMask();
+    MPXSetMaskForExtEvent(mask, MPXButtonRelease);
+    MPXAllowPropagateSuppress(mask);
+
+    mask = MPXGetNextExtEventMask();
+    MPXSetMaskForExtEvent(mask, MPXMotionNotify);
+    MPXAllowPropagateSuppress(mask);
+
+}
+
+/**************************************************************************
+ *
+ * Return the next available extension event mask.
+ *
+ */
+Mask
+MPXGetNextExtEventMask(void)
+{
+    int i;
+    Mask mask = lastExtEventMask;
+
+    if (lastExtEventMask == 0) {
+	FatalError("MPXGetNextExtEventMask: no more events are available.");
+    }
+    lastExtEventMask <<= 1;
+
+    for (i = 0; i < MAX_DEVICES; i++)
+	ExtValidMasks[i] |= mask;
+    return mask;
+}
+
+/**************************************************************************
+ *
+ * Assign the specified mask to the specified event.
+ *
+ */
+
+void
+MPXSetMaskForExtEvent(Mask mask, int event)
+{
+
+    EventInfo[ExtEventIndex].mask = mask;
+    EventInfo[ExtEventIndex++].type = event;
+
+    if ((event < LASTEvent) || (event >= 128))
+	FatalError("MaskForExtensionEvent: bogus event number");
+    SetMaskForEvent(mask, event);
+}
+
+/************************************************************************
+ *
+ * This function restores extension event types and masks to their 
+ * initial state.
+ *
+ */
+
+void
+MPXRestoreExtensionEvents(void)
+{
+    int i;
+
+    MPXReqCode = 0;
+    for (i = 0; i < ExtEventIndex - 1; i++) {
+	if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
+	    SetMaskForEvent(0, EventInfo[i].type);
+	EventInfo[i].mask = 0;
+	EventInfo[i].type = 0;
+    }
+
+    ExtEventIndex = 0;
+    lastExtEventMask = 1;
+    MPXButtonPress = 0;
+    MPXButtonRelease = 1;
+    MPXMotionNotify = 2;
+}
+
+/**************************************************************************
+ *
+ * Allow the specified event to have its propagation suppressed.
+ * The default is to not allow suppression of propagation.
+ *
+ */
+
+void
+MPXAllowPropagateSuppress(Mask mask)
+{
+    int i;
+
+    for (i = 0; i < MAX_DEVICES; i++)
+	PropagateMask[i] |= mask;
+}
diff --git a/mpx/getvers.c b/mpx/getvers.c
new file mode 100644
index 0000000..4663c54
--- /dev/null
+++ b/mpx/getvers.c
@@ -0,0 +1,80 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#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 <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+
+#include "mpxglobals.h"
+#include "getvers.h"
+
+XExtensionVersion AllExtensionVersions[128];
+
+/***********************************************************************
+ *
+ * Handle a request from a client with a different byte order than us.
+ *
+ */
+
+int
+SProcMPXGetExtensionVersion(register ClientPtr client)
+{
+    register char n;
+
+    REQUEST(mpxGetExtensionVersionReq);
+    swaps(&stuff->length, n);
+    swaps(&stuff->major_version, n);
+    swaps(&stuff->minor_version, n);
+    REQUEST_AT_LEAST_SIZE(mpxGetExtensionVersionReq);
+    return (ProcMPXGetExtensionVersion(client));
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the XGetExtensionVersion function.
+ */
+
+int
+ProcMPXGetExtensionVersion(register ClientPtr client)
+{
+    mpxGetExtensionVersionReply rep;
+
+    REQUEST(mpxGetExtensionVersionReq);
+    REQUEST_SIZE_MATCH(mpxGetExtensionVersionReq);
+
+    rep.repType = X_Reply;
+    rep.RepType = MPX_GetExtensionVersion;
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+
+    rep.major_version = AllExtensionVersions[MPXReqCode - 128].major_version;
+    rep.minor_version = AllExtensionVersions[MPXReqCode - 128].minor_version;
+    WriteReplyToClient(client, sizeof(mpxGetExtensionVersionReply), &rep);
+
+    return Success;
+}
+
+/***********************************************************************
+ *
+ * This procedure writes the reply for the MPXGetExtensionVersion function,
+ * if the client and server have a different byte ordering.
+ *
+ */
+
+void
+SRepMPXGetExtensionVersion(ClientPtr client, int size,
+			 mpxGetExtensionVersionReply * rep)
+{
+    register char n;
+
+    swaps(&rep->sequenceNumber, n);
+    swapl(&rep->length, n);
+    swaps(&rep->major_version, n);
+    swaps(&rep->minor_version, n);
+    WriteToClient(client, size, (char *)rep);
+}
diff --git a/mpx/getvers.h b/mpx/getvers.h
new file mode 100644
index 0000000..da24018
--- /dev/null
+++ b/mpx/getvers.h
@@ -0,0 +1,22 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef GETVERS_H
+#define GETVERS_H 1
+
+int SProcMPXGetExtensionVersion(ClientPtr	/* client */
+    );
+
+int ProcMPXGetExtensionVersion(ClientPtr	/* client */
+    );
+
+void SRepMPXGetExtensionVersion(ClientPtr /* client */ ,
+			      int /* size */ ,
+			      mpxGetExtensionVersionReply *	/* rep */
+    );
+
+#endif
+
diff --git a/mpx/mpxglobals.h b/mpx/mpxglobals.h
new file mode 100644
index 0000000..d74710c
--- /dev/null
+++ b/mpx/mpxglobals.h
@@ -0,0 +1,15 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+extern int MPXReqCode;
+extern int MPXEventBase;
+extern int MPXErrorBase;
+
+extern int MPXButtonPress;
+extern int MPXButtonRelease;
+extern int MPXMotionNotify;
+
+extern Mask PropagateMask[];
diff --git a/mpx/selectev.c b/mpx/selectev.c
new file mode 100644
index 0000000..d29d3f1
--- /dev/null
+++ b/mpx/selectev.c
@@ -0,0 +1,16 @@
+/* Copyright 2006 by Peter Hutterer <peter at cs.unisa.edu.au> */
+
+
+#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 <X11/extensions/MPX.h>
+#include <X11/extensions/MPXproto.h>
+#include "extnsionst.h"
+#include "extinit.h"	/* LookupDeviceIntRec */
+
diff --git a/os/utils.c b/os/utils.c
index 9824501..42d41ce 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -252,6 +252,9 @@ _X_EXPORT Bool noXIdleExtension = FALSE;
 #ifdef XV
 _X_EXPORT Bool noXvExtension = FALSE;
 #endif
+#ifdef MPX
+_X_EXPORT Bool noMPXExtension = FALSE;
+#endif
 
 #define X_INCLUDE_NETDB_H
 #include <X11/Xos_r.h>
commit bdf718907b3202815a04ec28a868689708f43da9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 28 18:06:34 2006 +1030

    dix:	missing parameter to SetCursorPosition in CheckMotion ifndef MPX
    
    mi:	missing include in misprite.c ifndef MPX

diff --git a/Changelog b/Changelog
index a9989eb..7d0d80c 100644
--- a/Changelog
+++ b/Changelog
@@ -8,6 +8,17 @@ Files:
 	dix/cursor.c
 	mi/mieq.c
 
+____________________________________________________________
+
+dix:	missing parameter to SetCursorPosition in CheckMotion ifndef MPX
+
+mi:	missing include in misprite.c ifndef MPX
+
+Files:
+	dix/events.c
+	mi/misprite.c
+
+
 == 27.11.06 ==
 mi:     free allocated memory in miDCCloseScreen and in miDCInitialize in case
 	of errors.
diff --git a/dix/events.c b/dix/events.c
index 27f42e1..8ef318a 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2136,7 +2136,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
 	{
 	    (*pSprite->hotPhys.pScreen->SetCursorPosition)(
-		pSprite->hotPhys.pScreen,
+                pDev, pSprite->hotPhys.pScreen,
 		pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
 	}
 #endif
diff --git a/mi/misprite.c b/mi/misprite.c
index ec90ad2..e55032b 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -56,15 +56,13 @@ in this Software without prior written authorization from The Open Group.
 # include   "mispritest.h"
 # include   "dixfontstr.h"
 # include   <X11/fonts/fontstruct.h>
+# include   "inputstr.h" 
 
 #ifdef RENDER
 # include   "mipict.h"
 #endif
 # include   "damage.h"
 
-#ifdef MPX
-# include   "inputstr.h" 
-#endif
 
 
 #define SPRITE_DEBUG_ENABLE 0
commit e88bc0e55a6937ff0b47fe38f60bfa8991196578
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 28 14:34:36 2006 +1030

    mi:     Bugfix: FreeCursor ignores negative refcounts.
    
    mieq:   Bugfix: Motion notifies did overwrite DeviceMotionNotifies

diff --git a/Changelog b/Changelog
index 5482251..a9989eb 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,13 @@
 MPX Changelog file
+== 28.11.06 ==
+mi:     Bugfix: FreeCursor ignores negative refcounts.
+
+mieq:   Bugfix: Motion notifies did overwrite DeviceMotionNotifies
+
+Files:
+	dix/cursor.c
+	mi/mieq.c
+
 == 27.11.06 ==
 mi:     free allocated memory in miDCCloseScreen and in miDCInitialize in case
 	of errors.
diff --git a/dix/cursor.c b/dix/cursor.c
index 92297b9..6da763b 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -117,7 +117,10 @@ FreeCursor(pointer value, XID cid)
     ScreenPtr	pscr;
     DeviceIntPtr pDev; 
 
-    if ( --pCurs->refcnt > 0)
+    /* FIXME: MPX: When FreeClientRessources is called, it calls FreeCursor
+     * too often. Refcnt gots < 0 and FreeCursorBits segfaults because the
+     * memory is already freed. */
+    if ( --pCurs->refcnt != 0)
 	return(Success);
 
     pDev = inputInfo.pointer;
diff --git a/mi/mieq.c b/mi/mieq.c
index 40a3a52..b40944e 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -119,7 +119,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
     if (e->u.u.type == MotionNotify)
         isMotion = inputInfo.pointer->id;
     else if (e->u.u.type == DeviceMotionNotify)
-        isMotion = pDev->id;
+        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. */
commit 85ea408e38f452bcf9109f14fd1016d159692a99
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 27 18:07:16 2006 +1030

    mi:     malloc checks for misprite and midispcur, code cleanup
    	removed IsMPDev()

diff --git a/Changelog b/Changelog
index b73e93a..5482251 100644
--- a/Changelog
+++ b/Changelog
@@ -14,12 +14,24 @@ Files:
 
 ____________________________________________________________
 
-mi:     mipointer.c cleanup, reducing code duplication, using MPHasCursor()
-	instead of IsMPDev()
+mi:     mipointer.c cleanup, reducing code duplication, using MPHasCursor(),
+	removing IsMPDev()
 
 Files:
 	mi/mipointer.c
 
+____________________________________________________________
+
+mi:     malloc checks for misprite and midispcur, code cleanup
+	removed IsMPDev()
+
+Files:
+	mi/misprite.c
+	mi/mipointer.c
+	mi/midispcur.c
+	dix/events.c
+
+
 == 23.11.06 ==
 mi:	closing memory leak, miPointer is freed in miPointerCloseScreen
 	bugfix: uninitialized pPointer in miPointerGetPosition ifndef MPX
diff --git a/dix/events.c b/dix/events.c
index d3b0e58..27f42e1 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -259,9 +259,9 @@ typedef struct {
 static SpritePtr sprite;		/* info about the cursor sprite */
 
 #ifdef MPX
-static SpritePtr mpsprites;             /* info about the MPX sprites */
+#define MPXDBG(...) fprintf (stderr, "MPX: " __VA_ARGS__)
 
-extern BOOL IsMPDev(DeviceIntPtr dev);
+static SpritePtr mpsprites;             /* info about the MPX sprites */
 
 /** 
  * True for the core pointer and any MPX device. 
@@ -371,7 +371,7 @@ XineramaSetCursorPosition(
     SpritePtr pSprite = sprite;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -416,7 +416,7 @@ XineramaConstrainCursor(DeviceIntPtr pDev)
     BoxRec newBox;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -445,7 +445,7 @@ XineramaCheckPhysLimits(
     if (!cursor)
 	return;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
  
@@ -583,7 +583,7 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
     SpritePtr pSprite = sprite;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -704,7 +704,7 @@ XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
     SpritePtr pSprite = sprite;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -748,7 +748,7 @@ ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
     int incx = 1, incy = 1;
     SpritePtr pSprite = sprite;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -794,7 +794,7 @@ CheckPhysLimits(
     SpritePtr pSprite = sprite;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -924,7 +924,7 @@ PointerConfinedToScreen(DeviceIntPtr pDev)
 {
     SpritePtr pSprite = sprite;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
     return pSprite->confined;
@@ -936,7 +936,7 @@ ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
     SpritePtr pSprite = sprite;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -979,7 +979,7 @@ PostNewCursor(DeviceIntPtr pDev)
     SpritePtr   pSprite = sprite;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -1018,7 +1018,7 @@ _X_EXPORT WindowPtr
 GetSpriteWindow(DeviceIntPtr pDev)
 {
 #ifdef MPX
-    if(IsMPDev(pDev))
+    if(MPHasCursor(pDev))
         return mpsprites[pDev->id].win;
 #endif
 
@@ -1036,7 +1036,7 @@ GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
 {
     SpritePtr pSprite = sprite;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
     *px = pSprite->hotPhys.x;
@@ -1860,7 +1860,7 @@ FixUpEventFromWindow(
 {
     SpritePtr pSprite = sprite;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -2094,7 +2094,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
     SpritePtr pSprite = sprite;
         
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
         
@@ -2131,7 +2131,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
         xeviehot.y = pSprite->hot.y;
 #endif
 	pSprite->hotPhys = pSprite->hot;
-#ifndef MPX /* XXX ndef!! */
+#if !defined MPX
 	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
 	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
 	{
@@ -2177,7 +2177,7 @@ WindowsRestructured()
     DeviceIntPtr pDev = inputInfo.devices;
     while(pDev)
     {
-        if (pDev != inputInfo.keyboard)
+        if (MPHasCursor(pDev))
             CheckMotion((xEvent *)NULL, pDev);
         pDev = pDev->next;
     }
@@ -2318,7 +2318,7 @@ NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
 {
     SpritePtr pSprite = sprite;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pSprite = &mpsprites[pDev->id];
 #endif
 
@@ -3051,7 +3051,7 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
     SpritePtr           pSprite = sprite;
 
 #ifdef MPX
-    if (IsMPDev(mouse))
+    if (MPHasCursor(mouse))
         pSprite = &mpsprites[mouse->id];
 #endif
 
diff --git a/mi/midispcur.c b/mi/midispcur.c
index 514fae8..0b4ef49 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -139,6 +139,7 @@ miDCInitialize (pScreen, screenFuncs)
     miPointerScreenFuncPtr  screenFuncs;
 {
     miDCScreenPtr   pScreenPriv;
+    miDCBufferPtr   pBuffer;
 
     if (miDCGeneration != serverGeneration)
     {
@@ -154,36 +155,33 @@ miDCInitialize (pScreen, screenFuncs)
     /*
      * initialize the entire private structure to zeros
      */
+#if !defined MPX
     pScreenPriv->pCoreBuffer = (miDCBufferPtr)xalloc(sizeof(miDCBufferRec));
-
-    pScreenPriv->pCoreBuffer->pSourceGC =
-	pScreenPriv->pCoreBuffer->pMaskGC =
-	pScreenPriv->pCoreBuffer->pSaveGC =
- 	pScreenPriv->pCoreBuffer->pRestoreGC =
- 	pScreenPriv->pCoreBuffer->pMoveGC =
- 	pScreenPriv->pCoreBuffer->pPixSourceGC =
-	pScreenPriv->pCoreBuffer->pPixMaskGC = NULL;
-#ifdef ARGB_CURSOR
-    pScreenPriv->pCoreBuffer->pRootPicture = NULL;
-    pScreenPriv->pCoreBuffer->pTempPicture = NULL;
-#endif
-    
-    pScreenPriv->pCoreBuffer->pSave = pScreenPriv->pCoreBuffer->pTemp = NULL;
-
-#ifdef MPX
+    if (!pScreenPriv->pCoreBuffer)
+    {
+        xfree((pointer)pScreenPriv);
+        return FALSE;
+    }
+    pBuffer = pScreenPriv->pCoreBuffer;
+#else /* ifdef MPX */
     {
         int mpBufferIdx = 0;
 
         pScreenPriv->pMPBuffers = (miDCBufferPtr)xalloc(MAX_DEVICES *
                                 sizeof(miDCBufferRec));
-
+        if (!pScreenPriv->pMPBuffers)
+        {
+            xfree((pointer)pScreenPriv);
+            return FALSE;
+        }
+ 
         /* virtual core pointer ID is 1 */
-        xfree(pScreenPriv->pCoreBuffer);
         pScreenPriv->pCoreBuffer = &pScreenPriv->pMPBuffers[1];
 
-        while (mpBufferIdx < MAX_DEVICES)
+        while(mpBufferIdx < MAX_DEVICES)
         {
-            miDCBufferPtr pBuffer = &pScreenPriv->pMPBuffers[mpBufferIdx];
+            pBuffer = &pScreenPriv->pMPBuffers[mpBufferIdx];
+#endif
             pBuffer->pSourceGC =
                 pBuffer->pMaskGC =
                 pBuffer->pSaveGC =
@@ -198,11 +196,13 @@ miDCInitialize (pScreen, screenFuncs)
 
             pBuffer->pSave = pBuffer->pTemp = NULL;
 
+#ifdef MPX
             mpBufferIdx++;
         }
     }
 #endif
 
+
     pScreenPriv->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = miDCCloseScreen;
     
diff --git a/mi/mipointer.c b/mi/mipointer.c
index db9a6f8..6ccc729 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -71,13 +71,6 @@ static miPointerPtr miPointer;
  */
 static miPointerRec miMPPointers[MAX_DEVICES];
 
-
-/* Check if the given device is a MP device. */
-_X_EXPORT Bool 
-IsMPDev(DeviceIntPtr pDev) 
-{
-    return (pDev && pDev->isMPDev && pDev->id < MAX_DEVICES);
-}
 #endif
 
 static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
diff --git a/mi/misprite.c b/mi/misprite.c
index e51599e..ec90ad2 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -187,11 +187,9 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     miSpriteCursorFuncPtr   cursorFuncs;
     miPointerScreenFuncPtr  screenFuncs;
 {
-#ifdef MPX
-    int mpCursorIdx = 0;
-#endif
     miSpriteScreenPtr	pScreenPriv;
     VisualPtr		pVisual;
+    miCursorInfoPtr     pCursorInfo;
     
     if (!DamageSetup (pScreen))
 	return FALSE;
@@ -239,73 +237,71 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     
     pScreenPriv->BlockHandler = pScreen->BlockHandler;
     
+#if !defined MPX
     pScreenPriv->cp = (miCursorInfoPtr)xalloc(sizeof(miCursorInfoRec));
-    pScreenPriv->cp->pCursor = NULL;
-    pScreenPriv->cp->x = 0;
-    pScreenPriv->cp->y = 0;
-    pScreenPriv->cp->isUp = FALSE;
-    pScreenPriv->cp->shouldBeUp = FALSE;
-    pScreenPriv->cp->pCacheWin = NullWindow;
-    pScreenPriv->cp->isInCacheWin = FALSE;
-    pScreenPriv->cp->checkPixels = TRUE;
-    pScreenPriv->cp->pInstalledMap = NULL;
-    pScreenPriv->cp->pColormap = NULL;
-    pScreenPriv->cp->colors[SOURCE_COLOR].red = 0;
-    pScreenPriv->cp->colors[SOURCE_COLOR].green = 0;
-    pScreenPriv->cp->colors[SOURCE_COLOR].blue = 0;
-    pScreenPriv->cp->colors[MASK_COLOR].red = 0;
-    pScreenPriv->cp->colors[MASK_COLOR].green = 0;
-    pScreenPriv->cp->colors[MASK_COLOR].blue = 0;
+    if (!pScreenPriv->cp)
+    {
+        xfree((pointer)pScreenPriv);
+        return FALSE;
+    }
+    pCursorInfo = pScreenPriv->cp;
+#else
+    /* alloc and zero memory for all MPX cursors */
+    pScreenPriv->mpCursors = (miCursorInfoPtr)xalloc(MAX_DEVICES * sizeof(miCursorInfoRec));
+    if (!pScreenPriv->mpCursors)
+    {
+        xfree((pointer)pScreenPriv->cp);
+        xfree((pointer)pScreenPriv);
+        return FALSE;
+    }
+    pScreenPriv->cp = &(pScreenPriv->mpCursors[1]);
+
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            pCursorInfo = &(pScreenPriv->mpCursors[mpCursorIdx]);
+#endif
+
+            pCursorInfo->pCursor = NULL;
+            pCursorInfo->x = 0;
+            pCursorInfo->y = 0;
+            pCursorInfo->isUp = FALSE;
+            pCursorInfo->shouldBeUp = FALSE;
+            pCursorInfo->pCacheWin = NullWindow;
+            pCursorInfo->isInCacheWin = FALSE;
+            pCursorInfo->checkPixels = TRUE;
+            pCursorInfo->pInstalledMap = NULL;
+            pCursorInfo->pColormap = NULL;
+            pCursorInfo->colors[SOURCE_COLOR].red = 0;
+            pCursorInfo->colors[SOURCE_COLOR].green = 0;
+            pCursorInfo->colors[SOURCE_COLOR].blue = 0;
+            pCursorInfo->colors[MASK_COLOR].red = 0;
+            pCursorInfo->colors[MASK_COLOR].green = 0;
+            pCursorInfo->colors[MASK_COLOR].blue = 0;
+
+#ifdef MPX
+            mpCursorIdx++;
+        }
+    }
+#endif
 
     pScreenPriv->funcs = cursorFuncs;
     pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv;
-    
+
     pScreen->CloseScreen = miSpriteCloseScreen;
     pScreen->GetImage = miSpriteGetImage;
     pScreen->GetSpans = miSpriteGetSpans;
     pScreen->SourceValidate = miSpriteSourceValidate;
-    
+
     pScreen->CopyWindow = miSpriteCopyWindow;
-    
+
     pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
-    
+
     pScreen->InstallColormap = miSpriteInstallColormap;
     pScreen->StoreColors = miSpriteStoreColors;
 
     pScreen->BlockHandler = miSpriteBlockHandler;
-    
-#ifdef MPX
-    /* alloc and zero memory for all MPX cursors */
-    pScreenPriv->mpCursors = (miCursorInfoPtr)xalloc(MAX_DEVICES * sizeof(miCursorInfoRec));
-    while (mpCursorIdx < MAX_DEVICES)
-    {
-        miCursorInfoPtr cursor = &(pScreenPriv->mpCursors[mpCursorIdx]);
-
-        cursor->id = mpCursorIdx;
-        cursor->pCursor = NULL;
-        cursor->x = 0;
-        cursor->y = 0;
-        cursor->isUp = FALSE;
-        cursor->shouldBeUp = FALSE;
-        cursor->pCacheWin = NullWindow;
-        cursor->isInCacheWin = FALSE;
-        cursor->checkPixels = TRUE;
-        cursor->pInstalledMap = NULL;
-        cursor->pColormap = NULL;
-        cursor->colors[SOURCE_COLOR].red = 0;
-        cursor->colors[SOURCE_COLOR].green = 0;
-        cursor->colors[SOURCE_COLOR].blue = 0;
-        cursor->colors[MASK_COLOR].red = 0;
-        cursor->colors[MASK_COLOR].green = 0;
-        cursor->colors[MASK_COLOR].blue = 0;
-
-        mpCursorIdx++;
-    }
-
-    /* virtual core pointer has id 1, we might as well save the memory */
-    xfree(pScreenPriv->cp);
-    pScreenPriv->cp = &(pScreenPriv->mpCursors[1]);
-#endif
 
     damageRegister = 0;
 
commit 023da4e804ad260eaf0c50d2ec7213dd514e2113
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 27 15:54:33 2006 +1030

    mi:     mipointer.c cleanup, reducing code duplication, using MPHasCursor()
    	instead of IsMPDev()

diff --git a/Changelog b/Changelog
index c309ad5..b73e93a 100644
--- a/Changelog
+++ b/Changelog
@@ -12,6 +12,14 @@ Files:
 	mi/misprite.c
 	mi/misprite.h
 
+____________________________________________________________
+
+mi:     mipointer.c cleanup, reducing code duplication, using MPHasCursor()
+	instead of IsMPDev()
+
+Files:
+	mi/mipointer.c
+
 == 23.11.06 ==
 mi:	closing memory leak, miPointer is freed in miPointerCloseScreen
 	bugfix: uninitialized pPointer in miPointerGetPosition ifndef MPX
diff --git a/mi/mipointer.c b/mi/mipointer.c
index acce4cc..db9a6f8 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -27,7 +27,6 @@ Except as contained in this notice, the name of The Open Group 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 Open Group.
 */
-#ifdef MPX
  /* 
   * MPX additions:
   * Copyright © 2006 Peter Hutterer
@@ -35,7 +34,6 @@ in this Software without prior written authorization from The Open Group.
   * Author: Peter Hutterer <peter at cs.unisa.edu.au>
   *
   */
-#endif
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -111,6 +109,7 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     Bool		    waitForUpdate;
 {
     miPointerScreenPtr	pScreenPriv;
+    miPointerPtr        pPointer;
 
     if (miPointerGeneration != serverGeneration)
     {
@@ -150,26 +149,15 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     /*
      * set up the pointer object
      */
+#if !defined MPX
     miPointer = (miPointerPtr)xalloc(sizeof(miPointerRec));
     if (!miPointer)
     {
         xfree((pointer)pScreenPriv);
         return FALSE;
     }
-    miPointer->pScreen = NULL;
-    miPointer->pSpriteScreen = NULL;
-    miPointer->pCursor = NULL;
-    miPointer->pSpriteCursor = NULL;
-    miPointer->limits.x1 = 0;
-    miPointer->limits.x2 = 32767;
-    miPointer->limits.y1 = 0;
-    miPointer->limits.y2 = 32767;
-    miPointer->confined = FALSE;
-    miPointer->x = 0;
-    miPointer->y = 0;
-
-#ifdef MPX
-    xfree(miPointer);
+    pPointer = miPointer;
+#else /* ifdef MPX */
     miPointer = &miMPPointers[1];
     {
         int mpPtrIdx = 0; /* loop counter */
@@ -178,17 +166,21 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
          */
         while(mpPtrIdx < MAX_DEVICES)
         {
-            miMPPointers[mpPtrIdx].pScreen = NULL;
-            miMPPointers[mpPtrIdx].pSpriteScreen = NULL;
-            miMPPointers[mpPtrIdx].pCursor = NULL;
-            miMPPointers[mpPtrIdx].pSpriteCursor = NULL;
-            miMPPointers[mpPtrIdx].limits.x1 = 0;
-            miMPPointers[mpPtrIdx].limits.x2 = 32767;
-            miMPPointers[mpPtrIdx].limits.y1 = 0;
-            miMPPointers[mpPtrIdx].limits.y2 = 32767;
-            miMPPointers[mpPtrIdx].confined = FALSE;
-            miMPPointers[mpPtrIdx].x = 0;
-            miMPPointers[mpPtrIdx].y = 0;
+            pPointer = &miMPPointers[mpPtrIdx];
+#endif
+
+            pPointer->pScreen = NULL;
+            pPointer->pSpriteScreen = NULL;
+            pPointer->pCursor = NULL;
+            pPointer->pSpriteCursor = NULL;
+            pPointer->limits.x1 = 0;
+            pPointer->limits.x2 = 32767;
+            pPointer->limits.y1 = 0;
+            pPointer->limits.y2 = 32767;
+            pPointer->confined = FALSE;
+            pPointer->x = 0;
+            pPointer->y = 0;
+#ifdef MPX
             mpPtrIdx++;
         }
     }
@@ -202,23 +194,26 @@ miPointerCloseScreen (index, pScreen)
     int		index;
     ScreenPtr	pScreen;
 {
-    int mpPointerIdx = 0;
     SetupScreen(pScreen);
+    miPointerPtr pPointer = miPointer;
 
 #ifdef MPX
+    int mpPointerIdx = 0;
+
     while(mpPointerIdx < MAX_DEVICES)
     {
-        if (pScreen == miMPPointers[mpPointerIdx].pScreen) 
-            miMPPointers[mpPointerIdx].pScreen = 0;
-        if (pScreen == miMPPointers[mpPointerIdx].pSpriteScreen) 
-            miMPPointers[mpPointerIdx].pSpriteScreen = 0;
+        pPointer = &miMPPointers[mpPointerIdx];
+#endif
+        if (pScreen == pPointer->pScreen)
+            pPointer->pScreen = 0;
+        if (pScreen == pPointer->pSpriteScreen)
+            pPointer->pSpriteScreen = 0;
+#ifdef MPX
         mpPointerIdx++;
     }
-#else
-    if (pScreen == miPointer->pScreen)
-	miPointer->pScreen = 0;
-    if (pScreen == miPointer->pSpriteScreen)
-	miPointer->pSpriteScreen = 0;
+#endif
+
+#if !defined MPX
     xfree((pointer)miPointer);
 #endif
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
@@ -256,19 +251,15 @@ miPointerDisplayCursor (pDev, pScreen, pCursor)
     ScreenPtr 	 pScreen;
     CursorPtr	 pCursor;
 {
+    miPointerPtr pPointer = miPointer;
 #ifdef MPX
     /* use core pointer for non MPX devices */
-    if (!IsMPDev(pDev))
-        pDev = inputInfo.pointer;
-
-    miMPPointers[pDev->id].pCursor = pCursor;
-    miMPPointers[pDev->id].pScreen = pScreen;
-    miPointerUpdateSprite(pDev);
-#else
-    miPointer->pCursor = pCursor;
-    miPointer->pScreen = pScreen;
-    miPointerUpdateSprite(inputInfo.pointer);
+    if (MPHasCursor(pDev))
+        pPointer = &miMPPointers[pDev->id];
 #endif
+    pPointer->pCursor = pCursor;
+    pPointer->pScreen = pScreen;
+    miPointerUpdateSprite(pDev);
     return TRUE;
 }
 
@@ -280,7 +271,7 @@ miPointerConstrainCursor (pDev, pScreen, pBox)
 {
     miPointerPtr pPointer = miPointer;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pPointer = &miMPPointers[pDev->id];
 #endif
     pPointer->limits = *pBox;
@@ -340,7 +331,7 @@ miPointerWarpCursor (pDev, pScreen, x, y)
     SetupScreen (pScreen);
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pPointer = &miMPPointers[pDev->id];
 #endif
 
@@ -394,16 +385,16 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     int			x, y, devx, devy;
     miPointerPtr        pPointer = miPointer;
 
-#ifdef MPX
     if (!pDev || 
-            !(pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev))
-#else
-    if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer))
+            !(pDev->coreEvents || pDev == inputInfo.pointer 
+#ifdef MPX
+                || pDev->isMPDev
 #endif
+             ))
         return;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pPointer = &miMPPointers[pDev->id];
 #endif
 
@@ -497,7 +488,7 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
 	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
 	NewCurrentScreen (pDev, pScreen, x, y);
 #ifdef MPX
-        if (IsMPDev(pDev))
+        if (MPHasCursor(pDev))
             pPointer = &miMPPointers[pDev->id];
 #endif
         pPointer->limits.x2 = pScreen->width;
@@ -515,7 +506,7 @@ miPointerGetScreen(DeviceIntPtr pDev)
 {
     miPointerPtr pPointer;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pPointer = &miMPPointers[pDev->id];
 #endif
     return pPointer->pScreen;
@@ -539,7 +530,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
 
     miPointerPtr        pPointer = miPointer;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pPointer = &(miMPPointers[pDev->id]);
 #endif
 
@@ -547,12 +538,12 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     if (!pScreen)
 	return;	    /* called before ready */
 
-#ifdef MPX
     if (!pDev || 
-            !(pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev))
-#else
-    if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer))
+            !(pDev->coreEvents || pDev == inputInfo.pointer 
+#ifdef MPX
+                || pDev->isMPDev
 #endif
+                ))
         return;
 
     if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
@@ -601,7 +592,7 @@ miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
 {
     miPointerPtr pPointer = miPointer;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pPointer = &miMPPointers[pDev->id];
 #endif
     *x = pPointer->x;
@@ -623,7 +614,7 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
     SetupScreen(pScreen);
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pPointer = &miMPPointers[pDev->id];
 #endif
 
commit a2340a73687dfd93affb6de28a33d73fd808c96b
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 27 14:47:23 2006 +1030

    mi:     free allocated memory in miDCCloseScreen and in miDCInitialize in case
    	of errors.
    	Some copyright notices.
    	misprite.c passes DeviceIntPtr around and down to DC (previously
    	miCursorInfoPtr and the plain device id).
    	Large cleanup in misprite.c to avoid code duplication.

diff --git a/Changelog b/Changelog
index 66f12f8..c309ad5 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,17 @@
 MPX Changelog file
+== 27.11.06 ==
+mi:     free allocated memory in miDCCloseScreen and in miDCInitialize in case
+	of errors.
+	Some copyright notices.
+	misprite.c passes DeviceIntPtr around and down to DC (previously
+	miCursorInfoPtr and the plain device id).
+	Large cleanup in misprite.c to avoid code duplication.
+
+Files:
+	mi/midispcur.c
+	mi/misprite.c
+	mi/misprite.h
+
 == 23.11.06 ==
 mi:	closing memory leak, miPointer is freed in miPointerCloseScreen
 	bugfix: uninitialized pPointer in miPointerGetPosition ifndef MPX
diff --git a/mi/midispcur.c b/mi/midispcur.c
index 8b961d5..514fae8 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -29,6 +29,12 @@ Except as contained in this notice, the name of The Open Group 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 Open Group.
 */
+/* 
+ * MPX additions:
+ * Copyright © 2006 Peter Hutterer
+ * Author: Peter Hutterer <peter at cs.unisa.edu.au>
+ *
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -55,9 +61,7 @@ in this Software without prior written authorization from The Open Group.
 #ifdef MPX
 # include "inputstr.h"
 
-
 #define SaneID(a) (a >= 0 && a < MAX_DEVICES)
-
 #endif
 
 /* per-screen private data */
@@ -102,20 +106,20 @@ typedef struct {
 
 static Bool	miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 static Bool	miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static Bool	miDCPutUpCursor(int deviceid, ScreenPtr pScreen, 
+static Bool	miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                 CursorPtr pCursor, int x, int y, 
                                 unsigned long source, unsigned long mask);
-static Bool	miDCSaveUnderCursor(int deviceid, ScreenPtr pScreen, 
+static Bool	miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                     int x, int y,
 				    int w, int h);
-static Bool	miDCRestoreUnderCursor(int deviceid, ScreenPtr pScreen, 
+static Bool	miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                        int x, int y,
 				       int w, int h);
-static Bool	miDCMoveCursor(int deviceid, ScreenPtr pScreen, 
+static Bool	miDCMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                CursorPtr pCursor, int x, int y, 
                                int w, int h, int dx, int dy,
 			       unsigned long source, unsigned long mask);
-static Bool	miDCChangeSave(int deviceid, ScreenPtr pScreen, 
+static Bool	miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen, 
                                int x, int y, int w, int h,	
                                int dx, int dy);
 
@@ -173,7 +177,7 @@ miDCInitialize (pScreen, screenFuncs)
         pScreenPriv->pMPBuffers = (miDCBufferPtr)xalloc(MAX_DEVICES *
                                 sizeof(miDCBufferRec));
 
-        /* virtual core pointer ID is 1, we might as well use the array */
+        /* virtual core pointer ID is 1 */
         xfree(pScreenPriv->pCoreBuffer);
         pScreenPriv->pCoreBuffer = &pScreenPriv->pMPBuffers[1];
 
@@ -206,6 +210,11 @@ miDCInitialize (pScreen, screenFuncs)
 
     if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
     {
+#ifdef MPX
+        xfree((pointer)pScreenPriv->pMPBuffers);
+#else
+        xfree((pointer)pScreenPriv->pCoreBuffer);
+#endif
 	xfree ((pointer) pScreenPriv);
 	return FALSE;
     }
@@ -256,6 +265,11 @@ miDCCloseScreen (index, pScreen)
             mpBufferIdx++;
         }
     }
+
+    xfree((pointer) pScreenPriv->pMPBuffers);
+#else
+
+    xfree((pointer) pScreenPriv->pCoreBuffer);
 #endif
 
     xfree ((pointer) pScreenPriv);
@@ -530,8 +544,8 @@ miDCMakeGC(
 
 
 static Bool
-miDCPutUpCursor (deviceid, pScreen, pCursor, x, y, source, mask)
-    int             deviceid;
+miDCPutUpCursor (pDev, pScreen, pCursor, x, y, source, mask)
+    DeviceIntPtr    pDev;
     ScreenPtr	    pScreen;
     CursorPtr	    pCursor;
     int		    x, y;
@@ -554,8 +568,8 @@ miDCPutUpCursor (deviceid, pScreen, pCursor, x, y, source, mask)
     pBuffer = pScreenPriv->pCoreBuffer;
 
 #ifdef MPX
-    if (SaneID(deviceid))
-            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+    if (MPHasCursor(pDev))
+            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
 #endif
 
 #ifdef ARGB_CURSOR
@@ -592,8 +606,8 @@ miDCPutUpCursor (deviceid, pScreen, pCursor, x, y, source, mask)
 }
 
 static Bool
-miDCSaveUnderCursor (deviceid, pScreen, x, y, w, h)
-    int         deviceid;
+miDCSaveUnderCursor (pDev, pScreen, x, y, w, h)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
     int		x, y, w, h;
 {
@@ -606,8 +620,8 @@ miDCSaveUnderCursor (deviceid, pScreen, x, y, w, h)
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
 #ifdef MPX
-    if (SaneID(deviceid))
-            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+    if (MPHasCursor(pDev))
+            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
 #endif
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
@@ -631,8 +645,8 @@ miDCSaveUnderCursor (deviceid, pScreen, x, y, w, h)
 }
 
 static Bool
-miDCRestoreUnderCursor (deviceid, pScreen, x, y, w, h)
-    int         deviceid;
+miDCRestoreUnderCursor (pDev, pScreen, x, y, w, h)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
     int		x, y, w, h;
 {
@@ -645,8 +659,8 @@ miDCRestoreUnderCursor (deviceid, pScreen, x, y, w, h)
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
 #ifdef MPX
-    if (SaneID(deviceid))
-            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+    if (MPHasCursor(pDev))
+            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
 #endif
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
@@ -663,8 +677,8 @@ miDCRestoreUnderCursor (deviceid, pScreen, x, y, w, h)
 }
 
 static Bool
-miDCChangeSave (deviceid, pScreen, x, y, w, h, dx, dy)
-    int             deviceid;
+miDCChangeSave (pDev, pScreen, x, y, w, h, dx, dy)
+    DeviceIntPtr    pDev;
     ScreenPtr	    pScreen;
     int		    x, y, w, h, dx, dy;
 {
@@ -678,8 +692,8 @@ miDCChangeSave (deviceid, pScreen, x, y, w, h, dx, dy)
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pBuffer = pScreenPriv->pCoreBuffer;
 #ifdef MPX
-    if (SaneID(deviceid))
-            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+    if (MPHasCursor(pDev))
+            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
 #endif
     pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
@@ -802,8 +816,8 @@ miDCChangeSave (deviceid, pScreen, x, y, w, h, dx, dy)
 }
 
 static Bool
-miDCMoveCursor (deviceid, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
-    int             deviceid;
+miDCMoveCursor (pDev, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
+    DeviceIntPtr    pDev;
     ScreenPtr	    pScreen;
     CursorPtr	    pCursor;
     int		    x, y, w, h, dx, dy;
@@ -829,8 +843,8 @@ miDCMoveCursor (deviceid, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
     pWin = WindowTable[pScreen->myNum];
     pBuffer = pScreenPriv->pCoreBuffer;
 #ifdef MPX
-    if (SaneID(deviceid))
-            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+    if (MPHasCursor(pDev))
+            pBuffer = &pScreenPriv->pMPBuffers[pDev->id];
 #endif
     pTemp = pBuffer->pTemp;
     if (!pTemp ||
diff --git a/mi/misprite.c b/mi/misprite.c
index ec83e80..e51599e 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -29,15 +29,12 @@ Except as contained in this notice, the name of The Open Group 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 Open Group.
 */
-#ifdef MPX
- /* 
-  * MPX additions:
-  * Copyright © 2006 Peter Hutterer
-  * License see above.
-  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
-  *
-  */
-#endif
+/* 
+ * MPX additions:
+ * Copyright © 2006 Peter Hutterer
+ * Author: Peter Hutterer <peter at cs.unisa.edu.au>
+ *
+ */
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -66,9 +63,7 @@ in this Software without prior written authorization from The Open Group.
 # include   "damage.h"
 
 #ifdef MPX
-# include   "inputstr.h" /* for MAX_DEVICES */
-
-static miCursorInfoPtr DevToSprite(DeviceIntPtr pDev, ScreenPtr pScreen);
+# include   "inputstr.h" 
 #endif
 
 
@@ -108,7 +103,7 @@ static void	    miSpriteStoreColors(ColormapPtr pMap, int ndef,
 static void	    miSpriteSaveDoomedAreas(WindowPtr pWin,
 					    RegionPtr pObscured, int dx,
 					    int dy);
-static void	    miSpriteComputeSaved(miCursorInfoPtr pDevCursor, 
+static void	    miSpriteComputeSaved(DeviceIntPtr pDev, 
                                          ScreenPtr pScreen);
 
 #define SCREEN_PROLOGUE(pScreen, field)\
@@ -142,9 +137,9 @@ _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
  * other misc functions
  */
 
-static void miSpriteRemoveCursor(miCursorInfoPtr pDevCursor, 
+static void miSpriteRemoveCursor(DeviceIntPtr pDev, 
                                  ScreenPtr pScreen); 
-static void miSpriteRestoreCursor(miCursorInfoPtr pDevCursor,
+static void miSpriteRestoreCursor(DeviceIntPtr pDev,
                                  ScreenPtr pScreen);
 
 static void
@@ -152,32 +147,30 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
 {
     ScreenPtr		    pScreen = closure;
     miSpriteScreenPtr	    pScreenPriv;
+    miCursorInfoPtr         pCursorInfo;
+    DeviceIntPtr            pDev = inputInfo.pointer;
     
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    
+    pCursorInfo = pScreenPriv->cp;
 
 #ifdef MPX
+    pDev = inputInfo.devices;
+    while(pDev)
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
+        if (MPHasCursor(pDev))
         {
-            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
-
-            if (pMPCursor->isUp && 
-                    RECT_IN_REGION (pScreen, pRegion, &pMPCursor->saved) != rgnOUT)
+            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+            if (pCursorInfo->isUp &&
+                    RECT_IN_REGION (pScreen, pRegion, &pCursorInfo->saved) 
+                         != rgnOUT) 
             {
-                SPRITE_DEBUG(("Damage remove MPX\n"));
-                miSpriteRemoveCursor(pMPCursor, pScreen);
+                SPRITE_DEBUG(("Damage remove\n"));
+                miSpriteRemoveCursor (pDev, pScreen);
             }
-            mpCursorIdx++;
+#ifdef MPX
         }
-    }
-#else
-    if (pScreenPriv->cp->isUp &&
-	RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->cp->saved) != rgnOUT)
-    {
-	SPRITE_DEBUG(("Damage remove\n"));
-	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
+        pDev = pDev->next;
     }
 #endif
 }
@@ -351,6 +344,8 @@ miSpriteCloseScreen (i, pScreen)
 
 #ifdef MPX
     xfree((pointer)(pScreenPriv->mpCursors));
+#else
+    xfree((pointer)(pScreenPriv->cp));
 #endif
     
     xfree ((pointer) pScreenPriv);
@@ -368,37 +363,33 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
 {
     ScreenPtr	    pScreen = pDrawable->pScreen;
     miSpriteScreenPtr    pScreenPriv;
+    DeviceIntPtr    pDev = inputInfo.pointer;
+    miCursorInfoPtr pCursorInfo;
     
     SCREEN_PROLOGUE (pScreen, GetImage);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-
-    if (pDrawable->type == DRAWABLE_WINDOW &&
-        pScreenPriv->cp->isUp &&
-        ORG_OVERLAP(&pScreenPriv->cp->saved,pDrawable->x,pDrawable->y, 
-                        sx, sy, w, h)) 
-    {
-	SPRITE_DEBUG (("GetImage remove\n"));
-	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
-    }
+    pCursorInfo = pScreenPriv->cp;
 
 #ifdef MPX
-    /* check for MPX cursors in the target region */
-    if (pDrawable->type == DRAWABLE_WINDOW)
+    pDev = inputInfo.devices;
+    while (pDev)
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
+        if (MPHasCursor(pDev))
         {
-            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
-            if (pMPCursor->isUp && 
-                    ORG_OVERLAP(&pMPCursor->saved,pDrawable->x,pDrawable->y,
-                        sx, sy, w, h)) 
-            {
-                SPRITE_DEBUG(("GetImage remove MPX\n"));
-            }
-            miSpriteRemoveCursor(pMPCursor, pScreen); 
-            mpCursorIdx++;
+             pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+             if (pDrawable->type == DRAWABLE_WINDOW &&
+                     pCursorInfo->isUp &&
+                     ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, 
+                         sx, sy, w, h)) 
+             {
+                 SPRITE_DEBUG (("GetImage remove\n"));
+                 miSpriteRemoveCursor (pDev, pScreen);
+             }
+#ifdef MPX
         }
+        pDev = pDev->next;
     }
 #endif
 
@@ -419,69 +410,51 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
 {
     ScreenPtr		    pScreen = pDrawable->pScreen;
     miSpriteScreenPtr	    pScreenPriv;
+    DeviceIntPtr            pDev = inputInfo.pointer;
+    miCursorInfoPtr         pCursorInfo;
     
     SCREEN_PROLOGUE (pScreen, GetSpans);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-
-    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->cp->isUp)
-    {
-	register DDXPointPtr    pts;
-	register int    	*widths;
-	register int    	nPts;
-	register int    	xorg,
-				yorg;
-
-	xorg = pDrawable->x;
-	yorg = pDrawable->y;
-
-	for (pts = ppt, widths = pwidth, nPts = nspans;
-	     nPts--;
-	     pts++, widths++)
- 	{
-	    if (SPN_OVERLAP(&pScreenPriv->cp->saved,pts->y+yorg,
-			     pts->x+xorg,*widths))
-	    {
-		SPRITE_DEBUG (("GetSpans remove\n"));
-		miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
-		break;
-	    }
-	}
-    }
+    pCursorInfo = pScreenPriv->cp;
 
 #ifdef MPX
-    if (pDrawable->type == DRAWABLE_WINDOW)
+    pDev = inputInfo.devices;
+    while(pDev)
     {
-
-        int mpCursorIdx = 0;
-
-        while(mpCursorIdx < MAX_DEVICES)
+        if (MPHasCursor(pDev))
         {
-            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
-            register DDXPointPtr    pts;
-            register int    	*widths;
-            register int    	nPts;
-            register int    	xorg,
-                     yorg;
-            xorg = pDrawable->x;
-            yorg = pDrawable->y;
-
-            for (pts = ppt, widths = pwidth, nPts = nspans;
-                    nPts--;
-                    pts++, widths++)
+            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+
+            if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp)
             {
-                if (SPN_OVERLAP(&pMPCursor->saved,pts->y+yorg,
-                            pts->x+xorg,*widths))
+                register DDXPointPtr    pts;
+                register int    	*widths;
+                register int    	nPts;
+                register int    	xorg,
+                         yorg;
+
+                xorg = pDrawable->x;
+                yorg = pDrawable->y;
+
+                for (pts = ppt, widths = pwidth, nPts = nspans;
+                        nPts--;
+                        pts++, widths++)
                 {
-                    SPRITE_DEBUG (("GetSpans remove\n"));
-                    miSpriteRemoveCursor (pMPCursor, pScreen);
-                    break;
+                    if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
+                                pts->x+xorg,*widths))
+                    {
+                        SPRITE_DEBUG (("GetSpans remove\n"));
+                        miSpriteRemoveCursor (pDev, pScreen);
+                        break;
+                    }
                 }
             }
-            mpCursorIdx++;
+#ifdef MPX
         }
+        pDev = pDev->next;
     }
-
 #endif
 
     (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
@@ -496,38 +469,36 @@ miSpriteSourceValidate (pDrawable, x, y, width, height)
 {
     ScreenPtr		    pScreen = pDrawable->pScreen;
     miSpriteScreenPtr	    pScreenPriv;
+    DeviceIntPtr            pDev = inputInfo.pointer;
+    miCursorInfoPtr         pCursorInfo;
     
     SCREEN_PROLOGUE (pScreen, SourceValidate);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-
-    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->cp->isUp &&
-	ORG_OVERLAP(&pScreenPriv->cp->saved, pDrawable->x, pDrawable->y,
-		    x, y, width, height))
-    {
-	SPRITE_DEBUG (("SourceValidate remove\n"));
-	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
-    }
+    pCursorInfo = pScreenPriv->cp;
 
 #ifdef MPX
-    if (pDrawable->type == DRAWABLE_WINDOW)
+    pDev = inputInfo.devices;
+    while(pDev)
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
+        if (MPHasCursor(pDev))
         {
-            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
-            if (pMPCursor->isUp && ORG_OVERLAP(&pMPCursor->saved,
-                        pDrawable->x, pDrawable->y, x, y, width, height)) 
+            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+            if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp &&
+                    ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
+                        x, y, width, height))
             {
-                SPRITE_DEBUG(("SourceValidate remove MPX\n"));
-                miSpriteRemoveCursor(pMPCursor, pScreen);
+                SPRITE_DEBUG (("SourceValidate remove\n"));
+                miSpriteRemoveCursor (pDev, pScreen);
             }
-            mpCursorIdx++;
+#ifdef MPX
         }
-
+        pDev = pDev->next;
     }
 #endif
 
+
     if (pScreen->SourceValidate)
 	(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
 
@@ -539,36 +510,34 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 {
     ScreenPtr	pScreen = pWindow->drawable.pScreen;
     miSpriteScreenPtr	    pScreenPriv;
+    DeviceIntPtr            pDev = inputInfo.pointer;
+    miCursorInfoPtr         pCursorInfo;
     
     SCREEN_PROLOGUE (pScreen, CopyWindow);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    /*
-     * Damage will take care of destination check
-     */
-    if (pScreenPriv->cp->isUp &&
-	RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->cp->saved) != rgnOUT)
-    {
-	SPRITE_DEBUG (("CopyWindow remove\n"));
-	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
-    }
+    pCursorInfo = pScreenPriv->cp;
+
 #ifdef MPX
+    pDev = inputInfo.devices;
+    while(pDev)
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
+        if (MPHasCursor(pDev))
         {
-            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
-
-            if (pMPCursor->isUp && RECT_IN_REGION (pScreen, prgnSrc,
-                                        &pMPCursor->saved) != rgnOUT)
-           
+            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+            /*
+             * Damage will take care of destination check
+             */
+            if (pCursorInfo->isUp &&
+                    RECT_IN_REGION (pScreen, prgnSrc, &pCursorInfo->saved) != rgnOUT)
             {
-                SPRITE_DEBUG(("CopyWindow remove MPX\n"));
-                miSpriteRemoveCursor(pMPCursor, pScreen);
+                SPRITE_DEBUG (("CopyWindow remove\n"));
+                miSpriteRemoveCursor (pDev, pScreen);
             }
-            mpCursorIdx++;
+#ifdef MPX
         }
-
+        pDev = pDev->next;
     }
 #endif
 
@@ -585,8 +554,11 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
 {
     ScreenPtr		pScreen = screenInfo.screens[i];
     miSpriteScreenPtr	pPriv;
+    DeviceIntPtr            pDev = inputInfo.pointer;
+    miCursorInfoPtr         pCursorInfo;
 
     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+    pCursorInfo = pPriv->cp;
 
     SCREEN_PROLOGUE(pScreen, BlockHandler);
     
@@ -595,28 +567,24 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
     SCREEN_EPILOGUE(pScreen, BlockHandler);
 
 #ifdef MPX
+    pDev = inputInfo.devices;
+    while(pDev)
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
+        if (MPHasCursor(pDev))
         {
-            miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
-            if (!pMPCursor->isUp && pMPCursor->shouldBeUp)
+            pCursorInfo = &pPriv->mpCursors[pDev->id];
+#endif
+            if (!pCursorInfo->isUp && pCursorInfo->shouldBeUp)
             {
-                SPRITE_DEBUG (("BlockHandler restore MPX\n"));
-                miSpriteRestoreCursor (pMPCursor, pScreen);
+                SPRITE_DEBUG (("BlockHandler restore\n"));
+                miSpriteRestoreCursor (pDev, pScreen);
             }
-
-            mpCursorIdx++;
+#ifdef MPX
         }
+        pDev = pDev->next;
     }
-#else
-    if (!pPriv->cp->isUp && pPriv->cp->shouldBeUp)
-    {
-	SPRITE_DEBUG (("BlockHandler restore\n"));
-	miSpriteRestoreCursor (pPriv->cp, pScreen);
-    }
-
 #endif
+
 }
 
 static void
@@ -625,8 +593,12 @@ miSpriteInstallColormap (pMap)
 {
     ScreenPtr		pScreen = pMap->pScreen;
     miSpriteScreenPtr	pPriv;
+    DeviceIntPtr            pDev = inputInfo.pointer;
+    miCursorInfoPtr         pCursorInfo;
+    int                     cursorIdx;
 
     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+    pCursorInfo = pPriv->cp;
 
     SCREEN_PROLOGUE(pScreen, InstallColormap);
     
@@ -634,30 +606,34 @@ miSpriteInstallColormap (pMap)
 
     SCREEN_EPILOGUE(pScreen, InstallColormap);
 
-
 #ifdef MPX
+    /* InstallColormap is called before devices are initialized. We cannot
+     * just run through the device list, we need to go through all possible
+     * sprite structs.*/
+    cursorIdx = 0;
+    while(cursorIdx < MAX_DEVICES)
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
+        pCursorInfo = &pPriv->mpCursors[cursorIdx];
+#endif
+        pCursorInfo->pInstalledMap = pMap;
+        if (pCursorInfo->pColormap != pMap)
         {
-            miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
-            pMPCursor->pInstalledMap = pMap;
-            if (pMPCursor->pColormap != pMap)
+            pCursorInfo->checkPixels = TRUE;
+            if (pCursorInfo->isUp)
             {
-                pMPCursor->checkPixels = TRUE;
-                if (pMPCursor->isUp)
-                    miSpriteRemoveCursor(pMPCursor, pScreen);
+#ifdef MPX
+                /* find matching device */
+                pDev = inputInfo.devices;
+                while(pDev && pDev->id != cursorIdx)
+                    pDev = pDev->next;
+                if (!pDev)
+                    pDev = inputInfo.pointer;
+#endif
+                miSpriteRemoveCursor (pDev, pScreen);
             }
-            mpCursorIdx++;
         }
-    }
-#else
-    pPriv->cp->pInstalledMap = pMap;
-    if (pPriv->cp->pColormap != pMap)
-    {
-    	pPriv->cp->checkPixels = TRUE;
-	if (pPriv->cp->isUp)
-	    miSpriteRemoveCursor (pPriv->cp, pScreen);
+#ifdef MPX
+        cursorIdx++;
     }
 #endif
 
@@ -674,10 +650,13 @@ miSpriteStoreColors (pMap, ndef, pdef)
     int			i;
     int			updated;
     VisualPtr		pVisual;
+    DeviceIntPtr            pDev = inputInfo.pointer;
+    miCursorInfoPtr         pCursorInfo;
 
     pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
     SCREEN_PROLOGUE(pScreen, StoreColors);
+    pCursorInfo = pPriv->cp;
     
     (*pScreen->StoreColors) (pMap, ndef, pdef);
 
@@ -698,23 +677,25 @@ miSpriteStoreColors (pMap, ndef, pdef)
 	    UpdateDAC(dev, plane,blue,blueMask)
 
 #ifdef MPX
+    pDev = inputInfo.devices;
+    while(pDev)
     {
-        int mpCursorIdx = 0;
-
-        while (mpCursorIdx < MAX_DEVICES)
+        if (MPHasCursor(pDev))
         {
-            miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
-
-            if (pPriv->cp->pColormap == pMap)
+            pCursorInfo = &pPriv->mpCursors[pDev->id];
+#endif
+            if (pCursorInfo->pColormap == pMap)
             {
                 updated = 0;
                 pVisual = pMap->pVisual;
                 if (pVisual->class == DirectColor)
                 {
+                    /* Direct color - match on any of the subfields */
+
                     for (i = 0; i < ndef; i++)
                     {
-                        CheckDirect (pMPCursor, SOURCE_COLOR)
-                        CheckDirect (pMPCursor, MASK_COLOR)
+                        CheckDirect (pPriv->cp, SOURCE_COLOR)
+                            CheckDirect (pPriv->cp, MASK_COLOR)
                     }
                 }
                 else
@@ -723,16 +704,16 @@ miSpriteStoreColors (pMap, ndef, pdef)
                     for (i = 0; i < ndef; i++)
                     {
                         if (pdef[i].pixel ==
-                                pMPCursor->colors[SOURCE_COLOR].pixel) 
+                                pCursorInfo->colors[SOURCE_COLOR].pixel) 
                         {
-                            pMPCursor->colors[SOURCE_COLOR] = pdef[i];
+                            pCursorInfo->colors[SOURCE_COLOR] = pdef[i];
                             if (++updated == 2)
                                 break;
                         }
                         if (pdef[i].pixel ==
-                                pMPCursor->colors[MASK_COLOR].pixel) 
+                                pCursorInfo->colors[MASK_COLOR].pixel) 
                         {
-                            pMPCursor->colors[MASK_COLOR] = pdef[i];
+                            pCursorInfo->colors[MASK_COLOR] = pdef[i];
                             if (++updated == 2)
                                 break;
                         }
@@ -740,54 +721,14 @@ miSpriteStoreColors (pMap, ndef, pdef)
                 }
                 if (updated)
                 {
-                    pMPCursor->checkPixels = TRUE;
-                    if (pMPCursor->isUp)
-                        miSpriteRemoveCursor (pMPCursor, pScreen);
+                    pCursorInfo->checkPixels = TRUE;
+                    if (pCursorInfo->isUp)
+                        miSpriteRemoveCursor (pDev, pScreen);
                 }
             }
-            mpCursorIdx++;
+#ifdef MPX
         }
-    }
-#else
-    if (pPriv->cp->pColormap == pMap)
-    {
-	updated = 0;
-	pVisual = pMap->pVisual;
-	if (pVisual->class == DirectColor)
-	{
-	    /* Direct color - match on any of the subfields */
-
-	    for (i = 0; i < ndef; i++)
-	    {
-		CheckDirect (pPriv->cp, SOURCE_COLOR)
-		CheckDirect (pPriv->cp, MASK_COLOR)
-	    }
-	}
-	else
-	{
-	    /* PseudoColor/GrayScale - match on exact pixel */
-	    for (i = 0; i < ndef; i++)
-	    {
-	    	if (pdef[i].pixel == pPriv->cp->colors[SOURCE_COLOR].pixel)
-	    	{
-		    pPriv->cp->colors[SOURCE_COLOR] = pdef[i];
-		    if (++updated == 2)
-		    	break;
-	    	}
-	    	if (pdef[i].pixel == pPriv->cp->colors[MASK_COLOR].pixel)
-	    	{
-		    pPriv->cp->colors[MASK_COLOR] = pdef[i];
-		    if (++updated == 2)
-		    	break;
-	    	}
-	    }
-	}
-    	if (updated)
-    	{
-	    pPriv->cp->checkPixels = TRUE;
-	    if (pPriv->cp->isUp)
-	    	miSpriteRemoveCursor (pPriv->cp, pScreen);
-    	}
+        pDev = pDev->next;
     }
 #endif
 
@@ -841,22 +782,27 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
     ScreenPtr		pScreen;
     miSpriteScreenPtr   pScreenPriv;
     BoxRec		cursorBox;
+    DeviceIntPtr        pDev = inputInfo.pointer;
+    miCursorInfoPtr     pCursorInfo;
 
     pScreen = pWin->drawable.pScreen;
     
     SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+    pCursorInfo = pScreenPriv->cp;
+
 #ifdef MPX
+    pDev = inputInfo.devices;
+    while(pDev)
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
+        if(MPHasCursor(pDev))
         {
-            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
-
-            if (pMPCursor->isUp)
+            pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+            if (pCursorInfo->isUp)
             {
-                cursorBox = pMPCursor->saved;
+                cursorBox = pCursorInfo->saved;
 
                 if (dx || dy)
                 {
@@ -866,25 +812,12 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
                     cursorBox.y2 += dy;
                 }
                 if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
-                    miSpriteRemoveCursor (pMPCursor, pScreen);
+                    miSpriteRemoveCursor (pDev, pScreen);
             }
-            mpCursorIdx++;
+
+#ifdef MPX
         }
-    }
-#else
-    if (pScreenPriv->cp->isUp)
-    {
-	cursorBox = pScreenPriv->cp->saved;
-
-	if (dx || dy)
- 	{
-	    cursorBox.x1 += dx;
-	    cursorBox.y1 += dy;
-	    cursorBox.x2 += dx;
-	    cursorBox.y2 += dy;
-	}
-	if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
-	    miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
+        pDev = pDev->next;
     }
 #endif
 
@@ -906,19 +839,19 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     CursorPtr	pCursor;
 {
     miSpriteScreenPtr	pScreenPriv;
+    miCursorInfoPtr pCursorInfo;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+    pCursorInfo = pScreenPriv->cp;
+
 #ifdef MPX
-    {
-        miCursorInfoPtr pMPCursor = DevToSprite(pDev, pScreen);
-        if (pCursor == pMPCursor->pCursor)
-            pMPCursor->checkPixels = TRUE;
-    }
-#else
-    if (pCursor == pScreenPriv->cp->pCursor)
-	pScreenPriv->cp->checkPixels = TRUE;
+    if (MPHasCursor(pDev))
+        pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
 #endif
 
+    if (pCursor == pCursorInfo->pCursor)
+	pCursorInfo->checkPixels = TRUE;
+
     return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
 }
 
@@ -947,7 +880,7 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     miCursorInfoPtr pPointer = pScreenPriv->cp;
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pPointer = &pScreenPriv->mpCursors[pDev->id];
 #endif
 
@@ -955,7 +888,7 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
     {
     	pPointer->shouldBeUp = FALSE;
     	if (pPointer->isUp)
-	    miSpriteRemoveCursor (pPointer, pScreen);
+	    miSpriteRemoveCursor (pDev, pScreen);
 	pPointer->pCursor = 0;
 	return;
     }
@@ -1041,14 +974,14 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
 #endif
 	{
 	    SPRITE_DEBUG (("SetCursor remove\n"));
-	    miSpriteRemoveCursor (pPointer, pScreen);
+	    miSpriteRemoveCursor (pDev, pScreen);
 	}
     }
 
     if (!pPointer->isUp && pPointer->pCursor)
     {
 	SPRITE_DEBUG (("SetCursor restore\n"));
-	miSpriteRestoreCursor (pPointer, pScreen);
+	miSpriteRestoreCursor (pDev, pScreen);
     }
 
 }
@@ -1066,7 +999,7 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
     pCursor = pScreenPriv->cp->pCursor;
 
 #ifdef MPX
-    if (IsMPDev(pDev))
+    if (MPHasCursor(pDev))
         pCursor = pScreenPriv->mpCursors[pDev->id].pCursor;
 #endif
     miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
@@ -1077,26 +1010,35 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
  */
 
 static void
-miSpriteRemoveCursor (pDevCursor, pScreen)
-    miCursorInfoPtr pDevCursor;
+miSpriteRemoveCursor (pDev, pScreen)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
 {
     miSpriteScreenPtr   pScreenPriv;
+    miCursorInfoPtr     pCursorInfo;
+
 
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    miSpriteIsUpFALSE (pDevCursor, pScreen, pScreenPriv);
-    pDevCursor->pCacheWin = NullWindow;
-    if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDevCursor->id, 
+    pCursorInfo = pScreenPriv->cp;
+
+#ifdef MPX
+    if (MPHasCursor(pDev))
+        pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+
+    miSpriteIsUpFALSE (pCursorInfo, pScreen, pScreenPriv);
+    pCursorInfo->pCacheWin = NullWindow;
+    if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDev,
                                          pScreen,
-					 pDevCursor->saved.x1,
-                                         pDevCursor->saved.y1,
-                                         pDevCursor->saved.x2 -
-                                         pDevCursor->saved.x1,
-                                         pDevCursor->saved.y2 -
-                                         pDevCursor->saved.y1))
+					 pCursorInfo->saved.x1,
+                                         pCursorInfo->saved.y1,
+                                         pCursorInfo->saved.x2 -
+                                         pCursorInfo->saved.x1,
+                                         pCursorInfo->saved.y2 -
+                                         pCursorInfo->saved.y1))
     {
-	miSpriteIsUpTRUE (pDevCursor, pScreen, pScreenPriv);
+	miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
     }
     DamageDrawInternal (pScreen, FALSE);
 }
@@ -1107,37 +1049,46 @@ miSpriteRemoveCursor (pDevCursor, pScreen)
  */
 
 static void
-miSpriteRestoreCursor (pDevCursor, pScreen)
-    miCursorInfoPtr pDevCursor;
+miSpriteRestoreCursor (pDev, pScreen)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
 {
     miSpriteScreenPtr   pScreenPriv;
     int			x, y;
     CursorPtr		pCursor;
+    miCursorInfoPtr     pCursorInfo;
 
     DamageDrawInternal (pScreen, TRUE);
-    miSpriteComputeSaved (pDevCursor, pScreen);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursor = pDevCursor->pCursor;
-    x = pDevCursor->x - (int)pCursor->bits->xhot;
-    y = pDevCursor->y - (int)pCursor->bits->yhot;
-    if ((*pScreenPriv->funcs->SaveUnderCursor) (pDevCursor->id, 
+    pCursorInfo = pScreenPriv->cp;
+
+#ifdef MPX
+    if (MPHasCursor(pDev))
+        pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+
+    miSpriteComputeSaved (pDev, pScreen);
+    pCursor = pCursorInfo->pCursor;
+
+    x = pCursorInfo->x - (int)pCursor->bits->xhot;
+    y = pCursorInfo->y - (int)pCursor->bits->yhot;
+    if ((*pScreenPriv->funcs->SaveUnderCursor) (pDev,
                                       pScreen,
-				      pDevCursor->saved.x1,
-				      pDevCursor->saved.y1,
-                                      pDevCursor->saved.x2 -
-                                      pDevCursor->saved.x1,
-                                      pDevCursor->saved.y2 -
-                                      pDevCursor->saved.y1))
+				      pCursorInfo->saved.x1,
+				      pCursorInfo->saved.y1,
+                                      pCursorInfo->saved.x2 -
+                                      pCursorInfo->saved.x1,
+                                      pCursorInfo->saved.y2 -
+                                      pCursorInfo->saved.y1))
     {
-	if (pDevCursor->checkPixels)
-	    miSpriteFindColors (pDevCursor, pScreen);
-	if ((*pScreenPriv->funcs->PutUpCursor) (pDevCursor->id, pScreen, 
+	if (pCursorInfo->checkPixels)
+	    miSpriteFindColors (pCursorInfo, pScreen);
+	if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen, 
                                   pCursor, x, y,
-				  pDevCursor->colors[SOURCE_COLOR].pixel,
-				  pDevCursor->colors[MASK_COLOR].pixel))
+				  pCursorInfo->colors[SOURCE_COLOR].pixel,
+				  pCursorInfo->colors[MASK_COLOR].pixel))
 	{
-	    miSpriteIsUpTRUE (pDevCursor, pScreen, pScreenPriv);
+	    miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv);
 	}
     }
     DamageDrawInternal (pScreen, FALSE);
@@ -1148,43 +1099,35 @@ miSpriteRestoreCursor (pDevCursor, pScreen)
  */
 
 static void
-miSpriteComputeSaved (pDevCursor, pScreen)
-    miCursorInfoPtr pDevCursor;
+miSpriteComputeSaved (pDev, pScreen)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
 {
     miSpriteScreenPtr   pScreenPriv;
     int		    x, y, w, h;
     int		    wpad, hpad;
     CursorPtr	    pCursor;
+    miCursorInfoPtr pCursorInfo;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursor = pDevCursor->pCursor;
-    x = pDevCursor->x - (int)pCursor->bits->xhot;
-    y = pDevCursor->y - (int)pCursor->bits->yhot;
+    pCursorInfo = pScreenPriv->cp;
+
+#ifdef MPX
+    if (MPHasCursor(pDev))
+        pCursorInfo = &pScreenPriv->mpCursors[pDev->id];
+#endif
+
+
+    pCursor = pCursorInfo->pCursor;
+    x = pCursorInfo->x - (int)pCursor->bits->xhot;
+    y = pCursorInfo->y - (int)pCursor->bits->yhot;
     w = pCursor->bits->width;
     h = pCursor->bits->height;
     wpad = SPRITE_PAD;
     hpad = SPRITE_PAD;
-    pDevCursor->saved.x1 = x - wpad;
-    pDevCursor->saved.y1 = y - hpad;
-    pDevCursor->saved.x2 = pDevCursor->saved.x1 + w + wpad * 2;
-    pDevCursor->saved.y2 = pDevCursor->saved.y1 + h + hpad * 2;
+    pCursorInfo->saved.x1 = x - wpad;
+    pCursorInfo->saved.y1 = y - hpad;
+    pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
+    pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
 }
 
-#ifdef MPX
-static miCursorInfoPtr DevToSprite(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
-    miSpriteScreenPtr pScreenPriv;
-    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    int mpCursorIdx = 0;
-    while(mpCursorIdx < MAX_DEVICES)
-    {
-        miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
-        if (pMPCursor->id == pDev->id)
-            return pMPCursor;
-        mpCursorIdx++;
-    }
-    return pScreenPriv->cp;
-}
-
-#endif
diff --git a/mi/misprite.h b/mi/misprite.h
index e0c55d0..96d2d7d 100644
--- a/mi/misprite.h
+++ b/mi/misprite.h
@@ -42,7 +42,7 @@ typedef struct {
 		CursorPtr /*pCursor*/
 );
     Bool	(*PutUpCursor)(
-                int /* deviceid */,
+                DeviceIntPtr /*pDev*/,
 		ScreenPtr /*pScreen*/,
 		CursorPtr /*pCursor*/,
 		int /*x*/,
@@ -51,7 +51,7 @@ typedef struct {
 		unsigned long /*mask*/
 );
     Bool	(*SaveUnderCursor)(
-                int /* deviceid */,
+                DeviceIntPtr /*pDev*/,
 		ScreenPtr /*pScreen*/,
 		int /*x*/,
 		int /*y*/,
@@ -59,7 +59,7 @@ typedef struct {
 		int /*h*/
 );
     Bool	(*RestoreUnderCursor)(
-                int /* deviceid */,
+                DeviceIntPtr /*pDev*/,
 		ScreenPtr /*pScreen*/,
 		int /*x*/,
 		int /*y*/,
@@ -67,7 +67,7 @@ typedef struct {
 		int /*h*/
 );
     Bool	(*MoveCursor)(
-                int /* deviceid */,
+                DeviceIntPtr /*pDev*/,
 		ScreenPtr /*pScreen*/,
 		CursorPtr /*pCursor*/,
 		int /*x*/,
@@ -80,7 +80,7 @@ typedef struct {
 		unsigned long /*mask*/
 );
     Bool	(*ChangeSave)(
-                int /* deviceid */,
+                DeviceIntPtr /*pDev*/,
 		ScreenPtr /*pScreen*/,
 		int /*x*/,
 		int /*y*/,
commit 1c7568b8a1417257fa67c7fca69aa253099b9461
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 23 17:15:14 2006 +1030

    mi:	closing memory leak, miPointer is freed in miPointerCloseScreen
    	bugfix: uninitialized pPointer in miPointerGetPosition ifndef MPX
    	adding DeviceIntPtr parameter to ScreenRec's cursor functions.
    	cleanup of miPointer code to use same scheme in each function
    
    dix:	MPHasCursor() function determines checking whether to invoke
    	cursor rendering.
    
    animcur: adding DeviceIntPtr parameter to cursor functions but animcur relies
    	 on the core pointer right now.
    
    xfixes: adding DeviceIntPtr parameter to cursor functions but xfixes relies on
    	the core pointer right now.
    
    rac:	adding DeviceIntPtr parameter to cursor functions but RAC relies on
    	the core pointer right now.
    
    ramdac:	adding DeviceIntPtr parameter to cursor functions but ramdac relies on
    	the core pointer right now.

diff --git a/Changelog b/Changelog
index 1f323ad..66f12f8 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,49 @@
 MPX Changelog file
+== 23.11.06 ==
+mi:	closing memory leak, miPointer is freed in miPointerCloseScreen
+	bugfix: uninitialized pPointer in miPointerGetPosition ifndef MPX
+	adding DeviceIntPtr parameter to ScreenRec's cursor functions.
+	cleanup of miPointer code to use same scheme in each function
+
+dix:	MPHasCursor() function determines checking whether to invoke
+	cursor rendering.
+
+animcur: adding DeviceIntPtr parameter to cursor functions but animcur relies
+	 on the core pointer right now.
+
+xfixes: adding DeviceIntPtr parameter to cursor functions but xfixes relies on
+	the core pointer right now.
+
+rac:	adding DeviceIntPtr parameter to cursor functions but RAC relies on
+	the core pointer right now.
+
+ramdac:	adding DeviceIntPtr parameter to cursor functions but ramdac relies on
+	the core pointer right now.
+
+Files:
+	mi/mipointer.c
+	mi/mipointer.h
+	mi/micursor.c
+	mi/mi.h
+	mi/mieq.c
+	include/cursor.h
+	include/inputstr.h
+	include/scrnintstr.h
+	include/dix.h
+	dix/events.c
+	dix/cursor.c
+	Xext/xtest.c
+	render/animcur.c
+	xfixes/cursor.c
+	XTrap/xtrapddmi.c
+	xkb/ddxFakeMtn.c
+	hw/xfree86/common/xf86Cursor.c
+	hw/xfree86/common/xf86RandR.c
+	hw/xfree86/rac/xf86RAC.c
+	hw/xfree86/ramdac/xf86Cursor.c
+	hw/xfree86/dri/dri.c
+
+
 == 22.11.06 ==
 
 mi:     added DevToSprite() conversion function
@@ -26,7 +71,7 @@ dix	GetSpriteWindow() adjusted for MPX
 Files:
         Xext/security.c
         Xi/exevents.c
-        ddx/ddxFakeMtn.c
+        xkb/ddxFakeMtn.c
         dix/events.c
         include/dix.h
 
diff --git a/XTrap/xtrapddmi.c b/XTrap/xtrapddmi.c
index 73a20c1..c633b8d 100644
--- a/XTrap/xtrapddmi.c
+++ b/XTrap/xtrapddmi.c
@@ -60,6 +60,7 @@ SOFTWARE.
 # include "extnsionst.h"        /* Server ExtensionEntry definitions */
 # include "scrnintstr.h"        /* Screen struct */
 #endif
+#include "inputstr.h"
 
 #include <X11/extensions/xtrapdi.h>
 #include <X11/extensions/xtrapddmi.h>
@@ -130,8 +131,8 @@ int XETrapSimulateXEvent(register xXTrapInputReq *request,
         {   /* Set new cursor position on screen */
             XETrap_avail.data.cur_x = x;
             XETrap_avail.data.cur_y = y;
-          NewCurrentScreen (pScr, x, y); /* fix from amnonc at mercury.co.il */
-            if (!(*pScr->SetCursorPosition)(pScr, x, y, xFalse))
+          NewCurrentScreen (inputInfo.pointer, pScr, x, y); /* fix from amnonc at mercury.co.il */
+            if (!(*pScr->SetCursorPosition)(inputInfo.pointer, pScr, x, y, xFalse))
             {
                 status = BadImplementation;
             }
diff --git a/Xext/xtest.c b/Xext/xtest.c
index 18111c0..66c84d7 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -433,13 +433,13 @@ ProcXTestFakeInput(client)
 	if (root != GetCurrentRootWindow())
 #endif
 	{
-	    NewCurrentScreen(root->drawable.pScreen,
+	    NewCurrentScreen(dev, root->drawable.pScreen,
 			     ev->u.keyButtonPointer.rootX,
 			     ev->u.keyButtonPointer.rootY);
 	    return client->noClientException;
 	}
 	(*root->drawable.pScreen->SetCursorPosition)
-	    (root->drawable.pScreen,
+	    (dev, root->drawable.pScreen,
 	     ev->u.keyButtonPointer.rootX,
 	     ev->u.keyButtonPointer.rootY, FALSE);
 	break;
diff --git a/dix/cursor.c b/dix/cursor.c
index b9ede1f..92297b9 100644
--- a/dix/cursor.c
+++ b/dix/cursor.c
@@ -59,6 +59,7 @@ SOFTWARE.
 #include "cursorstr.h"
 #include "dixfontstr.h"
 #include "opaque.h"
+#include "inputstr.h"
 
 typedef struct _GlyphShare {
     FontPtr font;
@@ -114,14 +115,26 @@ FreeCursor(pointer value, XID cid)
     CursorPtr 	pCurs = (CursorPtr)value;
 
     ScreenPtr	pscr;
+    DeviceIntPtr pDev; 
 
     if ( --pCurs->refcnt > 0)
 	return(Success);
 
+    pDev = inputInfo.pointer;
+
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
 	pscr = screenInfo.screens[nscr];
-	(void)( *pscr->UnrealizeCursor)( pscr, pCurs);
+#ifdef MPX
+        pDev = inputInfo.devices;
+        while(pDev)
+        {
+#endif
+            (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
+#ifdef MPX
+            pDev = pDev->next;
+        }
+#endif
     }
     FreeCursorBits(pCurs->bits);
     xfree( pCurs);
@@ -171,6 +184,7 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
     CursorPtr 	pCurs;
     int		nscr;
     ScreenPtr 	pscr;
+    DeviceIntPtr pDev; 
 
     pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
     if (!pCurs)
@@ -207,23 +221,62 @@ AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
     pCurs->backGreen = backGreen;
     pCurs->backBlue = backBlue;
 
+    pDev = inputInfo.pointer;
     /*
      * realize the cursor for every screen
      */
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
-	pscr = screenInfo.screens[nscr];
-        if (!( *pscr->RealizeCursor)( pscr, pCurs))
-	{
-	    while (--nscr >= 0)
-	    {
-		pscr = screenInfo.screens[nscr];
-		( *pscr->UnrealizeCursor)( pscr, pCurs);
-	    }
-	    FreeCursorBits(bits);
-	    xfree(pCurs);
-	    return (CursorPtr)NULL;
-	}
+        pscr = screenInfo.screens[nscr];
+#ifdef MPX
+        pDev = inputInfo.devices;
+        while(pDev)
+        {
+            if (MPHasCursor(pDev))
+            {
+#endif
+                if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
+                {
+#ifdef MPX
+                    /* Realize failed for device pDev on screen pscr.
+                     * We have to assume that for all devices before, realize
+                     * worked. We need to rollback all devices so far on the
+                     * current screen and then all devices on previous
+                     * screens.
+                     */
+                    DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
+                    while(pDevIt && pDevIt != pDev)
+                    {
+                        if (MPHasCursor(pDevIt))
+                            ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
+                        pDevIt = pDevIt->next;
+                    }
+#endif
+                    while (--nscr >= 0)
+                    {
+                        pscr = screenInfo.screens[nscr];
+#ifdef MPX
+                        /* now unrealize all devices on previous screens */
+                        pDevIt = inputInfo.devices;
+                        while (pDevIt)
+                        {
+                            if (MPHasCursor(pDevIt))
+                                ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
+                            pDevIt = pDevIt->next;
+                        }
+#else
+                        ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
+#endif
+                    }
+                    FreeCursorBits(bits);
+                    xfree(pCurs);
+                    return (CursorPtr)NULL;
+                }
+#ifdef MPX
+            }
+            pDev = pDev->next;
+        }
+#endif
     }
     return pCurs;
 }
@@ -260,6 +313,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     int		nscr;
     ScreenPtr 	pscr;
     GlyphSharePtr pShare;
+    DeviceIntPtr pDev;
 
     sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT,
 						  SecurityReadAccess);
@@ -398,23 +452,62 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
     pCurs->backGreen = backGreen;
     pCurs->backBlue = backBlue;
 
+    pDev = inputInfo.pointer;
     /*
      * realize the cursor for every screen
      */
     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
     {
-	pscr = screenInfo.screens[nscr];
-        if (!( *pscr->RealizeCursor)( pscr, pCurs))
-	{
-	    while (--nscr >= 0)
-	    {
-		pscr = screenInfo.screens[nscr];
-		( *pscr->UnrealizeCursor)( pscr, pCurs);
-	    }
-	    FreeCursorBits(pCurs->bits);
-	    xfree(pCurs);
-	    return BadAlloc;
-	}
+        pscr = screenInfo.screens[nscr];
+#ifdef MPX
+        pDev = inputInfo.devices;
+        while(pDev)
+        {
+            if (MPHasCursor(pDev))
+            {
+#endif
+                if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs))
+                {
+#ifdef MPX
+                    /* Realize failed for device pDev on screen pscr.
+                     * We have to assume that for all devices before, realize
+                     * worked. We need to rollback all devices so far on the
+                     * current screen and then all devices on previous
+                     * screens.
+                     */
+                    DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/
+                    while(pDevIt && pDevIt != pDev)
+                    {
+                        if (MPHasCursor(pDevIt))
+                            ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
+                        pDevIt = pDevIt->next;
+                    }
+#endif
+                    while (--nscr >= 0)
+                    {
+                        pscr = screenInfo.screens[nscr];
+#ifdef MPX
+                        /* now unrealize all devices on previous screens */
+                        pDevIt = inputInfo.devices;
+                        while (pDevIt)
+                        {
+                            if (MPHasCursor(pDevIt))
+                                ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs);
+                            pDevIt = pDevIt->next;
+                        }
+#else
+                        ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs);
+#endif
+                    }
+                    FreeCursorBits(bits);
+                    xfree(pCurs);
+                    return BadAlloc;
+                }
+#ifdef MPX
+            }
+            pDev = pDev->next;
+        }
+#endif
     }
     *ppCurs = pCurs;
     return Success;
diff --git a/dix/events.c b/dix/events.c
index 82d5d05..d3b0e58 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -262,6 +262,19 @@ static SpritePtr sprite;		/* info about the cursor sprite */
 static SpritePtr mpsprites;             /* info about the MPX sprites */
 
 extern BOOL IsMPDev(DeviceIntPtr dev);
+
+/** 
+ * True for the core pointer and any MPX device. 
+ * False for any other device (including keyboards).
+ * Does ID checking for sane range as well.
+ */
+_X_EXPORT Bool
+MPHasCursor(DeviceIntPtr pDev) 
+{
+    return (pDev == inputInfo.pointer || 
+            (pDev->isMPDev && pDev->id < MAX_DEVICES)); 
+}
+
 #endif
 
 #ifdef XEVIE
@@ -347,6 +360,7 @@ static void PostNewCursor(DeviceIntPtr pDev);
 
 static Bool
 XineramaSetCursorPosition(
+    DeviceIntPtr pDev,
     int x, 
     int y, 
     Bool generateEvent
@@ -354,12 +368,18 @@ XineramaSetCursorPosition(
     ScreenPtr pScreen;
     BoxRec box;
     int i;
+    SpritePtr pSprite = sprite;
+
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
 
     /* x,y are in Screen 0 coordinates.  We need to decide what Screen
        to send the message too and what the coordinates relative to 
        that screen are. */
 
-    pScreen = sprite->screen;
+    pScreen = pSprite->screen;
     x += panoramiXdataPtr[0].x;
     y += panoramiXdataPtr[0].y;
 
@@ -378,13 +398,13 @@ XineramaSetCursorPosition(
 	}
     }
 
-    sprite->screen = pScreen;
-    sprite->hotPhys.x = x - panoramiXdataPtr[0].x;
-    sprite->hotPhys.y = y - panoramiXdataPtr[0].y;
+    pSprite->screen = pScreen;
+    pSprite->hotPhys.x = x - panoramiXdataPtr[0].x;
+    pSprite->hotPhys.y = y - panoramiXdataPtr[0].y;
     x -= panoramiXdataPtr[pScreen->myNum].x;
     y -= panoramiXdataPtr[pScreen->myNum].y;
 
-    return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent);
+    return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
 }
 
 
@@ -451,7 +471,7 @@ XineramaCheckPhysLimits(
 
     if((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
     {
-	XineramaSetCursorPosition (new.x, new.y, generateEvents);
+	XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
 	if (!generateEvents)
 	    SyntheticMotion(new.x, new.y);
     }
@@ -597,7 +617,7 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
 	{
 	    XineramaSetCursorPosition(
-			pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
+			pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
 	}
 	XE_KBPTR.rootX = pSprite->hot.x;
 	XE_KBPTR.rootY = pSprite->hot.y;
@@ -693,7 +713,7 @@ XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
 		(pSprite->current->bits->yhot != cursor->bits->yhot))
 	    XineramaCheckPhysLimits(pDev, cursor, FALSE);
-    	(*pSprite->screen->DisplayCursor)(pSprite->screen, cursor);
+    	(*pSprite->screen->DisplayCursor)(pDev, pSprite->screen, cursor);
 	FreeCursor(pSprite->current, (Cursor)0);
 	pSprite->current = cursor;
 	pSprite->current->refcnt++;
@@ -785,7 +805,7 @@ CheckPhysLimits(
 	new.pScreen = pScreen;
     else
 	pScreen = new.pScreen;
-    (*pScreen->CursorLimits) (pScreen, cursor, &pSprite->hotLimits,
+    (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
 			      &pSprite->physLimits);
     pSprite->confined = confineToScreen;
     (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
@@ -808,8 +828,9 @@ CheckPhysLimits(
     {
 	if (pScreen != pSprite->hotPhys.pScreen)
 	    pSprite->hotPhys = new;
-	(*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
-	if (!generateEvents)
+        (*pScreen->SetCursorPosition) 
+            (pDev, pScreen, new.x, new.y, generateEvents); 
+        if (!generateEvents)
 	    SyntheticMotion(new.x, new.y);
     }
 }
@@ -932,8 +953,9 @@ ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 		(pSprite->current->bits->yhot != cursor->bits->yhot))
 	    CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
 			    (ScreenPtr)NULL);
-	(*sprite->hotPhys.pScreen->DisplayCursor) (pSprite->hotPhys.pScreen,
-						  cursor);
+        (*sprite->hotPhys.pScreen->DisplayCursor) (pDev,
+                                                   pSprite->hotPhys.pScreen,
+                                                   cursor);
 	FreeCursor(pSprite->current, (Cursor)0);
 	pSprite->current = cursor;
 	pSprite->current->refcnt++;
@@ -2208,10 +2230,9 @@ DefineInitialRootWindow(register WindowPtr win)
 {
     register ScreenPtr pScreen = win->drawable.pScreen;
     SpritePtr pSprite = sprite;
+    DeviceIntPtr pDev = inputInfo.pointer;
 #ifdef MPX
     int mpSpriteIdx = 0;
-    DeviceIntPtr pDev;
-
 
     while (mpSpriteIdx < MAX_DEVICES)
     {
@@ -2232,7 +2253,7 @@ DefineInitialRootWindow(register WindowPtr win)
         pSprite->current->refcnt++;
         spriteTraceGood = 1;
         ROOT = win;
-        (*pScreen->CursorLimits) ( pScreen, pSprite->current,
+        (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
                                    &pSprite->hotLimits, &pSprite->physLimits);
         pSprite->confined = FALSE;
 
@@ -2241,18 +2262,20 @@ DefineInitialRootWindow(register WindowPtr win)
         pDev = inputInfo.devices;
         while(pDev)
         {
-            if (pDev->id == mpSpriteIdx)
-                (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
-
+            if (pDev->id == mpSpriteIdx && MPHasCursor(pDev))
+            {
+#endif
+                (*pScreen->ConstrainCursor) (pDev, pScreen,
+                                             &pSprite->physLimits);
+                (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
+                                               pSprite->hot.y,
+                                               FALSE); 
+                (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
+#ifdef MPX
+            }
             pDev = pDev->next;
         }
-#else
-        (*pScreen->ConstrainCursor) (inputInfo.pointer, pScreen,
-                                     &pSprite->physLimits); 
 #endif
-        (*pScreen->SetCursorPosition) (pScreen, pSprite->hot.x, pSprite->hot.y,
-                                       FALSE); 
-        (*pScreen->DisplayCursor) (pScreen, pSprite->current);
 
 #ifdef PANORAMIX
         if(!noPanoramiXExtension) {
@@ -2291,35 +2314,43 @@ WindowHasNewCursor(WindowPtr pWin)
 }
 
 _X_EXPORT void
-NewCurrentScreen(ScreenPtr newScreen, int x, int y)
+NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
 {
-    sprite->hotPhys.x = x;
-    sprite->hotPhys.y = y;
+    SpritePtr pSprite = sprite;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+
+    pSprite->hotPhys.x = x;
+    pSprite->hotPhys.y = y;
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
-	sprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - 
+	pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - 
 			    panoramiXdataPtr[0].x;
-	sprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - 
+	pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - 
 			    panoramiXdataPtr[0].y;
-	if (newScreen != sprite->screen) {
-	    sprite->screen = newScreen;
+	if (newScreen != pSprite->screen) {
+	    pSprite->screen = newScreen;
 	    /* Make sure we tell the DDX to update its copy of the screen */
-	    if(sprite->confineWin)
-		XineramaConfineCursorToWindow(sprite->confineWin, TRUE);
+	    if(pSprite->confineWin)
+		XineramaConfineCursorToWindow(pSprite->confineWin, TRUE);
 	    else
 		XineramaConfineCursorToWindow(WindowTable[0], TRUE);
 	    /* if the pointer wasn't confined, the DDX won't get 
 	       told of the pointer warp so we reposition it here */
 	    if(!syncEvents.playingEvents)
-		(*sprite->screen->SetCursorPosition)(sprite->screen,
-		    sprite->hotPhys.x + panoramiXdataPtr[0].x - 
-			panoramiXdataPtr[sprite->screen->myNum].x,
-		    sprite->hotPhys.y + panoramiXdataPtr[0].y - 
-			panoramiXdataPtr[sprite->screen->myNum].y, FALSE);
+		(*pSprite->screen->SetCursorPosition)(
+                                                      pDev,
+                                                      pSprite->screen,
+		    pSprite->hotPhys.x + panoramiXdataPtr[0].x - 
+			panoramiXdataPtr[pSprite->screen->myNum].x,
+		    pSprite->hotPhys.y + panoramiXdataPtr[0].y - 
+			panoramiXdataPtr[pSprite->screen->myNum].y, FALSE);
 	}
     } else 
 #endif
-    if (newScreen != sprite->hotPhys.pScreen)
+    if (newScreen != pSprite->hotPhys.pScreen)
 	ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE);
 }
 
@@ -2430,7 +2461,7 @@ XineramaWarpPointer(ClientPtr client)
     if (sprite->hotShape)
 	ConfineToShape(inputInfo.pointer, sprite->hotShape, &x, &y);
 
-    XineramaSetCursorPosition(x, y, TRUE);
+    XineramaSetCursorPosition(inputInfo.pointer, x, y, TRUE);
 
     return Success;
 }
@@ -2518,11 +2549,12 @@ ProcWarpPointer(ClientPtr client)
 	if (sprite->hotShape)
 	    ConfineToShape(inputInfo.pointer, sprite->hotShape, &x, &y);
 #endif
-	(*newScreen->SetCursorPosition)(newScreen, x, y, TRUE);
+        (*newScreen->SetCursorPosition)(inputInfo.pointer, newScreen, x, y,
+                                        TRUE); 
     }
     else if (!PointerConfinedToScreen(inputInfo.pointer))
     {
-	NewCurrentScreen(newScreen, x, y);
+	NewCurrentScreen(inputInfo.pointer, newScreen, x, y);
     }
     return Success;
 }
@@ -4693,7 +4725,7 @@ ProcRecolorCursor(ClientPtr client)
 	else
 #endif
 	    displayed = (pscr == sprite->hotPhys.pScreen);
-	( *pscr->RecolorCursor)(pscr, pCursor,
+	( *pscr->RecolorCursor)(inputInfo.pointer, pscr, pCursor,
 				(pCursor == sprite->current) && displayed);
     }
     return (Success);
diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c
index 46d8128..27264a2 100644
--- a/hw/xfree86/common/xf86Cursor.c
+++ b/hw/xfree86/common/xf86Cursor.c
@@ -69,7 +69,7 @@ typedef struct {
 
 static Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y);
 static void xf86CrossScreen(ScreenPtr pScreen, Bool entering);
-static void xf86WarpCursor(ScreenPtr pScreen, int x, int y);
+static void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
 
 static void xf86PointerMoved(int scrnIndex, int x, int y);
 
@@ -269,7 +269,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
     (*pScr->AdjustFrame)(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0);
 
   if (pScreen == pCursorScreen)
-    xf86WarpCursor(pScreen, px, py);
+    xf86WarpCursor(inputInfo.pointer, pScreen, px, py);
 
   return Switched;
 }
@@ -430,11 +430,11 @@ xf86CrossScreen (ScreenPtr pScreen, Bool entering)
 
 /* ARGSUSED */
 static void
-xf86WarpCursor (ScreenPtr pScreen, int x, int y)
+xf86WarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     int    sigstate;
     sigstate = xf86BlockSIGIO ();
-  miPointerWarpCursor(pScreen,x,y);
+  miPointerWarpCursor(pDev, pScreen,x,y);
 
   xf86Info.currentScreen = pScreen;
     xf86UnblockSIGIO (sigstate);
diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c
index 288d721..87d5a36 100644
--- a/hw/xfree86/common/xf86RandR.c
+++ b/hw/xfree86/common/xf86RandR.c
@@ -34,6 +34,7 @@
 #include "xf86DDC.h"
 #include "mipointer.h"
 #include <randrstr.h>
+#include "inputstr.h"
 
 typedef struct _xf86RandRInfo {
     CreateScreenResourcesProcPtr    CreateScreenResources;
@@ -291,7 +292,7 @@ xf86RandRSetConfig (ScreenPtr		pScreen,
 
         xf86SetViewport(pScreen, px, py);
 
-        (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
+        (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE);
     }
 
     return TRUE;
diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c
index a49c632..76f0b70 100644
--- a/hw/xfree86/dri/dri.c
+++ b/hw/xfree86/dri/dri.c
@@ -70,6 +70,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "mi.h"
 #include "mipointer.h"
 #include "xf86_OSproc.h"
+#include "inputstr.h"
 
 #if !defined(PANORAMIX)
 extern Bool noPanoramiXExtension;
@@ -2013,7 +2014,7 @@ DRIAdjustFrame(int scrnIndex, int x, int y, int flags)
 	if (px > pScrn->frameX1) px = pScrn->frameX1;
 	if (py < pScrn->frameY0) py = pScrn->frameY0;
 	if (py > pScrn->frameY1) py = pScrn->frameY1;
-	pScreen->SetCursorPosition(pScreen, px, py, TRUE);
+	pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE);
 	return;
     }
 
diff --git a/hw/xfree86/rac/xf86RAC.c b/hw/xfree86/rac/xf86RAC.c
index 23dab86..022f474 100644
--- a/hw/xfree86/rac/xf86RAC.c
+++ b/hw/xfree86/rac/xf86RAC.c
@@ -154,13 +154,16 @@ static PixmapPtr RACCreatePixmap(ScreenPtr pScreen, int w, int h, int depth);
 static Bool  RACCreateGC(GCPtr pGC);
 static Bool RACSaveScreen(ScreenPtr pScreen, Bool unblank);
 static void RACStoreColors (ColormapPtr pmap, int ndef, xColorItem *pdefs);
-static void RACRecolorCursor (ScreenPtr pScreen, CursorPtr pCurs,
-			      Bool displayed);
-static Bool RACRealizeCursor (ScreenPtr   pScreen, CursorPtr   pCursor);
-static Bool RACUnrealizeCursor (ScreenPtr   pScreen, CursorPtr   pCursor);
-static Bool RACDisplayCursor (ScreenPtr pScreen, CursorPtr pCursor);
-static Bool RACSetCursorPosition (ScreenPtr   pScreen, int x, int y,
-				  Bool generateEvent);
+static void RACRecolorCursor (DeviceIntPtr pDev, ScreenPtr pScreen, 
+                              CursorPtr pCurs, Bool displayed);
+static Bool RACRealizeCursor (DeviceIntPtr pDev, ScreenPtr   pScreen, 
+                              CursorPtr pCursor);
+static Bool RACUnrealizeCursor (DeviceIntPtr pDev, ScreenPtr   pScreen, 
+                                CursorPtr pCursor);
+static Bool RACDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, 
+                              CursorPtr pCursor);
+static Bool RACSetCursorPosition (DeviceIntPtr pDev, ScreenPtr   pScreen, 
+                                  int x, int y, Bool generateEvent);
 static void RACAdjustFrame(int index, int x, int y, int flags);
 static Bool RACSwitchMode(int index, DisplayModePtr mode, int flags);
 static Bool RACEnterVT(int index, int flags);
@@ -586,6 +589,7 @@ RACStoreColors (
 
 static void
 RACRecolorCursor (    
+    DeviceIntPtr pDev,
     ScreenPtr pScreen,
     CursorPtr pCurs,
     Bool displayed
@@ -594,15 +598,16 @@ RACRecolorCursor (
     DPRINT_S("RACRecolorCursor",pScreen->myNum);
     SCREEN_PROLOG (RecolorCursor);
     ENABLE;
-    (*pScreen->RecolorCursor) (pScreen,pCurs,displayed);
+    (*pScreen->RecolorCursor) (pDev, pScreen,pCurs,displayed);
     
     SCREEN_EPILOG ( RecolorCursor, RACRecolorCursor);
 }
 
 static Bool
 RACRealizeCursor (    
-    ScreenPtr   pScreen,
-    CursorPtr   pCursor
+    DeviceIntPtr pDev,
+    ScreenPtr    pScreen,
+    CursorPtr    pCursor
     )
 {
     Bool val;
@@ -610,7 +615,7 @@ RACRealizeCursor (
     DPRINT_S("RACRealizeCursor",pScreen->myNum);
     SCREEN_PROLOG (RealizeCursor);
     ENABLE;
-    val = (*pScreen->RealizeCursor) (pScreen,pCursor);
+    val = (*pScreen->RealizeCursor) (pDev, pScreen,pCursor);
     
     SCREEN_EPILOG ( RealizeCursor, RACRealizeCursor);
     return val;
@@ -618,8 +623,9 @@ RACRealizeCursor (
 
 static Bool
 RACUnrealizeCursor (    
-    ScreenPtr   pScreen,
-    CursorPtr   pCursor
+    DeviceIntPtr pDev,
+    ScreenPtr    pScreen,
+    CursorPtr    pCursor
     )
 {
     Bool val;
@@ -627,7 +633,7 @@ RACUnrealizeCursor (
     DPRINT_S("RACUnrealizeCursor",pScreen->myNum);
     SCREEN_PROLOG (UnrealizeCursor);
     ENABLE;
-    val = (*pScreen->UnrealizeCursor) (pScreen,pCursor);
+    val = (*pScreen->UnrealizeCursor) (pDev, pScreen,pCursor);
     
     SCREEN_EPILOG ( UnrealizeCursor, RACUnrealizeCursor);
     return val;
@@ -635,8 +641,9 @@ RACUnrealizeCursor (
 
 static Bool
 RACDisplayCursor (    
-    ScreenPtr   pScreen,
-    CursorPtr   pCursor
+    DeviceIntPtr pDev,
+    ScreenPtr    pScreen,
+    CursorPtr    pCursor
     )
 {
     Bool val;
@@ -644,7 +651,7 @@ RACDisplayCursor (
     DPRINT_S("RACDisplayCursor",pScreen->myNum);
     SCREEN_PROLOG (DisplayCursor);
     ENABLE;
-    val = (*pScreen->DisplayCursor) (pScreen,pCursor);
+    val = (*pScreen->DisplayCursor) (pDev, pScreen,pCursor);
     
     SCREEN_EPILOG ( DisplayCursor, RACDisplayCursor);
     return val;
@@ -652,6 +659,7 @@ RACDisplayCursor (
 
 static Bool
 RACSetCursorPosition (    
+    DeviceIntPtr pDev,
     ScreenPtr   pScreen,
     int x, int y,
     Bool generateEvent)
@@ -661,7 +669,7 @@ RACSetCursorPosition (
     DPRINT_S("RACSetCursorPosition",pScreen->myNum);
     SCREEN_PROLOG (SetCursorPosition);
     ENABLE;
-    val = (*pScreen->SetCursorPosition) (pScreen,x,y,generateEvent);
+    val = (*pScreen->SetCursorPosition) (pDev, pScreen,x,y,generateEvent);
     
     SCREEN_EPILOG ( SetCursorPosition, RACSetCursorPosition);
     return val;
diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index ec813e0..5a8509b 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -38,7 +38,7 @@ static miPointerSpriteFuncRec xf86CursorSpriteFuncs = {
 /* Screen functions */
 
 static void xf86CursorInstallColormap(ColormapPtr);
-static void xf86CursorRecolorCursor(ScreenPtr, CursorPtr, Bool);
+static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr, Bool);
 static Bool xf86CursorCloseScreen(int, ScreenPtr);
 static void xf86CursorQueryBestSize(int, unsigned short*, unsigned short*,
 				    ScreenPtr);
@@ -181,6 +181,7 @@ xf86CursorInstallColormap(ColormapPtr pMap)
 
 static void
 xf86CursorRecolorCursor(
+    DeviceIntPtr pDev,
     ScreenPtr pScreen,
     CursorPtr pCurs,
     Bool displayed)
@@ -192,7 +193,7 @@ xf86CursorRecolorCursor(
 	return;
 
     if (ScreenPriv->SWCursor)
-	(*ScreenPriv->RecolorCursor)(pScreen, pCurs, displayed);
+	(*ScreenPriv->RecolorCursor)(pDev, pScreen, pCurs, displayed);
     else
 	xf86RecolorCursor(pScreen, pCurs, displayed);
 }
diff --git a/include/cursor.h b/include/cursor.h
index b28f8db..7aacf23 100644
--- a/include/cursor.h
+++ b/include/cursor.h
@@ -131,6 +131,7 @@ extern void CheckCursorConfinement(
     WindowPtr /*pWin*/);
 
 extern void NewCurrentScreen(
+    struct _DeviceIntRec* /*pDev*/,
     ScreenPtr /*newScreen*/,
     int /*x*/,
     int /*y*/);
diff --git a/include/dix.h b/include/dix.h
index d59cccc..6f2e43a 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -821,4 +821,8 @@ extern int xstrcasecmp(char *s1, char *s2);
 /* ffs.c */
 extern int ffs(int i);
 
+#ifdef MPX
+extern Bool MPHasCursor(DeviceIntPtr pDev);
+#endif
+
 #endif /* DIX_H */
diff --git a/include/inputstr.h b/include/inputstr.h
index 6f6b676..5128293 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -330,7 +330,7 @@ typedef struct _DeviceIntRec {
     int			nPrivates;
     DeviceUnwrapProc    unwrapProc;
 #ifdef MPX
-    Bool        isMPDev;                /* TRUE if multipointer device */
+    Bool                isMPDev;           /* TRUE if multipointer device */
 #endif
 } DeviceIntRec;
 
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 4fa2919..629d45e 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -121,6 +121,7 @@ typedef    void (* GetSpansProcPtr)(
 	char * /*pdstStart*/);
 
 typedef    void (* PointerNonInterestBoxProcPtr)(
+        DeviceIntPtr /*pDev*/,
 	ScreenPtr /*pScreen*/,
 	BoxPtr /*pBox*/);
 
@@ -262,29 +263,35 @@ typedef    void (* ConstrainCursorProcPtr)(
 	BoxPtr /*pBox*/);
 
 typedef    void (* CursorLimitsProcPtr)(
+        DeviceIntPtr /* pDev */,
 	ScreenPtr /*pScreen*/,
 	CursorPtr /*pCursor*/,
 	BoxPtr /*pHotBox*/,
 	BoxPtr /*pTopLeftBox*/);
 
 typedef    Bool (* DisplayCursorProcPtr)(
+        DeviceIntPtr /* pDev */,
 	ScreenPtr /*pScreen*/,
 	CursorPtr /*pCursor*/);
 
 typedef    Bool (* RealizeCursorProcPtr)(
+        DeviceIntPtr /* pDev */,
 	ScreenPtr /*pScreen*/,
 	CursorPtr /*pCursor*/);
 
 typedef    Bool (* UnrealizeCursorProcPtr)(
+        DeviceIntPtr /* pDev */,
 	ScreenPtr /*pScreen*/,
 	CursorPtr /*pCursor*/);
 
 typedef    void (* RecolorCursorProcPtr)(
+        DeviceIntPtr /* pDev */,
 	ScreenPtr /*pScreen*/,
 	CursorPtr /*pCursor*/,
 	Bool /*displayed*/);
 
 typedef    Bool (* SetCursorPositionProcPtr)(
+        DeviceIntPtr /* pDev */,
 	ScreenPtr /*pScreen*/,
 	int /*x*/,
 	int /*y*/,
diff --git a/mi/mi.h b/mi/mi.h
index 8d9d120..6b67e42 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -137,6 +137,7 @@ extern void miPutImage(
 /* micursor.c */
 
 extern void miRecolorCursor(
+    DeviceIntPtr /* pDev */,
     ScreenPtr /*pScr*/,
     CursorPtr /*pCurs*/,
     Bool /*displayed*/
diff --git a/mi/micursor.c b/mi/micursor.c
index 6e06fbc..af2cd08 100644
--- a/mi/micursor.c
+++ b/mi/micursor.c
@@ -52,24 +52,26 @@ SOFTWARE.
 #include "cursor.h"
 #include "misc.h"
 #include "mi.h"
+#include "inputstr.h"
 
 extern Bool Must_have_memory;
 
 _X_EXPORT void
-miRecolorCursor( pScr, pCurs, displayed)
-    ScreenPtr	pScr;
-    CursorPtr	pCurs;
-    Bool	displayed;
+miRecolorCursor( pDev, pScr, pCurs, displayed)
+    DeviceIntPtr pDev;
+    ScreenPtr	 pScr;
+    CursorPtr	 pCurs;
+    Bool	 displayed;
 {
     /*
      * This is guaranteed to correct any color-dependent state which may have
      * been bound up in private state created by RealizeCursor
      */
-    (* pScr->UnrealizeCursor)( pScr, pCurs);
+    (* pScr->UnrealizeCursor)( pDev, pScr, pCurs);
     Must_have_memory = TRUE; /* XXX */
-    (* pScr->RealizeCursor)( pScr, pCurs);
+    (* pScr->RealizeCursor)( pDev, pScr, pCurs);
     Must_have_memory = FALSE; /* XXX */
     if ( displayed)
-	(* pScr->DisplayCursor)( pScr, pCurs);
+	(* pScr->DisplayCursor)( pDev, pScr, pCurs);
 
 }
diff --git a/mi/mieq.c b/mi/mieq.c
index 2d12388..40a3a52 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -209,7 +209,7 @@ mieqProcessInputEvents()
                 miEventQueue.head = 0;
             else
                 ++miEventQueue.head;
-            NewCurrentScreen (miEventQueue.pDequeueScreen, x, y);
+            NewCurrentScreen (e->pDev, miEventQueue.pDequeueScreen, x, y);
         }
         else {
             if (miEventQueue.head == QUEUE_SIZE - 1)
diff --git a/mi/mipointer.c b/mi/mipointer.c
index f954ba6..acce4cc 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -68,7 +68,9 @@ static unsigned long miPointerGeneration = 0;
 static miPointerPtr miPointer;
 
 #ifdef MPX
-/* Multipointers */
+/* Multipointers 
+ * ID of a device == index in this array.
+ */
 static miPointerRec miMPPointers[MAX_DEVICES];
 
 
@@ -80,19 +82,26 @@ IsMPDev(DeviceIntPtr pDev)
 }
 #endif
 
-static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
+static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                                   CursorPtr pCursor);
+static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                                     CursorPtr pCursor);
+static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                                   CursorPtr pCursor);
 static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
                                      BoxPtr pBox); 
-static void miPointerPointerNonInterestBox(ScreenPtr
-            pScreen, BoxPtr pBox);
-static void miPointerCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
-				  BoxPtr pHotBox, BoxPtr pTopLeftBox);
-static Bool miPointerSetCursorPosition(ScreenPtr pScreen, int x, int y,
+static void miPointerPointerNonInterestBox(DeviceIntPtr pDev, 
+                                           ScreenPtr pScreen, BoxPtr pBox);
+static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
+                                  CursorPtr pCursor, BoxPtr pHotBox, 
+                                  BoxPtr pTopLeftBox);
+static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                                       int x, int y,
 				       Bool generateEvent);
 static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
-static void miPointerMove(ScreenPtr pScreen, int x, int y, unsigned long time);
+static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                          int x, int y,
+                          unsigned long time);
 
 _X_EXPORT Bool
 miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
@@ -101,9 +110,6 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     miPointerScreenFuncPtr  screenFuncs;
     Bool		    waitForUpdate;
 {
-#ifdef MPX
-    int mpPtrIdx = 0; /* loop counter */
-#endif
     miPointerScreenPtr	pScreenPriv;
 
     if (miPointerGeneration != serverGeneration)
@@ -147,7 +153,7 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     miPointer = (miPointerPtr)xalloc(sizeof(miPointerRec));
     if (!miPointer)
     {
-        xfree(pScreenPriv);
+        xfree((pointer)pScreenPriv);
         return FALSE;
     }
     miPointer->pScreen = NULL;
@@ -165,23 +171,26 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
 #ifdef MPX
     xfree(miPointer);
     miPointer = &miMPPointers[1];
-    /*
-     * Set up pointer objects for multipointer devices.
-     */
-    while(mpPtrIdx < MAX_DEVICES)
     {
-        miMPPointers[mpPtrIdx].pScreen = NULL;
-        miMPPointers[mpPtrIdx].pSpriteScreen = NULL;
-        miMPPointers[mpPtrIdx].pCursor = NULL;
-        miMPPointers[mpPtrIdx].pSpriteCursor = NULL;
-        miMPPointers[mpPtrIdx].limits.x1 = 0;
-        miMPPointers[mpPtrIdx].limits.x2 = 32767;
-        miMPPointers[mpPtrIdx].limits.y1 = 0;
-        miMPPointers[mpPtrIdx].limits.y2 = 32767;
-        miMPPointers[mpPtrIdx].confined = FALSE;
-        miMPPointers[mpPtrIdx].x = 0;
-        miMPPointers[mpPtrIdx].y = 0;
-        mpPtrIdx++;
+        int mpPtrIdx = 0; /* loop counter */
+        /*
+         * Set up pointer objects for multipointer devices.
+         */
+        while(mpPtrIdx < MAX_DEVICES)
+        {
+            miMPPointers[mpPtrIdx].pScreen = NULL;
+            miMPPointers[mpPtrIdx].pSpriteScreen = NULL;
+            miMPPointers[mpPtrIdx].pCursor = NULL;
+            miMPPointers[mpPtrIdx].pSpriteCursor = NULL;
+            miMPPointers[mpPtrIdx].limits.x1 = 0;
+            miMPPointers[mpPtrIdx].limits.x2 = 32767;
+            miMPPointers[mpPtrIdx].limits.y1 = 0;
+            miMPPointers[mpPtrIdx].limits.y2 = 32767;
+            miMPPointers[mpPtrIdx].confined = FALSE;
+            miMPPointers[mpPtrIdx].x = 0;
+            miMPPointers[mpPtrIdx].y = 0;
+            mpPtrIdx++;
+        }
     }
 #endif
 
@@ -196,10 +205,6 @@ miPointerCloseScreen (index, pScreen)
     int mpPointerIdx = 0;
     SetupScreen(pScreen);
 
-    if (pScreen == miPointer->pScreen)
-	miPointer->pScreen = 0;
-    if (pScreen == miPointer->pSpriteScreen)
-	miPointer->pSpriteScreen = 0;
 #ifdef MPX
     while(mpPointerIdx < MAX_DEVICES)
     {
@@ -209,6 +214,12 @@ miPointerCloseScreen (index, pScreen)
             miMPPointers[mpPointerIdx].pSpriteScreen = 0;
         mpPointerIdx++;
     }
+#else
+    if (pScreen == miPointer->pScreen)
+	miPointer->pScreen = 0;
+    if (pScreen == miPointer->pSpriteScreen)
+	miPointer->pSpriteScreen = 0;
+    xfree((pointer)miPointer);
 #endif
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
     xfree ((pointer) pScreenPriv);
@@ -220,67 +231,44 @@ miPointerCloseScreen (index, pScreen)
  */
 
 static Bool
-miPointerRealizeCursor (pScreen, pCursor)
-    ScreenPtr	pScreen;
-    CursorPtr	pCursor;
+miPointerRealizeCursor (pDev, pScreen, pCursor)
+    DeviceIntPtr pDev;
+    ScreenPtr	 pScreen;
+    CursorPtr	 pCursor;
 {
-    DeviceIntPtr pDev = inputInfo.pointer;
-
     SetupScreen(pScreen);
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
-    {
-        if (pDev != inputInfo.keyboard)
-            (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
-        pDev = pDev->next;
-    }
-    return TRUE;
-#else
     return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
-#endif
 }
 
 static Bool
-miPointerUnrealizeCursor (pScreen, pCursor)
-    ScreenPtr	pScreen;
-    CursorPtr	pCursor;
+miPointerUnrealizeCursor (pDev, pScreen, pCursor)
+    DeviceIntPtr pDev;
+    ScreenPtr	 pScreen;
+    CursorPtr	 pCursor;
 {
-    DeviceIntPtr pDev = inputInfo.pointer;
     SetupScreen(pScreen);
-
-#ifdef MPX
-    pDev = inputInfo.devices;
-    while(pDev)
-    {
-        if (pDev != inputInfo.keyboard)
-            (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
-        pDev = pDev->next;
-    }
-    return TRUE;
-#else
     return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
-#endif
 }
 
 static Bool
-miPointerDisplayCursor (pScreen, pCursor)
-    ScreenPtr	pScreen;
-    CursorPtr	pCursor;
+miPointerDisplayCursor (pDev, pScreen, pCursor)
+    DeviceIntPtr pDev;
+    ScreenPtr 	 pScreen;
+    CursorPtr	 pCursor;
 {
 #ifdef MPX
-    int mpPtrIdx = 0;
-    while (mpPtrIdx < MAX_DEVICES)
-    {
-        miMPPointers[mpPtrIdx].pCursor = pCursor;
-        miMPPointers[mpPtrIdx].pScreen = pScreen;
-        mpPtrIdx++;
-    }
+    /* use core pointer for non MPX devices */
+    if (!IsMPDev(pDev))
+        pDev = inputInfo.pointer;
 
-#endif
+    miMPPointers[pDev->id].pCursor = pCursor;
+    miMPPointers[pDev->id].pScreen = pScreen;
+    miPointerUpdateSprite(pDev);
+#else
     miPointer->pCursor = pCursor;
     miPointer->pScreen = pScreen;
     miPointerUpdateSprite(inputInfo.pointer);
+#endif
     return TRUE;
 }
 
@@ -301,20 +289,22 @@ miPointerConstrainCursor (pDev, pScreen, pBox)
 
 /*ARGSUSED*/
 static void
-miPointerPointerNonInterestBox (pScreen, pBox)
-    ScreenPtr	pScreen;
-    BoxPtr	pBox;
+miPointerPointerNonInterestBox (pDev, pScreen, pBox)
+    DeviceIntPtr pDev;
+    ScreenPtr	 pScreen;
+    BoxPtr	 pBox;
 {
     /* until DIX uses this, this will remain a stub */
 }
 
 /*ARGSUSED*/
 static void
-miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox)
-    ScreenPtr	pScreen;
-    CursorPtr	pCursor;
-    BoxPtr	pHotBox;
-    BoxPtr	pTopLeftBox;
+miPointerCursorLimits(pDev, pScreen, pCursor, pHotBox, pTopLeftBox)
+    DeviceIntPtr pDev;
+    ScreenPtr	 pScreen;
+    CursorPtr	 pCursor;
+    BoxPtr	 pHotBox;
+    BoxPtr	 pTopLeftBox;
 {
     *pTopLeftBox = *pHotBox;
 }
@@ -322,33 +312,40 @@ miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox)
 static Bool GenerateEvent;
 
 static Bool
-miPointerSetCursorPosition(pScreen, x, y, generateEvent)
-    ScreenPtr pScreen;
-    int       x, y;
-    Bool      generateEvent;
+miPointerSetCursorPosition(pDev, pScreen, x, y, generateEvent)
+    DeviceIntPtr pDev;
+    ScreenPtr    pScreen;
+    int          x, y;
+    Bool         generateEvent;
 {
     SetupScreen (pScreen);
 
     GenerateEvent = generateEvent;
     /* device dependent - must pend signal and call miPointerWarpCursor */
-    (*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y);
+    (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
     if (!generateEvent)
-	miPointerUpdateSprite(inputInfo.pointer);
+	miPointerUpdateSprite(pDev);
     return TRUE;
 }
 
 /* Once signals are ignored, the WarpCursor function can call this */
 
 _X_EXPORT void
-miPointerWarpCursor (pScreen, x, y)
-    ScreenPtr	pScreen;
-    int		x, y;
+miPointerWarpCursor (pDev, pScreen, x, y)
+    DeviceIntPtr pDev;
+    ScreenPtr	 pScreen;
+    int	   	 x, y;
 {
-    DeviceIntPtr pDev = inputInfo.pointer;
-
+    miPointerPtr pPointer = miPointer;
     SetupScreen (pScreen);
 
-    if (miPointer->pScreen != pScreen)
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pPointer = &miMPPointers[pDev->id];
+#endif
+
+
+    if (pPointer->pScreen != pScreen)
 	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
 
     if (GenerateEvent)
@@ -359,16 +356,16 @@ miPointerWarpCursor (pScreen, x, y)
     {
 	/* everything from miPointerMove except the event and history */
 
-    	if (!pScreenPriv->waitForUpdate && pScreen == miPointer->pSpriteScreen)
+    	if (!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
     	{
-	    miPointer->devx = x;
-	    miPointer->devy = y;
-	    if(!miPointer->pCursor->bits->emptyMask)
+	    pPointer->devx = x;
+	    pPointer->devy = y;
+	    if(!pPointer->pCursor->bits->emptyMask)
 		(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     	}
-	miPointer->x = x;
-	miPointer->y = y;
-	miPointer->pScreen = pScreen;
+	pPointer->x = x;
+	pPointer->y = y;
+	pPointer->pScreen = pScreen;
     }
 }
 
@@ -395,7 +392,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     miPointerScreenPtr	pScreenPriv;
     CursorPtr		pCursor;
     int			x, y, devx, devy;
-    miPointerPtr        pPointer;
+    miPointerPtr        pPointer = miPointer;
 
 #ifdef MPX
     if (!pDev || 
@@ -408,8 +405,6 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
 #ifdef MPX
     if (IsMPDev(pDev))
         pPointer = &miMPPointers[pDev->id];
-    else
-        pPointer = miPointer;
 #endif
 
     pScreen = pPointer->pScreen;
@@ -495,22 +490,18 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
 {
 	miPointerScreenPtr pScreenPriv;
 	ScreenPtr pScreen;
+        miPointerPtr pPointer = miPointer;
 
 	pScreen = screenInfo.screens[screen_no];
 	pScreenPriv = GetScreenPrivate (pScreen);
 	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
-	NewCurrentScreen (pScreen, x, y);
+	NewCurrentScreen (pDev, pScreen, x, y);
 #ifdef MPX
         if (IsMPDev(pDev))
-        {
-            miMPPointers[pDev->id].limits.x2 = pScreen->width;
-            miMPPointers[pDev->id].limits.y2 = pScreen->height;
-        }
+            pPointer = &miMPPointers[pDev->id];
 #endif
-        {
-            miPointer->limits.x2 = pScreen->width;
-            miPointer->limits.y2 = pScreen->height;
-        }
+        pPointer->limits.x2 = pScreen->width;
+        pPointer->limits.y2 = pScreen->height;
 }
 
 _X_EXPORT ScreenPtr
@@ -522,11 +513,12 @@ miPointerCurrentScreen ()
 _X_EXPORT ScreenPtr
 miPointerGetScreen(DeviceIntPtr pDev)
 {
+    miPointerPtr pPointer;
 #ifdef MPX
     if (IsMPDev(pDev))
-        return miMPPointers[pDev->id].pScreen;
+        pPointer = &miMPPointers[pDev->id];
 #endif
-    return miPointer->pScreen;
+    return pPointer->pScreen;
 }
 
 /* Move the pointer to x, y on the current screen, update the sprite, and
@@ -545,13 +537,11 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     ScreenPtr		pScreen;
     ScreenPtr		newScreen;
 
-    miPointerPtr        pPointer;
+    miPointerPtr        pPointer = miPointer;
 #ifdef MPX
     if (IsMPDev(pDev))
         pPointer = &(miMPPointers[pDev->id]);
-    else
 #endif
-        pPointer = miPointer;
 
     pScreen = pPointer->pScreen;
     if (!pScreen)
@@ -609,24 +599,19 @@ miPointerPosition (int *x, int *y)
 _X_EXPORT void
 miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
 {
+    miPointerPtr pPointer = miPointer;
 #ifdef MPX
     if (IsMPDev(pDev))
-    {
-        *x = miMPPointers[pDev->id].x;
-        *y = miMPPointers[pDev->id].y;
-    }
-    else
+        pPointer = &miMPPointers[pDev->id];
 #endif
-    {
-        *x = miPointer->x;
-        *y = miPointer->y;
-    }
+    *x = pPointer->x;
+    *y = pPointer->y;
 }
 
 void
-miPointerMove (ScreenPtr pScreen, int x, int y, unsigned long time)
+miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, unsigned long time)
 {
-    miPointerMoved(inputInfo.pointer, pScreen, x, y, time);
+    miPointerMoved(pDev, pScreen, x, y, time);
 }
 
 /* Move the pointer on the current screen,  and update the sprite. */
@@ -634,15 +619,13 @@ void
 miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
                      unsigned long time)
 {
-    miPointerPtr pPointer;
+    miPointerPtr pPointer = miPointer;
     SetupScreen(pScreen);
 
 #ifdef MPX
     if (IsMPDev(pDev))
         pPointer = &miMPPointers[pDev->id];
-    else
 #endif
-        pPointer = miPointer;
 
     if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer
 #ifdef MPX
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 1b01ba1..85c5c8b 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -72,6 +72,7 @@ typedef struct _miPointerScreenFuncRec {
                     int  /* entering */
                     );
     void	(*WarpCursor)(
+                    DeviceIntPtr /*pDev*/, 
                     ScreenPtr /* pScr */,
                     int  /* x */,
                     int  /* y */
@@ -99,6 +100,7 @@ extern Bool miPointerInitialize(
 );
 
 extern void miPointerWarpCursor(
+    DeviceIntPtr /*pDev*/,
     ScreenPtr /*pScreen*/,
     int /*x*/,
     int /*y*/
diff --git a/render/animcur.c b/render/animcur.c
index 8e4f59d..2b552a3 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -44,6 +44,7 @@
 #include "dixfontstr.h"
 #include "opaque.h"
 #include "picturestr.h"
+#include "inputstr.h"
 
 typedef struct _AnimCurElt {
     CursorPtr	pCursor;    /* cursor to show */
@@ -100,11 +101,13 @@ int	AnimCurGeneration;
 #define Unwrap(as,s,elt)    ((s)->elt = (as)->elt)
 
 static Bool
-AnimCurDisplayCursor (ScreenPtr pScreen,
+AnimCurDisplayCursor (DeviceIntPtr pDev, 
+                      ScreenPtr pScreen,
 		      CursorPtr pCursor);
 
 static Bool
-AnimCurSetCursorPosition (ScreenPtr pScreen,
+AnimCurSetCursorPosition (DeviceIntPtr pDev,
+                          ScreenPtr pScreen,
 			  int x,
 			  int y,
 			  Bool generateEvent);
@@ -134,7 +137,8 @@ AnimCurCloseScreen (int index, ScreenPtr pScreen)
 }
 
 static void 
-AnimCurCursorLimits (ScreenPtr pScreen,
+AnimCurCursorLimits (DeviceIntPtr pDev,
+                     ScreenPtr pScreen,
 		     CursorPtr pCursor,
 		     BoxPtr pHotBox,
 		     BoxPtr pTopLeftBox)
@@ -146,11 +150,13 @@ AnimCurCursorLimits (ScreenPtr pScreen,
     {
 	AnimCurPtr	ac = GetAnimCur(pCursor);
 
-	(*pScreen->CursorLimits) (pScreen, ac->elts[0].pCursor, pHotBox, pTopLeftBox);
+        (*pScreen->CursorLimits) (pDev, pScreen, ac->elts[0].pCursor, 
+                                  pHotBox, pTopLeftBox); 
     }
     else
     {
-	(*pScreen->CursorLimits) (pScreen, pCursor, pHotBox, pTopLeftBox);
+        (*pScreen->CursorLimits) (inputInfo.pointer, pScreen, pCursor,
+                                  pHotBox, pTopLeftBox); 
     }
     Wrap (as, pScreen, CursorLimits, AnimCurCursorLimits);
 }
@@ -187,7 +193,9 @@ AnimCurScreenBlockHandler (int screenNum,
 	     */
 	    DisplayCursor = pScreen->DisplayCursor;
 	    pScreen->DisplayCursor = as->DisplayCursor;
-	    (void) (*pScreen->DisplayCursor) (pScreen, ac->elts[elt].pCursor);
+	    (void) (*pScreen->DisplayCursor) (inputInfo.pointer, 
+                                              pScreen, 
+                                              ac->elts[elt].pCursor);
 	    as->DisplayCursor = pScreen->DisplayCursor;
 	    pScreen->DisplayCursor = DisplayCursor;
 
@@ -202,7 +210,8 @@ AnimCurScreenBlockHandler (int screenNum,
 }
 
 static Bool
-AnimCurDisplayCursor (ScreenPtr pScreen,
+AnimCurDisplayCursor (DeviceIntPtr pDev,
+                      ScreenPtr pScreen,
 		      CursorPtr pCursor)
 {
     AnimCurScreenPtr    as = GetAnimCurScreen(pScreen);
@@ -215,7 +224,8 @@ AnimCurDisplayCursor (ScreenPtr pScreen,
 	{
 	    AnimCurPtr		ac = GetAnimCur(pCursor);
 
-	    ret = (*pScreen->DisplayCursor) (pScreen, ac->elts[0].pCursor);
+	    ret = (*pScreen->DisplayCursor) 
+                (pDev, pScreen, ac->elts[0].pCursor);
 	    if (ret)
 	    {
 		animCurState.elt = 0;
@@ -231,14 +241,15 @@ AnimCurDisplayCursor (ScreenPtr pScreen,
     {
         animCurState.pCursor = 0;
 	animCurState.pScreen = 0;
-	ret = (*pScreen->DisplayCursor) (pScreen, pCursor);
+	ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
     }
     Wrap (as, pScreen, DisplayCursor, AnimCurDisplayCursor);
     return ret;
 }
 
 static Bool
-AnimCurSetCursorPosition (ScreenPtr pScreen,
+AnimCurSetCursorPosition (DeviceIntPtr pDev,
+                          ScreenPtr pScreen,
 			  int x,
 			  int y,
 			  Bool generateEvent)
@@ -249,13 +260,14 @@ AnimCurSetCursorPosition (ScreenPtr pScreen,
     Unwrap (as, pScreen, SetCursorPosition);
     if (animCurState.pCursor)
 	animCurState.pScreen = pScreen;
-    ret = (*pScreen->SetCursorPosition) (pScreen, x, y, generateEvent);
+    ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
     Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition);
     return ret;
 }
 
 static Bool 
-AnimCurRealizeCursor (ScreenPtr pScreen,
+AnimCurRealizeCursor (DeviceIntPtr pDev,
+                      ScreenPtr pScreen,
 		      CursorPtr pCursor)
 {
     AnimCurScreenPtr    as = GetAnimCurScreen(pScreen);
@@ -265,13 +277,14 @@ AnimCurRealizeCursor (ScreenPtr pScreen,
     if (IsAnimCur(pCursor))
 	ret = TRUE;
     else
-	ret = (*pScreen->RealizeCursor) (pScreen, pCursor);
+	ret = (*pScreen->RealizeCursor) (pDev, pScreen, pCursor);
     Wrap (as, pScreen, RealizeCursor, AnimCurRealizeCursor);
     return ret;
 }
 
 static Bool 
-AnimCurUnrealizeCursor (ScreenPtr pScreen,
+AnimCurUnrealizeCursor (DeviceIntPtr pDev,
+                        ScreenPtr pScreen,
 			CursorPtr pCursor)
 {
     AnimCurScreenPtr    as = GetAnimCurScreen(pScreen);
@@ -289,13 +302,14 @@ AnimCurUnrealizeCursor (ScreenPtr pScreen,
 	ret = TRUE;
     }
     else
-	ret = (*pScreen->UnrealizeCursor) (pScreen, pCursor);
+	ret = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor);
     Wrap (as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor);
     return ret;
 }
 
 static void
-AnimCurRecolorCursor (ScreenPtr pScreen,
+AnimCurRecolorCursor (DeviceIntPtr pDev,
+                      ScreenPtr pScreen,
 		      CursorPtr pCursor,
 		      Bool displayed)
 {
@@ -308,12 +322,12 @@ AnimCurRecolorCursor (ScreenPtr pScreen,
 	int	    i;
 
         for (i = 0; i < ac->nelt; i++)
-	    (*pScreen->RecolorCursor) (pScreen, ac->elts[i].pCursor,
+	    (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor,
 				       displayed && 
 				       animCurState.elt == i);
     }
     else
-	(*pScreen->RecolorCursor) (pScreen, pCursor, displayed);
+	(*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed);
     Wrap (as, pScreen, RecolorCursor, AnimCurRecolorCursor);
 }
 
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index 22f9b09..3bcd436 100755
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -122,7 +122,8 @@ typedef struct _CursorScreen {
 #define Unwrap(as,s,elt)	((s)->elt = (as)->elt)
 
 static Bool
-CursorDisplayCursor (ScreenPtr pScreen,
+CursorDisplayCursor (DeviceIntPtr pDev,
+                     ScreenPtr pScreen,
 		     CursorPtr pCursor)
 {
     CursorScreenPtr	cs = GetCursorScreen(pScreen);
@@ -131,9 +132,9 @@ CursorDisplayCursor (ScreenPtr pScreen,
     Unwrap (cs, pScreen, DisplayCursor);
 
     if (cs->pCursorHideCounts != NULL) {
-	ret = (*pScreen->DisplayCursor) (pScreen, pInvisibleCursor);
+	ret = (*pScreen->DisplayCursor) (pDev, pScreen, pInvisibleCursor);
     } else {
-	ret = (*pScreen->DisplayCursor) (pScreen, pCursor);
+	ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
     }
 
     if (pCursor != CursorCurrent)
@@ -866,7 +867,7 @@ ProcXFixesHideCursor (ClientPtr client)
     ret = createCursorHideCount(client, pWin->drawable.pScreen);
 
     if (ret == Success) {
-        (void) CursorDisplayCursor(pWin->drawable.pScreen, CursorCurrent);
+        (void) CursorDisplayCursor(inputInfo.pointer, pWin->drawable.pScreen, CursorCurrent);
     }
 
     return ret;
@@ -953,7 +954,7 @@ CursorFreeHideCount (pointer data, XID id)
     ScreenPtr pScreen = pChc->pScreen;
 
     deleteCursorHideCount(pChc, pChc->pScreen);
-    (void) CursorDisplayCursor(pScreen, CursorCurrent);
+    (void) CursorDisplayCursor(inputInfo.pointer, pScreen, CursorCurrent);
 
     return 1;
 }
diff --git a/xkb/ddxFakeMtn.c b/xkb/ddxFakeMtn.c
index 7e75c15..d15c5c1 100644
--- a/xkb/ddxFakeMtn.c
+++ b/xkb/ddxFakeMtn.c
@@ -113,7 +113,7 @@ ScreenPtr	   pScreen, oldScreen;
     }
 
     if (pScreen != oldScreen)
-	NewCurrentScreen(pScreen, oldX, oldY);
+	NewCurrentScreen(inputInfo.pointer, pScreen, oldX, oldY);
     if (pScreen->SetCursorPosition)
-	(*pScreen->SetCursorPosition)(pScreen, oldX, oldY, TRUE);
+	(*pScreen->SetCursorPosition)(inputInfo.pointer, pScreen, oldX, oldY, TRUE);
 }
commit f52d53e060d0468b658a565688d1f92c156405c7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 22 17:58:57 2006 +1030

    dix:	DeliverEventsToWindow adjusted for MPX
    
    mi:     sprite debugging disabled

diff --git a/Changelog b/Changelog
index 458060c..1f323ad 100644
--- a/Changelog
+++ b/Changelog
@@ -13,9 +13,10 @@ Xi:	fix: accessing other->buttons for keyboard segfaulted the server
 Files:
         mi/misprite.c
         mi/mipointer.c
-	dix/events.c
-	Xi/exevents.c
+        dix/events.c
+        Xi/exevents.c
 
+____________________________________________________________
 
 dix	GetSpriteWindow() adjusted for MPX
 	added device dependency for MPX to DoEnterLeaveEvents,
@@ -23,11 +24,23 @@ dix	GetSpriteWindow() adjusted for MPX
 	FixUpEventFromWindow.
 
 Files:
-	Xext/security.c
-	Xi/exevents.c
-	ddx/ddxFakeMtn.c
-	dix/events.c
-	include/dix.h
+        Xext/security.c
+        Xi/exevents.c
+        ddx/ddxFakeMtn.c
+        dix/events.c
+        include/dix.h
+
+____________________________________________________________
+
+dix:	DeliverEventsToWindow adjusted for MPX
+
+mi:     sprite debugging disabled
+
+Files:	
+        dix/events.c
+        Xi/exevents.c
+        mi/misprite.c
+        include/dix.h
 
 
 == 21.11.06 ==
@@ -43,6 +56,7 @@ Files:
 
 TAG: MPX_BEFORE_MIDC_API_BREAK
 
+____________________________________________________________
 
 mi:     added device ID to miSpriteCursorFuncRec functions
         added MPX code to midispcur.c
@@ -55,6 +69,7 @@ Files:
 
 BUG:   Core pointer changes whenever MPX cursor changes shape.
 
+____________________________________________________________
 
 mi:	constrain MPX cursors to screen 
 
@@ -66,6 +81,7 @@ Files:
 TAG:   MPX_BEFORE_DIX_API_BREAK
 
 
+____________________________________________________________
 
 dix:    moved sprite from static to be pointer of type SpritePtr
 	added SpriteRecs for MPX devices
@@ -89,6 +105,8 @@ Files:
         xfixes/cursor.c
 	mi/mieq.c
 
+____________________________________________________________
+
 dix:	WindowsRestructured() calls CheckMotion() on all devices
 
 mi:	core pointer was checked twice in miSpriteReportDamage,
@@ -112,6 +130,7 @@ Files:
         mi/misprite.c
         mi/mipointer.c
 
+____________________________________________________________
 
 mi:     added MPX to miSprite functions. 
 
@@ -149,6 +168,7 @@ Files:
         hw/xfree86/ramdac/xf86Cursor.c
         hw/xfree86/rac/xf86RAC.c
 
+____________________________________________________________
 
 mi:
         added miCursorInfoRec to contain info of the MPX cursors.
@@ -195,6 +215,7 @@ Files:
         configure.ac
         include/dix-config.h.in
 
+____________________________________________________________
 
 dix:    added isMPdev field to _DeviceIntRec, is used in GetPointerEvents()
 
@@ -210,6 +231,7 @@ Files:
         include/inputstr.h
         mi/mieq.c
 
+____________________________________________________________
 
 mieq:  EQ processing handles MP devices 
 
diff --git a/Xi/exevents.c b/Xi/exevents.c
index d89c379..ecbb199 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -394,7 +394,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
     event.window = pWin->drawable.id;
     event.time = currentTime.milliseconds;
 
-    (void)DeliverEventsToWindow(pWin, (xEvent *) & event, 1,
+    (void)DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
 				DeviceFocusChangeMask, NullGrab, dev->id);
 
     if ((type == DeviceFocusIn) &&
@@ -490,7 +490,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
 	    }
 	}
 
-	(void)DeliverEventsToWindow(pWin, (xEvent *) sev, evcount,
+	(void)DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
 				    DeviceStateNotifyMask, NullGrab, dev->id);
 	xfree(sev);
     }
@@ -820,7 +820,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
     ev->u.u.type |= 0x80;
     if (propagate) {
 	for (; pWin; pWin = pWin->parent) {
-	    if (DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id))
+	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id))
 		return Success;
 	    if (pWin == effectiveFocus)
 		return Success;
@@ -830,7 +830,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
 		break;
 	}
     } else
-	(void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id));
+	(void)(DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id));
     return Success;
 }
 
@@ -1229,7 +1229,7 @@ FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
 
     while (p1) {
         p2 = p1->firstChild;
-        (void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id);
+        (void)DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab, dev->id);
         FindInterestedChildren(dev, p2, mask, ev, count);
         p1 = p1->nextSib;
     }
@@ -1249,7 +1249,7 @@ SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
 
     for (i = 0; i < screenInfo.numScreens; i++) {
         pWin = WindowTable[i];
-        (void)DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, dev->id);
+        (void)DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab, dev->id);
         p1 = pWin->firstChild;
         FindInterestedChildren(dev, p1, mask, ev, count);
     }
diff --git a/dix/events.c b/dix/events.c
index 492e4a4..82d5d05 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1673,8 +1673,8 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
 }
 
 int
-DeliverEventsToWindow(register WindowPtr pWin, xEvent *pEvents, int count, 
-                      Mask filter, GrabPtr grab, int mskidx)
+DeliverEventsToWindow(DeviceIntPtr pDev, register WindowPtr pWin, xEvent
+        *pEvents, int count, Mask filter, GrabPtr grab, int mskidx)
 {
     int deliveries = 0, nondeliveries = 0;
     int attempt;
@@ -1736,7 +1736,7 @@ DeliverEventsToWindow(register WindowPtr pWin, xEvent *pEvents, int count,
     {
 	GrabRec tempGrab;
 
-	tempGrab.device = inputInfo.pointer;
+	tempGrab.device = pDev;
 	tempGrab.resource = client->clientAsMask;
 	tempGrab.window = pWin;
 	tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
@@ -1745,11 +1745,11 @@ DeliverEventsToWindow(register WindowPtr pWin, xEvent *pEvents, int count,
 	tempGrab.pointerMode = GrabModeAsync;
 	tempGrab.confineTo = NullWindow;
 	tempGrab.cursor = NullCursor;
-	(*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab,
+	(*inputInfo.pointer->ActivateGrab)(pDev, &tempGrab,
 					   currentTime, TRUE);
     }
     else if ((type == MotionNotify) && deliveries)
-	inputInfo.pointer->valuator->motionHintWindow = pWin;
+	pDev->valuator->motionHintWindow = pWin;
 #ifdef XINPUT
     else
     {
@@ -1911,7 +1911,7 @@ DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
 	    if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
 	    {
 		FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
-		deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
+		deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter,
 						   grab, mskidx);
 		if (deliveries > 0)
 		    return deliveries;
@@ -1936,7 +1936,7 @@ DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
 	    if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
 	    {
 		FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
-		deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
+		deliveries = DeliverEventsToWindow(dev, pWin, xE, count, filter,
 						   grab, 0);
 		if (deliveries > 0)
 		    return deliveries;
@@ -1971,20 +1971,20 @@ DeliverEvents(register WindowPtr pWin, register xEvent *xE, int count,
     if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
 	xE->u.destroyNotify.event = pWin->drawable.id;
     if (filter != StructureAndSubMask)
-	return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0);
-    deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask,
+	return DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, filter, NullGrab, 0);
+    deliveries = DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, StructureNotifyMask,
 				       NullGrab, 0);
     if (pWin->parent)
     {
 	xE->u.destroyNotify.event = pWin->parent->drawable.id;
-	deliveries += DeliverEventsToWindow(pWin->parent, xE, count,
+	deliveries += DeliverEventsToWindow(inputInfo.pointer, pWin->parent, xE, count,
 					    SubstructureNotifyMask, NullGrab,
 					    0);
 	if (xE->u.u.type == ReparentNotify)
 	{
 	    xE->u.destroyNotify.event = otherParent->drawable.id;
-	    deliveries += DeliverEventsToWindow(otherParent, xE, count,
-						SubstructureNotifyMask,
+            deliveries += DeliverEventsToWindow(inputInfo.pointer,
+                    otherParent, xE, count, SubstructureNotifyMask,
 						NullGrab, 0);
 	}
     }
@@ -2723,7 +2723,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
     FixUpEventFromWindow(inputInfo.pointer, xE, focus, None, FALSE);
     if (xE->u.u.type & EXTENSION_EVENT_BASE)
 	mskidx = keybd->id;
-    (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
+    (void)DeliverEventsToWindow(keybd, focus, xE, count, filters[xE->u.u.type],
 				NullGrab, mskidx);
 }
 
@@ -3394,7 +3394,7 @@ EnterLeaveEvent(
 	    (void)TryClientEvents(rClient(grab), &event, 1, mask,
 				  filters[type], grab);
 	else
-	    (void)DeliverEventsToWindow(pWin, &event, 1, filters[type],
+	    (void)DeliverEventsToWindow(pDev, pWin, &event, 1, filters[type],
 					NullGrab, 0);
     }
     if ((type == EnterNotify) && (mask & KeymapStateMask))
@@ -3416,7 +3416,7 @@ EnterLeaveEvent(
 	    (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
 				  KeymapStateMask, grab);
 	else
-	    (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
+	    (void)DeliverEventsToWindow(pDev, pWin, (xEvent *)&ke, 1,
 					KeymapStateMask, NullGrab, 0);
     }
 }
@@ -3507,8 +3507,8 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr
     event.u.u.type = type;
     event.u.u.detail = detail;
     event.u.focus.window = pWin->drawable.id;
-    (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab,
-				0);
+    (void)DeliverEventsToWindow(dev, pWin, &event, 1, filters[type], NullGrab,
+                                0);
     if ((type == FocusIn) &&
 	((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
     {
@@ -3523,7 +3523,7 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr
 #endif
 	memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
 	ke.type = KeymapNotify;
-	(void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
+	(void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
 				    KeymapStateMask, NullGrab, 0);
     }
 }
@@ -4318,8 +4318,8 @@ ProcSendEvent(ClientPtr client)
     {
 	for (;pWin; pWin = pWin->parent)
 	{
-	    if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
-				      NullGrab, 0))
+            if (DeliverEventsToWindow(inputInfo.pointer, pWin, &stuff->event,
+                                    1, stuff->eventMask, NullGrab, 0))
 		return Success;
 	    if (pWin == effectiveFocus)
 		return Success;
@@ -4329,8 +4329,8 @@ ProcSendEvent(ClientPtr client)
 	}
     }
     else
-	(void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
-				    NullGrab, 0);
+        (void)DeliverEventsToWindow(inputInfo.pointer, pWin, &stuff->event, 1,
+                                    stuff->eventMask, NullGrab, 0);
     return Success;
 }
 
diff --git a/include/dix.h b/include/dix.h
index 0c66d8d..d59cccc 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -570,6 +570,7 @@ extern void ReleaseActiveGrabs(
     ClientPtr client);
 
 extern int DeliverEventsToWindow(
+    DeviceIntPtr /* pWin */,
     WindowPtr /* pWin */,
     xEventPtr /* pEvents */,
     int /* count */,
diff --git a/mi/misprite.c b/mi/misprite.c
index 8907a3d..ec83e80 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -72,7 +72,7 @@ static miCursorInfoPtr DevToSprite(DeviceIntPtr pDev, ScreenPtr pScreen);
 #endif
 
 
-#define SPRITE_DEBUG_ENABLE 1
+#define SPRITE_DEBUG_ENABLE 0
 #if SPRITE_DEBUG_ENABLE
 #define SPRITE_DEBUG(x)	ErrorF x
 #else
commit 8c16f21d5df08b028e93440d632939a5fdbf5876
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 22 17:06:47 2006 +1030

    dix	GetSpriteWindow() adjusted for MPX
    	added device dependency for MPX to DoEnterLeaveEvents,
    	EnterLeaveEvents, EnterNotifies, LeaveNotifies and
    	FixUpEventFromWindow.

diff --git a/Changelog b/Changelog
index 93f1455..458060c 100644
--- a/Changelog
+++ b/Changelog
@@ -17,6 +17,19 @@ Files:
 	Xi/exevents.c
 
 
+dix	GetSpriteWindow() adjusted for MPX
+	added device dependency for MPX to DoEnterLeaveEvents,
+	EnterLeaveEvents, EnterNotifies, LeaveNotifies and
+	FixUpEventFromWindow.
+
+Files:
+	Xext/security.c
+	Xi/exevents.c
+	ddx/ddxFakeMtn.c
+	dix/events.c
+	include/dix.h
+
+
 == 21.11.06 ==
 mi:     added MPX to miSpriteReportDamage
         added id field to miCursorInfoPtr, required to pass through to miDC
diff --git a/Xext/security.c b/Xext/security.c
index ac76279..c1c8f1f 100644
--- a/Xext/security.c
+++ b/Xext/security.c
@@ -745,12 +745,12 @@ SecurityDetermineEventPropogationLimits(
 
     if (pFocusWin == PointerRootWin)
     { /* focus follows the pointer */
-	*ppWin = GetSpriteWindow();
+	*ppWin = GetSpriteWindow(dev);
 	*ppStopWin = NULL; /* propogate all the way to the root */
     }
     else
     { /* a real window is set for the focus */
-	WindowPtr pSpriteWin = GetSpriteWindow();
+	WindowPtr pSpriteWin = GetSpriteWindow(dev);
 	*ppStopWin = pFocusWin->parent; /* don't go past the focus window */
 
 	/* if the pointer is in a subwindow of the focus window, start
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 13687e3..d89c379 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -276,9 +276,9 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
     if (grab)
 	DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count);
     else if (other->focus)
-	DeliverFocusedEvent(other, xE, GetSpriteWindow(), count);
+	DeliverFocusedEvent(other, xE, GetSpriteWindow(other), count);
     else
-	DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow,
+	DeliverDeviceEvents(GetSpriteWindow(other), xE, NullGrab, NullWindow,
 			    other, count);
 
     if (deactivateDeviceGrab == TRUE)
@@ -781,7 +781,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
 {
     WindowPtr pWin;
     WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
-    WindowPtr spriteWin = GetSpriteWindow();
+    WindowPtr spriteWin = GetSpriteWindow(d);
 
     if (dest == PointerWindow)
 	pWin = spriteWin;
diff --git a/dix/events.c b/dix/events.c
index bb6bcfc..492e4a4 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -270,6 +270,7 @@ _X_EXPORT HotSpot xeviehot;
 #endif
 
 static void DoEnterLeaveEvents(
+    DeviceIntPtr pDev, 
     WindowPtr fromWin,
     WindowPtr toWin,
     int mode
@@ -614,8 +615,9 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	if (prevSpriteWin != NullWindow) {
 	    if (!xE)
 		UpdateCurrentTimeIf();
-	    DoEnterLeaveEvents(prevSpriteWin, pSprite->win, NotifyNormal);
-	}
+            DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win,
+                               NotifyNormal); 
+        }
 	PostNewCursor(pDev);
         return FALSE;
     }
@@ -991,8 +993,13 @@ GetCurrentRootWindow()
 }
 
 _X_EXPORT WindowPtr
-GetSpriteWindow()
+GetSpriteWindow(DeviceIntPtr pDev)
 {
+#ifdef MPX
+    if(IsMPDev(pDev))
+        return mpsprites[pDev->id].win;
+#endif
+
     return sprite->win;
 }
 
@@ -1321,7 +1328,7 @@ ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
 	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
 	ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
     }
-    DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
+    DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
     mouse->valuator->motionHintWindow = NullWindow;
     if (syncEvents.playingEvents)
 	mouse->grabTime = syncEvents.time;
@@ -1351,7 +1358,7 @@ DeactivatePointerGrab(register DeviceIntPtr mouse)
 	if (dev->sync.other == grab)
 	    dev->sync.other = NullGrab;
     }
-    DoEnterLeaveEvents(grab->window, sprite->win, NotifyUngrab);
+    DoEnterLeaveEvents(mouse, grab->window, sprite->win, NotifyUngrab);
     if (grab->confineTo)
 	ConfineCursorToWindow(ROOT, FALSE, FALSE);
     PostNewCursor(inputInfo.pointer);
@@ -1823,11 +1830,18 @@ MaybeDeliverEventsToClient(register WindowPtr pWin, xEvent *pEvents,
 
 static void
 FixUpEventFromWindow(
+    DeviceIntPtr pDev,
     xEvent *xE,
     WindowPtr pWin,
     Window child,
     Bool calcChild)
 {
+    SpritePtr pSprite = sprite;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+
     if (calcChild)
     {
         WindowPtr w=spriteTrace[spriteTraceGood-1];
@@ -1857,7 +1871,7 @@ FixUpEventFromWindow(
     }
     XE_KBPTR.root = ROOT->drawable.id;
     XE_KBPTR.event = pWin->drawable.id;
-    if (sprite->hot.pScreen == pWin->drawable.pScreen)
+    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
     {
 	XE_KBPTR.sameScreen = xTrue;
 	XE_KBPTR.child = child;
@@ -1896,7 +1910,7 @@ DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
 	{
 	    if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
 	    {
-		FixUpEventFromWindow(xE, pWin, child, FALSE);
+		FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
 		deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
 						   grab, mskidx);
 		if (deliveries > 0)
@@ -1921,7 +1935,7 @@ DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
 	{
 	    if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
 	    {
-		FixUpEventFromWindow(xE, pWin, child, FALSE);
+		FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
 		deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
 						   grab, 0);
 		if (deliveries > 0)
@@ -2125,8 +2139,9 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	if (prevSpriteWin != NullWindow) {
 	    if (!xE)
 		UpdateCurrentTimeIf();
-	    DoEnterLeaveEvents(prevSpriteWin, pSprite->win, NotifyNormal);
-	}
+            DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win,
+                               NotifyNormal); 
+        }
 	PostNewCursor(pDev);
         return FALSE;
     }
@@ -2600,7 +2615,7 @@ CheckPassiveGrabsOnWindow(
 #endif
 	    (*device->ActivateGrab)(device, grab, currentTime, TRUE);
  
-	    FixUpEventFromWindow(xE, grab->window, None, TRUE);
+	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
 
 	    (void) TryClientEvents(rClient(grab), xE, count,
 				   filters[xE->u.u.type],
@@ -2705,7 +2720,7 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
 	    return;
     }
     /* just deliver it to the focus window */
-    FixUpEventFromWindow(xE, focus, None, FALSE);
+    FixUpEventFromWindow(inputInfo.pointer, xE, focus, None, FALSE);
     if (xE->u.u.type & EXTENSION_EVENT_BASE)
 	mskidx = keybd->id;
     (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
@@ -2745,7 +2760,7 @@ DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev,
     }
     if (!deliveries)
     {
-	FixUpEventFromWindow(xE, grab->window, None, TRUE);
+	FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
 	deliveries = TryClientEvents(rClient(grab), xE, count,
 				     (Mask)grab->eventMask,
 				     filters[xE->u.u.type], grab);
@@ -3321,6 +3336,7 @@ CommonAncestor(
 
 static void
 EnterLeaveEvent(
+    DeviceIntPtr pDev,
     int type,
     int mode,
     int detail,
@@ -3330,7 +3346,7 @@ EnterLeaveEvent(
     xEvent		event;
     register DeviceIntPtr keybd = inputInfo.keyboard;
     WindowPtr		focus;
-    register DeviceIntPtr mouse = inputInfo.pointer;
+    register DeviceIntPtr mouse = pDev;
     register GrabPtr	grab = mouse->grab;
     Mask		mask;
 
@@ -3355,7 +3371,7 @@ EnterLeaveEvent(
 	event.u.enterLeave.rootX = sprite->hot.x;
 	event.u.enterLeave.rootY = sprite->hot.y;
 	/* Counts on the same initial structure of crossing & button events! */
-	FixUpEventFromWindow(&event, pWin, None, FALSE);
+	FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
 	/* Enter/Leave events always set child */
 	event.u.enterLeave.child = child;
 	event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
@@ -3406,18 +3422,26 @@ EnterLeaveEvent(
 }
 
 static void
-EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail)
+EnterNotifies(DeviceIntPtr pDev, 
+              WindowPtr ancestor, 
+              WindowPtr child, 
+              int mode, 
+              int detail) 
 {
     WindowPtr	parent = child->parent;
 
     if (ancestor == parent)
 	return;
-    EnterNotifies(ancestor, parent, mode, detail);
-    EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id);
-}
+    EnterNotifies(pDev, ancestor, parent, mode, detail);
+    EnterLeaveEvent(pDev, EnterNotify, mode, detail, parent,
+                    child->drawable.id); }
 
 static void
-LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
+LeaveNotifies(DeviceIntPtr pDev, 
+              WindowPtr child, 
+              WindowPtr ancestor, 
+              int mode, 
+              int detail)
 {
     register WindowPtr  pWin;
 
@@ -3425,36 +3449,45 @@ LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
 	return;
     for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
     {
-	EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id);
-	child = pWin;
+        EnterLeaveEvent(pDev, LeaveNotify, mode, detail, pWin,
+                        child->drawable.id); 
+        child = pWin;
     }
 }
 
 static void
-DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode)
+DoEnterLeaveEvents(DeviceIntPtr pDev, 
+        WindowPtr fromWin, 
+        WindowPtr toWin, 
+        int mode) 
 {
     if (fromWin == toWin)
 	return;
     if (IsParent(fromWin, toWin))
     {
-	EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None);
-	EnterNotifies(fromWin, toWin, mode, NotifyVirtual);
-	EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None);
+        EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin,
+                        None); 
+        EnterNotifies(pDev, fromWin, toWin, mode,
+                      NotifyVirtual);
+        EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None);
     }
     else if (IsParent(toWin, fromWin))
     {
-	EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None);
-	LeaveNotifies(fromWin, toWin, mode, NotifyVirtual);
-	EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None);
+	EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin, 
+                        None);
+	LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual);
+	EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None);
     }
     else
     { /* neither fromWin nor toWin is descendent of the other */
 	WindowPtr common = CommonAncestor(toWin, fromWin);
 	/* common == NullWindow ==> different screens */
-	EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None);
-	LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual);
-	EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual);
-	EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None);
+        EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin,
+                        None); 
+        LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual);
+	EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual);
+        EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin,
+                        None); 
     }
 }
 
diff --git a/include/dix.h b/include/dix.h
index a5a570a..0c66d8d 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -525,7 +525,7 @@ extern Bool IsParent(
 
 extern WindowPtr GetCurrentRootWindow(void);
 
-extern WindowPtr GetSpriteWindow(void);
+extern WindowPtr GetSpriteWindow(DeviceIntPtr pDev);
 
 
 extern void NoticeEventTime(xEventPtr /* xE */);
diff --git a/xkb/ddxFakeMtn.c b/xkb/ddxFakeMtn.c
index 3dd733b..7e75c15 100644
--- a/xkb/ddxFakeMtn.c
+++ b/xkb/ddxFakeMtn.c
@@ -54,7 +54,7 @@ int 		   oldX,oldY;
 ScreenPtr	   pScreen, oldScreen;
 
     GetSpritePosition(inputInfo.pointer, &oldX, &oldY);
-    pScreen = oldScreen = GetSpriteWindow()->drawable.pScreen;
+    pScreen = oldScreen = GetSpriteWindow(inputInfo.pointer)->drawable.pScreen;
 
 #ifdef PANORAMIX
     if (!noPanoramiXExtension) {
commit 70383105de279df553874efa56b37a7b3e426ea1
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 22 15:27:16 2006 +1030

    mi:     added DevToSprite() conversion function
            fixed miSpriteRealize to use passed pDev argument instead of looping.
    
    dix:    changed sprite dependency and added MPX functionality to parts of
            events.c (XineramaChangeToCursor, XineramaCheckPhysLimits,
            XineramaConstrainCursor)
    
    Xi:	fix: accessing other->buttons for keyboard segfaulted the server

diff --git a/Changelog b/Changelog
index 40ccea3..93f1455 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,22 @@
 MPX Changelog file
+== 22.11.06 ==
+
+mi:     added DevToSprite() conversion function
+        fixed miSpriteRealize to use passed pDev argument instead of looping.
+
+dix:    changed sprite dependency and added MPX functionality to parts of
+        events.c (XineramaChangeToCursor, XineramaCheckPhysLimits,
+        XineramaConstrainCursor)
+
+Xi:	fix: accessing other->buttons for keyboard segfaulted the server
+
+Files:
+        mi/misprite.c
+        mi/mipointer.c
+	dix/events.c
+	Xi/exevents.c
+
+
 == 21.11.06 ==
 mi:     added MPX to miSpriteReportDamage
         added id field to miCursorInfoPtr, required to pass through to miDC
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 7f7e128..13687e3 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -125,11 +125,7 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
 	key = xE->u.u.detail;
 	NoticeEventTime(xE);
 	xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state |
-#ifdef MPX
-            other->button->state;
-#else
-	    inputInfo.pointer->button->state;
-#endif
+	    inputInfo.pointer->button->state; /* FIXME: change for MPX */
 	bit = 1 << (key & 7);
     }
     if (DeviceEventCallback) {
diff --git a/dix/events.c b/dix/events.c
index a06a051..bb6bcfc 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -388,10 +388,19 @@ XineramaSetCursorPosition(
 
 
 static void
-XineramaConstrainCursor(void)
+XineramaConstrainCursor(DeviceIntPtr pDev)
 {
-    ScreenPtr pScreen = sprite->screen;
-    BoxRec newBox = sprite->physLimits;
+    SpritePtr pSprite = sprite;
+    ScreenPtr pScreen;
+    BoxRec newBox;
+
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+
+    pScreen = pSprite->screen;
+    newBox = pSprite->physLimits;
 
     /* Translate the constraining box to the screen
        the sprite is actually on */
@@ -400,40 +409,46 @@ XineramaConstrainCursor(void)
     newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
     newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
 
-    (* pScreen->ConstrainCursor)(inputInfo.pointer, pScreen, &newBox);
+    (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
 }
 
 static void
 XineramaCheckPhysLimits(
+    DeviceIntPtr pDev,
     CursorPtr cursor,
     Bool generateEvents
 ){
     HotSpot new;
+    SpritePtr pSprite = sprite;
 
     if (!cursor)
 	return;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
  
-    new = sprite->hotPhys;
+    new = pSprite->hotPhys;
 
     /* I don't care what the DDX has to say about it */
-    sprite->physLimits = sprite->hotLimits;
+    pSprite->physLimits = pSprite->hotLimits;
 
     /* constrain the pointer to those limits */
-    if (new.x < sprite->physLimits.x1)
-	new.x = sprite->physLimits.x1;
+    if (new.x < pSprite->physLimits.x1)
+	new.x = pSprite->physLimits.x1;
     else
-	if (new.x >= sprite->physLimits.x2)
-	    new.x = sprite->physLimits.x2 - 1;
-    if (new.y < sprite->physLimits.y1)
-	new.y = sprite->physLimits.y1;
+	if (new.x >= pSprite->physLimits.x2)
+	    new.x = pSprite->physLimits.x2 - 1;
+    if (new.y < pSprite->physLimits.y1)
+	new.y = pSprite->physLimits.y1;
     else
-	if (new.y >= sprite->physLimits.y2)
-	    new.y = sprite->physLimits.y2 - 1;
+	if (new.y >= pSprite->physLimits.y2)
+	    new.y = pSprite->physLimits.y2 - 1;
 
-    if (sprite->hotShape)  /* more work if the shape is a mess */
-	ConfineToShape(inputInfo.pointer, sprite->hotShape, &new.x, &new.y);
+    if (pSprite->hotShape)  /* more work if the shape is a mess */
+	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
 
-    if((new.x != sprite->hotPhys.x) || (new.y != sprite->hotPhys.y))
+    if((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
     {
 	XineramaSetCursorPosition (new.x, new.y, generateEvents);
 	if (!generateEvents)
@@ -441,7 +456,7 @@ XineramaCheckPhysLimits(
     }
 
     /* Tell DDX what the limits are */
-    XineramaConstrainCursor();
+    XineramaConstrainCursor(pDev);
 }
 
 
@@ -655,7 +670,8 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
 	sprite->confined = FALSE;
 	sprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
 
-	XineramaCheckPhysLimits(sprite->current, generateEvents);
+        XineramaCheckPhysLimits(inputInfo.pointer, sprite->current,
+                                generateEvents); 
     }
 }
 
@@ -663,15 +679,22 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
 static void
 XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 {
-    if (cursor != sprite->current)
-    {
-	if ((sprite->current->bits->xhot != cursor->bits->xhot) ||
-		(sprite->current->bits->yhot != cursor->bits->yhot))
-	    XineramaCheckPhysLimits(cursor, FALSE);
-    	(*sprite->screen->DisplayCursor)(sprite->screen, cursor);
-	FreeCursor(sprite->current, (Cursor)0);
-	sprite->current = cursor;
-	sprite->current->refcnt++;
+    SpritePtr pSprite = sprite;
+
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+
+    if (cursor != pSprite->current)
+    {
+	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
+		(pSprite->current->bits->yhot != cursor->bits->yhot))
+	    XineramaCheckPhysLimits(pDev, cursor, FALSE);
+    	(*pSprite->screen->DisplayCursor)(pSprite->screen, cursor);
+	FreeCursor(pSprite->current, (Cursor)0);
+	pSprite->current = cursor;
+	pSprite->current->refcnt++;
     }
 }
 
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 2769223..f954ba6 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -227,8 +227,18 @@ miPointerRealizeCursor (pScreen, pCursor)
     DeviceIntPtr pDev = inputInfo.pointer;
 
     SetupScreen(pScreen);
-
+#ifdef MPX
+    pDev = inputInfo.devices;
+    while(pDev)
+    {
+        if (pDev != inputInfo.keyboard)
+            (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
+        pDev = pDev->next;
+    }
+    return TRUE;
+#else
     return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
+#endif
 }
 
 static Bool
@@ -239,7 +249,18 @@ miPointerUnrealizeCursor (pScreen, pCursor)
     DeviceIntPtr pDev = inputInfo.pointer;
     SetupScreen(pScreen);
 
+#ifdef MPX
+    pDev = inputInfo.devices;
+    while(pDev)
+    {
+        if (pDev != inputInfo.keyboard)
+            (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
+        pDev = pDev->next;
+    }
+    return TRUE;
+#else
     return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
+#endif
 }
 
 static Bool
diff --git a/mi/misprite.c b/mi/misprite.c
index dcb9e60..8907a3d 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -67,8 +67,11 @@ in this Software without prior written authorization from The Open Group.
 
 #ifdef MPX
 # include   "inputstr.h" /* for MAX_DEVICES */
+
+static miCursorInfoPtr DevToSprite(DeviceIntPtr pDev, ScreenPtr pScreen);
 #endif
 
+
 #define SPRITE_DEBUG_ENABLE 1
 #if SPRITE_DEBUG_ENABLE
 #define SPRITE_DEBUG(x)	ErrorF x
@@ -907,16 +910,9 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 #ifdef MPX
     {
-        int mpCursorIdx = 0;
-        while (mpCursorIdx < MAX_DEVICES)
-        {
-            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
-
-            if (pCursor == pMPCursor->pCursor)
-                pMPCursor->checkPixels = TRUE;
-
-            mpCursorIdx++;
-        }
+        miCursorInfoPtr pMPCursor = DevToSprite(pDev, pScreen);
+        if (pCursor == pMPCursor->pCursor)
+            pMPCursor->checkPixels = TRUE;
     }
 #else
     if (pCursor == pScreenPriv->cp->pCursor)
@@ -1174,3 +1170,21 @@ miSpriteComputeSaved (pDevCursor, pScreen)
     pDevCursor->saved.x2 = pDevCursor->saved.x1 + w + wpad * 2;
     pDevCursor->saved.y2 = pDevCursor->saved.y1 + h + hpad * 2;
 }
+
+#ifdef MPX
+static miCursorInfoPtr DevToSprite(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+    miSpriteScreenPtr pScreenPriv;
+    pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+    int mpCursorIdx = 0;
+    while(mpCursorIdx < MAX_DEVICES)
+    {
+        miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
+        if (pMPCursor->id == pDev->id)
+            return pMPCursor;
+        mpCursorIdx++;
+    }
+    return pScreenPriv->cp;
+}
+
+#endif
commit efd4f3c6ffec804c68ba5df17cc117da264fb7c4
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 21 20:31:30 2006 +1030

    dix:	WindowsRestructured() calls CheckMotion() on all devices
    
    mi:	core pointer was checked twice in miSpriteReportDamage,
    	miSpriteInstallColormap, miSpriteStoreColors, miSpriteSaveDoomedAreas
    	and miSpriteRealiseCursor
    	using damage bug (see comment in file) to avoid artefacts

diff --git a/Changelog b/Changelog
index d872517..40ccea3 100644
--- a/Changelog
+++ b/Changelog
@@ -58,6 +58,18 @@ Files:
         xfixes/cursor.c
 	mi/mieq.c
 
+dix:	WindowsRestructured() calls CheckMotion() on all devices
+
+mi:	core pointer was checked twice in miSpriteReportDamage,
+	miSpriteInstallColormap, miSpriteStoreColors, miSpriteSaveDoomedAreas
+	and miSpriteRealiseCursor 
+	using damage bug (see comment in file) to avoid artefacts
+
+Files:
+	dix/events.c
+	mi/misprite.c
+	mi/mispritest.h
+
 == 20.11.06 ==
 
 mi:     moved core pointer information from miSpriteScreenRec into a
diff --git a/dix/events.c b/dix/events.c
index 2def704..a06a051 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2072,7 +2072,7 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
         xeviehot.y = pSprite->hot.y;
 #endif
 	pSprite->hotPhys = pSprite->hot;
-#ifndef MPX
+#ifndef MPX /* XXX ndef!! */
 	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
 	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
 	{
@@ -2113,7 +2113,17 @@ CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 _X_EXPORT void
 WindowsRestructured()
 {
+#ifdef MPX
+    DeviceIntPtr pDev = inputInfo.devices;
+    while(pDev)
+    {
+        if (pDev != inputInfo.keyboard)
+            CheckMotion((xEvent *)NULL, pDev);
+        pDev = pDev->next;
+    }
+#else
     (void) CheckMotion((xEvent *)NULL, inputInfo.pointer);
+#endif
 }
 
 #ifdef PANORAMIX
diff --git a/mi/misprite.c b/mi/misprite.c
index 81e51ed..dcb9e60 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -69,7 +69,7 @@ in this Software without prior written authorization from The Open Group.
 # include   "inputstr.h" /* for MAX_DEVICES */
 #endif
 
-#define SPRITE_DEBUG_ENABLE 0
+#define SPRITE_DEBUG_ENABLE 1
 #if SPRITE_DEBUG_ENABLE
 #define SPRITE_DEBUG(x)	ErrorF x
 #else
@@ -152,12 +152,6 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
     
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     
-    if (pScreenPriv->cp->isUp &&
-	RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->cp->saved) != rgnOUT)
-    {
-	SPRITE_DEBUG(("Damage remove\n"));
-	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
-    }
 
 #ifdef MPX
     {
@@ -175,6 +169,13 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
             mpCursorIdx++;
         }
     }
+#else
+    if (pScreenPriv->cp->isUp &&
+	RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->cp->saved) != rgnOUT)
+    {
+	SPRITE_DEBUG(("Damage remove\n"));
+	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
+    }
 #endif
 }
 
@@ -310,6 +311,8 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     pScreenPriv->cp = &(pScreenPriv->mpCursors[1]);
 #endif
 
+    damageRegister = 0;
+
     return TRUE;
 }
 
@@ -388,7 +391,7 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
                     ORG_OVERLAP(&pMPCursor->saved,pDrawable->x,pDrawable->y,
                         sx, sy, w, h)) 
             {
-                SPRITE_DEBUG("GetImage remove MPX\n");
+                SPRITE_DEBUG(("GetImage remove MPX\n"));
             }
             miSpriteRemoveCursor(pMPCursor, pScreen); 
             mpCursorIdx++;
@@ -588,12 +591,6 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
 
     SCREEN_EPILOGUE(pScreen, BlockHandler);
 
-    if (!pPriv->cp->isUp && pPriv->cp->shouldBeUp)
-    {
-	SPRITE_DEBUG (("BlockHandler restore\n"));
-	miSpriteRestoreCursor (pPriv->cp, pScreen);
-    }
-
 #ifdef MPX
     {
         int mpCursorIdx = 0;
@@ -609,6 +606,13 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
             mpCursorIdx++;
         }
     }
+#else
+    if (!pPriv->cp->isUp && pPriv->cp->shouldBeUp)
+    {
+	SPRITE_DEBUG (("BlockHandler restore\n"));
+	miSpriteRestoreCursor (pPriv->cp, pScreen);
+    }
+
 #endif
 }
 
@@ -627,13 +631,6 @@ miSpriteInstallColormap (pMap)
 
     SCREEN_EPILOGUE(pScreen, InstallColormap);
 
-    pPriv->cp->pInstalledMap = pMap;
-    if (pPriv->cp->pColormap != pMap)
-    {
-    	pPriv->cp->checkPixels = TRUE;
-	if (pPriv->cp->isUp)
-	    miSpriteRemoveCursor (pPriv->cp, pScreen);
-    }
 
 #ifdef MPX
     {
@@ -651,6 +648,14 @@ miSpriteInstallColormap (pMap)
             mpCursorIdx++;
         }
     }
+#else
+    pPriv->cp->pInstalledMap = pMap;
+    if (pPriv->cp->pColormap != pMap)
+    {
+    	pPriv->cp->checkPixels = TRUE;
+	if (pPriv->cp->isUp)
+	    miSpriteRemoveCursor (pPriv->cp, pScreen);
+    }
 #endif
 
 }
@@ -675,14 +680,6 @@ miSpriteStoreColors (pMap, ndef, pdef)
 
     SCREEN_EPILOGUE(pScreen, StoreColors);
 
-    if (pPriv->cp->pColormap == pMap)
-    {
-	updated = 0;
-	pVisual = pMap->pVisual;
-	if (pVisual->class == DirectColor)
-	{
-	    /* Direct color - match on any of the subfields */
-
 #define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
 
 #define UpdateDAC(dev, plane,dac,mask) {\
@@ -697,39 +694,6 @@ miSpriteStoreColors (pMap, ndef, pdef)
 	    UpdateDAC(dev, plane,green,greenMask) \
 	    UpdateDAC(dev, plane,blue,blueMask)
 
-	    for (i = 0; i < ndef; i++)
-	    {
-		CheckDirect (pPriv->cp, SOURCE_COLOR)
-		CheckDirect (pPriv->cp, MASK_COLOR)
-	    }
-	}
-	else
-	{
-	    /* PseudoColor/GrayScale - match on exact pixel */
-	    for (i = 0; i < ndef; i++)
-	    {
-	    	if (pdef[i].pixel == pPriv->cp->colors[SOURCE_COLOR].pixel)
-	    	{
-		    pPriv->cp->colors[SOURCE_COLOR] = pdef[i];
-		    if (++updated == 2)
-		    	break;
-	    	}
-	    	if (pdef[i].pixel == pPriv->cp->colors[MASK_COLOR].pixel)
-	    	{
-		    pPriv->cp->colors[MASK_COLOR] = pdef[i];
-		    if (++updated == 2)
-		    	break;
-	    	}
-	    }
-	}
-    	if (updated)
-    	{
-	    pPriv->cp->checkPixels = TRUE;
-	    if (pPriv->cp->isUp)
-	    	miSpriteRemoveCursor (pPriv->cp, pScreen);
-    	}
-    }
-
 #ifdef MPX
     {
         int mpCursorIdx = 0;
@@ -781,6 +745,47 @@ miSpriteStoreColors (pMap, ndef, pdef)
             mpCursorIdx++;
         }
     }
+#else
+    if (pPriv->cp->pColormap == pMap)
+    {
+	updated = 0;
+	pVisual = pMap->pVisual;
+	if (pVisual->class == DirectColor)
+	{
+	    /* Direct color - match on any of the subfields */
+
+	    for (i = 0; i < ndef; i++)
+	    {
+		CheckDirect (pPriv->cp, SOURCE_COLOR)
+		CheckDirect (pPriv->cp, MASK_COLOR)
+	    }
+	}
+	else
+	{
+	    /* PseudoColor/GrayScale - match on exact pixel */
+	    for (i = 0; i < ndef; i++)
+	    {
+	    	if (pdef[i].pixel == pPriv->cp->colors[SOURCE_COLOR].pixel)
+	    	{
+		    pPriv->cp->colors[SOURCE_COLOR] = pdef[i];
+		    if (++updated == 2)
+		    	break;
+	    	}
+	    	if (pdef[i].pixel == pPriv->cp->colors[MASK_COLOR].pixel)
+	    	{
+		    pPriv->cp->colors[MASK_COLOR] = pdef[i];
+		    if (++updated == 2)
+		    	break;
+	    	}
+	    }
+	}
+    	if (updated)
+    	{
+	    pPriv->cp->checkPixels = TRUE;
+	    if (pPriv->cp->isUp)
+	    	miSpriteRemoveCursor (pPriv->cp, pScreen);
+    	}
+    }
 #endif
 
 }
@@ -839,20 +844,6 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
     SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    if (pScreenPriv->cp->isUp)
-    {
-	cursorBox = pScreenPriv->cp->saved;
-
-	if (dx || dy)
- 	{
-	    cursorBox.x1 += dx;
-	    cursorBox.y1 += dy;
-	    cursorBox.x2 += dx;
-	    cursorBox.y2 += dy;
-	}
-	if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
-	    miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
-    }
 #ifdef MPX
     {
         int mpCursorIdx = 0;
@@ -877,6 +868,21 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
             mpCursorIdx++;
         }
     }
+#else
+    if (pScreenPriv->cp->isUp)
+    {
+	cursorBox = pScreenPriv->cp->saved;
+
+	if (dx || dy)
+ 	{
+	    cursorBox.x1 += dx;
+	    cursorBox.y1 += dy;
+	    cursorBox.x2 += dx;
+	    cursorBox.y2 += dy;
+	}
+	if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
+	    miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
+    }
 #endif
 
     (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
@@ -899,8 +905,6 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     miSpriteScreenPtr	pScreenPriv;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    if (pCursor == pScreenPriv->cp->pCursor)
-	pScreenPriv->cp->checkPixels = TRUE;
 #ifdef MPX
     {
         int mpCursorIdx = 0;
@@ -914,6 +918,9 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
             mpCursorIdx++;
         }
     }
+#else
+    if (pCursor == pScreenPriv->cp->pCursor)
+	pScreenPriv->cp->checkPixels = TRUE;
 #endif
 
     return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
@@ -942,37 +949,37 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
     miSpriteScreenPtr	pScreenPriv;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    miCursorInfoPtr pointer = pScreenPriv->cp;
+    miCursorInfoPtr pPointer = pScreenPriv->cp;
 #ifdef MPX
     if (IsMPDev(pDev))
-        pointer = &pScreenPriv->mpCursors[pDev->id];
+        pPointer = &pScreenPriv->mpCursors[pDev->id];
 #endif
 
     if (!pCursor)
     {
-    	pointer->shouldBeUp = FALSE;
-    	if (pointer->isUp)
-	    miSpriteRemoveCursor (pointer, pScreen);
-	pointer->pCursor = 0;
+    	pPointer->shouldBeUp = FALSE;
+    	if (pPointer->isUp)
+	    miSpriteRemoveCursor (pPointer, pScreen);
+	pPointer->pCursor = 0;
 	return;
     }
-    pointer->shouldBeUp = TRUE;
-    if (pointer->x == x &&
-	pointer->y == y &&
-	pointer->pCursor == pCursor &&
-	!pointer->checkPixels)
+    pPointer->shouldBeUp = TRUE;
+    if (pPointer->x == x &&
+	pPointer->y == y &&
+	pPointer->pCursor == pCursor &&
+	!pPointer->checkPixels)
     {
 	return;
     }
-    pointer->x = x;
-    pointer->y = y;
-    pointer->pCacheWin = NullWindow;
-    if (pointer->checkPixels || pointer->pCursor != pCursor)
+    pPointer->x = x;
+    pPointer->y = y;
+    pPointer->pCacheWin = NullWindow;
+    if (pPointer->checkPixels || pPointer->pCursor != pCursor)
     {
-	pointer->pCursor = pCursor;
-	miSpriteFindColors (pointer, pScreen);
+	pPointer->pCursor = pCursor;
+	miSpriteFindColors (pPointer, pScreen);
     }
-    if (pointer->isUp) {
+    if (pPointer->isUp) {
 #if 0
         /* FIXME: Disabled for MPX, should be rewritten */
 	int	sx, sy;
@@ -1038,14 +1045,14 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
 #endif
 	{
 	    SPRITE_DEBUG (("SetCursor remove\n"));
-	    miSpriteRemoveCursor (pointer, pScreen);
+	    miSpriteRemoveCursor (pPointer, pScreen);
 	}
     }
 
-    if (!pointer->isUp && pointer->pCursor)
+    if (!pPointer->isUp && pPointer->pCursor)
     {
 	SPRITE_DEBUG (("SetCursor restore\n"));
-	miSpriteRestoreCursor (pointer, pScreen);
+	miSpriteRestoreCursor (pPointer, pScreen);
     }
 
 }
diff --git a/mi/mispritest.h b/mi/mispritest.h
index ff4bb4a..0ba5365 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -97,17 +97,26 @@ typedef struct {
 #define MASK_COLOR	1
 
 static int damageRegister = 0;
+/*
+ * FIXME: MPX uses a bug at the moment. The semaphore system in place will
+ * call miSpriteIsUpTRUE multiple times and thus DamageUnregister() will never
+ * be called in miSpriteIsUpFALSE. 
+ * This gets rid of cursor rendering artefacts but I don't know how this
+ * affects applications.
+ * Without any semaphore system in place DamageRegister will be called twice
+ * and segfault.
+ */
 #define miSpriteIsUpTRUE(pDevCursor, pScreen, pScreenPriv) if (!pDevCursor->isUp) { \
     pDevCursor->isUp = TRUE; \
     if (!damageRegister ) { \
-        damageRegister++; \
         DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
     } \
+    damageRegister++; \
 }
 
 #define miSpriteIsUpFALSE(pDevCursor, pScreen, pScreenPriv) if (pDevCursor->isUp) { \
-    if (damageRegister) { \
-        damageRegister--; \
+    damageRegister--; \
+    if (!damageRegister) { \
         DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
     } \
     pDevCursor->isUp = FALSE; \
commit 9db851c22d4befb95bfb074b96620261d8e32ac9
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 21 18:15:04 2006 +1030

    dix:    moved sprite from static to be pointer of type SpritePtr
    	added SpriteRecs for MPX devices
    	changed sprite dependency and added MPX functionality to parts
    	of events.c (ConfineToShape, PostNewCursor, XineramaCheckMotion,
    	CheckMotion, XineramaChangeToCursor, ChangeToCursor, CheckPhysLimits,
    	PointerConfinedToScreen)
    	added DeviceIntRec param to GetSpritePosition(). This required some
    	minor changes in ddx, xtest, xkb and xfixes.
    
    mi:	changed miPointer to pointer instead of static struct.

diff --git a/Changelog b/Changelog
index 18bbeb4..d872517 100644
--- a/Changelog
+++ b/Changelog
@@ -34,6 +34,30 @@ Files:
 
 TAG:   MPX_BEFORE_DIX_API_BREAK
 
+
+
+dix:    moved sprite from static to be pointer of type SpritePtr
+	added SpriteRecs for MPX devices
+	changed sprite dependency and added MPX functionality to parts 
+	of events.c (ConfineToShape, PostNewCursor, XineramaCheckMotion,
+	CheckMotion, XineramaChangeToCursor, ChangeToCursor, CheckPhysLimits,
+	PointerConfinedToScreen) 
+	added DeviceIntRec param to GetSpritePosition(). This required some
+	minor changes in ddx, xtest, xkb and xfixes.
+
+mi:	changed miPointer to pointer instead of static struct.
+
+Files:
+        dix/events.c
+        dix/exevents.c
+        Xext/xtest.c
+        ddx/ddxFakeBtn.c
+        ddx/ddxFakeMtn.c
+        ddx/ddxDevBtn.c
+        xkb/xkbActions.c
+        xfixes/cursor.c
+	mi/mieq.c
+
 == 20.11.06 ==
 
 mi:     moved core pointer information from miSpriteScreenRec into a
diff --git a/Xext/xtest.c b/Xext/xtest.c
index 83f8b8c..18111c0 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -379,7 +379,7 @@ ProcXTestFakeInput(client)
 	if (ev->u.u.detail == xTrue)
 	{
 	    int x, y;
-	    GetSpritePosition(&x, &y);
+	    GetSpritePosition(inputInfo.pointer, &x, &y);
 	    ev->u.keyButtonPointer.rootX += x;
 	    ev->u.keyButtonPointer.rootY += y;
 	}
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 92a5f05..7f7e128 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -119,13 +119,17 @@ ProcessOtherEvent(xEventPtr xE, register DeviceIntPtr other, int count)
     deviceValuator *xV = (deviceValuator *) xE;
 
     if (xE->u.u.type != DeviceValuator) {
-	GetSpritePosition(&rootX, &rootY);
+	GetSpritePosition(other, &rootX, &rootY);
 	xE->u.keyButtonPointer.rootX = rootX;
 	xE->u.keyButtonPointer.rootY = rootY;
 	key = xE->u.u.detail;
 	NoticeEventTime(xE);
 	xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state |
+#ifdef MPX
+            other->button->state;
+#else
 	    inputInfo.pointer->button->state;
+#endif
 	bit = 1 << (key & 7);
     }
     if (DeviceEventCallback) {
diff --git a/dix/events.c b/dix/events.c
index 4c33fd4..2def704 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -236,7 +236,7 @@ static WindowPtr *spriteTrace = (WindowPtr *)NULL;
 static int spriteTraceSize = 0;
 static int spriteTraceGood;
 
-static  struct {
+typedef struct {
     CursorPtr	current;
     BoxRec	hotLimits;	/* logical constraints of hot spot */
     Bool	confined;	/* confined to screen */
@@ -254,7 +254,15 @@ static  struct {
     WindowPtr   windows[MAXSCREENS];
     WindowPtr	confineWin;	/* confine window */ 
 #endif
-} sprite;			/* info about the cursor sprite */
+} SpriteRec, *SpritePtr;
+
+static SpritePtr sprite;		/* info about the cursor sprite */
+
+#ifdef MPX
+static SpritePtr mpsprites;             /* info about the MPX sprites */
+
+extern BOOL IsMPDev(DeviceIntPtr dev);
+#endif
 
 #ifdef XEVIE
 _X_EXPORT WindowPtr xeviewin;
@@ -326,12 +334,12 @@ static CARD8 criticalEvents[32] =
 };
 
 #ifdef PANORAMIX
-static void ConfineToShape(RegionPtr shape, int *px, int *py);
-static void PostNewCursor(void);
+static void ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py);
+static void PostNewCursor(DeviceIntPtr pDev);
 
 #define SyntheticMotion(x, y) \
     PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \
-                              sprite.screen->myNum, \
+                              sprite->screen->myNum, \
                         syncEvents.playingEvents ? \
                           syncEvents.time.milliseconds : \
                           currentTime.milliseconds);
@@ -350,7 +358,7 @@ XineramaSetCursorPosition(
        to send the message too and what the coordinates relative to 
        that screen are. */
 
-    pScreen = sprite.screen;
+    pScreen = sprite->screen;
     x += panoramiXdataPtr[0].x;
     y += panoramiXdataPtr[0].y;
 
@@ -369,9 +377,9 @@ XineramaSetCursorPosition(
 	}
     }
 
-    sprite.screen = pScreen;
-    sprite.hotPhys.x = x - panoramiXdataPtr[0].x;
-    sprite.hotPhys.y = y - panoramiXdataPtr[0].y;
+    sprite->screen = pScreen;
+    sprite->hotPhys.x = x - panoramiXdataPtr[0].x;
+    sprite->hotPhys.y = y - panoramiXdataPtr[0].y;
     x -= panoramiXdataPtr[pScreen->myNum].x;
     y -= panoramiXdataPtr[pScreen->myNum].y;
 
@@ -382,8 +390,8 @@ XineramaSetCursorPosition(
 static void
 XineramaConstrainCursor(void)
 {
-    ScreenPtr pScreen = sprite.screen;
-    BoxRec newBox = sprite.physLimits;
+    ScreenPtr pScreen = sprite->screen;
+    BoxRec newBox = sprite->physLimits;
 
     /* Translate the constraining box to the screen
        the sprite is actually on */
@@ -405,27 +413,27 @@ XineramaCheckPhysLimits(
     if (!cursor)
 	return;
  
-    new = sprite.hotPhys;
+    new = sprite->hotPhys;
 
     /* I don't care what the DDX has to say about it */
-    sprite.physLimits = sprite.hotLimits;
+    sprite->physLimits = sprite->hotLimits;
 
     /* constrain the pointer to those limits */
-    if (new.x < sprite.physLimits.x1)
-	new.x = sprite.physLimits.x1;
+    if (new.x < sprite->physLimits.x1)
+	new.x = sprite->physLimits.x1;
     else
-	if (new.x >= sprite.physLimits.x2)
-	    new.x = sprite.physLimits.x2 - 1;
-    if (new.y < sprite.physLimits.y1)
-	new.y = sprite.physLimits.y1;
+	if (new.x >= sprite->physLimits.x2)
+	    new.x = sprite->physLimits.x2 - 1;
+    if (new.y < sprite->physLimits.y1)
+	new.y = sprite->physLimits.y1;
     else
-	if (new.y >= sprite.physLimits.y2)
-	    new.y = sprite.physLimits.y2 - 1;
+	if (new.y >= sprite->physLimits.y2)
+	    new.y = sprite->physLimits.y2 - 1;
 
-    if (sprite.hotShape)  /* more work if the shape is a mess */
-	ConfineToShape(sprite.hotShape, &new.x, &new.y);
+    if (sprite->hotShape)  /* more work if the shape is a mess */
+	ConfineToShape(inputInfo.pointer, sprite->hotShape, &new.x, &new.y);
 
-    if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
+    if((new.x != sprite->hotPhys.x) || (new.y != sprite->hotPhys.y))
     {
 	XineramaSetCursorPosition (new.x, new.y, generateEvents);
 	if (!generateEvents)
@@ -441,7 +449,7 @@ static Bool
 XineramaSetWindowPntrs(WindowPtr pWin)
 {
     if(pWin == WindowTable[0]) {
-	    memcpy(sprite.windows, WindowTable, 
+	    memcpy(sprite->windows, WindowTable, 
 				PanoramiXNumScreens*sizeof(WindowPtr));
     } else {
 	PanoramiXRes *win;
@@ -453,8 +461,8 @@ XineramaSetWindowPntrs(WindowPtr pWin)
 	    return FALSE;
 
 	for(i = 0; i < PanoramiXNumScreens; i++) {
-	   sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
-	   if(!sprite.windows[i])  /* window is being unmapped */
+	   sprite->windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
+	   if(!sprite->windows[i])  /* window is being unmapped */
 		return FALSE;
 	}
     }
@@ -469,9 +477,9 @@ XineramaCheckVirtualMotion(
 
     if (qe)
     {
-	sprite.hot.pScreen = qe->pScreen;  /* should always be Screen 0 */
-	sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
-	sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
+	sprite->hot.pScreen = qe->pScreen;  /* should always be Screen 0 */
+	sprite->hot.x = qe->event->u.keyButtonPointer.rootX;
+	sprite->hot.y = qe->event->u.keyButtonPointer.rootY;
 	pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
 					 NullWindow;
     }
@@ -485,8 +493,8 @@ XineramaCheckVirtualMotion(
 
 	i = PanoramiXNumScreens - 1;
 	
-	REGION_COPY(sprite.screen, &sprite.Reg2, 
-					&sprite.windows[i]->borderSize); 
+	REGION_COPY(sprite->screen, &sprite->Reg2, 
+					&sprite->windows[i]->borderSize); 
 	off_x = panoramiXdataPtr[i].x;
 	off_y = panoramiXdataPtr[i].y;
 
@@ -495,97 +503,105 @@ XineramaCheckVirtualMotion(
 	    y = off_y - panoramiXdataPtr[i].y;
 
 	    if(x || y)
-		REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y);
+		REGION_TRANSLATE(sprite->screen, &sprite->Reg2, x, y);
 		
-	    REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, 
-					&sprite.windows[i]->borderSize);
+	    REGION_UNION(sprite->screen, &sprite->Reg2, &sprite->Reg2, 
+					&sprite->windows[i]->borderSize);
 
 	    off_x = panoramiXdataPtr[i].x;
 	    off_y = panoramiXdataPtr[i].y;
 	}
 
-	lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2);
+	lims = *REGION_EXTENTS(sprite->screen, &sprite->Reg2);
 
-        if (sprite.hot.x < lims.x1)
-            sprite.hot.x = lims.x1;
-        else if (sprite.hot.x >= lims.x2)
-            sprite.hot.x = lims.x2 - 1;
-        if (sprite.hot.y < lims.y1)
-            sprite.hot.y = lims.y1;
-        else if (sprite.hot.y >= lims.y2)
-            sprite.hot.y = lims.y2 - 1;
+        if (sprite->hot.x < lims.x1)
+            sprite->hot.x = lims.x1;
+        else if (sprite->hot.x >= lims.x2)
+            sprite->hot.x = lims.x2 - 1;
+        if (sprite->hot.y < lims.y1)
+            sprite->hot.y = lims.y1;
+        else if (sprite->hot.y >= lims.y2)
+            sprite->hot.y = lims.y2 - 1;
 
-	if (REGION_NUM_RECTS(&sprite.Reg2) > 1) 
-	    ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y);
+	if (REGION_NUM_RECTS(&sprite->Reg2) > 1) 
+	    ConfineToShape(inputInfo.pointer, &sprite->Reg2, &sprite->hot.x, &sprite->hot.y);
 
 	if (qe)
 	{
-	    qe->pScreen = sprite.hot.pScreen;
-	    qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
-	    qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
+	    qe->pScreen = sprite->hot.pScreen;
+	    qe->event->u.keyButtonPointer.rootX = sprite->hot.x;
+	    qe->event->u.keyButtonPointer.rootY = sprite->hot.y;
 	}
     }
 #ifdef XEVIE
-    xeviehot.x = sprite.hot.x;
-    xeviehot.y = sprite.hot.y;
+    xeviehot.x = sprite->hot.x;
+    xeviehot.y = sprite->hot.y;
 #endif
 }
 
 
 static Bool
-XineramaCheckMotion(xEvent *xE)
+XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
-    WindowPtr prevSpriteWin = sprite.win;
+    WindowPtr prevSpriteWin;
+    SpritePtr pSprite = sprite;
+
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+
+    prevSpriteWin = pSprite->win;
 
     if (xE && !syncEvents.playingEvents)
     {
 	/* Motion events entering DIX get translated to Screen 0
 	   coordinates.  Replayed events have already been 
 	   translated since they've entered DIX before */
-	XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
+	XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
 			  panoramiXdataPtr[0].x;
-	XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
+	XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y -
 			  panoramiXdataPtr[0].y;
-	sprite.hot.x = XE_KBPTR.rootX;
-	sprite.hot.y = XE_KBPTR.rootY;
-	if (sprite.hot.x < sprite.physLimits.x1)
-	    sprite.hot.x = sprite.physLimits.x1;
-	else if (sprite.hot.x >= sprite.physLimits.x2)
-	    sprite.hot.x = sprite.physLimits.x2 - 1;
-	if (sprite.hot.y < sprite.physLimits.y1)
-	    sprite.hot.y = sprite.physLimits.y1;
-	else if (sprite.hot.y >= sprite.physLimits.y2)
-	    sprite.hot.y = sprite.physLimits.y2 - 1;
-
-	if (sprite.hotShape) 
-	    ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
-
-	sprite.hotPhys = sprite.hot;
-	if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
-	    (sprite.hotPhys.y != XE_KBPTR.rootY))
+	pSprite->hot.x = XE_KBPTR.rootX;
+	pSprite->hot.y = XE_KBPTR.rootY;
+	if (pSprite->hot.x < pSprite->physLimits.x1)
+	    pSprite->hot.x = pSprite->physLimits.x1;
+	else if (pSprite->hot.x >= pSprite->physLimits.x2)
+	    pSprite->hot.x = pSprite->physLimits.x2 - 1;
+	if (pSprite->hot.y < pSprite->physLimits.y1)
+	    pSprite->hot.y = pSprite->physLimits.y1;
+	else if (pSprite->hot.y >= pSprite->physLimits.y2)
+	    pSprite->hot.y = pSprite->physLimits.y2 - 1;
+
+	if (pSprite->hotShape) 
+	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
+
+	pSprite->hotPhys = pSprite->hot;
+	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
+	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
 	{
 	    XineramaSetCursorPosition(
-			sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
+			pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
 	}
-	XE_KBPTR.rootX = sprite.hot.x;
-	XE_KBPTR.rootY = sprite.hot.y;
+	XE_KBPTR.rootX = pSprite->hot.x;
+	XE_KBPTR.rootY = pSprite->hot.y;
     }
 
 #ifdef XEVIE
-    xeviehot.x = sprite.hot.x;
-    xeviehot.y = sprite.hot.y;
+    xeviehot.x = pSprite->hot.x;
+    xeviehot.y = pSprite->hot.y;
     xeviewin =
 #endif
-    sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
+    pSprite->win = XYToWindow(pSprite->hot.x, pSprite->hot.y);
 
-    if (sprite.win != prevSpriteWin)
+    if (pSprite->win != prevSpriteWin)
     {
 	if (prevSpriteWin != NullWindow) {
 	    if (!xE)
 		UpdateCurrentTimeIf();
-	    DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
+	    DoEnterLeaveEvents(prevSpriteWin, pSprite->win, NotifyNormal);
 	}
-	PostNewCursor();
+	PostNewCursor(pDev);
         return FALSE;
     }
     return TRUE;
@@ -599,7 +615,7 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
     if (syncEvents.playingEvents)
     {
 	XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin);
-	SyntheticMotion(sprite.hot.x, sprite.hot.y);
+	SyntheticMotion(sprite->hot.x, sprite->hot.y);
     }
     else
     {
@@ -610,8 +626,8 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
 
 	i = PanoramiXNumScreens - 1;
 	
-	REGION_COPY(sprite.screen, &sprite.Reg1, 
-					&sprite.windows[i]->borderSize); 
+	REGION_COPY(sprite->screen, &sprite->Reg1, 
+					&sprite->windows[i]->borderSize); 
 	off_x = panoramiXdataPtr[i].x;
 	off_y = panoramiXdataPtr[i].y;
 
@@ -620,42 +636,42 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
 	    y = off_y - panoramiXdataPtr[i].y;
 
 	    if(x || y)
-		REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y);
+		REGION_TRANSLATE(sprite->screen, &sprite->Reg1, x, y);
 		
-	    REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, 
-					&sprite.windows[i]->borderSize);
+	    REGION_UNION(sprite->screen, &sprite->Reg1, &sprite->Reg1, 
+					&sprite->windows[i]->borderSize);
 
 	    off_x = panoramiXdataPtr[i].x;
 	    off_y = panoramiXdataPtr[i].y;
 	}
 
-	sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1);
+	sprite->hotLimits = *REGION_EXTENTS(sprite->screen, &sprite->Reg1);
 
-	if(REGION_NUM_RECTS(&sprite.Reg1) > 1)
-	   sprite.hotShape = &sprite.Reg1;
+	if(REGION_NUM_RECTS(&sprite->Reg1) > 1)
+	   sprite->hotShape = &sprite->Reg1;
 	else
-	   sprite.hotShape = NullRegion;
+	   sprite->hotShape = NullRegion;
 	
-	sprite.confined = FALSE;
-	sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
+	sprite->confined = FALSE;
+	sprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
 
-	XineramaCheckPhysLimits(sprite.current, generateEvents);
+	XineramaCheckPhysLimits(sprite->current, generateEvents);
     }
 }
 
 
 static void
-XineramaChangeToCursor(CursorPtr cursor)
+XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 {
-    if (cursor != sprite.current)
+    if (cursor != sprite->current)
     {
-	if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
-		(sprite.current->bits->yhot != cursor->bits->yhot))
+	if ((sprite->current->bits->xhot != cursor->bits->xhot) ||
+		(sprite->current->bits->yhot != cursor->bits->yhot))
 	    XineramaCheckPhysLimits(cursor, FALSE);
-    	(*sprite.screen->DisplayCursor)(sprite.screen, cursor);
-	FreeCursor(sprite.current, (Cursor)0);
-	sprite.current = cursor;
-	sprite.current->refcnt++;
+    	(*sprite->screen->DisplayCursor)(sprite->screen, cursor);
+	FreeCursor(sprite->current, (Cursor)0);
+	sprite->current = cursor;
+	sprite->current->refcnt++;
     }
 }
 
@@ -680,15 +696,20 @@ SetCriticalEvent(int event)
 
 #ifdef SHAPE
 static void
-ConfineToShape(RegionPtr shape, int *px, int *py)
+ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
 {
     BoxRec box;
     int x = *px, y = *py;
     int incx = 1, incy = 1;
+    SpritePtr pSprite = sprite;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
 
-    if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box))
+    if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box))
 	return;
-    box = *REGION_EXTENTS(sprite.hot.pScreen, shape);
+    box = *REGION_EXTENTS(pSprite->hot.pScreen, shape);
     /* this is rather crude */
     do {
 	x += incx;
@@ -710,7 +731,7 @@ ConfineToShape(RegionPtr shape, int *px, int *py)
 	    else if (y < box.y1)
 		return; /* should never get here! */
 	}
-    } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box));
+    } while (!POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box));
     *px = x;
     *py = y;
 }
@@ -718,43 +739,50 @@ ConfineToShape(RegionPtr shape, int *px, int *py)
 
 static void
 CheckPhysLimits(
+    DeviceIntPtr pDev, 
     CursorPtr cursor,
     Bool generateEvents,
     Bool confineToScreen,
     ScreenPtr pScreen)
 {
     HotSpot new;
+    SpritePtr pSprite = sprite;
+
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
 
     if (!cursor)
 	return;
-    new = sprite.hotPhys;
+    new = pSprite->hotPhys;
     if (pScreen)
 	new.pScreen = pScreen;
     else
 	pScreen = new.pScreen;
-    (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
-			      &sprite.physLimits);
-    sprite.confined = confineToScreen;
-    (* pScreen->ConstrainCursor)(inputInfo.pointer, pScreen, &sprite.physLimits);
-    if (new.x < sprite.physLimits.x1)
-	new.x = sprite.physLimits.x1;
+    (*pScreen->CursorLimits) (pScreen, cursor, &pSprite->hotLimits,
+			      &pSprite->physLimits);
+    pSprite->confined = confineToScreen;
+    (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
+    if (new.x < pSprite->physLimits.x1)
+	new.x = pSprite->physLimits.x1;
     else
-	if (new.x >= sprite.physLimits.x2)
-	    new.x = sprite.physLimits.x2 - 1;
-    if (new.y < sprite.physLimits.y1)
-	new.y = sprite.physLimits.y1;
+	if (new.x >= pSprite->physLimits.x2)
+	    new.x = pSprite->physLimits.x2 - 1;
+    if (new.y < pSprite->physLimits.y1)
+	new.y = pSprite->physLimits.y1;
     else
-	if (new.y >= sprite.physLimits.y2)
-	    new.y = sprite.physLimits.y2 - 1;
+	if (new.y >= pSprite->physLimits.y2)
+	    new.y = pSprite->physLimits.y2 - 1;
 #ifdef SHAPE
-    if (sprite.hotShape)
-	ConfineToShape(sprite.hotShape, &new.x, &new.y); 
+    if (pSprite->hotShape)
+	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 
 #endif
-    if ((pScreen != sprite.hotPhys.pScreen) ||
-	(new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
+    if ((pScreen != pSprite->hotPhys.pScreen) ||
+	(new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
     {
-	if (pScreen != sprite.hotPhys.pScreen)
-	    sprite.hotPhys = new;
+	if (pScreen != pSprite->hotPhys.pScreen)
+	    pSprite->hotPhys = new;
 	(*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
 	if (!generateEvents)
 	    SyntheticMotion(new.x, new.y);
@@ -774,9 +802,9 @@ CheckVirtualMotion(
 #endif
     if (qe)
     {
-	sprite.hot.pScreen = qe->pScreen;
-	sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
-	sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
+	sprite->hot.pScreen = qe->pScreen;
+	sprite->hot.x = qe->event->u.keyButtonPointer.rootX;
+	sprite->hot.y = qe->event->u.keyButtonPointer.rootY;
 	pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
 					 NullWindow;
     }
@@ -784,36 +812,36 @@ CheckVirtualMotion(
     {
 	BoxRec lims;
 
-	if (sprite.hot.pScreen != pWin->drawable.pScreen)
+	if (sprite->hot.pScreen != pWin->drawable.pScreen)
 	{
-	    sprite.hot.pScreen = pWin->drawable.pScreen;
-	    sprite.hot.x = sprite.hot.y = 0;
+	    sprite->hot.pScreen = pWin->drawable.pScreen;
+	    sprite->hot.x = sprite->hot.y = 0;
 	}
 	lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
-	if (sprite.hot.x < lims.x1)
-	    sprite.hot.x = lims.x1;
-	else if (sprite.hot.x >= lims.x2)
-	    sprite.hot.x = lims.x2 - 1;
-	if (sprite.hot.y < lims.y1)
-	    sprite.hot.y = lims.y1;
-	else if (sprite.hot.y >= lims.y2)
-	    sprite.hot.y = lims.y2 - 1;
+	if (sprite->hot.x < lims.x1)
+	    sprite->hot.x = lims.x1;
+	else if (sprite->hot.x >= lims.x2)
+	    sprite->hot.x = lims.x2 - 1;
+	if (sprite->hot.y < lims.y1)
+	    sprite->hot.y = lims.y1;
+	else if (sprite->hot.y >= lims.y2)
+	    sprite->hot.y = lims.y2 - 1;
 #ifdef SHAPE
 	if (wBoundingShape(pWin))
-	    ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);
+	    ConfineToShape(inputInfo.pointer, &pWin->borderSize, &sprite->hot.x, &sprite->hot.y);
 #endif
 	if (qe)
 	{
-	    qe->pScreen = sprite.hot.pScreen;
-	    qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
-	    qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
+	    qe->pScreen = sprite->hot.pScreen;
+	    qe->event->u.keyButtonPointer.rootX = sprite->hot.x;
+	    qe->event->u.keyButtonPointer.rootY = sprite->hot.y;
 	}
     }
 #ifdef XEVIE
-    xeviehot.x = sprite.hot.x;
-    xeviehot.y = sprite.hot.y;
+    xeviehot.x = sprite->hot.x;
+    xeviehot.y = sprite->hot.y;
 #endif
-    ROOT = WindowTable[sprite.hot.pScreen->myNum];
+    ROOT = WindowTable[sprite->hot.pScreen->myNum];
 }
 
 static void
@@ -831,47 +859,59 @@ ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
     if (syncEvents.playingEvents)
     {
 	CheckVirtualMotion((QdEventPtr)NULL, pWin);
-	SyntheticMotion(sprite.hot.x, sprite.hot.y);
+	SyntheticMotion(sprite->hot.x, sprite->hot.y);
     }
     else
     {
-	sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
+	sprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
 #ifdef SHAPE
-	sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize
+	sprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
 					       : NullRegion;
 #endif
-	CheckPhysLimits(sprite.current, generateEvents, confineToScreen,
-			pScreen);
+        CheckPhysLimits(inputInfo.pointer, sprite->current, generateEvents,
+                        confineToScreen, pScreen);
     }
 }
 
 _X_EXPORT Bool
-PointerConfinedToScreen()
+PointerConfinedToScreen(DeviceIntPtr pDev)
 {
-    return sprite.confined;
+    SpritePtr pSprite = sprite;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+    return pSprite->confined;
 }
 
 static void
-ChangeToCursor(CursorPtr cursor)
+ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
 {
+    SpritePtr pSprite = sprite;
+
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
-	XineramaChangeToCursor(cursor);
+	XineramaChangeToCursor(pDev, cursor);
 	return;
     }
 #endif
 
-    if (cursor != sprite.current)
+    if (cursor != pSprite->current)
     {
-	if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
-		(sprite.current->bits->yhot != cursor->bits->yhot))
-	    CheckPhysLimits(cursor, FALSE, sprite.confined,
+	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
+		(pSprite->current->bits->yhot != cursor->bits->yhot))
+	    CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
 			    (ScreenPtr)NULL);
-	(*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
+	(*sprite->hotPhys.pScreen->DisplayCursor) (pSprite->hotPhys.pScreen,
 						  cursor);
-	FreeCursor(sprite.current, (Cursor)0);
-	sprite.current = cursor;
-	sprite.current->refcnt++;
+	FreeCursor(pSprite->current, (Cursor)0);
+	pSprite->current = cursor;
+	pSprite->current->refcnt++;
     }
 }
 
@@ -885,10 +925,17 @@ IsParent(register WindowPtr a, register WindowPtr b)
 }
 
 static void
-PostNewCursor(void)
+PostNewCursor(DeviceIntPtr pDev)
 {
     register    WindowPtr win;
-    register    GrabPtr grab = inputInfo.pointer->grab;
+    register    GrabPtr grab = pDev->grab;
+    SpritePtr   pSprite = sprite;
+
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+
 
     if (syncEvents.playingEvents)
 	return;
@@ -896,20 +943,20 @@ PostNewCursor(void)
     {
 	if (grab->cursor)
 	{
-	    ChangeToCursor(grab->cursor);
+	    ChangeToCursor(pDev, grab->cursor);
 	    return;
 	}
-	if (IsParent(grab->window, sprite.win))
-	    win = sprite.win;
+	if (IsParent(grab->window, pSprite->win))
+	    win = pSprite->win;
 	else
 	    win = grab->window;
     }
     else
-	win = sprite.win;
+	win = pSprite->win;
     for (; win; win = win->parent)
 	if (win->optional && win->optional->cursor != NullCursor)
 	{
-	    ChangeToCursor(win->optional->cursor);
+	    ChangeToCursor(pDev, win->optional->cursor);
 	    return;
 	}
 }
@@ -923,20 +970,25 @@ GetCurrentRootWindow()
 _X_EXPORT WindowPtr
 GetSpriteWindow()
 {
-    return sprite.win;
+    return sprite->win;
 }
 
 _X_EXPORT CursorPtr
 GetSpriteCursor()
 {
-    return sprite.current;
+    return sprite->current;
 }
 
 _X_EXPORT void
-GetSpritePosition(int *px, int *py)
+GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
 {
-    *px = sprite.hotPhys.x;
-    *py = sprite.hotPhys.y;
+    SpritePtr pSprite = sprite;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+    *px = pSprite->hotPhys.x;
+    *py = pSprite->hotPhys.y;
 }
 
 #ifdef PANORAMIX
@@ -944,7 +996,7 @@ _X_EXPORT int
 XineramaGetCursorScreen()
 {
     if(!noPanoramiXExtension) {
-	return sprite.screen->myNum;
+	return sprite->screen->myNum;
     } else {
 	return 0;
     }
@@ -1013,7 +1065,7 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 	 */
 	if (xE->u.u.type == MotionNotify)
 	    XE_KBPTR.root =
-		WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
+		WindowTable[sprite->hotPhys.pScreen->myNum]->drawable.id;
 	eventinfo.events = xE;
 	eventinfo.count = count;
 	CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
@@ -1022,21 +1074,21 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
     {
 #ifdef PANORAMIX
 	if(!noPanoramiXExtension) {
-	    XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
+	    XE_KBPTR.rootX += panoramiXdataPtr[sprite->screen->myNum].x -
 			      panoramiXdataPtr[0].x;
-	    XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
+	    XE_KBPTR.rootY += panoramiXdataPtr[sprite->screen->myNum].y -
 			      panoramiXdataPtr[0].y;
 	}
 #endif
-	sprite.hotPhys.x = XE_KBPTR.rootX;
-	sprite.hotPhys.y = XE_KBPTR.rootY;
+	sprite->hotPhys.x = XE_KBPTR.rootX;
+	sprite->hotPhys.y = XE_KBPTR.rootY;
 	/* do motion compression */
 	if (tail &&
 	    (tail->event->u.u.type == MotionNotify) &&
-	    (tail->pScreen == sprite.hotPhys.pScreen))
+	    (tail->pScreen == sprite->hotPhys.pScreen))
 	{
-	    tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x;
-	    tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y;
+	    tail->event->u.keyButtonPointer.rootX = sprite->hotPhys.x;
+	    tail->event->u.keyButtonPointer.rootY = sprite->hotPhys.y;
 	    tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
 	    tail->months = currentTime.months;
 	    return;
@@ -1047,7 +1099,7 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
 	return;
     qe->next = (QdEventPtr)NULL;
     qe->device = device;
-    qe->pScreen = sprite.hotPhys.pScreen;
+    qe->pScreen = sprite->hotPhys.pScreen;
     qe->months = currentTime.months;
     qe->event = (xEvent *)(qe + 1);
     qe->evcount = count;
@@ -1083,10 +1135,10 @@ PlayReleasedEvents(void)
 	    if(!noPanoramiXExtension) {
 		qe->event->u.keyButtonPointer.rootX += 
 			panoramiXdataPtr[0].x - 
-			panoramiXdataPtr[sprite.screen->myNum].x;
+			panoramiXdataPtr[sprite->screen->myNum].x;
 		qe->event->u.keyButtonPointer.rootY += 
 			panoramiXdataPtr[0].y - 
-			panoramiXdataPtr[sprite.screen->myNum].y;
+			panoramiXdataPtr[sprite->screen->myNum].y;
 	    }
 #endif
 	    (*qe->device->public.processInputProc)(qe->event, qe->device,
@@ -1171,14 +1223,14 @@ playmore:
     /* the following may have been skipped during replay, so do it now */
     if ((grab = inputInfo.pointer->grab) && grab->confineTo)
     {
-	if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
-	    sprite.hotPhys.x = sprite.hotPhys.y = 0;
+	if (grab->confineTo->drawable.pScreen != sprite->hotPhys.pScreen)
+	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
 	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
     }
     else
-	ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
+	ConfineCursorToWindow(WindowTable[sprite->hotPhys.pScreen->myNum],
 			      TRUE, FALSE);
-    PostNewCursor();
+    PostNewCursor(inputInfo.pointer);
 }
 
 #ifdef RANDR
@@ -1189,12 +1241,12 @@ ScreenRestructured (ScreenPtr pScreen)
 
     if ((grab = inputInfo.pointer->grab) && grab->confineTo)
     {
-	if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
-	    sprite.hotPhys.x = sprite.hotPhys.y = 0;
+	if (grab->confineTo->drawable.pScreen != sprite->hotPhys.pScreen)
+	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
 	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
     }
     else
-	ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
+	ConfineCursorToWindow(WindowTable[sprite->hotPhys.pScreen->myNum],
 			      TRUE, FALSE);
 }
 #endif
@@ -1238,12 +1290,12 @@ ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
                     TimeStamp time, Bool autoGrab)
 {
     WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
-				     : sprite.win;
+				     : sprite->win;
 
     if (grab->confineTo)
     {
-	if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
-	    sprite.hotPhys.x = sprite.hotPhys.y = 0;
+	if (grab->confineTo->drawable.pScreen != sprite->hotPhys.pScreen)
+	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
 	ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
     }
     DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
@@ -1257,7 +1309,7 @@ ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
     mouse->activeGrab = *grab;
     mouse->grab = &mouse->activeGrab;
     mouse->fromPassiveGrab = autoGrab;
-    PostNewCursor();
+    PostNewCursor(inputInfo.pointer);
     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
 }
 
@@ -1276,10 +1328,10 @@ DeactivatePointerGrab(register DeviceIntPtr mouse)
 	if (dev->sync.other == grab)
 	    dev->sync.other = NullGrab;
     }
-    DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
+    DoEnterLeaveEvents(grab->window, sprite->win, NotifyUngrab);
     if (grab->confineTo)
 	ConfineCursorToWindow(ROOT, FALSE, FALSE);
-    PostNewCursor();
+    PostNewCursor(inputInfo.pointer);
     if (grab->cursor)
 	FreeCursor(grab->cursor, (Cursor)0);
     ComputeFreezes();
@@ -1295,7 +1347,7 @@ ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
     else if (keybd->focus)
 	oldWin = keybd->focus->win;
     else
-	oldWin = sprite.win;
+	oldWin = sprite->win;
     if (oldWin == FollowKeyboardWin)
 	oldWin = inputInfo.keyboard->focus->win;
     if (keybd->valuator)
@@ -1317,7 +1369,7 @@ DeactivateKeyboardGrab(register DeviceIntPtr keybd)
     register GrabPtr grab = keybd->grab;
     register DeviceIntPtr dev;
     register WindowPtr focusWin = keybd->focus ? keybd->focus->win
-					       : sprite.win;
+					       : sprite->win;
 
     if (focusWin == FollowKeyboardWin)
 	focusWin = inputInfo.keyboard->focus->win;
@@ -1782,7 +1834,7 @@ FixUpEventFromWindow(
     }
     XE_KBPTR.root = ROOT->drawable.id;
     XE_KBPTR.event = pWin->drawable.id;
-    if (sprite.hot.pScreen == pWin->drawable.pScreen)
+    if (sprite->hot.pScreen == pWin->drawable.pScreen)
     {
 	XE_KBPTR.sameScreen = xTrue;
 	XE_KBPTR.child = child;
@@ -1916,8 +1968,8 @@ PointInBorderSize(WindowPtr pWin, int x, int y)
 	int i;
 
 	for(i = 1; i < PanoramiXNumScreens; i++) {
-	   if(POINT_IN_REGION(sprite.screen, 
-			&sprite.windows[i]->borderSize, 
+	   if(POINT_IN_REGION(sprite->screen, 
+			&sprite->windows[i]->borderSize, 
 			x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, 
 			y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, 
 			&box))
@@ -1977,74 +2029,82 @@ XYToWindow(int x, int y)
 }
 
 static Bool
-CheckMotion(xEvent *xE)
+CheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
-    WindowPtr prevSpriteWin = sprite.win;
+    WindowPtr prevSpriteWin;
+    SpritePtr pSprite = sprite;
+        
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pSprite = &mpsprites[pDev->id];
+#endif
+        
+    prevSpriteWin = pSprite->win;
 
 #ifdef PANORAMIX
     if(!noPanoramiXExtension)
-	return XineramaCheckMotion(xE);
+	return XineramaCheckMotion(xE, pDev);
 #endif
 
     if (xE && !syncEvents.playingEvents)
     {
-	if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
+	if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
 	{
-	    sprite.hot.pScreen = sprite.hotPhys.pScreen;
-	    ROOT = WindowTable[sprite.hot.pScreen->myNum];
+	    pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
+	    ROOT = WindowTable[pSprite->hot.pScreen->myNum];
 	}
-	sprite.hot.x = XE_KBPTR.rootX;
-	sprite.hot.y = XE_KBPTR.rootY;
-	if (sprite.hot.x < sprite.physLimits.x1)
-	    sprite.hot.x = sprite.physLimits.x1;
-	else if (sprite.hot.x >= sprite.physLimits.x2)
-	    sprite.hot.x = sprite.physLimits.x2 - 1;
-	if (sprite.hot.y < sprite.physLimits.y1)
-	    sprite.hot.y = sprite.physLimits.y1;
-	else if (sprite.hot.y >= sprite.physLimits.y2)
-	    sprite.hot.y = sprite.physLimits.y2 - 1;
+	pSprite->hot.x = XE_KBPTR.rootX;
+	pSprite->hot.y = XE_KBPTR.rootY;
+	if (pSprite->hot.x < pSprite->physLimits.x1)
+	    pSprite->hot.x = pSprite->physLimits.x1;
+	else if (pSprite->hot.x >= pSprite->physLimits.x2)
+	    pSprite->hot.x = pSprite->physLimits.x2 - 1;
+	if (pSprite->hot.y < pSprite->physLimits.y1)
+	    pSprite->hot.y = pSprite->physLimits.y1;
+	else if (pSprite->hot.y >= pSprite->physLimits.y2)
+	    pSprite->hot.y = pSprite->physLimits.y2 - 1;
 #ifdef SHAPE
-	if (sprite.hotShape)
-	    ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
+	if (pSprite->hotShape)
+	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
 #endif
 #ifdef XEVIE
-        xeviehot.x = sprite.hot.x;
-        xeviehot.y = sprite.hot.y;
+        xeviehot.x = pSprite->hot.x;
+        xeviehot.y = pSprite->hot.y;
 #endif
-	sprite.hotPhys = sprite.hot;
+	pSprite->hotPhys = pSprite->hot;
 #ifndef MPX
-	if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
-	    (sprite.hotPhys.y != XE_KBPTR.rootY))
+	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
+	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
 	{
-	    (*sprite.hotPhys.pScreen->SetCursorPosition)(
-		sprite.hotPhys.pScreen,
-		sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
+	    (*pSprite->hotPhys.pScreen->SetCursorPosition)(
+		pSprite->hotPhys.pScreen,
+		pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
 	}
 #endif
-	XE_KBPTR.rootX = sprite.hot.x;
-	XE_KBPTR.rootY = sprite.hot.y;
+	XE_KBPTR.rootX = pSprite->hot.x;
+	XE_KBPTR.rootY = pSprite->hot.y;
     }
 
 #ifdef XEVIE
     xeviewin =
 #endif
-    sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
+    pSprite->win = XYToWindow(pSprite->hot.x, pSprite->hot.y);
 #ifdef notyet
-    if (!(sprite.win->deliverableEvents &
+    if (!(pSprite->win->deliverableEvents &
 	  Motion_Filter(inputInfo.pointer->button))
 	!syncEvents.playingEvents)
     {
 	/* XXX Do PointerNonInterestBox here */
     }
 #endif
-    if (sprite.win != prevSpriteWin)
+    if (pSprite->win != prevSpriteWin)
     {
 	if (prevSpriteWin != NullWindow) {
 	    if (!xE)
 		UpdateCurrentTimeIf();
-	    DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
+	    DoEnterLeaveEvents(prevSpriteWin, pSprite->win, NotifyNormal);
 	}
-	PostNewCursor();
+	PostNewCursor(pDev);
         return FALSE;
     }
     return TRUE;
@@ -2053,7 +2113,7 @@ CheckMotion(xEvent *xE)
 _X_EXPORT void
 WindowsRestructured()
 {
-    (void) CheckMotion((xEvent *)NULL);
+    (void) CheckMotion((xEvent *)NULL, inputInfo.pointer);
 }
 
 #ifdef PANORAMIX
@@ -2068,29 +2128,29 @@ void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
 
     if (noPanoramiXExtension) return;
     
-    sprite.hot.x        -= xoff;
-    sprite.hot.y        -= yoff;
+    sprite->hot.x        -= xoff;
+    sprite->hot.y        -= yoff;
 
-    sprite.hotPhys.x    -= xoff;
-    sprite.hotPhys.y    -= yoff;
+    sprite->hotPhys.x    -= xoff;
+    sprite->hotPhys.y    -= yoff;
 
-    sprite.hotLimits.x1 -= xoff; 
-    sprite.hotLimits.y1 -= yoff;
-    sprite.hotLimits.x2 -= xoff;
-    sprite.hotLimits.y2 -= yoff;
+    sprite->hotLimits.x1 -= xoff; 
+    sprite->hotLimits.y1 -= yoff;
+    sprite->hotLimits.x2 -= xoff;
+    sprite->hotLimits.y2 -= yoff;
 
-    if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1))
-        REGION_TRANSLATE(sprite.screen, &sprite.Reg1,    xoff, yoff);
-    if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2))
-        REGION_TRANSLATE(sprite.screen, &sprite.Reg2,    xoff, yoff);
+    if (REGION_NOTEMPTY(sprite->screen, &sprite->Reg1))
+        REGION_TRANSLATE(sprite->screen, &sprite->Reg1,    xoff, yoff);
+    if (REGION_NOTEMPTY(sprite->screen, &sprite->Reg2))
+        REGION_TRANSLATE(sprite->screen, &sprite->Reg2,    xoff, yoff);
 
     /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
     if ((grab = inputInfo.pointer->grab) && grab->confineTo) {
-	if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
-	    sprite.hotPhys.x = sprite.hotPhys.y = 0;
+	if (grab->confineTo->drawable.pScreen != sprite->hotPhys.pScreen)
+	    sprite->hotPhys.x = sprite->hotPhys.y = 0;
 	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
     } else
-	ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
+	ConfineCursorToWindow(WindowTable[sprite->hotPhys.pScreen->myNum],
 			      TRUE, FALSE);
 }
 #endif
@@ -2099,55 +2159,72 @@ void
 DefineInitialRootWindow(register WindowPtr win)
 {
     register ScreenPtr pScreen = win->drawable.pScreen;
+    SpritePtr pSprite = sprite;
+#ifdef MPX
+    int mpSpriteIdx = 0;
+    DeviceIntPtr pDev;
+
+
+    while (mpSpriteIdx < MAX_DEVICES)
+    {
+        pSprite = &mpsprites[mpSpriteIdx];
+#endif
 
-    sprite.hotPhys.pScreen = pScreen;
-    sprite.hotPhys.x = pScreen->width / 2;
-    sprite.hotPhys.y = pScreen->height / 2;
-    sprite.hot = sprite.hotPhys;
-    sprite.hotLimits.x2 = pScreen->width;
-    sprite.hotLimits.y2 = pScreen->height;
+        pSprite->hotPhys.pScreen = pScreen;
+        pSprite->hotPhys.x = pScreen->width / 2;
+        pSprite->hotPhys.y = pScreen->height / 2;
+        pSprite->hot = pSprite->hotPhys;
+        pSprite->hotLimits.x2 = pScreen->width;
+        pSprite->hotLimits.y2 = pScreen->height;
 #ifdef XEVIE
-    xeviewin =
+        xeviewin =
 #endif
-    sprite.win = win;
-    sprite.current = wCursor (win);
-    sprite.current->refcnt++;
-    spriteTraceGood = 1;
-    ROOT = win;
-/* FIXME: This only limits the core pointer, not the MPX pointer */
-    (*pScreen->CursorLimits) (
-	pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
-    sprite.confined = FALSE;
+            pSprite->win = win;
+        pSprite->current = wCursor (win);
+        pSprite->current->refcnt++;
+        spriteTraceGood = 1;
+        ROOT = win;
+        (*pScreen->CursorLimits) ( pScreen, pSprite->current,
+                                   &pSprite->hotLimits, &pSprite->physLimits);
+        pSprite->confined = FALSE;
+
 #ifdef MPX
-    {
-        DeviceIntPtr pDev = inputInfo.devices;
+        /* this is ugly */
+        pDev = inputInfo.devices;
         while(pDev)
         {
-            (*pScreen->ConstrainCursor) (pDev, pScreen, &sprite.physLimits);
+            if (pDev->id == mpSpriteIdx)
+                (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
+
             pDev = pDev->next;
         }
-    }
 #else
-    (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
+        (*pScreen->ConstrainCursor) (inputInfo.pointer, pScreen,
+                                     &pSprite->physLimits); 
 #endif
-    (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
-    (*pScreen->DisplayCursor) (pScreen, sprite.current);
+        (*pScreen->SetCursorPosition) (pScreen, pSprite->hot.x, pSprite->hot.y,
+                                       FALSE); 
+        (*pScreen->DisplayCursor) (pScreen, pSprite->current);
 
 #ifdef PANORAMIX
-    if(!noPanoramiXExtension) {
-	sprite.hotLimits.x1 = -panoramiXdataPtr[0].x;
-	sprite.hotLimits.y1 = -panoramiXdataPtr[0].y;
-	sprite.hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
-	sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
-	sprite.physLimits = sprite.hotLimits;
-	sprite.confineWin = NullWindow;
+        if(!noPanoramiXExtension) {
+            pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
+            pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
+            pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
+            pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
+            pSprite->physLimits = pSprite->hotLimits;
+            pSprite->confineWin = NullWindow;
 #ifdef SHAPE
-        sprite.hotShape = NullRegion;
+            pSprite->hotShape = NullRegion;
 #endif
-	sprite.screen = pScreen;
-	/* gotta UNINIT these someplace */
-	REGION_NULL(pScreen, &sprite.Reg1);
-	REGION_NULL(pScreen, &sprite.Reg2);
+            pSprite->screen = pScreen;
+            /* gotta UNINIT these someplace */
+            REGION_NULL(pScreen, &pSprite->Reg1);
+            REGION_NULL(pScreen, &pSprite->Reg2);
+        }
+#endif
+#ifdef MPX
+        mpSpriteIdx++;
     }
 #endif
 }
@@ -2162,39 +2239,39 @@ DefineInitialRootWindow(register WindowPtr win)
 void
 WindowHasNewCursor(WindowPtr pWin)
 {
-    PostNewCursor();
+    PostNewCursor(inputInfo.pointer);
 }
 
 _X_EXPORT void
 NewCurrentScreen(ScreenPtr newScreen, int x, int y)
 {
-    sprite.hotPhys.x = x;
-    sprite.hotPhys.y = y;
+    sprite->hotPhys.x = x;
+    sprite->hotPhys.y = y;
 #ifdef PANORAMIX
     if(!noPanoramiXExtension) {
-	sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - 
+	sprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - 
 			    panoramiXdataPtr[0].x;
-	sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - 
+	sprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - 
 			    panoramiXdataPtr[0].y;
-	if (newScreen != sprite.screen) {
-	    sprite.screen = newScreen;
+	if (newScreen != sprite->screen) {
+	    sprite->screen = newScreen;
 	    /* Make sure we tell the DDX to update its copy of the screen */
-	    if(sprite.confineWin)
-		XineramaConfineCursorToWindow(sprite.confineWin, TRUE);
+	    if(sprite->confineWin)
+		XineramaConfineCursorToWindow(sprite->confineWin, TRUE);
 	    else
 		XineramaConfineCursorToWindow(WindowTable[0], TRUE);
 	    /* if the pointer wasn't confined, the DDX won't get 
 	       told of the pointer warp so we reposition it here */
 	    if(!syncEvents.playingEvents)
-		(*sprite.screen->SetCursorPosition)(sprite.screen,
-		    sprite.hotPhys.x + panoramiXdataPtr[0].x - 
-			panoramiXdataPtr[sprite.screen->myNum].x,
-		    sprite.hotPhys.y + panoramiXdataPtr[0].y - 
-			panoramiXdataPtr[sprite.screen->myNum].y, FALSE);
+		(*sprite->screen->SetCursorPosition)(sprite->screen,
+		    sprite->hotPhys.x + panoramiXdataPtr[0].x - 
+			panoramiXdataPtr[sprite->screen->myNum].x,
+		    sprite->hotPhys.y + panoramiXdataPtr[0].y - 
+			panoramiXdataPtr[sprite->screen->myNum].y, FALSE);
 	}
     } else 
 #endif
-    if (newScreen != sprite.hotPhys.pScreen)
+    if (newScreen != sprite->hotPhys.pScreen)
 	ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE);
 }
 
@@ -2222,7 +2299,7 @@ XineramaPointInWindowIsVisible(
     yoff = y + panoramiXdataPtr[0].y;  
 
     for(i = 1; i < PanoramiXNumScreens; i++) {
-	pWin = sprite.windows[i];
+	pWin = sprite->windows[i];
 	pScreen = pWin->drawable.pScreen;
 	x = xoff - panoramiXdataPtr[i].x;
 	y = yoff - panoramiXdataPtr[i].y;
@@ -2255,8 +2332,8 @@ XineramaWarpPointer(ClientPtr client)
 	if (!dest)
 	    return BadWindow;
     }
-    x = sprite.hotPhys.x;
-    y = sprite.hotPhys.y;
+    x = sprite->hotPhys.x;
+    y = sprite->hotPhys.y;
 
     if (stuff->srcWid != None)
     {
@@ -2294,16 +2371,16 @@ XineramaWarpPointer(ClientPtr client)
     x += stuff->dstX;
     y += stuff->dstY;
 
-    if (x < sprite.physLimits.x1)
-	x = sprite.physLimits.x1;
-    else if (x >= sprite.physLimits.x2)
-	x = sprite.physLimits.x2 - 1;
-    if (y < sprite.physLimits.y1)
-	y = sprite.physLimits.y1;
-    else if (y >= sprite.physLimits.y2)
-	y = sprite.physLimits.y2 - 1;
-    if (sprite.hotShape)
-	ConfineToShape(sprite.hotShape, &x, &y);
+    if (x < sprite->physLimits.x1)
+	x = sprite->physLimits.x1;
+    else if (x >= sprite->physLimits.x2)
+	x = sprite->physLimits.x2 - 1;
+    if (y < sprite->physLimits.y1)
+	y = sprite->physLimits.y1;
+    else if (y >= sprite->physLimits.y2)
+	y = sprite->physLimits.y2 - 1;
+    if (sprite->hotShape)
+	ConfineToShape(inputInfo.pointer, sprite->hotShape, &x, &y);
 
     XineramaSetCursorPosition(x, y, TRUE);
 
@@ -2335,8 +2412,8 @@ ProcWarpPointer(ClientPtr client)
 	if (!dest)
 	    return BadWindow;
     }
-    x = sprite.hotPhys.x;
-    y = sprite.hotPhys.y;
+    x = sprite->hotPhys.x;
+    y = sprite->hotPhys.y;
 
     if (stuff->srcWid != None)
     {
@@ -2349,7 +2426,7 @@ ProcWarpPointer(ClientPtr client)
 
 	winX = source->drawable.x;
 	winY = source->drawable.y;
-	if (source->drawable.pScreen != sprite.hotPhys.pScreen ||
+	if (source->drawable.pScreen != sprite->hotPhys.pScreen ||
 	    x < winX + stuff->srcX ||
 	    y < winY + stuff->srcY ||
 	    (stuff->srcWidth != 0 &&
@@ -2365,7 +2442,7 @@ ProcWarpPointer(ClientPtr client)
 	y = dest->drawable.y;
 	newScreen = dest->drawable.pScreen;
     } else 
-	newScreen = sprite.hotPhys.pScreen;
+	newScreen = sprite->hotPhys.pScreen;
 
     x += stuff->dstX;
     y += stuff->dstY;
@@ -2379,23 +2456,23 @@ ProcWarpPointer(ClientPtr client)
     else if (y >= newScreen->height)
 	y = newScreen->height - 1;
 
-    if (newScreen == sprite.hotPhys.pScreen)
+    if (newScreen == sprite->hotPhys.pScreen)
     {
-	if (x < sprite.physLimits.x1)
-	    x = sprite.physLimits.x1;
-	else if (x >= sprite.physLimits.x2)
-	    x = sprite.physLimits.x2 - 1;
-	if (y < sprite.physLimits.y1)
-	    y = sprite.physLimits.y1;
-	else if (y >= sprite.physLimits.y2)
-	    y = sprite.physLimits.y2 - 1;
+	if (x < sprite->physLimits.x1)
+	    x = sprite->physLimits.x1;
+	else if (x >= sprite->physLimits.x2)
+	    x = sprite->physLimits.x2 - 1;
+	if (y < sprite->physLimits.y1)
+	    y = sprite->physLimits.y1;
+	else if (y >= sprite->physLimits.y2)
+	    y = sprite->physLimits.y2 - 1;
 #if defined(SHAPE)
-	if (sprite.hotShape)
-	    ConfineToShape(sprite.hotShape, &x, &y);
+	if (sprite->hotShape)
+	    ConfineToShape(inputInfo.pointer, sprite->hotShape, &x, &y);
 #endif
 	(*newScreen->SetCursorPosition)(newScreen, x, y, TRUE);
     }
-    else if (!PointerConfinedToScreen())
+    else if (!PointerConfinedToScreen(inputInfo.pointer))
     {
 	NewCurrentScreen(newScreen, x, y);
     }
@@ -2405,7 +2482,7 @@ ProcWarpPointer(ClientPtr client)
 static Bool 
 BorderSizeNotEmpty(WindowPtr pWin)
 {
-     if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize))
+     if(REGION_NOTEMPTY(sprite->hotPhys.pScreen, &pWin->borderSize))
 	return TRUE;
 
 #ifdef PANORAMIX
@@ -2413,7 +2490,7 @@ BorderSizeNotEmpty(WindowPtr pWin)
 	int i;
 
 	for(i = 1; i < PanoramiXNumScreens; i++) {
-	    if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize))
+	    if(REGION_NOTEMPTY(sprite->screen, &sprite->windows[i]->borderSize))
 		return TRUE;
 	}
      }
@@ -2624,10 +2701,10 @@ DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev,
 	else
 	    focus = PointerRootWin;
 	if (focus == PointerRootWin)
-	    deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow,
+	    deliveries = DeliverDeviceEvents(sprite->win, xE, grab, NullWindow,
 					     thisDev, count);
-	else if (focus && (focus == sprite.win || IsParent(focus, sprite.win)))
-	    deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus,
+	else if (focus && (focus == sprite->win || IsParent(focus, sprite->win)))
+	    deliveries = DeliverDeviceEvents(sprite->win, xE, grab, focus,
 					     thisDev, count);
 	else if (focus)
 	    deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
@@ -2760,8 +2837,8 @@ drawable.id:0;
     )))
 #endif
     XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state);
-    XE_KBPTR.rootX = sprite.hot.x;
-    XE_KBPTR.rootY = sprite.hot.y;
+    XE_KBPTR.rootX = sprite->hot.x;
+    XE_KBPTR.rootY = sprite->hot.y;
     key = xE->u.u.detail;
     kptr = &keyc->down[key >> 3];
     bit = 1 << (key & 7);
@@ -2837,7 +2914,7 @@ drawable.id:0;
     if (grab)
 	DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
     else
-	DeliverFocusedEvent(keybd, xE, sprite.win, count);
+	DeliverFocusedEvent(keybd, xE, sprite->win, count);
     if (deactivateGrab)
         (*keybd->DeactivateGrab)(keybd);
 
@@ -2891,6 +2968,13 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
     register GrabPtr	grab = mouse->grab;
     Bool                deactivateGrab = FALSE;
     register ButtonClassPtr butc = mouse->button;
+    SpritePtr           pSprite = sprite;
+
+#ifdef MPX
+    if (IsMPDev(mouse))
+        pSprite = &mpsprites[mouse->id];
+#endif
+
 #ifdef XKB
     XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
 #endif
@@ -2926,7 +3010,7 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
 	    /* see comment in EnqueueEvents regarding the next three lines */
 	    if (xE->u.u.type == MotionNotify)
 		XE_KBPTR.root =
-		    WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
+		    WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id;
 	    eventinfo.events = xE;
 	    eventinfo.count = count;
 	    CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
@@ -2938,8 +3022,8 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
 	register BYTE *kptr;
 	int           bit;
 
-	XE_KBPTR.rootX = sprite.hot.x;
-	XE_KBPTR.rootY = sprite.hot.y;
+	XE_KBPTR.rootX = pSprite->hot.x;
+	XE_KBPTR.rootY = pSprite->hot.y;
 
 	key = xE->u.u.detail;
 	kptr = &butc->down[key >> 3];
@@ -2980,12 +3064,12 @@ ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count
 	    FatalError("bogus pointer event from ddx");
 	}
     }
-    else if (!CheckMotion(xE))
+    else if (!CheckMotion(xE, mouse))
 	return;
     if (grab)
 	DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
     else
-	DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
+	DeliverDeviceEvents(pSprite->win, xE, NullGrab, NullWindow,
 			    mouse, count);
     if (deactivateGrab)
         (*mouse->DeactivateGrab)(mouse);
@@ -3235,8 +3319,8 @@ EnterLeaveEvent(
 	event.u.u.type = type;
 	event.u.u.detail = detail;
 	event.u.enterLeave.time = currentTime.milliseconds;
-	event.u.enterLeave.rootX = sprite.hot.x;
-	event.u.enterLeave.rootY = sprite.hot.y;
+	event.u.enterLeave.rootX = sprite->hot.x;
+	event.u.enterLeave.rootY = sprite->hot.y;
 	/* Counts on the same initial structure of crossing & button events! */
 	FixUpEventFromWindow(&event, pWin, None, FALSE);
 	/* Enter/Leave events always set child */
@@ -3441,7 +3525,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
    	{
 	    if (fromWin == PointerRootWin)
-		FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
+		FocusOutEvents(dev, sprite->win, ROOT, mode, NotifyPointer,
 			       TRUE);
 	    /* Notify all the roots */
 #ifdef PANORAMIX
@@ -3454,8 +3538,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	}
 	else
 	{
-	    if (IsParent(fromWin, sprite.win))
-	      FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
+	    if (IsParent(fromWin, sprite->win))
+	      FocusOutEvents(dev, sprite->win, fromWin, mode, NotifyPointer,
 			     FALSE);
 	    FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
 	    /* next call catches the root too, if the screen changed */
@@ -3471,7 +3555,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	    for (i=0; i<screenInfo.numScreens; i++)
 	        FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
 	if (toWin == PointerRootWin)
-	    (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
+	    (void)FocusInEvents(dev, ROOT, sprite->win, NullWindow, mode,
 				NotifyPointer, TRUE);
     }
     else
@@ -3479,7 +3563,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
 	{
 	    if (fromWin == PointerRootWin)
-		FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
+		FocusOutEvents(dev, sprite->win, ROOT, mode, NotifyPointer,
 			       TRUE);
 #ifdef PANORAMIX
  	    if ( !noPanoramiXExtension )
@@ -3492,8 +3576,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 	      (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
 				  NotifyNonlinearVirtual, TRUE);
 	    FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
-	    if (IsParent(toWin, sprite.win))
-    	       (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
+	    if (IsParent(toWin, sprite->win))
+    	       (void)FocusInEvents(dev, toWin, sprite->win, NullWindow, mode,
 				   NotifyPointer, FALSE);
 	}
 	else
@@ -3504,21 +3588,21 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 		FocusOutEvents(dev, fromWin->parent, toWin, mode,
 			       NotifyVirtual, FALSE);
 		FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
-		if ((IsParent(toWin, sprite.win)) &&
-			(sprite.win != fromWin) &&
-			(!IsParent(fromWin, sprite.win)) &&
-			(!IsParent(sprite.win, fromWin)))
-		    (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+		if ((IsParent(toWin, sprite->win)) &&
+			(sprite->win != fromWin) &&
+			(!IsParent(fromWin, sprite->win)) &&
+			(!IsParent(sprite->win, fromWin)))
+		    (void)FocusInEvents(dev, toWin, sprite->win, NullWindow,
 					mode, NotifyPointer, FALSE);
 	    }
 	    else
 		if (IsParent(fromWin, toWin))
 		{
-		    if ((IsParent(fromWin, sprite.win)) &&
-			    (sprite.win != fromWin) &&
-			    (!IsParent(toWin, sprite.win)) &&
-			    (!IsParent(sprite.win, toWin)))
-			FocusOutEvents(dev, sprite.win, fromWin, mode,
+		    if ((IsParent(fromWin, sprite->win)) &&
+			    (sprite->win != fromWin) &&
+			    (!IsParent(toWin, sprite->win)) &&
+			    (!IsParent(sprite->win, toWin)))
+			FocusOutEvents(dev, sprite->win, fromWin, mode,
 				       NotifyPointer, FALSE);
 		    FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
 		    (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
@@ -3530,8 +3614,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 		/* neither fromWin or toWin is child of other */
 		    WindowPtr common = CommonAncestor(toWin, fromWin);
 		/* common == NullWindow ==> different screens */
-		    if (IsParent(fromWin, sprite.win))
-			FocusOutEvents(dev, sprite.win, fromWin, mode,
+		    if (IsParent(fromWin, sprite->win))
+			FocusOutEvents(dev, sprite->win, fromWin, mode,
 				       NotifyPointer, FALSE);
 		    FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
 		    if (fromWin->parent != NullWindow)
@@ -3541,8 +3625,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
 		      (void)FocusInEvents(dev, common, toWin, toWin, mode,
 					  NotifyNonlinearVirtual, FALSE);
 		    FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
-		    if (IsParent(toWin, sprite.win))
-			(void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
+		    if (IsParent(toWin, sprite->win))
+			(void)FocusInEvents(dev, toWin, sprite->win, NullWindow,
 					    mode, NotifyPointer, FALSE);
 		}
 	}
@@ -3808,7 +3892,7 @@ ProcChangeActivePointerGrab(ClientPtr client)
     grab->cursor = newCursor;
     if (newCursor)
 	newCursor->refcnt++;
-    PostNewCursor();
+    PostNewCursor(inputInfo.pointer);
     if (oldCursor)
 	FreeCursor(oldCursor, (Cursor)0);
     grab->eventMask = stuff->eventMask;
@@ -3958,15 +4042,15 @@ ProcQueryPointer(ClientPtr client)
     rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
     rep.length = 0;
     rep.root = (ROOT)->drawable.id;
-    rep.rootX = sprite.hot.x;
-    rep.rootY = sprite.hot.y;
+    rep.rootX = sprite->hot.x;
+    rep.rootY = sprite->hot.y;
     rep.child = None;
-    if (sprite.hot.pScreen == pWin->drawable.pScreen)
+    if (sprite->hot.pScreen == pWin->drawable.pScreen)
     {
 	rep.sameScreen = xTrue;
-	rep.winX = sprite.hot.x - pWin->drawable.x;
-	rep.winY = sprite.hot.y - pWin->drawable.y;
-	for (t = sprite.win; t; t = t->parent)
+	rep.winX = sprite->hot.x - pWin->drawable.x;
+	rep.winY = sprite->hot.y - pWin->drawable.y;
+	for (t = sprite->win; t; t = t->parent)
 	    if (t->parent == pWin)
 	    {
 		rep.child = t->drawable.id;
@@ -4001,7 +4085,19 @@ InitEvents()
 {
     int i;
 
-    sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL;
+    sprite = (SpritePtr)xalloc(sizeof(SpriteRec));
+    if (!sprite)
+        FatalError("failed to allocate sprite struct");
+
+#ifdef MPX
+    mpsprites = (SpritePtr)xalloc(MAX_DEVICES * sizeof(SpriteRec));
+    if (!mpsprites)
+        FatalError("failed to allocate MPX sprite structs");
+    xfree(sprite);
+    sprite = &mpsprites[1];
+#endif
+
+    sprite->hot.pScreen = sprite->hotPhys.pScreen = (ScreenPtr)NULL;
     inputInfo.numDevices = 0;
     inputInfo.devices = (DeviceIntPtr)NULL;
     inputInfo.off_devices = (DeviceIntPtr)NULL;
@@ -4020,13 +4116,34 @@ InitEvents()
 #ifdef XEVIE
     xeviewin =
 #endif
-    sprite.win = NullWindow;
-    sprite.current = NullCursor;
-    sprite.hotLimits.x1 = 0;
-    sprite.hotLimits.y1 = 0;
-    sprite.hotLimits.x2 = 0;
-    sprite.hotLimits.y2 = 0;
-    sprite.confined = FALSE;
+    sprite->win = NullWindow;
+    sprite->current = NullCursor;
+    sprite->hotLimits.x1 = 0;
+    sprite->hotLimits.y1 = 0;
+    sprite->hotLimits.x2 = 0;
+    sprite->hotLimits.y2 = 0;
+    sprite->confined = FALSE;
+
+#ifdef MPX
+    {
+        int mpSpriteIdx = 0;
+        while(mpSpriteIdx < MAX_DEVICES)
+        {
+            SpritePtr pSprite = &mpsprites[mpSpriteIdx];
+            pSprite->hot.pScreen = pSprite->hotPhys.pScreen = (ScreenPtr)NULL;
+            pSprite->win = NullWindow;
+            pSprite->current = NullCursor;
+            pSprite->hotLimits.x1 = 0;
+            pSprite->hotLimits.y1 = 0;
+            pSprite->hotLimits.x2 = 0;
+            pSprite->hotLimits.y2 = 0;
+            pSprite->confined = FALSE;
+
+            mpSpriteIdx++;
+        }
+    }
+#endif
+
     syncEvents.replayDev = (DeviceIntPtr)NULL;
     syncEvents.replayWin = NullWindow;
     while (syncEvents.pending)
@@ -4055,6 +4172,13 @@ CloseDownEvents(void)
   xfree(spriteTrace);
   spriteTrace = NULL;
   spriteTraceSize = 0;
+
+#ifdef MPX
+  /* sprite points to mpsprites[1] in MPX, don't free it separately */
+  xfree(mpsprites);
+#else
+  xfree(sprite);
+#endif
 }
 
 int
@@ -4092,7 +4216,7 @@ ProcSendEvent(ClientPtr client)
     }
 
     if (stuff->destination == PointerWindow)
-	pWin = sprite.win;
+	pWin = sprite->win;
     else if (stuff->destination == InputFocus)
     {
 	WindowPtr inputFocus = inputInfo.keyboard->focus->win;
@@ -4105,10 +4229,10 @@ ProcSendEvent(ClientPtr client)
    	if (inputFocus == PointerRootWin)
 	    inputFocus = ROOT;
 
-	if (IsParent(inputFocus, sprite.win))
+	if (IsParent(inputFocus, sprite->win))
 	{
 	    effectiveFocus = inputFocus;
-	    pWin = sprite.win;
+	    pWin = sprite->win;
 	}
 	else
 	    effectiveFocus = pWin = inputFocus;
@@ -4499,12 +4623,12 @@ ProcRecolorCursor(ClientPtr client)
 	pscr = screenInfo.screens[nscr];
 #ifdef PANORAMIX
 	if(!noPanoramiXExtension)
-	    displayed = (pscr == sprite.screen);
+	    displayed = (pscr == sprite->screen);
 	else
 #endif
-	    displayed = (pscr == sprite.hotPhys.pScreen);
+	    displayed = (pscr == sprite->hotPhys.pScreen);
 	( *pscr->RecolorCursor)(pscr, pCursor,
-				(pCursor == sprite.current) && displayed);
+				(pCursor == sprite->current) && displayed);
     }
     return (Success);
 }
diff --git a/include/cursor.h b/include/cursor.h
index bdf4fd3..b28f8db 100644
--- a/include/cursor.h
+++ b/include/cursor.h
@@ -59,6 +59,8 @@ SOFTWARE.
 #define ARGB_CURSOR
 #endif
 
+struct _DeviceIntRec;
+
 typedef struct _Cursor *CursorPtr;
 typedef struct _CursorMetric *CursorMetricPtr;
 
@@ -133,9 +135,10 @@ extern void NewCurrentScreen(
     int /*x*/,
     int /*y*/);
 
-extern Bool PointerConfinedToScreen(void);
+extern Bool PointerConfinedToScreen(struct _DeviceIntRec* /* pDev */);
 
 extern void GetSpritePosition(
+    struct _DeviceIntRec* /* pDev */,
     int * /*px*/,
     int * /*py*/);
 
diff --git a/mi/mieq.c b/mi/mieq.c
index 30a61e6..2d12388 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -239,11 +239,9 @@ mieqProcessInputEvents()
             }
 
 #ifdef MPX
-            /* MPX devices send both core and Xi events. Depending on what
-             * event we have, dev is set to either the core pointer or the
-             * device. This gives us the right processing function but we need
-             * to pass the right device in too.
-             * Any device that is not a MP device is processed as usual.
+            /* 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 
              */
             if (e->pDev->isMPDev)
                 dev->public.processInputProc(e->event, e->pDev, e->nevents);
@@ -252,11 +250,7 @@ mieqProcessInputEvents()
             dev->public.processInputProc(e->event, dev, e->nevents);
         }
 #ifdef MPX
-        /* 
-         * This is inefficient as we update the sprite for each event rather
-         * than at the end of the event queue. But we don't know if the
-         * next event is from the same device, so it's better to do it here.
-         */
+        /* Update the sprite now. Next event may be from different device.  */
         if (e->event[0].u.u.type == MotionNotify && 
                 (e->pDev->isMPDev || e->pDev->coreEvents))
         {
diff --git a/mi/mipointer.c b/mi/mipointer.c
index d3f5a54..2769223 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -1,5 +1,5 @@
 /*
- * mipointer.c
+ * miPointer->c
  */
 
 
@@ -65,7 +65,7 @@ static unsigned long miPointerGeneration = 0;
  * until more than one pointer device exists.
  */
 
-static miPointerRec miPointer;
+static miPointerPtr miPointer;
 
 #ifdef MPX
 /* Multipointers */
@@ -144,19 +144,27 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     /*
      * set up the pointer object
      */
-    miPointer.pScreen = NULL;
-    miPointer.pSpriteScreen = NULL;
-    miPointer.pCursor = NULL;
-    miPointer.pSpriteCursor = NULL;
-    miPointer.limits.x1 = 0;
-    miPointer.limits.x2 = 32767;
-    miPointer.limits.y1 = 0;
-    miPointer.limits.y2 = 32767;
-    miPointer.confined = FALSE;
-    miPointer.x = 0;
-    miPointer.y = 0;
+    miPointer = (miPointerPtr)xalloc(sizeof(miPointerRec));
+    if (!miPointer)
+    {
+        xfree(pScreenPriv);
+        return FALSE;
+    }
+    miPointer->pScreen = NULL;
+    miPointer->pSpriteScreen = NULL;
+    miPointer->pCursor = NULL;
+    miPointer->pSpriteCursor = NULL;
+    miPointer->limits.x1 = 0;
+    miPointer->limits.x2 = 32767;
+    miPointer->limits.y1 = 0;
+    miPointer->limits.y2 = 32767;
+    miPointer->confined = FALSE;
+    miPointer->x = 0;
+    miPointer->y = 0;
 
 #ifdef MPX
+    xfree(miPointer);
+    miPointer = &miMPPointers[1];
     /*
      * Set up pointer objects for multipointer devices.
      */
@@ -188,10 +196,10 @@ miPointerCloseScreen (index, pScreen)
     int mpPointerIdx = 0;
     SetupScreen(pScreen);
 
-    if (pScreen == miPointer.pScreen)
-	miPointer.pScreen = 0;
-    if (pScreen == miPointer.pSpriteScreen)
-	miPointer.pSpriteScreen = 0;
+    if (pScreen == miPointer->pScreen)
+	miPointer->pScreen = 0;
+    if (pScreen == miPointer->pSpriteScreen)
+	miPointer->pSpriteScreen = 0;
 #ifdef MPX
     while(mpPointerIdx < MAX_DEVICES)
     {
@@ -249,8 +257,8 @@ miPointerDisplayCursor (pScreen, pCursor)
     }
 
 #endif
-    miPointer.pCursor = pCursor;
-    miPointer.pScreen = pScreen;
+    miPointer->pCursor = pCursor;
+    miPointer->pScreen = pScreen;
     miPointerUpdateSprite(inputInfo.pointer);
     return TRUE;
 }
@@ -261,14 +269,13 @@ miPointerConstrainCursor (pDev, pScreen, pBox)
     ScreenPtr	pScreen;
     BoxPtr	pBox;
 {
+    miPointerPtr pPointer = miPointer;
 #ifdef MPX
     if (IsMPDev(pDev))
-    {
-        miMPPointers[pDev->id].limits = *pBox;
-    }
+        pPointer = &miMPPointers[pDev->id];
 #endif
-    miPointer.limits = *pBox;
-    miPointer.confined = PointerConfinedToScreen();
+    pPointer->limits = *pBox;
+    pPointer->confined = PointerConfinedToScreen(pDev);
 }
 
 /*ARGSUSED*/
@@ -320,7 +327,7 @@ miPointerWarpCursor (pScreen, x, y)
 
     SetupScreen (pScreen);
 
-    if (miPointer.pScreen != pScreen)
+    if (miPointer->pScreen != pScreen)
 	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
 
     if (GenerateEvent)
@@ -331,16 +338,16 @@ miPointerWarpCursor (pScreen, x, y)
     {
 	/* everything from miPointerMove except the event and history */
 
-    	if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
+    	if (!pScreenPriv->waitForUpdate && pScreen == miPointer->pSpriteScreen)
     	{
-	    miPointer.devx = x;
-	    miPointer.devy = y;
-	    if(!miPointer.pCursor->bits->emptyMask)
+	    miPointer->devx = x;
+	    miPointer->devy = y;
+	    if(!miPointer->pCursor->bits->emptyMask)
 		(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     	}
-	miPointer.x = x;
-	miPointer.y = y;
-	miPointer.pScreen = pScreen;
+	miPointer->x = x;
+	miPointer->y = y;
+	miPointer->pScreen = pScreen;
     }
 }
 
@@ -367,7 +374,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     miPointerScreenPtr	pScreenPriv;
     CursorPtr		pCursor;
     int			x, y, devx, devy;
-    miPointerPtr        pointer;
+    miPointerPtr        pPointer;
 
 #ifdef MPX
     if (!pDev || 
@@ -379,66 +386,66 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
 
 #ifdef MPX
     if (IsMPDev(pDev))
-        pointer = &miMPPointers[pDev->id];
+        pPointer = &miMPPointers[pDev->id];
     else
-        pointer = &miPointer;
+        pPointer = miPointer;
 #endif
 
-    pScreen = pointer->pScreen;
+    pScreen = pPointer->pScreen;
     if (!pScreen)
 	return;
 
-    x = pointer->x;
-    y = pointer->y;
-    devx = pointer->devx;
-    devy = pointer->devy;
+    x = pPointer->x;
+    y = pPointer->y;
+    devx = pPointer->devx;
+    devy = pPointer->devy;
 
     pScreenPriv = GetScreenPrivate (pScreen);
     /*
      * if the cursor has switched screens, disable the sprite
      * on the old screen
      */
-    if (pScreen != pointer->pSpriteScreen)
+    if (pScreen != pPointer->pSpriteScreen)
     {
-	if (pointer->pSpriteScreen)
+	if (pPointer->pSpriteScreen)
 	{
 	    miPointerScreenPtr  pOldPriv;
     	
-	    pOldPriv = GetScreenPrivate (pointer->pSpriteScreen);
-	    if (pointer->pCursor)
+	    pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
+	    if (pPointer->pCursor)
 	    {
 	    	(*pOldPriv->spriteFuncs->SetCursor)
-			    	(pDev, pointer->pSpriteScreen, NullCursor, 0, 0);
+			    	(pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
 	    }
-	    (*pOldPriv->screenFuncs->CrossScreen) (pointer->pSpriteScreen, FALSE);
+	    (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
 	}
 	(*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
 	(*pScreenPriv->spriteFuncs->SetCursor)
-				(pDev, pScreen, pointer->pCursor, x, y);
-	pointer->devx = x;
-	pointer->devy = y;
-	pointer->pSpriteCursor = pointer->pCursor;
-	pointer->pSpriteScreen = pScreen;
+				(pDev, pScreen, pPointer->pCursor, x, y);
+	pPointer->devx = x;
+	pPointer->devy = y;
+	pPointer->pSpriteCursor = pPointer->pCursor;
+	pPointer->pSpriteScreen = pScreen;
     }
     /*
      * if the cursor has changed, display the new one
      */
-    else if (pointer->pCursor != pointer->pSpriteCursor)
+    else if (pPointer->pCursor != pPointer->pSpriteCursor)
     {
-	pCursor = pointer->pCursor;
+	pCursor = pPointer->pCursor;
 	if (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)
 	    pCursor = NullCursor;
 	(*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
 
-	pointer->devx = x;
-	pointer->devy = y;
-	pointer->pSpriteCursor = pointer->pCursor;
+	pPointer->devx = x;
+	pPointer->devy = y;
+	pPointer->pSpriteCursor = pPointer->pCursor;
     }
     else if (x != devx || y != devy)
     {
-	pointer->devx = x;
-	pointer->devy = y;
-	if(!pointer->pCursor->bits->emptyMask)
+	pPointer->devx = x;
+	pPointer->devy = y;
+	if(!pPointer->pCursor->bits->emptyMask)
 	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     }
 }
@@ -451,7 +458,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
 void
 miPointerDeltaCursor (int dx, int dy, unsigned long time)
 {
-    int x = miPointer.x + dx, y = miPointer.y + dy;
+    int x = miPointer->x + dx, y = miPointer->y + dy;
 
     miPointerSetPosition(inputInfo.pointer, &x, &y, time);
 }
@@ -480,8 +487,8 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
         }
 #endif
         {
-            miPointer.limits.x2 = pScreen->width;
-            miPointer.limits.y2 = pScreen->height;
+            miPointer->limits.x2 = pScreen->width;
+            miPointer->limits.y2 = pScreen->height;
         }
 }
 
@@ -498,7 +505,7 @@ miPointerGetScreen(DeviceIntPtr pDev)
     if (IsMPDev(pDev))
         return miMPPointers[pDev->id].pScreen;
 #endif
-    return miPointer.pScreen;
+    return miPointer->pScreen;
 }
 
 /* Move the pointer to x, y on the current screen, update the sprite, and
@@ -517,15 +524,15 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     ScreenPtr		pScreen;
     ScreenPtr		newScreen;
 
-    miPointerPtr        pointer;
+    miPointerPtr        pPointer;
 #ifdef MPX
     if (IsMPDev(pDev))
-        pointer = &(miMPPointers[pDev->id]);
+        pPointer = &(miMPPointers[pDev->id]);
     else
 #endif
-        pointer = &miPointer;
+        pPointer = miPointer;
 
-    pScreen = pointer->pScreen;
+    pScreen = pPointer->pScreen;
     if (!pScreen)
 	return;	    /* called before ready */
 
@@ -540,7 +547,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
     {
 	pScreenPriv = GetScreenPrivate (pScreen);
-	if (!pointer->confined)
+	if (!pPointer->confined)
 	{
 	    newScreen = pScreen;
 	    (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
@@ -550,23 +557,24 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
 		(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
 		pScreenPriv = GetScreenPrivate (pScreen);
 	    	/* Smash the confine to the new screen */
-                pointer->limits.x2 = pScreen->width;
-                pointer->limits.y2 = pScreen->height;
+                pPointer->limits.x2 = pScreen->width;
+                pPointer->limits.y2 = pScreen->height;
 	    }
 	}
     }
     /* Constrain the sprite to the current limits. */
-    if (*x < pointer->limits.x1)
-	*x = pointer->limits.x1;
-    if (*x >= pointer->limits.x2)
-	*x = pointer->limits.x2 - 1;
-    if (*y < pointer->limits.y1)
-	*y = pointer->limits.y1;
-    if (*y >= pointer->limits.y2)
-	*y = pointer->limits.y2 - 1;
-
-    if (pointer->x == *x && pointer->y == *y && pointer->pScreen == pScreen)
-	return;
+    if (*x < pPointer->limits.x1)
+	*x = pPointer->limits.x1;
+    if (*x >= pPointer->limits.x2)
+	*x = pPointer->limits.x2 - 1;
+    if (*y < pPointer->limits.y1)
+	*y = pPointer->limits.y1;
+    if (*y >= pPointer->limits.y2)
+	*y = pPointer->limits.y2 - 1;
+
+    if (pPointer->x == *x && pPointer->y == *y && 
+            pPointer->pScreen == pScreen) 
+        return;
 
     miPointerMoved(pDev, pScreen, *x, *y, time);
 }
@@ -589,8 +597,8 @@ miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
     else
 #endif
     {
-        *x = miPointer.x;
-        *y = miPointer.y;
+        *x = miPointer->x;
+        *y = miPointer->y;
     }
 }
 
@@ -605,30 +613,30 @@ void
 miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
                      unsigned long time)
 {
-    miPointerPtr pointer;
+    miPointerPtr pPointer;
     SetupScreen(pScreen);
 
 #ifdef MPX
     if (IsMPDev(pDev))
-        pointer = &miMPPointers[pDev->id];
+        pPointer = &miMPPointers[pDev->id];
     else
 #endif
-        pointer = &miPointer;
+        pPointer = miPointer;
 
     if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer
 #ifdef MPX
                 || pDev->isMPDev
 #endif
                 ) &&
-        !pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
+        !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
     {
-	pointer->devx = x;
-	pointer->devy = y;
-	if(!pointer->pCursor->bits->emptyMask)
+	pPointer->devx = x;
+	pPointer->devy = y;
+	if(!pPointer->pCursor->bits->emptyMask)
 	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     }
 
-    pointer->x = x;
-    pointer->y = y;
-    pointer->pScreen = pScreen;
+    pPointer->x = x;
+    pPointer->y = y;
+    pPointer->pScreen = pScreen;
 }
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
index c75e744..22f9b09 100755
--- a/xfixes/cursor.c
+++ b/xfixes/cursor.c
@@ -355,7 +355,7 @@ ProcXFixesGetCursorImage (ClientPtr client)
     pCursor = CursorCurrent;
     if (!pCursor)
 	return BadCursor;
-    GetSpritePosition (&x, &y);
+    GetSpritePosition (inputInfo.pointer, &x, &y);
     width = pCursor->bits->width;
     height = pCursor->bits->height;
     npixels = width * height;
@@ -503,7 +503,7 @@ ProcXFixesGetCursorImageAndName (ClientPtr client)
     pCursor = CursorCurrent;
     if (!pCursor)
 	return BadCursor;
-    GetSpritePosition (&x, &y);
+    GetSpritePosition (inputInfo.pointer, &x, &y);
     width = pCursor->bits->width;
     height = pCursor->bits->height;
     npixels = width * height;
diff --git a/xkb/ddxDevBtn.c b/xkb/ddxDevBtn.c
index 3de8f87..dd7d445 100644
--- a/xkb/ddxDevBtn.c
+++ b/xkb/ddxDevBtn.c
@@ -60,7 +60,7 @@ int			nAxes, i, count;
     if (nAxes > 6)
 	nAxes = 6;
 
-    GetSpritePosition(&x,&y);
+    GetSpritePosition(dev, &x,&y);
     btn= (deviceKeyButtonPointer *) &events[0];
     val= (deviceValuator *) &events[1];
     if (press)		btn->type= DeviceButtonPress;
diff --git a/xkb/ddxFakeBtn.c b/xkb/ddxFakeBtn.c
index f7b746b..3f23542 100644
--- a/xkb/ddxFakeBtn.c
+++ b/xkb/ddxFakeBtn.c
@@ -49,7 +49,7 @@ DevicePtr ptr;
 
     if ((ptr = LookupPointerDevice())==NULL)
 	return;
-    GetSpritePosition(&x,&y);
+    GetSpritePosition(inputInfo.pointer, &x,&y);
     ev.u.u.type = event;
     ev.u.u.detail = button;
     ev.u.keyButtonPointer.time = GetTimeInMillis();
diff --git a/xkb/ddxFakeMtn.c b/xkb/ddxFakeMtn.c
index a19819f..3dd733b 100644
--- a/xkb/ddxFakeMtn.c
+++ b/xkb/ddxFakeMtn.c
@@ -53,7 +53,7 @@ XkbDDXFakePointerMotion(unsigned flags,int x,int y)
 int 		   oldX,oldY;
 ScreenPtr	   pScreen, oldScreen;
 
-    GetSpritePosition(&oldX, &oldY);
+    GetSpritePosition(inputInfo.pointer, &oldX, &oldY);
     pScreen = oldScreen = GetSpriteWindow()->drawable.pScreen;
 
 #ifdef PANORAMIX
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index e0bf89c..7b074b5 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -875,7 +875,7 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
     if ((filter->keycode!=0)&&(filter->keycode!=keycode))
 	return 1;
 
-    GetSpritePosition(&x,&y);
+    GetSpritePosition(inputInfo.pointer, &x,&y);
     ev.u.keyButtonPointer.time = GetTimeInMillis();
     ev.u.keyButtonPointer.rootX = x;
     ev.u.keyButtonPointer.rootY = y;
commit fd8b9a6eaee28a453a00af14195b81ef1890a577
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 21 15:24:43 2006 +1030

    TAG:   MPX_BEFORE_DIX_API_BREAK

diff --git a/Changelog b/Changelog
index 80e1846..18bbeb4 100644
--- a/Changelog
+++ b/Changelog
@@ -32,6 +32,8 @@ Files:
 	mi/mipointer.c
 	include/scrnintstr.h
 
+TAG:   MPX_BEFORE_DIX_API_BREAK
+
 == 20.11.06 ==
 
 mi:     moved core pointer information from miSpriteScreenRec into a
commit 447efdc01d4f8922205ba26e52c9e5ff9f5cb90e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 21 14:46:00 2006 +1030

    mi:	constrain MPX cursors to screen

diff --git a/Changelog b/Changelog
index 3477d43..80e1846 100644
--- a/Changelog
+++ b/Changelog
@@ -24,6 +24,14 @@ Files:
 
 BUG:   Core pointer changes whenever MPX cursor changes shape.
 
+
+mi:	constrain MPX cursors to screen 
+
+Files:
+	dix/events.c
+	mi/mipointer.c
+	include/scrnintstr.h
+
 == 20.11.06 ==
 
 mi:     moved core pointer information from miSpriteScreenRec into a
diff --git a/dix/events.c b/dix/events.c
index f50e246..4c33fd4 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -392,7 +392,7 @@ XineramaConstrainCursor(void)
     newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
     newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
 
-    (* pScreen->ConstrainCursor)(pScreen, &newBox);
+    (* pScreen->ConstrainCursor)(inputInfo.pointer, pScreen, &newBox);
 }
 
 static void
@@ -735,7 +735,7 @@ CheckPhysLimits(
     (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
 			      &sprite.physLimits);
     sprite.confined = confineToScreen;
-    (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits);
+    (* pScreen->ConstrainCursor)(inputInfo.pointer, pScreen, &sprite.physLimits);
     if (new.x < sprite.physLimits.x1)
 	new.x = sprite.physLimits.x1;
     else
@@ -2118,7 +2118,18 @@ DefineInitialRootWindow(register WindowPtr win)
     (*pScreen->CursorLimits) (
 	pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
     sprite.confined = FALSE;
+#ifdef MPX
+    {
+        DeviceIntPtr pDev = inputInfo.devices;
+        while(pDev)
+        {
+            (*pScreen->ConstrainCursor) (pDev, pScreen, &sprite.physLimits);
+            pDev = pDev->next;
+        }
+    }
+#else
     (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
+#endif
     (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
     (*pScreen->DisplayCursor) (pScreen, sprite.current);
 
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index 3613515..4fa2919 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -257,6 +257,7 @@ typedef    Bool (* UnrealizeFontProcPtr)(
 	FontPtr /*pFont*/);
 
 typedef    void (* ConstrainCursorProcPtr)(
+        DeviceIntPtr /*pDev*/,
 	ScreenPtr /*pScreen*/,
 	BoxPtr /*pBox*/);
 
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 8f049c4..d3f5a54 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -83,8 +83,10 @@ IsMPDev(DeviceIntPtr pDev)
 static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static void miPointerConstrainCursor(ScreenPtr pScreen, BoxPtr pBox);
-static void miPointerPointerNonInterestBox(ScreenPtr pScreen, BoxPtr pBox);
+static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                                     BoxPtr pBox); 
+static void miPointerPointerNonInterestBox(ScreenPtr
+            pScreen, BoxPtr pBox);
 static void miPointerCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
 				  BoxPtr pHotBox, BoxPtr pTopLeftBox);
 static Bool miPointerSetCursorPosition(ScreenPtr pScreen, int x, int y,
@@ -254,10 +256,17 @@ miPointerDisplayCursor (pScreen, pCursor)
 }
 
 static void
-miPointerConstrainCursor (pScreen, pBox)
+miPointerConstrainCursor (pDev, pScreen, pBox)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
     BoxPtr	pBox;
 {
+#ifdef MPX
+    if (IsMPDev(pDev))
+    {
+        miMPPointers[pDev->id].limits = *pBox;
+    }
+#endif
     miPointer.limits = *pBox;
     miPointer.confined = PointerConfinedToScreen();
 }
commit 1107d8bea22eea26f7b666f1c00a53360b7d237e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 21 14:00:46 2006 +1030

    mi:     added device ID to miSpriteCursorFuncRec functions
            added MPX code to midispcur.c
    
    BUG:   Core pointer changes whenever MPX cursor changes shape.

diff --git a/Changelog b/Changelog
index e0bdedd..3477d43 100644
--- a/Changelog
+++ b/Changelog
@@ -12,6 +12,18 @@ Files:
 
 TAG: MPX_BEFORE_MIDC_API_BREAK
 
+
+mi:     added device ID to miSpriteCursorFuncRec functions
+        added MPX code to midispcur.c
+
+
+Files:
+        mi/midispcur.c
+        mi/misprite.c
+        mi/mispritest.h
+
+BUG:   Core pointer changes whenever MPX cursor changes shape.
+
 == 20.11.06 ==
 
 mi:     moved core pointer information from miSpriteScreenRec into a
diff --git a/mi/midispcur.c b/mi/midispcur.c
index a46331b..8b961d5 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -54,6 +54,10 @@ in this Software without prior written authorization from The Open Group.
 
 #ifdef MPX
 # include "inputstr.h"
+
+
+#define SaneID(a) (a >= 0 && a < MAX_DEVICES)
+
 #endif
 
 /* per-screen private data */
@@ -98,18 +102,22 @@ typedef struct {
 
 static Bool	miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 static Bool	miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static Bool	miDCPutUpCursor(ScreenPtr pScreen, CursorPtr pCursor,
-				int x, int y, unsigned long source,
-				unsigned long mask);
-static Bool	miDCSaveUnderCursor(ScreenPtr pScreen, int x, int y,
+static Bool	miDCPutUpCursor(int deviceid, ScreenPtr pScreen, 
+                                CursorPtr pCursor, int x, int y, 
+                                unsigned long source, unsigned long mask);
+static Bool	miDCSaveUnderCursor(int deviceid, ScreenPtr pScreen, 
+                                    int x, int y,
 				    int w, int h);
-static Bool	miDCRestoreUnderCursor(ScreenPtr pScreen, int x, int y,
+static Bool	miDCRestoreUnderCursor(int deviceid, ScreenPtr pScreen, 
+                                       int x, int y,
 				       int w, int h);
-static Bool	miDCMoveCursor(ScreenPtr pScreen, CursorPtr pCursor,
-			       int x, int y, int w, int h, int dx, int dy,
+static Bool	miDCMoveCursor(int deviceid, ScreenPtr pScreen, 
+                               CursorPtr pCursor, int x, int y, 
+                               int w, int h, int dx, int dy,
 			       unsigned long source, unsigned long mask);
-static Bool	miDCChangeSave(ScreenPtr pScreen, int x, int y, int w, int h,	
-			       int dx, int dy);
+static Bool	miDCChangeSave(int deviceid, ScreenPtr pScreen, 
+                               int x, int y, int w, int h,	
+                               int dx, int dy);
 
 static miSpriteCursorFuncRec miDCFuncs = {
     miDCRealizeCursor,
@@ -214,24 +222,42 @@ miDCCloseScreen (index, pScreen)
     ScreenPtr	pScreen;
 {
     miDCScreenPtr   pScreenPriv;
+    miDCBufferPtr   pBuffer;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
-    tossGC (pScreenPriv->pCoreBuffer->pSourceGC);
-    tossGC (pScreenPriv->pCoreBuffer->pMaskGC);
-    tossGC (pScreenPriv->pCoreBuffer->pSaveGC);
-    tossGC (pScreenPriv->pCoreBuffer->pRestoreGC);
-    tossGC (pScreenPriv->pCoreBuffer->pMoveGC);
-    tossGC (pScreenPriv->pCoreBuffer->pPixSourceGC);
-    tossGC (pScreenPriv->pCoreBuffer->pPixMaskGC);
-    tossPix (pScreenPriv->pCoreBuffer->pSave);
-    tossPix (pScreenPriv->pCoreBuffer->pTemp);
+    pBuffer = pScreenPriv->pCoreBuffer;
+
+#ifdef MPX
+    {
+        int mpBufferIdx = 0;
+        while (mpBufferIdx < MAX_DEVICES) 
+        {
+            pBuffer = &pScreenPriv->pMPBuffers[mpBufferIdx];
+
+#endif
+            tossGC (pBuffer->pSourceGC);
+            tossGC (pBuffer->pMaskGC);
+            tossGC (pBuffer->pSaveGC);
+            tossGC (pBuffer->pRestoreGC);
+            tossGC (pBuffer->pMoveGC);
+            tossGC (pBuffer->pPixSourceGC);
+            tossGC (pBuffer->pPixMaskGC);
+            tossPix (pBuffer->pSave);
+            tossPix (pBuffer->pTemp);
 #ifdef ARGB_CURSOR
 #if 0				/* This has been free()d before */
-    tossPict (pScreenPriv->pRootPicture);
+            tossPict (pScreenPriv->pRootPicture);
 #endif 
-    tossPict (pScreenPriv->pCoreBuffer->pTempPicture);
+            tossPict (pBuffer->pTempPicture);
 #endif
+
+#ifdef MPX
+            mpBufferIdx++;
+        }
+    }
+#endif
+
     xfree ((pointer) pScreenPriv);
     return (*pScreen->CloseScreen) (index, pScreen);
 }
@@ -504,7 +530,8 @@ miDCMakeGC(
 
 
 static Bool
-miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
+miDCPutUpCursor (deviceid, pScreen, pCursor, x, y, source, mask)
+    int             deviceid;
     ScreenPtr	    pScreen;
     CursorPtr	    pCursor;
     int		    x, y;
@@ -512,6 +539,7 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
 {
     miDCScreenPtr   pScreenPriv;
     miDCCursorPtr   pPriv;
+    miDCBufferPtr   pBuffer;
     WindowPtr	    pWin;
 
     pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
@@ -523,15 +551,22 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
     }
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pWin = WindowTable[pScreen->myNum];
+    pBuffer = pScreenPriv->pCoreBuffer;
+
+#ifdef MPX
+    if (SaneID(deviceid))
+            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+#endif
+
 #ifdef ARGB_CURSOR
     if (pPriv->pPicture)
     {
-	if (!EnsurePicture(pScreenPriv->pCoreBuffer->pRootPicture, &pWin->drawable, pWin))
+	if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
 	    return FALSE;
 	CompositePicture (PictOpOver,
 			  pPriv->pPicture,
 			  NULL,
-			  pScreenPriv->pCoreBuffer->pRootPicture,
+			  pBuffer->pRootPicture,
 			  0, 0, 0, 0, 
 			  x, y, 
 			  pCursor->bits->width,
@@ -540,16 +575,16 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
     else
 #endif
     {
-	if (!EnsureGC(pScreenPriv->pCoreBuffer->pSourceGC, pWin))
+	if (!EnsureGC(pBuffer->pSourceGC, pWin))
 	    return FALSE;
-	if (!EnsureGC(pScreenPriv->pCoreBuffer->pMaskGC, pWin))
+	if (!EnsureGC(pBuffer->pMaskGC, pWin))
 	{
-	    FreeGC (pScreenPriv->pCoreBuffer->pSourceGC, (GContext) 0);
-	    pScreenPriv->pCoreBuffer->pSourceGC = 0;
+	    FreeGC (pBuffer->pSourceGC, (GContext) 0);
+	    pBuffer->pSourceGC = 0;
 	    return FALSE;
 	}
 	miDCPutBits ((DrawablePtr)pWin, pPriv,
-		     pScreenPriv->pCoreBuffer->pSourceGC, pScreenPriv->pCoreBuffer->pMaskGC,
+		     pBuffer->pSourceGC, pBuffer->pMaskGC,
 		     x, y, pCursor->bits->width, pCursor->bits->height,
 		     source, mask);
     }
@@ -557,30 +592,37 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
 }
 
 static Bool
-miDCSaveUnderCursor (pScreen, x, y, w, h)
+miDCSaveUnderCursor (deviceid, pScreen, x, y, w, h)
+    int         deviceid;
     ScreenPtr	pScreen;
     int		x, y, w, h;
 {
     miDCScreenPtr   pScreenPriv;
+    miDCBufferPtr   pBuffer;
     PixmapPtr	    pSave;
     WindowPtr	    pWin;
     GCPtr	    pGC;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pSave = pScreenPriv->pCoreBuffer->pSave;
+    pBuffer = pScreenPriv->pCoreBuffer;
+#ifdef MPX
+    if (SaneID(deviceid))
+            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+#endif
+    pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
     {
 	if (pSave)
 	    (*pScreen->DestroyPixmap) (pSave);
-	pScreenPriv->pCoreBuffer->pSave = pSave =
+	pBuffer->pSave = pSave =
 		(*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth);
 	if (!pSave)
 	    return FALSE;
     }
-    if (!EnsureGC(pScreenPriv->pCoreBuffer->pSaveGC, pWin))
+    if (!EnsureGC(pBuffer->pSaveGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pCoreBuffer->pSaveGC;
+    pGC = pBuffer->pSaveGC;
     if (pSave->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pSave, pGC);
     (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
@@ -589,23 +631,30 @@ miDCSaveUnderCursor (pScreen, x, y, w, h)
 }
 
 static Bool
-miDCRestoreUnderCursor (pScreen, x, y, w, h)
+miDCRestoreUnderCursor (deviceid, pScreen, x, y, w, h)
+    int         deviceid;
     ScreenPtr	pScreen;
     int		x, y, w, h;
 {
     miDCScreenPtr   pScreenPriv;
+    miDCBufferPtr   pBuffer;
     PixmapPtr	    pSave;
     WindowPtr	    pWin;
     GCPtr	    pGC;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pSave = pScreenPriv->pCoreBuffer->pSave;
+    pBuffer = pScreenPriv->pCoreBuffer;
+#ifdef MPX
+    if (SaneID(deviceid))
+            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+#endif
+    pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     if (!pSave)
 	return FALSE;
-    if (!EnsureGC(pScreenPriv->pCoreBuffer->pRestoreGC, pWin))
+    if (!EnsureGC(pBuffer->pRestoreGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pCoreBuffer->pRestoreGC;
+    pGC = pBuffer->pRestoreGC;
     if (pWin->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pWin, pGC);
     (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
@@ -614,27 +663,34 @@ miDCRestoreUnderCursor (pScreen, x, y, w, h)
 }
 
 static Bool
-miDCChangeSave (pScreen, x, y, w, h, dx, dy)
+miDCChangeSave (deviceid, pScreen, x, y, w, h, dx, dy)
+    int             deviceid;
     ScreenPtr	    pScreen;
     int		    x, y, w, h, dx, dy;
 {
     miDCScreenPtr   pScreenPriv;
+    miDCBufferPtr   pBuffer;
     PixmapPtr	    pSave;
     WindowPtr	    pWin;
     GCPtr	    pGC;
     int		    sourcex, sourcey, destx, desty, copyw, copyh;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pSave = pScreenPriv->pCoreBuffer->pSave;
+    pBuffer = pScreenPriv->pCoreBuffer;
+#ifdef MPX
+    if (SaneID(deviceid))
+            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+#endif
+    pSave = pBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     /*
      * restore the bits which are about to get trashed
      */
     if (!pSave)
 	return FALSE;
-    if (!EnsureGC(pScreenPriv->pCoreBuffer->pRestoreGC, pWin))
+    if (!EnsureGC(pBuffer->pRestoreGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pCoreBuffer->pRestoreGC;
+    pGC = pBuffer->pRestoreGC;
     if (pWin->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pWin, pGC);
     /*
@@ -672,9 +728,9 @@ miDCChangeSave (pScreen, x, y, w, h, dx, dy)
 	(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
 			       0, sourcey, -dx, copyh, x + dx, desty);
     }
-    if (!EnsureGC(pScreenPriv->pCoreBuffer->pSaveGC, pWin))
+    if (!EnsureGC(pBuffer->pSaveGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pCoreBuffer->pSaveGC;
+    pGC = pBuffer->pSaveGC;
     if (pSave->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pSave, pGC);
     /*
@@ -746,7 +802,8 @@ miDCChangeSave (pScreen, x, y, w, h, dx, dy)
 }
 
 static Bool
-miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
+miDCMoveCursor (deviceid, pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
+    int             deviceid;
     ScreenPtr	    pScreen;
     CursorPtr	    pCursor;
     int		    x, y, w, h, dx, dy;
@@ -754,6 +811,7 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
 {
     miDCCursorPtr   pPriv;
     miDCScreenPtr   pScreenPriv;
+    miDCBufferPtr   pBuffer;
     int		    status;
     WindowPtr	    pWin;
     GCPtr	    pGC;
@@ -769,39 +827,44 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
     }
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pWin = WindowTable[pScreen->myNum];
-    pTemp = pScreenPriv->pCoreBuffer->pTemp;
+    pBuffer = pScreenPriv->pCoreBuffer;
+#ifdef MPX
+    if (SaneID(deviceid))
+            pBuffer = &pScreenPriv->pMPBuffers[deviceid];
+#endif
+    pTemp = pBuffer->pTemp;
     if (!pTemp ||
-	pTemp->drawable.width != pScreenPriv->pCoreBuffer->pSave->drawable.width ||
-	pTemp->drawable.height != pScreenPriv->pCoreBuffer->pSave->drawable.height)
+	pTemp->drawable.width != pBuffer->pSave->drawable.width ||
+	pTemp->drawable.height != pBuffer->pSave->drawable.height)
     {
 	if (pTemp)
 	    (*pScreen->DestroyPixmap) (pTemp);
 #ifdef ARGB_CURSOR
-	if (pScreenPriv->pCoreBuffer->pTempPicture)
+	if (pBuffer->pTempPicture)
 	{
-	    FreePicture (pScreenPriv->pCoreBuffer->pTempPicture, 0);
-	    pScreenPriv->pCoreBuffer->pTempPicture = 0;
+	    FreePicture (pBuffer->pTempPicture, 0);
+	    pBuffer->pTempPicture = 0;
 	}
 #endif
-	pScreenPriv->pCoreBuffer->pTemp = pTemp = (*pScreen->CreatePixmap)
-	    (pScreen, w, h, pScreenPriv->pCoreBuffer->pSave->drawable.depth);
+	pBuffer->pTemp = pTemp = (*pScreen->CreatePixmap)
+	    (pScreen, w, h, pBuffer->pSave->drawable.depth);
 	if (!pTemp)
 	    return FALSE;
     }
-    if (!pScreenPriv->pCoreBuffer->pMoveGC)
+    if (!pBuffer->pMoveGC)
     {
-	pScreenPriv->pCoreBuffer->pMoveGC = CreateGC ((DrawablePtr)pTemp,
+	pBuffer->pMoveGC = CreateGC ((DrawablePtr)pTemp,
 	    GCGraphicsExposures, &gcval, &status);
-	if (!pScreenPriv->pCoreBuffer->pMoveGC)
+	if (!pBuffer->pMoveGC)
 	    return FALSE;
     }
     /*
      * copy the saved area to a temporary pixmap
      */
-    pGC = pScreenPriv->pCoreBuffer->pMoveGC;
+    pGC = pBuffer->pMoveGC;
     if (pGC->serialNumber != pTemp->drawable.serialNumber)
 	ValidateGC ((DrawablePtr) pTemp, pGC);
-    (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pCoreBuffer->pSave,
+    (*pGC->ops->CopyArea)((DrawablePtr)pBuffer->pSave,
 			  (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0);
     
     /*
@@ -810,12 +873,12 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
 #ifdef ARGB_CURSOR
     if (pPriv->pPicture)
     {
-	if (!EnsurePicture(pScreenPriv->pCoreBuffer->pTempPicture, &pTemp->drawable, pWin))
+	if (!EnsurePicture(pBuffer->pTempPicture, &pTemp->drawable, pWin))
 	    return FALSE;
 	CompositePicture (PictOpOver,
 			  pPriv->pPicture,
 			  NULL,
-			  pScreenPriv->pCoreBuffer->pTempPicture,
+			  pBuffer->pTempPicture,
 			  0, 0, 0, 0, 
 			  dx, dy, 
 			  pCursor->bits->width,
@@ -824,22 +887,22 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
     else
 #endif
     {
-	if (!pScreenPriv->pCoreBuffer->pPixSourceGC)
+	if (!pBuffer->pPixSourceGC)
 	{
-	    pScreenPriv->pCoreBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
+	    pBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
 		GCGraphicsExposures, &gcval, &status);
-	    if (!pScreenPriv->pCoreBuffer->pPixSourceGC)
+	    if (!pBuffer->pPixSourceGC)
 		return FALSE;
 	}
-	if (!pScreenPriv->pCoreBuffer->pPixMaskGC)
+	if (!pBuffer->pPixMaskGC)
 	{
-	    pScreenPriv->pCoreBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
+	    pBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
 		GCGraphicsExposures, &gcval, &status);
-	    if (!pScreenPriv->pCoreBuffer->pPixMaskGC)
+	    if (!pBuffer->pPixMaskGC)
 		return FALSE;
 	}
 	miDCPutBits ((DrawablePtr)pTemp, pPriv,
-		     pScreenPriv->pCoreBuffer->pPixSourceGC, pScreenPriv->pCoreBuffer->pPixMaskGC,
+		     pBuffer->pPixSourceGC, pBuffer->pPixMaskGC,
 		     dx, dy, pCursor->bits->width, pCursor->bits->height,
 		     source, mask);
     }
@@ -848,9 +911,9 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
      * copy the temporary pixmap onto the screen
      */
 
-    if (!EnsureGC(pScreenPriv->pCoreBuffer->pRestoreGC, pWin))
+    if (!EnsureGC(pBuffer->pRestoreGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pCoreBuffer->pRestoreGC;
+    pGC = pBuffer->pRestoreGC;
     if (pWin->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pWin, pGC);
 
diff --git a/mi/misprite.c b/mi/misprite.c
index c9e4174..81e51ed 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -1084,7 +1084,8 @@ miSpriteRemoveCursor (pDevCursor, pScreen)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     miSpriteIsUpFALSE (pDevCursor, pScreen, pScreenPriv);
     pDevCursor->pCacheWin = NullWindow;
-    if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
+    if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDevCursor->id, 
+                                         pScreen,
 					 pDevCursor->saved.x1,
                                          pDevCursor->saved.y1,
                                          pDevCursor->saved.x2 -
@@ -1117,7 +1118,8 @@ miSpriteRestoreCursor (pDevCursor, pScreen)
     pCursor = pDevCursor->pCursor;
     x = pDevCursor->x - (int)pCursor->bits->xhot;
     y = pDevCursor->y - (int)pCursor->bits->yhot;
-    if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
+    if ((*pScreenPriv->funcs->SaveUnderCursor) (pDevCursor->id, 
+                                      pScreen,
 				      pDevCursor->saved.x1,
 				      pDevCursor->saved.y1,
                                       pDevCursor->saved.x2 -
@@ -1127,7 +1129,8 @@ miSpriteRestoreCursor (pDevCursor, pScreen)
     {
 	if (pDevCursor->checkPixels)
 	    miSpriteFindColors (pDevCursor, pScreen);
-	if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
+	if ((*pScreenPriv->funcs->PutUpCursor) (pDevCursor->id, pScreen, 
+                                  pCursor, x, y,
 				  pDevCursor->colors[SOURCE_COLOR].pixel,
 				  pDevCursor->colors[MASK_COLOR].pixel))
 	{
diff --git a/mi/misprite.h b/mi/misprite.h
index 5173b77..e0c55d0 100644
--- a/mi/misprite.h
+++ b/mi/misprite.h
@@ -42,6 +42,7 @@ typedef struct {
 		CursorPtr /*pCursor*/
 );
     Bool	(*PutUpCursor)(
+                int /* deviceid */,
 		ScreenPtr /*pScreen*/,
 		CursorPtr /*pCursor*/,
 		int /*x*/,
@@ -50,6 +51,7 @@ typedef struct {
 		unsigned long /*mask*/
 );
     Bool	(*SaveUnderCursor)(
+                int /* deviceid */,
 		ScreenPtr /*pScreen*/,
 		int /*x*/,
 		int /*y*/,
@@ -57,6 +59,7 @@ typedef struct {
 		int /*h*/
 );
     Bool	(*RestoreUnderCursor)(
+                int /* deviceid */,
 		ScreenPtr /*pScreen*/,
 		int /*x*/,
 		int /*y*/,
@@ -64,6 +67,7 @@ typedef struct {
 		int /*h*/
 );
     Bool	(*MoveCursor)(
+                int /* deviceid */,
 		ScreenPtr /*pScreen*/,
 		CursorPtr /*pCursor*/,
 		int /*x*/,
@@ -76,6 +80,7 @@ typedef struct {
 		unsigned long /*mask*/
 );
     Bool	(*ChangeSave)(
+                int /* deviceid */,
 		ScreenPtr /*pScreen*/,
 		int /*x*/,
 		int /*y*/,
commit 3bad452d12d620df91b1f37d06c650ded96bfafe
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Tue Nov 21 11:26:21 2006 +1030

    mi:     added MPX to miSpriteReportDamage
            added id field to miCursorInfoPtr, required to pass through to miDC
            core pointer uses mpCursors array as well.
            added miDCBufferRec for future use with MPX
    
    TAG: MPX_BEFORE_MIDC_API_BREAK

diff --git a/Changelog b/Changelog
index bcf5e8b..e0bdedd 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,17 @@
 MPX Changelog file
+== 21.11.06 ==
+mi:     added MPX to miSpriteReportDamage
+        added id field to miCursorInfoPtr, required to pass through to miDC
+        core pointer uses mpCursors array as well.
+        added miDCBufferRec for future use with MPX
+
+Files:
+        mi/midispcur.c
+        mi/misprite.c
+        mi/mispritest.h
+
+TAG: MPX_BEFORE_MIDC_API_BREAK
+
 == 20.11.06 ==
 
 mi:     moved core pointer information from miSpriteScreenRec into a
diff --git a/mi/midispcur.c b/mi/midispcur.c
index de009cb..a46331b 100644
--- a/mi/midispcur.c
+++ b/mi/midispcur.c
@@ -52,6 +52,10 @@ in this Software without prior written authorization from The Open Group.
 # include   "picturestr.h"
 #endif
 
+#ifdef MPX
+# include "inputstr.h"
+#endif
+
 /* per-screen private data */
 
 static int	miDCScreenIndex;
@@ -64,12 +68,19 @@ typedef struct {
     GCPtr	    pSaveGC, pRestoreGC;
     GCPtr	    pMoveGC;
     GCPtr	    pPixSourceGC, pPixMaskGC;
-    CloseScreenProcPtr CloseScreen;
     PixmapPtr	    pSave, pTemp;
 #ifdef ARGB_CURSOR
     PicturePtr	    pRootPicture;
     PicturePtr	    pTempPicture;
 #endif
+} miDCBufferRec, *miDCBufferPtr;
+
+typedef struct {
+    miDCBufferPtr pCoreBuffer; /* for core pointer */
+#ifdef MPX
+    miDCBufferPtr pMPBuffers;   /* for MPX pointers */
+#endif
+    CloseScreenProcPtr CloseScreen;
 } miDCScreenRec, *miDCScreenPtr;
 
 /* per-cursor per-screen private data */
@@ -131,20 +142,54 @@ miDCInitialize (pScreen, screenFuncs)
     /*
      * initialize the entire private structure to zeros
      */
-
-    pScreenPriv->pSourceGC =
-	pScreenPriv->pMaskGC =
-	pScreenPriv->pSaveGC =
- 	pScreenPriv->pRestoreGC =
- 	pScreenPriv->pMoveGC =
- 	pScreenPriv->pPixSourceGC =
-	pScreenPriv->pPixMaskGC = NULL;
+    pScreenPriv->pCoreBuffer = (miDCBufferPtr)xalloc(sizeof(miDCBufferRec));
+
+    pScreenPriv->pCoreBuffer->pSourceGC =
+	pScreenPriv->pCoreBuffer->pMaskGC =
+	pScreenPriv->pCoreBuffer->pSaveGC =
+ 	pScreenPriv->pCoreBuffer->pRestoreGC =
+ 	pScreenPriv->pCoreBuffer->pMoveGC =
+ 	pScreenPriv->pCoreBuffer->pPixSourceGC =
+	pScreenPriv->pCoreBuffer->pPixMaskGC = NULL;
 #ifdef ARGB_CURSOR
-    pScreenPriv->pRootPicture = NULL;
-    pScreenPriv->pTempPicture = NULL;
+    pScreenPriv->pCoreBuffer->pRootPicture = NULL;
+    pScreenPriv->pCoreBuffer->pTempPicture = NULL;
 #endif
     
-    pScreenPriv->pSave = pScreenPriv->pTemp = NULL;
+    pScreenPriv->pCoreBuffer->pSave = pScreenPriv->pCoreBuffer->pTemp = NULL;
+
+#ifdef MPX
+    {
+        int mpBufferIdx = 0;
+
+        pScreenPriv->pMPBuffers = (miDCBufferPtr)xalloc(MAX_DEVICES *
+                                sizeof(miDCBufferRec));
+
+        /* virtual core pointer ID is 1, we might as well use the array */
+        xfree(pScreenPriv->pCoreBuffer);
+        pScreenPriv->pCoreBuffer = &pScreenPriv->pMPBuffers[1];
+
+        while (mpBufferIdx < MAX_DEVICES)
+        {
+            miDCBufferPtr pBuffer = &pScreenPriv->pMPBuffers[mpBufferIdx];
+            pBuffer->pSourceGC =
+                pBuffer->pMaskGC =
+                pBuffer->pSaveGC =
+                pBuffer->pRestoreGC =
+                pBuffer->pMoveGC =
+                pBuffer->pPixSourceGC =
+                pBuffer->pPixMaskGC = NULL;
+#ifdef ARGB_CURSOR
+            pBuffer->pRootPicture = NULL;
+            pBuffer->pTempPicture = NULL;
+#endif
+
+            pBuffer->pSave = pBuffer->pTemp = NULL;
+
+            mpBufferIdx++;
+        }
+    }
+#endif
 
     pScreenPriv->CloseScreen = pScreen->CloseScreen;
     pScreen->CloseScreen = miDCCloseScreen;
@@ -172,20 +217,20 @@ miDCCloseScreen (index, pScreen)
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
-    tossGC (pScreenPriv->pSourceGC);
-    tossGC (pScreenPriv->pMaskGC);
-    tossGC (pScreenPriv->pSaveGC);
-    tossGC (pScreenPriv->pRestoreGC);
-    tossGC (pScreenPriv->pMoveGC);
-    tossGC (pScreenPriv->pPixSourceGC);
-    tossGC (pScreenPriv->pPixMaskGC);
-    tossPix (pScreenPriv->pSave);
-    tossPix (pScreenPriv->pTemp);
+    tossGC (pScreenPriv->pCoreBuffer->pSourceGC);
+    tossGC (pScreenPriv->pCoreBuffer->pMaskGC);
+    tossGC (pScreenPriv->pCoreBuffer->pSaveGC);
+    tossGC (pScreenPriv->pCoreBuffer->pRestoreGC);
+    tossGC (pScreenPriv->pCoreBuffer->pMoveGC);
+    tossGC (pScreenPriv->pCoreBuffer->pPixSourceGC);
+    tossGC (pScreenPriv->pCoreBuffer->pPixMaskGC);
+    tossPix (pScreenPriv->pCoreBuffer->pSave);
+    tossPix (pScreenPriv->pCoreBuffer->pTemp);
 #ifdef ARGB_CURSOR
 #if 0				/* This has been free()d before */
     tossPict (pScreenPriv->pRootPicture);
 #endif 
-    tossPict (pScreenPriv->pTempPicture);
+    tossPict (pScreenPriv->pCoreBuffer->pTempPicture);
 #endif
     xfree ((pointer) pScreenPriv);
     return (*pScreen->CloseScreen) (index, pScreen);
@@ -481,12 +526,12 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
 #ifdef ARGB_CURSOR
     if (pPriv->pPicture)
     {
-	if (!EnsurePicture(pScreenPriv->pRootPicture, &pWin->drawable, pWin))
+	if (!EnsurePicture(pScreenPriv->pCoreBuffer->pRootPicture, &pWin->drawable, pWin))
 	    return FALSE;
 	CompositePicture (PictOpOver,
 			  pPriv->pPicture,
 			  NULL,
-			  pScreenPriv->pRootPicture,
+			  pScreenPriv->pCoreBuffer->pRootPicture,
 			  0, 0, 0, 0, 
 			  x, y, 
 			  pCursor->bits->width,
@@ -495,16 +540,16 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
     else
 #endif
     {
-	if (!EnsureGC(pScreenPriv->pSourceGC, pWin))
+	if (!EnsureGC(pScreenPriv->pCoreBuffer->pSourceGC, pWin))
 	    return FALSE;
-	if (!EnsureGC(pScreenPriv->pMaskGC, pWin))
+	if (!EnsureGC(pScreenPriv->pCoreBuffer->pMaskGC, pWin))
 	{
-	    FreeGC (pScreenPriv->pSourceGC, (GContext) 0);
-	    pScreenPriv->pSourceGC = 0;
+	    FreeGC (pScreenPriv->pCoreBuffer->pSourceGC, (GContext) 0);
+	    pScreenPriv->pCoreBuffer->pSourceGC = 0;
 	    return FALSE;
 	}
 	miDCPutBits ((DrawablePtr)pWin, pPriv,
-		     pScreenPriv->pSourceGC, pScreenPriv->pMaskGC,
+		     pScreenPriv->pCoreBuffer->pSourceGC, pScreenPriv->pCoreBuffer->pMaskGC,
 		     x, y, pCursor->bits->width, pCursor->bits->height,
 		     source, mask);
     }
@@ -522,20 +567,20 @@ miDCSaveUnderCursor (pScreen, x, y, w, h)
     GCPtr	    pGC;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pSave = pScreenPriv->pSave;
+    pSave = pScreenPriv->pCoreBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
     {
 	if (pSave)
 	    (*pScreen->DestroyPixmap) (pSave);
-	pScreenPriv->pSave = pSave =
+	pScreenPriv->pCoreBuffer->pSave = pSave =
 		(*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth);
 	if (!pSave)
 	    return FALSE;
     }
-    if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
+    if (!EnsureGC(pScreenPriv->pCoreBuffer->pSaveGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pSaveGC;
+    pGC = pScreenPriv->pCoreBuffer->pSaveGC;
     if (pSave->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pSave, pGC);
     (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
@@ -554,13 +599,13 @@ miDCRestoreUnderCursor (pScreen, x, y, w, h)
     GCPtr	    pGC;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pSave = pScreenPriv->pSave;
+    pSave = pScreenPriv->pCoreBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     if (!pSave)
 	return FALSE;
-    if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
+    if (!EnsureGC(pScreenPriv->pCoreBuffer->pRestoreGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pRestoreGC;
+    pGC = pScreenPriv->pCoreBuffer->pRestoreGC;
     if (pWin->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pWin, pGC);
     (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
@@ -580,16 +625,16 @@ miDCChangeSave (pScreen, x, y, w, h, dx, dy)
     int		    sourcex, sourcey, destx, desty, copyw, copyh;
 
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
-    pSave = pScreenPriv->pSave;
+    pSave = pScreenPriv->pCoreBuffer->pSave;
     pWin = WindowTable[pScreen->myNum];
     /*
      * restore the bits which are about to get trashed
      */
     if (!pSave)
 	return FALSE;
-    if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
+    if (!EnsureGC(pScreenPriv->pCoreBuffer->pRestoreGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pRestoreGC;
+    pGC = pScreenPriv->pCoreBuffer->pRestoreGC;
     if (pWin->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pWin, pGC);
     /*
@@ -627,9 +672,9 @@ miDCChangeSave (pScreen, x, y, w, h, dx, dy)
 	(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
 			       0, sourcey, -dx, copyh, x + dx, desty);
     }
-    if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
+    if (!EnsureGC(pScreenPriv->pCoreBuffer->pSaveGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pSaveGC;
+    pGC = pScreenPriv->pCoreBuffer->pSaveGC;
     if (pSave->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pSave, pGC);
     /*
@@ -724,39 +769,39 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
     }
     pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
     pWin = WindowTable[pScreen->myNum];
-    pTemp = pScreenPriv->pTemp;
+    pTemp = pScreenPriv->pCoreBuffer->pTemp;
     if (!pTemp ||
-	pTemp->drawable.width != pScreenPriv->pSave->drawable.width ||
-	pTemp->drawable.height != pScreenPriv->pSave->drawable.height)
+	pTemp->drawable.width != pScreenPriv->pCoreBuffer->pSave->drawable.width ||
+	pTemp->drawable.height != pScreenPriv->pCoreBuffer->pSave->drawable.height)
     {
 	if (pTemp)
 	    (*pScreen->DestroyPixmap) (pTemp);
 #ifdef ARGB_CURSOR
-	if (pScreenPriv->pTempPicture)
+	if (pScreenPriv->pCoreBuffer->pTempPicture)
 	{
-	    FreePicture (pScreenPriv->pTempPicture, 0);
-	    pScreenPriv->pTempPicture = 0;
+	    FreePicture (pScreenPriv->pCoreBuffer->pTempPicture, 0);
+	    pScreenPriv->pCoreBuffer->pTempPicture = 0;
 	}
 #endif
-	pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap)
-	    (pScreen, w, h, pScreenPriv->pSave->drawable.depth);
+	pScreenPriv->pCoreBuffer->pTemp = pTemp = (*pScreen->CreatePixmap)
+	    (pScreen, w, h, pScreenPriv->pCoreBuffer->pSave->drawable.depth);
 	if (!pTemp)
 	    return FALSE;
     }
-    if (!pScreenPriv->pMoveGC)
+    if (!pScreenPriv->pCoreBuffer->pMoveGC)
     {
-	pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp,
+	pScreenPriv->pCoreBuffer->pMoveGC = CreateGC ((DrawablePtr)pTemp,
 	    GCGraphicsExposures, &gcval, &status);
-	if (!pScreenPriv->pMoveGC)
+	if (!pScreenPriv->pCoreBuffer->pMoveGC)
 	    return FALSE;
     }
     /*
      * copy the saved area to a temporary pixmap
      */
-    pGC = pScreenPriv->pMoveGC;
+    pGC = pScreenPriv->pCoreBuffer->pMoveGC;
     if (pGC->serialNumber != pTemp->drawable.serialNumber)
 	ValidateGC ((DrawablePtr) pTemp, pGC);
-    (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave,
+    (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pCoreBuffer->pSave,
 			  (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0);
     
     /*
@@ -765,12 +810,12 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
 #ifdef ARGB_CURSOR
     if (pPriv->pPicture)
     {
-	if (!EnsurePicture(pScreenPriv->pTempPicture, &pTemp->drawable, pWin))
+	if (!EnsurePicture(pScreenPriv->pCoreBuffer->pTempPicture, &pTemp->drawable, pWin))
 	    return FALSE;
 	CompositePicture (PictOpOver,
 			  pPriv->pPicture,
 			  NULL,
-			  pScreenPriv->pTempPicture,
+			  pScreenPriv->pCoreBuffer->pTempPicture,
 			  0, 0, 0, 0, 
 			  dx, dy, 
 			  pCursor->bits->width,
@@ -779,22 +824,22 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
     else
 #endif
     {
-	if (!pScreenPriv->pPixSourceGC)
+	if (!pScreenPriv->pCoreBuffer->pPixSourceGC)
 	{
-	    pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
+	    pScreenPriv->pCoreBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
 		GCGraphicsExposures, &gcval, &status);
-	    if (!pScreenPriv->pPixSourceGC)
+	    if (!pScreenPriv->pCoreBuffer->pPixSourceGC)
 		return FALSE;
 	}
-	if (!pScreenPriv->pPixMaskGC)
+	if (!pScreenPriv->pCoreBuffer->pPixMaskGC)
 	{
-	    pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
+	    pScreenPriv->pCoreBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
 		GCGraphicsExposures, &gcval, &status);
-	    if (!pScreenPriv->pPixMaskGC)
+	    if (!pScreenPriv->pCoreBuffer->pPixMaskGC)
 		return FALSE;
 	}
 	miDCPutBits ((DrawablePtr)pTemp, pPriv,
-		     pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC,
+		     pScreenPriv->pCoreBuffer->pPixSourceGC, pScreenPriv->pCoreBuffer->pPixMaskGC,
 		     dx, dy, pCursor->bits->width, pCursor->bits->height,
 		     source, mask);
     }
@@ -803,9 +848,9 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
      * copy the temporary pixmap onto the screen
      */
 
-    if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
+    if (!EnsureGC(pScreenPriv->pCoreBuffer->pRestoreGC, pWin))
 	return FALSE;
-    pGC = pScreenPriv->pRestoreGC;
+    pGC = pScreenPriv->pCoreBuffer->pRestoreGC;
     if (pWin->drawable.serialNumber != pGC->serialNumber)
 	ValidateGC ((DrawablePtr) pWin, pGC);
 
diff --git a/mi/misprite.c b/mi/misprite.c
index 2624878..c9e4174 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -158,6 +158,24 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
 	SPRITE_DEBUG(("Damage remove\n"));
 	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
     }
+
+#ifdef MPX
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
+
+            if (pMPCursor->isUp && 
+                    RECT_IN_REGION (pScreen, pRegion, &pMPCursor->saved) != rgnOUT)
+            {
+                SPRITE_DEBUG(("Damage remove MPX\n"));
+                miSpriteRemoveCursor(pMPCursor, pScreen);
+            }
+            mpCursorIdx++;
+        }
+    }
+#endif
 }
 
 /*
@@ -266,6 +284,7 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     {
         miCursorInfoPtr cursor = &(pScreenPriv->mpCursors[mpCursorIdx]);
 
+        cursor->id = mpCursorIdx;
         cursor->pCursor = NULL;
         cursor->x = 0;
         cursor->y = 0;
@@ -285,6 +304,10 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
 
         mpCursorIdx++;
     }
+
+    /* virtual core pointer has id 1, we might as well save the memory */
+    xfree(pScreenPriv->cp);
+    pScreenPriv->cp = &(pScreenPriv->mpCursors[1]);
 #endif
 
     return TRUE;
diff --git a/mi/mispritest.h b/mi/mispritest.h
index e423534..ff4bb4a 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -44,6 +44,7 @@ in this Software without prior written authorization from The Open Group.
 # include   "damage.h"
 
 typedef struct {
+    int             id;                 /* id, corresponds with device id */
     CursorPtr	    pCursor;
     int		    x;			/* cursor hotspot */
     int		    y;
commit b1bbdf464d2f8799fa3429c1c27ca998c5f3e94a
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 20 17:58:30 2006 +1030

    mi:     added MPX to miSprite functions.
    
    NOTE: This version will render multiple cursors but with an artefact each time
    when devices alternate.

diff --git a/Changelog b/Changelog
index a04f0f1..bcf5e8b 100644
--- a/Changelog
+++ b/Changelog
@@ -10,6 +10,18 @@ Files:
         mi/misprite.c
         mi/mipointer.c
 
+
+mi:     added MPX to miSprite functions. 
+
+Files:
+        mi/mispritest.h
+        mi/misprite.c
+        mi/mipointer.c
+        dix/events.c
+
+NOTE: This version will render multiple cursors but with an artefact each time
+when devices alternate.
+
 == 17.11.06 ==
 dix:    moved isMPdev field to end of _DeviceIntRec structure
 
diff --git a/dix/events.c b/dix/events.c
index 19ed97c..f50e246 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2114,6 +2114,7 @@ DefineInitialRootWindow(register WindowPtr win)
     sprite.current->refcnt++;
     spriteTraceGood = 1;
     ROOT = win;
+/* FIXME: This only limits the core pointer, not the MPX pointer */
     (*pScreen->CursorLimits) (
 	pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
     sprite.confined = FALSE;
diff --git a/mi/misprite.c b/mi/misprite.c
index 6d5ffdf..2624878 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -105,7 +105,8 @@ static void	    miSpriteStoreColors(ColormapPtr pMap, int ndef,
 static void	    miSpriteSaveDoomedAreas(WindowPtr pWin,
 					    RegionPtr pObscured, int dx,
 					    int dy);
-static void	    miSpriteComputeSaved(ScreenPtr pScreen);
+static void	    miSpriteComputeSaved(miCursorInfoPtr pDevCursor, 
+                                         ScreenPtr pScreen);
 
 #define SCREEN_PROLOGUE(pScreen, field)\
   ((pScreen)->field = \
@@ -138,8 +139,10 @@ _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
  * other misc functions
  */
 
-static void miSpriteRemoveCursor(ScreenPtr pScreen);
-static void miSpriteRestoreCursor(ScreenPtr pScreen);
+static void miSpriteRemoveCursor(miCursorInfoPtr pDevCursor, 
+                                 ScreenPtr pScreen); 
+static void miSpriteRestoreCursor(miCursorInfoPtr pDevCursor,
+                                 ScreenPtr pScreen);
 
 static void
 miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
@@ -153,7 +156,7 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
 	RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->cp->saved) != rgnOUT)
     {
 	SPRITE_DEBUG(("Damage remove\n"));
-	miSpriteRemoveCursor (pScreen);
+	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
     }
 }
 
@@ -314,8 +317,12 @@ miSpriteCloseScreen (i, pScreen)
     pScreen->StoreColors = pScreenPriv->StoreColors;
 
     pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
-    miSpriteIsUpFALSE (pScreen, pScreenPriv);
+    miSpriteIsUpFALSE (pScreenPriv->cp, pScreen, pScreenPriv);
     DamageDestroy (pScreenPriv->pDamage);
+
+#ifdef MPX
+    xfree((pointer)(pScreenPriv->mpCursors));
+#endif
     
     xfree ((pointer) pScreenPriv);
 
@@ -343,9 +350,29 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
                         sx, sy, w, h)) 
     {
 	SPRITE_DEBUG (("GetImage remove\n"));
-	miSpriteRemoveCursor (pScreen);
+	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
     }
 
+#ifdef MPX
+    /* check for MPX cursors in the target region */
+    if (pDrawable->type == DRAWABLE_WINDOW)
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
+            if (pMPCursor->isUp && 
+                    ORG_OVERLAP(&pMPCursor->saved,pDrawable->x,pDrawable->y,
+                        sx, sy, w, h)) 
+            {
+                SPRITE_DEBUG("GetImage remove MPX\n");
+            }
+            miSpriteRemoveCursor(pMPCursor, pScreen); 
+            mpCursorIdx++;
+        }
+    }
+#endif
+
     (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
 			  format, planemask, pdstLine);
 
@@ -387,12 +414,47 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
 			     pts->x+xorg,*widths))
 	    {
 		SPRITE_DEBUG (("GetSpans remove\n"));
-		miSpriteRemoveCursor (pScreen);
+		miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
 		break;
 	    }
 	}
     }
 
+#ifdef MPX
+    if (pDrawable->type == DRAWABLE_WINDOW)
+    {
+
+        int mpCursorIdx = 0;
+
+        while(mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
+            register DDXPointPtr    pts;
+            register int    	*widths;
+            register int    	nPts;
+            register int    	xorg,
+                     yorg;
+            xorg = pDrawable->x;
+            yorg = pDrawable->y;
+
+            for (pts = ppt, widths = pwidth, nPts = nspans;
+                    nPts--;
+                    pts++, widths++)
+            {
+                if (SPN_OVERLAP(&pMPCursor->saved,pts->y+yorg,
+                            pts->x+xorg,*widths))
+                {
+                    SPRITE_DEBUG (("GetSpans remove\n"));
+                    miSpriteRemoveCursor (pMPCursor, pScreen);
+                    break;
+                }
+            }
+            mpCursorIdx++;
+        }
+    }
+
+#endif
+
     (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
 
     SCREEN_EPILOGUE (pScreen, GetSpans);
@@ -415,8 +477,27 @@ miSpriteSourceValidate (pDrawable, x, y, width, height)
 		    x, y, width, height))
     {
 	SPRITE_DEBUG (("SourceValidate remove\n"));
-	miSpriteRemoveCursor (pScreen);
+	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
+    }
+
+#ifdef MPX
+    if (pDrawable->type == DRAWABLE_WINDOW)
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
+            if (pMPCursor->isUp && ORG_OVERLAP(&pMPCursor->saved,
+                        pDrawable->x, pDrawable->y, x, y, width, height)) 
+            {
+                SPRITE_DEBUG(("SourceValidate remove MPX\n"));
+                miSpriteRemoveCursor(pMPCursor, pScreen);
+            }
+            mpCursorIdx++;
+        }
+
     }
+#endif
 
     if (pScreen->SourceValidate)
 	(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
@@ -440,8 +521,27 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 	RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->cp->saved) != rgnOUT)
     {
 	SPRITE_DEBUG (("CopyWindow remove\n"));
-	miSpriteRemoveCursor (pScreen);
+	miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
     }
+#ifdef MPX
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
+
+            if (pMPCursor->isUp && RECT_IN_REGION (pScreen, prgnSrc,
+                                        &pMPCursor->saved) != rgnOUT)
+           
+            {
+                SPRITE_DEBUG(("CopyWindow remove MPX\n"));
+                miSpriteRemoveCursor(pMPCursor, pScreen);
+            }
+            mpCursorIdx++;
+        }
+
+    }
+#endif
 
     (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
     SCREEN_EPILOGUE (pScreen, CopyWindow);
@@ -468,8 +568,25 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
     if (!pPriv->cp->isUp && pPriv->cp->shouldBeUp)
     {
 	SPRITE_DEBUG (("BlockHandler restore\n"));
-	miSpriteRestoreCursor (pScreen);
+	miSpriteRestoreCursor (pPriv->cp, pScreen);
     }
+
+#ifdef MPX
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
+            if (!pMPCursor->isUp && pMPCursor->shouldBeUp)
+            {
+                SPRITE_DEBUG (("BlockHandler restore MPX\n"));
+                miSpriteRestoreCursor (pMPCursor, pScreen);
+            }
+
+            mpCursorIdx++;
+        }
+    }
+#endif
 }
 
 static void
@@ -492,8 +609,27 @@ miSpriteInstallColormap (pMap)
     {
     	pPriv->cp->checkPixels = TRUE;
 	if (pPriv->cp->isUp)
-	    miSpriteRemoveCursor (pScreen);
+	    miSpriteRemoveCursor (pPriv->cp, pScreen);
     }
+
+#ifdef MPX
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
+            pMPCursor->pInstalledMap = pMap;
+            if (pMPCursor->pColormap != pMap)
+            {
+                pMPCursor->checkPixels = TRUE;
+                if (pMPCursor->isUp)
+                    miSpriteRemoveCursor(pMPCursor, pScreen);
+            }
+            mpCursorIdx++;
+        }
+    }
+#endif
+
 }
 
 static void
@@ -526,22 +662,22 @@ miSpriteStoreColors (pMap, ndef, pdef)
 
 #define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
 
-#define UpdateDAC(plane,dac,mask) {\
-    if (MaskMatch (pPriv->cp->colors[plane].pixel,pdef[i].pixel,mask)) {\
-	pPriv->cp->colors[plane].dac = pdef[i].dac; \
+#define UpdateDAC(dev, plane,dac,mask) {\
+    if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
+	dev->colors[plane].dac = pdef[i].dac; \
 	updated = 1; \
     } \
 }
 
-#define CheckDirect(plane) \
-	    UpdateDAC(plane,red,redMask) \
-	    UpdateDAC(plane,green,greenMask) \
-	    UpdateDAC(plane,blue,blueMask)
+#define CheckDirect(dev, plane) \
+	    UpdateDAC(dev, plane,red,redMask) \
+	    UpdateDAC(dev, plane,green,greenMask) \
+	    UpdateDAC(dev, plane,blue,blueMask)
 
 	    for (i = 0; i < ndef; i++)
 	    {
-		CheckDirect (SOURCE_COLOR)
-		CheckDirect (MASK_COLOR)
+		CheckDirect (pPriv->cp, SOURCE_COLOR)
+		CheckDirect (pPriv->cp, MASK_COLOR)
 	    }
 	}
 	else
@@ -567,23 +703,75 @@ miSpriteStoreColors (pMap, ndef, pdef)
     	{
 	    pPriv->cp->checkPixels = TRUE;
 	    if (pPriv->cp->isUp)
-	    	miSpriteRemoveCursor (pScreen);
+	    	miSpriteRemoveCursor (pPriv->cp, pScreen);
     	}
     }
+
+#ifdef MPX
+    {
+        int mpCursorIdx = 0;
+
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pPriv->mpCursors[mpCursorIdx];
+
+            if (pPriv->cp->pColormap == pMap)
+            {
+                updated = 0;
+                pVisual = pMap->pVisual;
+                if (pVisual->class == DirectColor)
+                {
+                    for (i = 0; i < ndef; i++)
+                    {
+                        CheckDirect (pMPCursor, SOURCE_COLOR)
+                        CheckDirect (pMPCursor, MASK_COLOR)
+                    }
+                }
+                else
+                {
+                    /* PseudoColor/GrayScale - match on exact pixel */
+                    for (i = 0; i < ndef; i++)
+                    {
+                        if (pdef[i].pixel ==
+                                pMPCursor->colors[SOURCE_COLOR].pixel) 
+                        {
+                            pMPCursor->colors[SOURCE_COLOR] = pdef[i];
+                            if (++updated == 2)
+                                break;
+                        }
+                        if (pdef[i].pixel ==
+                                pMPCursor->colors[MASK_COLOR].pixel) 
+                        {
+                            pMPCursor->colors[MASK_COLOR] = pdef[i];
+                            if (++updated == 2)
+                                break;
+                        }
+                    }
+                }
+                if (updated)
+                {
+                    pMPCursor->checkPixels = TRUE;
+                    if (pMPCursor->isUp)
+                        miSpriteRemoveCursor (pMPCursor, pScreen);
+                }
+            }
+            mpCursorIdx++;
+        }
+    }
+#endif
+
 }
 
 static void
-miSpriteFindColors (ScreenPtr pScreen)
+miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
 {
-    miSpriteScreenPtr	pScreenPriv = (miSpriteScreenPtr)
-			    pScreen->devPrivates[miSpriteScreenIndex].ptr;
     CursorPtr		pCursor;
     xColorItem		*sourceColor, *maskColor;
 
-    pCursor = pScreenPriv->cp->pCursor;
-    sourceColor = &pScreenPriv->cp->colors[SOURCE_COLOR];
-    maskColor = &pScreenPriv->cp->colors[MASK_COLOR];
-    if (pScreenPriv->cp->pColormap != pScreenPriv->cp->pInstalledMap ||
+    pCursor = pDevCursor->pCursor;
+    sourceColor = &pDevCursor->colors[SOURCE_COLOR];
+    maskColor = &pDevCursor->colors[MASK_COLOR];
+    if (pDevCursor->pColormap != pDevCursor->pInstalledMap ||
 	!(pCursor->foreRed == sourceColor->red &&
 	  pCursor->foreGreen == sourceColor->green &&
           pCursor->foreBlue == sourceColor->blue &&
@@ -591,20 +779,22 @@ miSpriteFindColors (ScreenPtr pScreen)
 	  pCursor->backGreen == maskColor->green &&
 	  pCursor->backBlue == maskColor->blue))
     {
-	pScreenPriv->cp->pColormap = pScreenPriv->cp->pInstalledMap;
+	pDevCursor->pColormap = pDevCursor->pInstalledMap;
 	sourceColor->red = pCursor->foreRed;
 	sourceColor->green = pCursor->foreGreen;
 	sourceColor->blue = pCursor->foreBlue;
-	FakeAllocColor (pScreenPriv->cp->pColormap, sourceColor);
+	FakeAllocColor (pDevCursor->pColormap, sourceColor);
 	maskColor->red = pCursor->backRed;
 	maskColor->green = pCursor->backGreen;
 	maskColor->blue = pCursor->backBlue;
-	FakeAllocColor (pScreenPriv->cp->pColormap, maskColor);
+	FakeAllocColor (pDevCursor->pColormap, maskColor);
 	/* "free" the pixels right away, don't let this confuse you */
-	FakeFreeColor(pScreenPriv->cp->pColormap, sourceColor->pixel);
-	FakeFreeColor(pScreenPriv->cp->pColormap, maskColor->pixel);
+	FakeFreeColor(pDevCursor->pColormap, sourceColor->pixel);
+	FakeFreeColor(pDevCursor->pColormap, maskColor->pixel);
     }
-    pScreenPriv->cp->checkPixels = FALSE;
+
+    pDevCursor->checkPixels = FALSE;
+
 }
 
 /*
@@ -638,8 +828,33 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
 	    cursorBox.y2 += dy;
 	}
 	if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
-	    miSpriteRemoveCursor (pScreen);
+	    miSpriteRemoveCursor (pScreenPriv->cp, pScreen);
+    }
+#ifdef MPX
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
+
+            if (pMPCursor->isUp)
+            {
+                cursorBox = pMPCursor->saved;
+
+                if (dx || dy)
+                {
+                    cursorBox.x1 += dx;
+                    cursorBox.y1 += dy;
+                    cursorBox.x2 += dx;
+                    cursorBox.y2 += dy;
+                }
+                if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
+                    miSpriteRemoveCursor (pMPCursor, pScreen);
+            }
+            mpCursorIdx++;
+        }
     }
+#endif
 
     (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
 
@@ -663,6 +878,21 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     if (pCursor == pScreenPriv->cp->pCursor)
 	pScreenPriv->cp->checkPixels = TRUE;
+#ifdef MPX
+    {
+        int mpCursorIdx = 0;
+        while (mpCursorIdx < MAX_DEVICES)
+        {
+            miCursorInfoPtr pMPCursor = &pScreenPriv->mpCursors[mpCursorIdx];
+
+            if (pCursor == pMPCursor->pCursor)
+                pMPCursor->checkPixels = TRUE;
+
+            mpCursorIdx++;
+        }
+    }
+#endif
+
     return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
 }
 
@@ -689,101 +919,112 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
     miSpriteScreenPtr	pScreenPriv;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
+    miCursorInfoPtr pointer = pScreenPriv->cp;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pointer = &pScreenPriv->mpCursors[pDev->id];
+#endif
+
     if (!pCursor)
     {
-    	pScreenPriv->cp->shouldBeUp = FALSE;
-    	if (pScreenPriv->cp->isUp)
-	    miSpriteRemoveCursor (pScreen);
-	pScreenPriv->cp->pCursor = 0;
+    	pointer->shouldBeUp = FALSE;
+    	if (pointer->isUp)
+	    miSpriteRemoveCursor (pointer, pScreen);
+	pointer->pCursor = 0;
 	return;
     }
-    pScreenPriv->cp->shouldBeUp = TRUE;
-    if (pScreenPriv->cp->x == x &&
-	pScreenPriv->cp->y == y &&
-	pScreenPriv->cp->pCursor == pCursor &&
-	!pScreenPriv->cp->checkPixels)
+    pointer->shouldBeUp = TRUE;
+    if (pointer->x == x &&
+	pointer->y == y &&
+	pointer->pCursor == pCursor &&
+	!pointer->checkPixels)
     {
 	return;
     }
-    pScreenPriv->cp->x = x;
-    pScreenPriv->cp->y = y;
-    pScreenPriv->cp->pCacheWin = NullWindow;
-    if (pScreenPriv->cp->checkPixels || pScreenPriv->cp->pCursor != pCursor)
+    pointer->x = x;
+    pointer->y = y;
+    pointer->pCacheWin = NullWindow;
+    if (pointer->checkPixels || pointer->pCursor != pCursor)
     {
-	pScreenPriv->cp->pCursor = pCursor;
-	miSpriteFindColors (pScreen);
+	pointer->pCursor = pCursor;
+	miSpriteFindColors (pointer, pScreen);
     }
-    if (pScreenPriv->cp->isUp) {
+    if (pointer->isUp) {
+#if 0
+        /* FIXME: Disabled for MPX, should be rewritten */
 	int	sx, sy;
 	/*
 	 * check to see if the old saved region
 	 * encloses the new sprite, in which case we use
 	 * the flicker-free MoveCursor primitive.
 	 */
-	sx = pScreenPriv->cp->x - (int)pCursor->bits->xhot;
-	sy = pScreenPriv->cp->y - (int)pCursor->bits->yhot;
-	if (sx + (int) pCursor->bits->width >= pScreenPriv->cp->saved.x1 &&
-	    sx < pScreenPriv->cp->saved.x2 &&
-	    sy + (int) pCursor->bits->height >= pScreenPriv->cp->saved.y1 &&
-	    sy < pScreenPriv->cp->saved.y2 &&
+	sx = pointer->x - (int)pCursor->bits->xhot;
+	sy = pointer->y - (int)pCursor->bits->yhot;
+	if (sx + (int) pCursor->bits->width >= pointer->saved.x1 &&
+	    sx < pointer->saved.x2 &&
+	    sy + (int) pCursor->bits->height >= pointer->saved.y1 &&
+	    sy < pointer->saved.y2 &&
 	    (int) pCursor->bits->width + (2 * SPRITE_PAD) ==
-		pScreenPriv->cp->saved.x2 - pScreenPriv->cp->saved.x1 &&
+		pointer->saved.x2 - pointer->saved.x1 &&
 	    (int) pCursor->bits->height + (2 * SPRITE_PAD) ==
-		pScreenPriv->cp->saved.y2 - pScreenPriv->cp->saved.y1
+		pointer->saved.y2 - pointer->saved.y1
 	    )
 	{
 	    DamageDrawInternal (pScreen, TRUE);
 	    miSpriteIsUpFALSE (pScreen, pScreenPriv);
-	    if (!(sx >= pScreenPriv->cp->saved.x1 &&
-                  sx + (int)pCursor->bits->width < pScreenPriv->cp->saved.x2
-                  && sy >= pScreenPriv->cp->saved.y1 &&
+	    if (!(sx >= pointer->saved.x1 &&
+                  sx + (int)pCursor->bits->width < pointer->saved.x2
+                  && sy >= pointer->saved.y1 &&
                   sy + (int)pCursor->bits->height <
-                                pScreenPriv->cp->saved.y2)) 
+                                pointer->saved.y2)) 
             {
 		int oldx1, oldy1, dx, dy;
 
-		oldx1 = pScreenPriv->cp->saved.x1;
-		oldy1 = pScreenPriv->cp->saved.y1;
+		oldx1 = pointer->saved.x1;
+		oldy1 = pointer->saved.y1;
 		dx = oldx1 - (sx - SPRITE_PAD);
 		dy = oldy1 - (sy - SPRITE_PAD);
-		pScreenPriv->cp->saved.x1 -= dx;
-		pScreenPriv->cp->saved.y1 -= dy;
-		pScreenPriv->cp->saved.x2 -= dx;
-		pScreenPriv->cp->saved.y2 -= dy;
+		pointer->saved.x1 -= dx;
+		pointer->saved.y1 -= dy;
+		pointer->saved.x2 -= dx;
+		pointer->saved.y2 -= dy;
 		(void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
-				pScreenPriv->cp->saved.x1,
- 				pScreenPriv->cp->saved.y1,
-                                pScreenPriv->cp->saved.x2 -
-                                pScreenPriv->cp->saved.x1,
-                                pScreenPriv->cp->saved.y2 -
-                                pScreenPriv->cp->saved.y1,
+				pointer->saved.x1,
+ 				pointer->saved.y1,
+                                pointer->saved.x2 -
+                                pointer->saved.x1,
+                                pointer->saved.y2 -
+                                pointer->saved.y1,
 				dx, dy);
 	    }
 	    (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
-				  pScreenPriv->cp->saved.x1,
- 				  pScreenPriv->cp->saved.y1,
-                                  pScreenPriv->cp->saved.x2 -
-                                  pScreenPriv->cp->saved.x1,
-                                  pScreenPriv->cp->saved.y2 -
-                                  pScreenPriv->cp->saved.y1,
-				  sx - pScreenPriv->cp->saved.x1,
-				  sy - pScreenPriv->cp->saved.y1,
-				  pScreenPriv->cp->colors[SOURCE_COLOR].pixel,
-				  pScreenPriv->cp->colors[MASK_COLOR].pixel);
+				  pointer->saved.x1,
+ 				  pointer->saved.y1,
+                                  pointer->saved.x2 -
+                                  pointer->saved.x1,
+                                  pointer->saved.y2 -
+                                  pointer->saved.y1,
+				  sx - pointer->saved.x1,
+				  sy - pointer->saved.y1,
+				  pointer->colors[SOURCE_COLOR].pixel,
+				  pointer->colors[MASK_COLOR].pixel);
 	    miSpriteIsUpTRUE (pScreen, pScreenPriv);
 	    DamageDrawInternal (pScreen, FALSE);
 	}
 	else
+#endif
 	{
 	    SPRITE_DEBUG (("SetCursor remove\n"));
-	    miSpriteRemoveCursor (pScreen);
+	    miSpriteRemoveCursor (pointer, pScreen);
 	}
     }
-    if (!pScreenPriv->cp->isUp && pScreenPriv->cp->pCursor)
+
+    if (!pointer->isUp && pointer->pCursor)
     {
 	SPRITE_DEBUG (("SetCursor restore\n"));
-	miSpriteRestoreCursor (pScreen);
+	miSpriteRestoreCursor (pointer, pScreen);
     }
+
 }
 
 static void
@@ -797,6 +1038,7 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     pCursor = pScreenPriv->cp->pCursor;
+
 #ifdef MPX
     if (IsMPDev(pDev))
         pCursor = pScreenPriv->mpCursors[pDev->id].pCursor;
@@ -809,24 +1051,25 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
  */
 
 static void
-miSpriteRemoveCursor (pScreen)
+miSpriteRemoveCursor (pDevCursor, pScreen)
+    miCursorInfoPtr pDevCursor;
     ScreenPtr	pScreen;
 {
     miSpriteScreenPtr   pScreenPriv;
 
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    miSpriteIsUpFALSE (pScreen, pScreenPriv);
-    pScreenPriv->cp->pCacheWin = NullWindow;
+    miSpriteIsUpFALSE (pDevCursor, pScreen, pScreenPriv);
+    pDevCursor->pCacheWin = NullWindow;
     if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
-					 pScreenPriv->cp->saved.x1,
-                                         pScreenPriv->cp->saved.y1,
-                                         pScreenPriv->cp->saved.x2 -
-                                         pScreenPriv->cp->saved.x1,
-                                         pScreenPriv->cp->saved.y2 -
-                                         pScreenPriv->cp->saved.y1))
+					 pDevCursor->saved.x1,
+                                         pDevCursor->saved.y1,
+                                         pDevCursor->saved.x2 -
+                                         pDevCursor->saved.x1,
+                                         pDevCursor->saved.y2 -
+                                         pDevCursor->saved.y1))
     {
-	miSpriteIsUpTRUE (pScreen, pScreenPriv);
+	miSpriteIsUpTRUE (pDevCursor, pScreen, pScreenPriv);
     }
     DamageDrawInternal (pScreen, FALSE);
 }
@@ -837,7 +1080,8 @@ miSpriteRemoveCursor (pScreen)
  */
 
 static void
-miSpriteRestoreCursor (pScreen)
+miSpriteRestoreCursor (pDevCursor, pScreen)
+    miCursorInfoPtr pDevCursor;
     ScreenPtr	pScreen;
 {
     miSpriteScreenPtr   pScreenPriv;
@@ -845,26 +1089,26 @@ miSpriteRestoreCursor (pScreen)
     CursorPtr		pCursor;
 
     DamageDrawInternal (pScreen, TRUE);
-    miSpriteComputeSaved (pScreen);
+    miSpriteComputeSaved (pDevCursor, pScreen);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursor = pScreenPriv->cp->pCursor;
-    x = pScreenPriv->cp->x - (int)pCursor->bits->xhot;
-    y = pScreenPriv->cp->y - (int)pCursor->bits->yhot;
+    pCursor = pDevCursor->pCursor;
+    x = pDevCursor->x - (int)pCursor->bits->xhot;
+    y = pDevCursor->y - (int)pCursor->bits->yhot;
     if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
-				      pScreenPriv->cp->saved.x1,
-				      pScreenPriv->cp->saved.y1,
-                                      pScreenPriv->cp->saved.x2 -
-                                      pScreenPriv->cp->saved.x1,
-                                      pScreenPriv->cp->saved.y2 -
-                                      pScreenPriv->cp->saved.y1))
+				      pDevCursor->saved.x1,
+				      pDevCursor->saved.y1,
+                                      pDevCursor->saved.x2 -
+                                      pDevCursor->saved.x1,
+                                      pDevCursor->saved.y2 -
+                                      pDevCursor->saved.y1))
     {
-	if (pScreenPriv->cp->checkPixels)
-	    miSpriteFindColors (pScreen);
+	if (pDevCursor->checkPixels)
+	    miSpriteFindColors (pDevCursor, pScreen);
 	if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
-				  pScreenPriv->cp->colors[SOURCE_COLOR].pixel,
-				  pScreenPriv->cp->colors[MASK_COLOR].pixel))
+				  pDevCursor->colors[SOURCE_COLOR].pixel,
+				  pDevCursor->colors[MASK_COLOR].pixel))
 	{
-	    miSpriteIsUpTRUE (pScreen, pScreenPriv);
+	    miSpriteIsUpTRUE (pDevCursor, pScreen, pScreenPriv);
 	}
     }
     DamageDrawInternal (pScreen, FALSE);
@@ -875,7 +1119,8 @@ miSpriteRestoreCursor (pScreen)
  */
 
 static void
-miSpriteComputeSaved (pScreen)
+miSpriteComputeSaved (pDevCursor, pScreen)
+    miCursorInfoPtr pDevCursor;
     ScreenPtr	pScreen;
 {
     miSpriteScreenPtr   pScreenPriv;
@@ -884,15 +1129,15 @@ miSpriteComputeSaved (pScreen)
     CursorPtr	    pCursor;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursor = pScreenPriv->cp->pCursor;
-    x = pScreenPriv->cp->x - (int)pCursor->bits->xhot;
-    y = pScreenPriv->cp->y - (int)pCursor->bits->yhot;
+    pCursor = pDevCursor->pCursor;
+    x = pDevCursor->x - (int)pCursor->bits->xhot;
+    y = pDevCursor->y - (int)pCursor->bits->yhot;
     w = pCursor->bits->width;
     h = pCursor->bits->height;
     wpad = SPRITE_PAD;
     hpad = SPRITE_PAD;
-    pScreenPriv->cp->saved.x1 = x - wpad;
-    pScreenPriv->cp->saved.y1 = y - hpad;
-    pScreenPriv->cp->saved.x2 = pScreenPriv->cp->saved.x1 + w + wpad * 2;
-    pScreenPriv->cp->saved.y2 = pScreenPriv->cp->saved.y1 + h + hpad * 2;
+    pDevCursor->saved.x1 = x - wpad;
+    pDevCursor->saved.y1 = y - hpad;
+    pDevCursor->saved.x2 = pDevCursor->saved.x1 + w + wpad * 2;
+    pDevCursor->saved.y2 = pDevCursor->saved.y1 + h + hpad * 2;
 }
diff --git a/mi/mispritest.h b/mi/mispritest.h
index 4608c4e..e423534 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -95,14 +95,21 @@ typedef struct {
 #define SOURCE_COLOR	0
 #define MASK_COLOR	1
 
-#define miSpriteIsUpTRUE(pScreen, pScreenPriv) if (!pScreenPriv->cp->isUp) { \
-    pScreenPriv->cp->isUp = TRUE; \
-    DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
+static int damageRegister = 0;
+#define miSpriteIsUpTRUE(pDevCursor, pScreen, pScreenPriv) if (!pDevCursor->isUp) { \
+    pDevCursor->isUp = TRUE; \
+    if (!damageRegister ) { \
+        damageRegister++; \
+        DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
+    } \
 }
 
-#define miSpriteIsUpFALSE(pScreen, pScreenPriv) if (pScreenPriv->cp->isUp) { \
-    DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
-    pScreenPriv->cp->isUp = FALSE; \
+#define miSpriteIsUpFALSE(pDevCursor, pScreen, pScreenPriv) if (pDevCursor->isUp) { \
+    if (damageRegister) { \
+        damageRegister--; \
+        DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
+    } \
+    pDevCursor->isUp = FALSE; \
 }
 
 /*
commit 7b4b619d4c268804199f9f4775eb56604f0b80e8
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Mon Nov 20 13:10:07 2006 +1030

    mi:     moved core pointer information from miSpriteScreenRec into a
            miCursorInfoRec.
            bugfix in mipointer, semicolon after preprocessor statement

diff --git a/Changelog b/Changelog
index 484ac4d..a04f0f1 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,14 @@
 MPX Changelog file
+== 20.11.06 ==
+
+mi:     moved core pointer information from miSpriteScreenRec into a
+        miCursorInfoRec.
+        bugfix in mipointer, semicolon after preprocessor statement
+
+Files:
+        mi/mispritest.h
+        mi/misprite.c
+        mi/mipointer.c
 
 == 17.11.06 ==
 dix:    moved isMPdev field to end of _DeviceIntRec structure
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 832aa5a..1b01ba1 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -189,7 +189,7 @@ extern int miPointerScreenIndex;
 
 #ifdef MPX
 _X_EXPORT Bool IsMPDev(DeviceIntPtr pDev);
-#endif;
+#endif
 
 
 #endif /* MIPOINTER_H */
diff --git a/mi/misprite.c b/mi/misprite.c
index f0530d2..6d5ffdf 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -149,8 +149,8 @@ miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
     
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     
-    if (pScreenPriv->isUp &&
-	RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
+    if (pScreenPriv->cp->isUp &&
+	RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->cp->saved) != rgnOUT)
     {
 	SPRITE_DEBUG(("Damage remove\n"));
 	miSpriteRemoveCursor (pScreen);
@@ -221,23 +221,25 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     
     pScreenPriv->BlockHandler = pScreen->BlockHandler;
     
-    pScreenPriv->pCursor = NULL;
-    pScreenPriv->x = 0;
-    pScreenPriv->y = 0;
-    pScreenPriv->isUp = FALSE;
-    pScreenPriv->shouldBeUp = FALSE;
-    pScreenPriv->pCacheWin = NullWindow;
-    pScreenPriv->isInCacheWin = FALSE;
-    pScreenPriv->checkPixels = TRUE;
-    pScreenPriv->pInstalledMap = NULL;
-    pScreenPriv->pColormap = NULL;
+    pScreenPriv->cp = (miCursorInfoPtr)xalloc(sizeof(miCursorInfoRec));
+    pScreenPriv->cp->pCursor = NULL;
+    pScreenPriv->cp->x = 0;
+    pScreenPriv->cp->y = 0;
+    pScreenPriv->cp->isUp = FALSE;
+    pScreenPriv->cp->shouldBeUp = FALSE;
+    pScreenPriv->cp->pCacheWin = NullWindow;
+    pScreenPriv->cp->isInCacheWin = FALSE;
+    pScreenPriv->cp->checkPixels = TRUE;
+    pScreenPriv->cp->pInstalledMap = NULL;
+    pScreenPriv->cp->pColormap = NULL;
+    pScreenPriv->cp->colors[SOURCE_COLOR].red = 0;
+    pScreenPriv->cp->colors[SOURCE_COLOR].green = 0;
+    pScreenPriv->cp->colors[SOURCE_COLOR].blue = 0;
+    pScreenPriv->cp->colors[MASK_COLOR].red = 0;
+    pScreenPriv->cp->colors[MASK_COLOR].green = 0;
+    pScreenPriv->cp->colors[MASK_COLOR].blue = 0;
+
     pScreenPriv->funcs = cursorFuncs;
-    pScreenPriv->colors[SOURCE_COLOR].red = 0;
-    pScreenPriv->colors[SOURCE_COLOR].green = 0;
-    pScreenPriv->colors[SOURCE_COLOR].blue = 0;
-    pScreenPriv->colors[MASK_COLOR].red = 0;
-    pScreenPriv->colors[MASK_COLOR].green = 0;
-    pScreenPriv->colors[MASK_COLOR].blue = 0;
     pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv;
     
     pScreen->CloseScreen = miSpriteCloseScreen;
@@ -267,6 +269,16 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
         cursor->isUp = FALSE;
         cursor->shouldBeUp = FALSE;
         cursor->pCacheWin = NullWindow;
+        cursor->isInCacheWin = FALSE;
+        cursor->checkPixels = TRUE;
+        cursor->pInstalledMap = NULL;
+        cursor->pColormap = NULL;
+        cursor->colors[SOURCE_COLOR].red = 0;
+        cursor->colors[SOURCE_COLOR].green = 0;
+        cursor->colors[SOURCE_COLOR].blue = 0;
+        cursor->colors[MASK_COLOR].red = 0;
+        cursor->colors[MASK_COLOR].green = 0;
+        cursor->colors[MASK_COLOR].blue = 0;
 
         mpCursorIdx++;
     }
@@ -326,8 +338,9 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
     if (pDrawable->type == DRAWABLE_WINDOW &&
-        pScreenPriv->isUp &&
-	ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
+        pScreenPriv->cp->isUp &&
+        ORG_OVERLAP(&pScreenPriv->cp->saved,pDrawable->x,pDrawable->y, 
+                        sx, sy, w, h)) 
     {
 	SPRITE_DEBUG (("GetImage remove\n"));
 	miSpriteRemoveCursor (pScreen);
@@ -355,7 +368,7 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
-    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
+    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->cp->isUp)
     {
 	register DDXPointPtr    pts;
 	register int    	*widths;
@@ -370,7 +383,7 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
 	     nPts--;
 	     pts++, widths++)
  	{
-	    if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
+	    if (SPN_OVERLAP(&pScreenPriv->cp->saved,pts->y+yorg,
 			     pts->x+xorg,*widths))
 	    {
 		SPRITE_DEBUG (("GetSpans remove\n"));
@@ -397,8 +410,8 @@ miSpriteSourceValidate (pDrawable, x, y, width, height)
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
 
-    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
-	ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
+    if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->cp->isUp &&
+	ORG_OVERLAP(&pScreenPriv->cp->saved, pDrawable->x, pDrawable->y,
 		    x, y, width, height))
     {
 	SPRITE_DEBUG (("SourceValidate remove\n"));
@@ -423,8 +436,8 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
     /*
      * Damage will take care of destination check
      */
-    if (pScreenPriv->isUp &&
-	RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->saved) != rgnOUT)
+    if (pScreenPriv->cp->isUp &&
+	RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->cp->saved) != rgnOUT)
     {
 	SPRITE_DEBUG (("CopyWindow remove\n"));
 	miSpriteRemoveCursor (pScreen);
@@ -452,7 +465,7 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
 
     SCREEN_EPILOGUE(pScreen, BlockHandler);
 
-    if (!pPriv->isUp && pPriv->shouldBeUp)
+    if (!pPriv->cp->isUp && pPriv->cp->shouldBeUp)
     {
 	SPRITE_DEBUG (("BlockHandler restore\n"));
 	miSpriteRestoreCursor (pScreen);
@@ -474,11 +487,11 @@ miSpriteInstallColormap (pMap)
 
     SCREEN_EPILOGUE(pScreen, InstallColormap);
 
-    pPriv->pInstalledMap = pMap;
-    if (pPriv->pColormap != pMap)
+    pPriv->cp->pInstalledMap = pMap;
+    if (pPriv->cp->pColormap != pMap)
     {
-    	pPriv->checkPixels = TRUE;
-	if (pPriv->isUp)
+    	pPriv->cp->checkPixels = TRUE;
+	if (pPriv->cp->isUp)
 	    miSpriteRemoveCursor (pScreen);
     }
 }
@@ -503,7 +516,7 @@ miSpriteStoreColors (pMap, ndef, pdef)
 
     SCREEN_EPILOGUE(pScreen, StoreColors);
 
-    if (pPriv->pColormap == pMap)
+    if (pPriv->cp->pColormap == pMap)
     {
 	updated = 0;
 	pVisual = pMap->pVisual;
@@ -514,8 +527,8 @@ miSpriteStoreColors (pMap, ndef, pdef)
 #define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
 
 #define UpdateDAC(plane,dac,mask) {\
-    if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\
-	pPriv->colors[plane].dac = pdef[i].dac; \
+    if (MaskMatch (pPriv->cp->colors[plane].pixel,pdef[i].pixel,mask)) {\
+	pPriv->cp->colors[plane].dac = pdef[i].dac; \
 	updated = 1; \
     } \
 }
@@ -536,15 +549,15 @@ miSpriteStoreColors (pMap, ndef, pdef)
 	    /* PseudoColor/GrayScale - match on exact pixel */
 	    for (i = 0; i < ndef; i++)
 	    {
-	    	if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel)
+	    	if (pdef[i].pixel == pPriv->cp->colors[SOURCE_COLOR].pixel)
 	    	{
-		    pPriv->colors[SOURCE_COLOR] = pdef[i];
+		    pPriv->cp->colors[SOURCE_COLOR] = pdef[i];
 		    if (++updated == 2)
 		    	break;
 	    	}
-	    	if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
+	    	if (pdef[i].pixel == pPriv->cp->colors[MASK_COLOR].pixel)
 	    	{
-		    pPriv->colors[MASK_COLOR] = pdef[i];
+		    pPriv->cp->colors[MASK_COLOR] = pdef[i];
 		    if (++updated == 2)
 		    	break;
 	    	}
@@ -552,8 +565,8 @@ miSpriteStoreColors (pMap, ndef, pdef)
 	}
     	if (updated)
     	{
-	    pPriv->checkPixels = TRUE;
-	    if (pPriv->isUp)
+	    pPriv->cp->checkPixels = TRUE;
+	    if (pPriv->cp->isUp)
 	    	miSpriteRemoveCursor (pScreen);
     	}
     }
@@ -567,10 +580,10 @@ miSpriteFindColors (ScreenPtr pScreen)
     CursorPtr		pCursor;
     xColorItem		*sourceColor, *maskColor;
 
-    pCursor = pScreenPriv->pCursor;
-    sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
-    maskColor = &pScreenPriv->colors[MASK_COLOR];
-    if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
+    pCursor = pScreenPriv->cp->pCursor;
+    sourceColor = &pScreenPriv->cp->colors[SOURCE_COLOR];
+    maskColor = &pScreenPriv->cp->colors[MASK_COLOR];
+    if (pScreenPriv->cp->pColormap != pScreenPriv->cp->pInstalledMap ||
 	!(pCursor->foreRed == sourceColor->red &&
 	  pCursor->foreGreen == sourceColor->green &&
           pCursor->foreBlue == sourceColor->blue &&
@@ -578,20 +591,20 @@ miSpriteFindColors (ScreenPtr pScreen)
 	  pCursor->backGreen == maskColor->green &&
 	  pCursor->backBlue == maskColor->blue))
     {
-	pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
+	pScreenPriv->cp->pColormap = pScreenPriv->cp->pInstalledMap;
 	sourceColor->red = pCursor->foreRed;
 	sourceColor->green = pCursor->foreGreen;
 	sourceColor->blue = pCursor->foreBlue;
-	FakeAllocColor (pScreenPriv->pColormap, sourceColor);
+	FakeAllocColor (pScreenPriv->cp->pColormap, sourceColor);
 	maskColor->red = pCursor->backRed;
 	maskColor->green = pCursor->backGreen;
 	maskColor->blue = pCursor->backBlue;
-	FakeAllocColor (pScreenPriv->pColormap, maskColor);
+	FakeAllocColor (pScreenPriv->cp->pColormap, maskColor);
 	/* "free" the pixels right away, don't let this confuse you */
-	FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
-	FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
+	FakeFreeColor(pScreenPriv->cp->pColormap, sourceColor->pixel);
+	FakeFreeColor(pScreenPriv->cp->pColormap, maskColor->pixel);
     }
-    pScreenPriv->checkPixels = FALSE;
+    pScreenPriv->cp->checkPixels = FALSE;
 }
 
 /*
@@ -613,9 +626,9 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
     SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    if (pScreenPriv->isUp)
+    if (pScreenPriv->cp->isUp)
     {
-	cursorBox = pScreenPriv->saved;
+	cursorBox = pScreenPriv->cp->saved;
 
 	if (dx || dy)
  	{
@@ -648,8 +661,8 @@ miSpriteRealizeCursor (pDev, pScreen, pCursor)
     miSpriteScreenPtr	pScreenPriv;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    if (pCursor == pScreenPriv->pCursor)
-	pScreenPriv->checkPixels = TRUE;
+    if (pCursor == pScreenPriv->cp->pCursor)
+	pScreenPriv->cp->checkPixels = TRUE;
     return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
 }
 
@@ -678,80 +691,85 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     if (!pCursor)
     {
-    	pScreenPriv->shouldBeUp = FALSE;
-    	if (pScreenPriv->isUp)
+    	pScreenPriv->cp->shouldBeUp = FALSE;
+    	if (pScreenPriv->cp->isUp)
 	    miSpriteRemoveCursor (pScreen);
-	pScreenPriv->pCursor = 0;
+	pScreenPriv->cp->pCursor = 0;
 	return;
     }
-    pScreenPriv->shouldBeUp = TRUE;
-    if (pScreenPriv->x == x &&
-	pScreenPriv->y == y &&
-	pScreenPriv->pCursor == pCursor &&
-	!pScreenPriv->checkPixels)
+    pScreenPriv->cp->shouldBeUp = TRUE;
+    if (pScreenPriv->cp->x == x &&
+	pScreenPriv->cp->y == y &&
+	pScreenPriv->cp->pCursor == pCursor &&
+	!pScreenPriv->cp->checkPixels)
     {
 	return;
     }
-    pScreenPriv->x = x;
-    pScreenPriv->y = y;
-    pScreenPriv->pCacheWin = NullWindow;
-    if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
+    pScreenPriv->cp->x = x;
+    pScreenPriv->cp->y = y;
+    pScreenPriv->cp->pCacheWin = NullWindow;
+    if (pScreenPriv->cp->checkPixels || pScreenPriv->cp->pCursor != pCursor)
     {
-	pScreenPriv->pCursor = pCursor;
+	pScreenPriv->cp->pCursor = pCursor;
 	miSpriteFindColors (pScreen);
     }
-    if (pScreenPriv->isUp) {
+    if (pScreenPriv->cp->isUp) {
 	int	sx, sy;
 	/*
 	 * check to see if the old saved region
 	 * encloses the new sprite, in which case we use
 	 * the flicker-free MoveCursor primitive.
 	 */
-	sx = pScreenPriv->x - (int)pCursor->bits->xhot;
-	sy = pScreenPriv->y - (int)pCursor->bits->yhot;
-	if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 &&
-	    sx < pScreenPriv->saved.x2 &&
-	    sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 &&
-	    sy < pScreenPriv->saved.y2 &&
+	sx = pScreenPriv->cp->x - (int)pCursor->bits->xhot;
+	sy = pScreenPriv->cp->y - (int)pCursor->bits->yhot;
+	if (sx + (int) pCursor->bits->width >= pScreenPriv->cp->saved.x1 &&
+	    sx < pScreenPriv->cp->saved.x2 &&
+	    sy + (int) pCursor->bits->height >= pScreenPriv->cp->saved.y1 &&
+	    sy < pScreenPriv->cp->saved.y2 &&
 	    (int) pCursor->bits->width + (2 * SPRITE_PAD) ==
-		pScreenPriv->saved.x2 - pScreenPriv->saved.x1 &&
+		pScreenPriv->cp->saved.x2 - pScreenPriv->cp->saved.x1 &&
 	    (int) pCursor->bits->height + (2 * SPRITE_PAD) ==
-		pScreenPriv->saved.y2 - pScreenPriv->saved.y1
+		pScreenPriv->cp->saved.y2 - pScreenPriv->cp->saved.y1
 	    )
 	{
 	    DamageDrawInternal (pScreen, TRUE);
 	    miSpriteIsUpFALSE (pScreen, pScreenPriv);
-	    if (!(sx >= pScreenPriv->saved.x1 &&
-	      	  sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 &&
-	      	  sy >= pScreenPriv->saved.y1 &&
-	      	  sy + (int)pCursor->bits->height < pScreenPriv->saved.y2))
-	    {
+	    if (!(sx >= pScreenPriv->cp->saved.x1 &&
+                  sx + (int)pCursor->bits->width < pScreenPriv->cp->saved.x2
+                  && sy >= pScreenPriv->cp->saved.y1 &&
+                  sy + (int)pCursor->bits->height <
+                                pScreenPriv->cp->saved.y2)) 
+            {
 		int oldx1, oldy1, dx, dy;
 
-		oldx1 = pScreenPriv->saved.x1;
-		oldy1 = pScreenPriv->saved.y1;
+		oldx1 = pScreenPriv->cp->saved.x1;
+		oldy1 = pScreenPriv->cp->saved.y1;
 		dx = oldx1 - (sx - SPRITE_PAD);
 		dy = oldy1 - (sy - SPRITE_PAD);
-		pScreenPriv->saved.x1 -= dx;
-		pScreenPriv->saved.y1 -= dy;
-		pScreenPriv->saved.x2 -= dx;
-		pScreenPriv->saved.y2 -= dy;
+		pScreenPriv->cp->saved.x1 -= dx;
+		pScreenPriv->cp->saved.y1 -= dy;
+		pScreenPriv->cp->saved.x2 -= dx;
+		pScreenPriv->cp->saved.y2 -= dy;
 		(void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
-				pScreenPriv->saved.x1,
- 				pScreenPriv->saved.y1,
-				pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
-				pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
+				pScreenPriv->cp->saved.x1,
+ 				pScreenPriv->cp->saved.y1,
+                                pScreenPriv->cp->saved.x2 -
+                                pScreenPriv->cp->saved.x1,
+                                pScreenPriv->cp->saved.y2 -
+                                pScreenPriv->cp->saved.y1,
 				dx, dy);
 	    }
 	    (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
-				  pScreenPriv->saved.x1,
- 				  pScreenPriv->saved.y1,
-				  pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
-				  pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
-				  sx - pScreenPriv->saved.x1,
-				  sy - pScreenPriv->saved.y1,
-				  pScreenPriv->colors[SOURCE_COLOR].pixel,
-				  pScreenPriv->colors[MASK_COLOR].pixel);
+				  pScreenPriv->cp->saved.x1,
+ 				  pScreenPriv->cp->saved.y1,
+                                  pScreenPriv->cp->saved.x2 -
+                                  pScreenPriv->cp->saved.x1,
+                                  pScreenPriv->cp->saved.y2 -
+                                  pScreenPriv->cp->saved.y1,
+				  sx - pScreenPriv->cp->saved.x1,
+				  sy - pScreenPriv->cp->saved.y1,
+				  pScreenPriv->cp->colors[SOURCE_COLOR].pixel,
+				  pScreenPriv->cp->colors[MASK_COLOR].pixel);
 	    miSpriteIsUpTRUE (pScreen, pScreenPriv);
 	    DamageDrawInternal (pScreen, FALSE);
 	}
@@ -761,7 +779,7 @@ miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
 	    miSpriteRemoveCursor (pScreen);
 	}
     }
-    if (!pScreenPriv->isUp && pScreenPriv->pCursor)
+    if (!pScreenPriv->cp->isUp && pScreenPriv->cp->pCursor)
     {
 	SPRITE_DEBUG (("SetCursor restore\n"));
 	miSpriteRestoreCursor (pScreen);
@@ -778,7 +796,7 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
     CursorPtr pCursor;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursor = pScreenPriv->pCursor;
+    pCursor = pScreenPriv->cp->pCursor;
 #ifdef MPX
     if (IsMPDev(pDev))
         pCursor = pScreenPriv->mpCursors[pDev->id].pCursor;
@@ -799,12 +817,14 @@ miSpriteRemoveCursor (pScreen)
     DamageDrawInternal (pScreen, TRUE);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
     miSpriteIsUpFALSE (pScreen, pScreenPriv);
-    pScreenPriv->pCacheWin = NullWindow;
+    pScreenPriv->cp->pCacheWin = NullWindow;
     if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
-					 pScreenPriv->saved.x1,
-					 pScreenPriv->saved.y1,
-					 pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
-					 pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
+					 pScreenPriv->cp->saved.x1,
+                                         pScreenPriv->cp->saved.y1,
+                                         pScreenPriv->cp->saved.x2 -
+                                         pScreenPriv->cp->saved.x1,
+                                         pScreenPriv->cp->saved.y2 -
+                                         pScreenPriv->cp->saved.y1))
     {
 	miSpriteIsUpTRUE (pScreen, pScreenPriv);
     }
@@ -827,20 +847,22 @@ miSpriteRestoreCursor (pScreen)
     DamageDrawInternal (pScreen, TRUE);
     miSpriteComputeSaved (pScreen);
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursor = pScreenPriv->pCursor;
-    x = pScreenPriv->x - (int)pCursor->bits->xhot;
-    y = pScreenPriv->y - (int)pCursor->bits->yhot;
+    pCursor = pScreenPriv->cp->pCursor;
+    x = pScreenPriv->cp->x - (int)pCursor->bits->xhot;
+    y = pScreenPriv->cp->y - (int)pCursor->bits->yhot;
     if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
-				      pScreenPriv->saved.x1,
-				      pScreenPriv->saved.y1,
-				      pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
-				      pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
+				      pScreenPriv->cp->saved.x1,
+				      pScreenPriv->cp->saved.y1,
+                                      pScreenPriv->cp->saved.x2 -
+                                      pScreenPriv->cp->saved.x1,
+                                      pScreenPriv->cp->saved.y2 -
+                                      pScreenPriv->cp->saved.y1))
     {
-	if (pScreenPriv->checkPixels)
+	if (pScreenPriv->cp->checkPixels)
 	    miSpriteFindColors (pScreen);
 	if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
-				  pScreenPriv->colors[SOURCE_COLOR].pixel,
-				  pScreenPriv->colors[MASK_COLOR].pixel))
+				  pScreenPriv->cp->colors[SOURCE_COLOR].pixel,
+				  pScreenPriv->cp->colors[MASK_COLOR].pixel))
 	{
 	    miSpriteIsUpTRUE (pScreen, pScreenPriv);
 	}
@@ -862,15 +884,15 @@ miSpriteComputeSaved (pScreen)
     CursorPtr	    pCursor;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    pCursor = pScreenPriv->pCursor;
-    x = pScreenPriv->x - (int)pCursor->bits->xhot;
-    y = pScreenPriv->y - (int)pCursor->bits->yhot;
+    pCursor = pScreenPriv->cp->pCursor;
+    x = pScreenPriv->cp->x - (int)pCursor->bits->xhot;
+    y = pScreenPriv->cp->y - (int)pCursor->bits->yhot;
     w = pCursor->bits->width;
     h = pCursor->bits->height;
     wpad = SPRITE_PAD;
     hpad = SPRITE_PAD;
-    pScreenPriv->saved.x1 = x - wpad;
-    pScreenPriv->saved.y1 = y - hpad;
-    pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2;
-    pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2;
+    pScreenPriv->cp->saved.x1 = x - wpad;
+    pScreenPriv->cp->saved.y1 = y - hpad;
+    pScreenPriv->cp->saved.x2 = pScreenPriv->cp->saved.x1 + w + wpad * 2;
+    pScreenPriv->cp->saved.y2 = pScreenPriv->cp->saved.y1 + h + hpad * 2;
 }
diff --git a/mi/mispritest.h b/mi/mispritest.h
index 24ab11e..4608c4e 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -43,7 +43,6 @@ in this Software without prior written authorization from The Open Group.
 #endif
 # include   "damage.h"
 
-#ifdef MPX
 typedef struct {
     CursorPtr	    pCursor;
     int		    x;			/* cursor hotspot */
@@ -52,8 +51,12 @@ typedef struct {
     Bool	    isUp;		/* cursor in frame buffer */
     Bool	    shouldBeUp;		/* cursor should be displayed */
     WindowPtr	    pCacheWin;		/* window the cursor last seen in */
+    Bool	    isInCacheWin;
+    Bool	    checkPixels;	/* check colormap collision */
+    xColorItem	    colors[2];
+    ColormapPtr	    pInstalledMap;
+    ColormapPtr	    pColormap;
 } miCursorInfoRec, *miCursorInfoPtr;
-#endif
 
 /*
  * per screen information
@@ -79,18 +82,8 @@ typedef struct {
     /* os layer procedures */
     ScreenBlockHandlerProcPtr		BlockHandler;
 
-    CursorPtr	    pCursor;
-    int		    x;			/* cursor hotspot */
-    int		    y;
-    BoxRec	    saved;		/* saved area from the screen */
-    Bool	    isUp;		/* cursor in frame buffer */
-    Bool	    shouldBeUp;		/* cursor should be displayed */
-    WindowPtr	    pCacheWin;		/* window the cursor last seen in */
-    Bool	    isInCacheWin;
-    Bool	    checkPixels;	/* check colormap collision */
-    xColorItem	    colors[2];
-    ColormapPtr	    pInstalledMap;
-    ColormapPtr	    pColormap;
+    miCursorInfoPtr  cp;                 /* core pointer */
+
     VisualPtr	    pVisual;
     miSpriteCursorFuncPtr    funcs;
     DamagePtr	    pDamage;		/* damage tracking structure */
@@ -102,14 +95,14 @@ typedef struct {
 #define SOURCE_COLOR	0
 #define MASK_COLOR	1
 
-#define miSpriteIsUpTRUE(pScreen, pScreenPriv) if (!pScreenPriv->isUp) { \
-    pScreenPriv->isUp = TRUE; \
+#define miSpriteIsUpTRUE(pScreen, pScreenPriv) if (!pScreenPriv->cp->isUp) { \
+    pScreenPriv->cp->isUp = TRUE; \
     DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
 }
 
-#define miSpriteIsUpFALSE(pScreen, pScreenPriv) if (pScreenPriv->isUp) { \
+#define miSpriteIsUpFALSE(pScreen, pScreenPriv) if (pScreenPriv->cp->isUp) { \
     DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
-    pScreenPriv->isUp = FALSE; \
+    pScreenPriv->cp->isUp = FALSE; \
 }
 
 /*
commit 90bea69dfdd63f58ee326887359ad1b35a31cb5f
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 17 18:03:43 2006 +1030

    mi:
            added miCursorInfoRec to contain info of the MPX cursors.
            calling miUpdatePointerSprite() from event queue for MPX devices.
            adding device-specific processing to miPointer*() functions.
    
    dix:    Call to SetCursorPosition in CheckMotion() temporarily disabled.
    
    xfree86/common: call to miPointerUpdateSprite() disabled, is done from the EQ
    
    NOTE: This build will not display cursor images.
    BUG: The second mouse does to take correct x coordinates.

diff --git a/Changelog b/Changelog
index 86bce4d..484ac4d 100644
--- a/Changelog
+++ b/Changelog
@@ -25,6 +25,29 @@ Files:
         hw/xfree86/ramdac/xf86Cursor.c
         hw/xfree86/rac/xf86RAC.c
 
+
+mi:
+        added miCursorInfoRec to contain info of the MPX cursors.
+        calling miUpdatePointerSprite() from event queue for MPX devices.
+        adding device-specific processing to miPointer*() functions.
+
+dix:    Call to SetCursorPosition in CheckMotion() temporarily disabled.
+
+xfree86/common: call to miPointerUpdateSprite() disabled, is done from the EQ 
+
+NOTE: This build will not display cursor images. 
+BUG: The second mouse does to take correct x coordinates.
+
+Files:
+        mi/mispritestr.h
+        mi/misprite.c
+        mi/mipointer.c
+        mi/mipointer.h
+        mi/mieq.c
+        dix/events.c
+        hw/xfree86/common/xf86Events.c
+
+
 == 16.11.06 ==
 dix: 
         merge with code cleanup from master
diff --git a/dix/events.c b/dix/events.c
index e5701ee..19ed97c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2012,6 +2012,7 @@ CheckMotion(xEvent *xE)
         xeviehot.y = sprite.hot.y;
 #endif
 	sprite.hotPhys = sprite.hot;
+#ifndef MPX
 	if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
 	    (sprite.hotPhys.y != XE_KBPTR.rootY))
 	{
@@ -2019,6 +2020,7 @@ CheckMotion(xEvent *xE)
 		sprite.hotPhys.pScreen,
 		sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
 	}
+#endif
 	XE_KBPTR.rootX = sprite.hot.x;
 	XE_KBPTR.rootY = sprite.hot.y;
     }
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 5469426..a552491 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -246,7 +246,10 @@ ProcessInputEvents ()
   xf86Info.inputPending = FALSE;
 
   mieqProcessInputEvents();
+#ifndef MPX
+  /* For MPX, this is done inside the mieqProcessInputEvents() */
   miPointerUpdateSprite(inputInfo.pointer);
+#endif
 
   miPointerGetPosition(inputInfo.pointer, &x, &y);
   xf86SetViewport(xf86Info.currentScreen, x, y);
diff --git a/mi/mieq.c b/mi/mieq.c
index d199335..30a61e6 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -251,5 +251,17 @@ mieqProcessInputEvents()
 #endif
             dev->public.processInputProc(e->event, dev, e->nevents);
         }
+#ifdef MPX
+        /* 
+         * This is inefficient as we update the sprite for each event rather
+         * than at the end of the event queue. But we don't know if the
+         * next event is from the same device, so it's better to do it here.
+         */
+        if (e->event[0].u.u.type == MotionNotify && 
+                (e->pDev->isMPDev || e->pDev->coreEvents))
+        {
+            miPointerUpdateSprite(e->pDev);
+        }
+#endif
     }
 }
diff --git a/mi/mipointer.c b/mi/mipointer.c
index 7d5d18f..8f049c4 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -70,6 +70,14 @@ static miPointerRec miPointer;
 #ifdef MPX
 /* Multipointers */
 static miPointerRec miMPPointers[MAX_DEVICES];
+
+
+/* Check if the given device is a MP device. */
+_X_EXPORT Bool 
+IsMPDev(DeviceIntPtr pDev) 
+{
+    return (pDev && pDev->isMPDev && pDev->id < MAX_DEVICES);
+}
 #endif
 
 static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
@@ -175,12 +183,23 @@ miPointerCloseScreen (index, pScreen)
     int		index;
     ScreenPtr	pScreen;
 {
+    int mpPointerIdx = 0;
     SetupScreen(pScreen);
 
     if (pScreen == miPointer.pScreen)
 	miPointer.pScreen = 0;
     if (pScreen == miPointer.pSpriteScreen)
 	miPointer.pSpriteScreen = 0;
+#ifdef MPX
+    while(mpPointerIdx < MAX_DEVICES)
+    {
+        if (pScreen == miMPPointers[mpPointerIdx].pScreen) 
+            miMPPointers[mpPointerIdx].pScreen = 0;
+        if (pScreen == miMPPointers[mpPointerIdx].pSpriteScreen) 
+            miMPPointers[mpPointerIdx].pSpriteScreen = 0;
+        mpPointerIdx++;
+    }
+#endif
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
     xfree ((pointer) pScreenPriv);
     return (*pScreen->CloseScreen) (index, pScreen);
@@ -218,6 +237,16 @@ miPointerDisplayCursor (pScreen, pCursor)
     ScreenPtr	pScreen;
     CursorPtr	pCursor;
 {
+#ifdef MPX
+    int mpPtrIdx = 0;
+    while (mpPtrIdx < MAX_DEVICES)
+    {
+        miMPPointers[mpPtrIdx].pCursor = pCursor;
+        miMPPointers[mpPtrIdx].pScreen = pScreen;
+        mpPtrIdx++;
+    }
+
+#endif
     miPointer.pCursor = pCursor;
     miPointer.pScreen = pScreen;
     miPointerUpdateSprite(inputInfo.pointer);
@@ -329,65 +358,78 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
     miPointerScreenPtr	pScreenPriv;
     CursorPtr		pCursor;
     int			x, y, devx, devy;
+    miPointerPtr        pointer;
 
+#ifdef MPX
+    if (!pDev || 
+            !(pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev))
+#else
     if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer))
+#endif
         return;
 
-    pScreen = miPointer.pScreen;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pointer = &miMPPointers[pDev->id];
+    else
+        pointer = &miPointer;
+#endif
+
+    pScreen = pointer->pScreen;
     if (!pScreen)
 	return;
 
-    x = miPointer.x;
-    y = miPointer.y;
-    devx = miPointer.devx;
-    devy = miPointer.devy;
+    x = pointer->x;
+    y = pointer->y;
+    devx = pointer->devx;
+    devy = pointer->devy;
 
     pScreenPriv = GetScreenPrivate (pScreen);
     /*
      * if the cursor has switched screens, disable the sprite
      * on the old screen
      */
-    if (pScreen != miPointer.pSpriteScreen)
+    if (pScreen != pointer->pSpriteScreen)
     {
-	if (miPointer.pSpriteScreen)
+	if (pointer->pSpriteScreen)
 	{
 	    miPointerScreenPtr  pOldPriv;
     	
-	    pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen);
-	    if (miPointer.pCursor)
+	    pOldPriv = GetScreenPrivate (pointer->pSpriteScreen);
+	    if (pointer->pCursor)
 	    {
 	    	(*pOldPriv->spriteFuncs->SetCursor)
-			    	(pDev, miPointer.pSpriteScreen, NullCursor, 0, 0);
+			    	(pDev, pointer->pSpriteScreen, NullCursor, 0, 0);
 	    }
-	    (*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE);
+	    (*pOldPriv->screenFuncs->CrossScreen) (pointer->pSpriteScreen, FALSE);
 	}
 	(*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
 	(*pScreenPriv->spriteFuncs->SetCursor)
-				(pDev, pScreen, miPointer.pCursor, x, y);
-	miPointer.devx = x;
-	miPointer.devy = y;
-	miPointer.pSpriteCursor = miPointer.pCursor;
-	miPointer.pSpriteScreen = pScreen;
+				(pDev, pScreen, pointer->pCursor, x, y);
+	pointer->devx = x;
+	pointer->devy = y;
+	pointer->pSpriteCursor = pointer->pCursor;
+	pointer->pSpriteScreen = pScreen;
     }
     /*
      * if the cursor has changed, display the new one
      */
-    else if (miPointer.pCursor != miPointer.pSpriteCursor)
+    else if (pointer->pCursor != pointer->pSpriteCursor)
     {
-	pCursor = miPointer.pCursor;
+	pCursor = pointer->pCursor;
 	if (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)
 	    pCursor = NullCursor;
 	(*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
 
-	miPointer.devx = x;
-	miPointer.devy = y;
-	miPointer.pSpriteCursor = miPointer.pCursor;
+	pointer->devx = x;
+	pointer->devy = y;
+	pointer->pSpriteCursor = pointer->pCursor;
     }
     else if (x != devx || y != devy)
     {
-	miPointer.devx = x;
-	miPointer.devy = y;
-	if(!miPointer.pCursor->bits->emptyMask)
+	pointer->devx = x;
+	pointer->devy = y;
+	if(!pointer->pCursor->bits->emptyMask)
 	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     }
 }
@@ -421,8 +463,17 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
 	pScreenPriv = GetScreenPrivate (pScreen);
 	(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
 	NewCurrentScreen (pScreen, x, y);
-   	miPointer.limits.x2 = pScreen->width;
-   	miPointer.limits.y2 = pScreen->height;
+#ifdef MPX
+        if (IsMPDev(pDev))
+        {
+            miMPPointers[pDev->id].limits.x2 = pScreen->width;
+            miMPPointers[pDev->id].limits.y2 = pScreen->height;
+        }
+#endif
+        {
+            miPointer.limits.x2 = pScreen->width;
+            miPointer.limits.y2 = pScreen->height;
+        }
 }
 
 _X_EXPORT ScreenPtr
@@ -434,6 +485,10 @@ miPointerCurrentScreen ()
 _X_EXPORT ScreenPtr
 miPointerGetScreen(DeviceIntPtr pDev)
 {
+#ifdef MPX
+    if (IsMPDev(pDev))
+        return miMPPointers[pDev->id].pScreen;
+#endif
     return miPointer.pScreen;
 }
 
@@ -453,7 +508,15 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     ScreenPtr		pScreen;
     ScreenPtr		newScreen;
 
-    pScreen = miPointer.pScreen;
+    miPointerPtr        pointer;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pointer = &(miMPPointers[pDev->id]);
+    else
+#endif
+        pointer = &miPointer;
+
+    pScreen = pointer->pScreen;
     if (!pScreen)
 	return;	    /* called before ready */
 
@@ -468,7 +531,7 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
     {
 	pScreenPriv = GetScreenPrivate (pScreen);
-	if (!miPointer.confined)
+	if (!pointer->confined)
 	{
 	    newScreen = pScreen;
 	    (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
@@ -478,22 +541,22 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
 		(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
 		pScreenPriv = GetScreenPrivate (pScreen);
 	    	/* Smash the confine to the new screen */
-	    	miPointer.limits.x2 = pScreen->width;
-	    	miPointer.limits.y2 = pScreen->height;
+                pointer->limits.x2 = pScreen->width;
+                pointer->limits.y2 = pScreen->height;
 	    }
 	}
     }
     /* Constrain the sprite to the current limits. */
-    if (*x < miPointer.limits.x1)
-	*x = miPointer.limits.x1;
-    if (*x >= miPointer.limits.x2)
-	*x = miPointer.limits.x2 - 1;
-    if (*y < miPointer.limits.y1)
-	*y = miPointer.limits.y1;
-    if (*y >= miPointer.limits.y2)
-	*y = miPointer.limits.y2 - 1;
-
-    if (miPointer.x == *x && miPointer.y == *y && miPointer.pScreen == pScreen)
+    if (*x < pointer->limits.x1)
+	*x = pointer->limits.x1;
+    if (*x >= pointer->limits.x2)
+	*x = pointer->limits.x2 - 1;
+    if (*y < pointer->limits.y1)
+	*y = pointer->limits.y1;
+    if (*y >= pointer->limits.y2)
+	*y = pointer->limits.y2 - 1;
+
+    if (pointer->x == *x && pointer->y == *y && pointer->pScreen == pScreen)
 	return;
 
     miPointerMoved(pDev, pScreen, *x, *y, time);
@@ -508,8 +571,18 @@ miPointerPosition (int *x, int *y)
 _X_EXPORT void
 miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
 {
-    *x = miPointer.x;
-    *y = miPointer.y;
+#ifdef MPX
+    if (IsMPDev(pDev))
+    {
+        *x = miMPPointers[pDev->id].x;
+        *y = miMPPointers[pDev->id].y;
+    }
+    else
+#endif
+    {
+        *x = miPointer.x;
+        *y = miPointer.y;
+    }
 }
 
 void
@@ -523,18 +596,30 @@ void
 miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
                      unsigned long time)
 {
+    miPointerPtr pointer;
     SetupScreen(pScreen);
 
-    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer) &&
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pointer = &miMPPointers[pDev->id];
+    else
+#endif
+        pointer = &miPointer;
+
+    if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer
+#ifdef MPX
+                || pDev->isMPDev
+#endif
+                ) &&
         !pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
     {
-	miPointer.devx = x;
-	miPointer.devy = y;
-	if(!miPointer.pCursor->bits->emptyMask)
+	pointer->devx = x;
+	pointer->devy = y;
+	if(!pointer->pCursor->bits->emptyMask)
 	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     }
 
-    miPointer.x = x;
-    miPointer.y = y;
-    miPointer.pScreen = pScreen;
+    pointer->x = x;
+    pointer->y = y;
+    pointer->pScreen = pScreen;
 }
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 8e66ae6..832aa5a 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -187,4 +187,9 @@ extern void miPointerMoved(
 
 extern int miPointerScreenIndex;
 
+#ifdef MPX
+_X_EXPORT Bool IsMPDev(DeviceIntPtr pDev);
+#endif;
+
+
 #endif /* MIPOINTER_H */
diff --git a/mi/misprite.c b/mi/misprite.c
index cc7ab95..f0530d2 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -65,6 +65,10 @@ in this Software without prior written authorization from The Open Group.
 #endif
 # include   "damage.h"
 
+#ifdef MPX
+# include   "inputstr.h" /* for MAX_DEVICES */
+#endif
+
 #define SPRITE_DEBUG_ENABLE 0
 #if SPRITE_DEBUG_ENABLE
 #define SPRITE_DEBUG(x)	ErrorF x
@@ -165,6 +169,9 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
     miSpriteCursorFuncPtr   cursorFuncs;
     miPointerScreenFuncPtr  screenFuncs;
 {
+#ifdef MPX
+    int mpCursorIdx = 0;
+#endif
     miSpriteScreenPtr	pScreenPriv;
     VisualPtr		pVisual;
     
@@ -247,6 +254,24 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
 
     pScreen->BlockHandler = miSpriteBlockHandler;
     
+#ifdef MPX
+    /* alloc and zero memory for all MPX cursors */
+    pScreenPriv->mpCursors = (miCursorInfoPtr)xalloc(MAX_DEVICES * sizeof(miCursorInfoRec));
+    while (mpCursorIdx < MAX_DEVICES)
+    {
+        miCursorInfoPtr cursor = &(pScreenPriv->mpCursors[mpCursorIdx]);
+
+        cursor->pCursor = NULL;
+        cursor->x = 0;
+        cursor->y = 0;
+        cursor->isUp = FALSE;
+        cursor->shouldBeUp = FALSE;
+        cursor->pCacheWin = NullWindow;
+
+        mpCursorIdx++;
+    }
+#endif
+
     return TRUE;
 }
 
@@ -750,9 +775,15 @@ miSpriteMoveCursor (pDev, pScreen, x, y)
     int		x, y;
 {
     miSpriteScreenPtr	pScreenPriv;
+    CursorPtr pCursor;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    miSpriteSetCursor (pDev, pScreen, pScreenPriv->pCursor, x, y);
+    pCursor = pScreenPriv->pCursor;
+#ifdef MPX
+    if (IsMPDev(pDev))
+        pCursor = pScreenPriv->mpCursors[pDev->id].pCursor;
+#endif
+    miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
 }
 
 /*
diff --git a/mi/mispritest.h b/mi/mispritest.h
index 5075f05..24ab11e 100644
--- a/mi/mispritest.h
+++ b/mi/mispritest.h
@@ -43,6 +43,18 @@ in this Software without prior written authorization from The Open Group.
 #endif
 # include   "damage.h"
 
+#ifdef MPX
+typedef struct {
+    CursorPtr	    pCursor;
+    int		    x;			/* cursor hotspot */
+    int		    y;
+    BoxRec	    saved;		/* saved area from the screen */
+    Bool	    isUp;		/* cursor in frame buffer */
+    Bool	    shouldBeUp;		/* cursor should be displayed */
+    WindowPtr	    pCacheWin;		/* window the cursor last seen in */
+} miCursorInfoRec, *miCursorInfoPtr;
+#endif
+
 /*
  * per screen information
  */
@@ -82,6 +94,9 @@ typedef struct {
     VisualPtr	    pVisual;
     miSpriteCursorFuncPtr    funcs;
     DamagePtr	    pDamage;		/* damage tracking structure */
+#ifdef MPX
+    miCursorInfoPtr mpCursors;         /* all cursor's info */
+#endif
 } miSpriteScreenRec, *miSpriteScreenPtr;
 
 #define SOURCE_COLOR	0
commit 94e106a898c44daeb228bcb031b85f996ddc96b0
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Fri Nov 17 15:10:37 2006 +1030

    dix:    moved isMPdev field to end of _DeviceIntRec structure
    
    mi:
            added miMPPointers array to mipointer.c
            added DeviceIntPtr to all miPointerSpriteFuncs. Coming from miPointer
            we use inputInfo.pointer as standard value. ABI BREAK!
    
    ramdac:
            forcing failed HW Cursor initialisation. MPX needs software rendering.
            changes to use new miPointerSpriteFunc (this required externing
            inputInfo, should probably be fixed at a later point).
    
    RAC: changes to use new miPointerSpriteFuncs.

diff --git a/Changelog b/Changelog
index 87501fb..86bce4d 100644
--- a/Changelog
+++ b/Changelog
@@ -1,5 +1,30 @@
 MPX Changelog file
 
+== 17.11.06 ==
+dix:    moved isMPdev field to end of _DeviceIntRec structure
+
+mi:     
+        added miMPPointers array to mipointer.c
+        added DeviceIntPtr to all miPointerSpriteFuncs. Coming from miPointer
+        we use inputInfo.pointer as standard value. ABI BREAK!
+
+ramdac: 
+        forcing failed HW Cursor initialisation. MPX needs software rendering.
+        changes to use new miPointerSpriteFunc (this required externing
+        inputInfo, should probably be fixed at a later point).
+
+
+RAC: changes to use new miPointerSpriteFuncs.
+
+Files: 
+        include/inputstr.h
+        mi/mipointer.c
+        mi/mipointer.h
+        mi/misprite.c
+        hw/xfree86/ramdac/xf86HWCurs.c
+        hw/xfree86/ramdac/xf86Cursor.c
+        hw/xfree86/rac/xf86RAC.c
+
 == 16.11.06 ==
 dix: 
         merge with code cleanup from master
diff --git a/hw/xfree86/rac/xf86RAC.c b/hw/xfree86/rac/xf86RAC.c
index aba8622..23dab86 100644
--- a/hw/xfree86/rac/xf86RAC.c
+++ b/hw/xfree86/rac/xf86RAC.c
@@ -224,11 +224,14 @@ static void RACPolyGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int xInit,
 static void RACPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDraw,
 			  int dx, int dy, int xOrg, int yOrg );
 /* miSpriteFuncs */
-static Bool RACSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCur);
-static Bool RACSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCur);
-static void RACSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCur,
-			       int x, int y);
-static void RACSpriteMoveCursor(ScreenPtr pScreen, int x, int y);
+static Bool RACSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                                   CursorPtr pCur); 
+static Bool RACSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                                     CursorPtr pCur);
+static void RACSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                               CursorPtr pCur, int x, int y);
+static void RACSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                                int x, int y); 
 #ifdef RENDER
 static void RACComposite(CARD8 op, PicturePtr pSrc,  PicturePtr pMask,
 			 PicturePtr pDst, INT16 xSrc, INT16 ySrc,
@@ -1158,46 +1161,47 @@ RACPushPixels(
 
 /* miSpriteFuncs */
 static Bool
-RACSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCur)
+RACSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur)
 {
     Bool val;
     SPRITE_PROLOG;
     DPRINT_S("RACSpriteRealizeCursor",pScreen->myNum);
     ENABLE;
-    val = PointPriv->spriteFuncs->RealizeCursor(pScreen, pCur);
+    val = PointPriv->spriteFuncs->RealizeCursor(pDev, pScreen, pCur);
     SPRITE_EPILOG;
     return val;
 }
 
 static Bool
-RACSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCur)
+RACSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur)
 {
     Bool val;
     SPRITE_PROLOG;
     DPRINT_S("RACSpriteUnrealizeCursor",pScreen->myNum);
     ENABLE;
-    val = PointPriv->spriteFuncs->UnrealizeCursor(pScreen, pCur);
+    val = PointPriv->spriteFuncs->UnrealizeCursor(pDev, pScreen, pCur);
     SPRITE_EPILOG;
     return val;
 }
 
 static void
-RACSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCur, int x, int y)
+RACSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                   CursorPtr pCur, int x, int y) 
 {
     SPRITE_PROLOG;
     DPRINT_S("RACSpriteSetCursor",pScreen->myNum);
     ENABLE;
-    PointPriv->spriteFuncs->SetCursor(pScreen, pCur, x, y);
+    PointPriv->spriteFuncs->SetCursor(pDev, pScreen, pCur, x, y);
     SPRITE_EPILOG;
 }
 
 static void
-RACSpriteMoveCursor(ScreenPtr pScreen, int x, int y)
+RACSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     SPRITE_PROLOG;
     DPRINT_S("RACSpriteMoveCursor",pScreen->myNum);
     ENABLE;
-    PointPriv->spriteFuncs->MoveCursor(pScreen, x, y);
+    PointPriv->spriteFuncs->MoveCursor(pDev, pScreen, x, y);
     SPRITE_EPILOG;
 }
 
diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c
index a903f7f..ec813e0 100644
--- a/hw/xfree86/ramdac/xf86Cursor.c
+++ b/hw/xfree86/ramdac/xf86Cursor.c
@@ -8,15 +8,25 @@
 #include "colormapst.h"
 #include "cursorstr.h"
 
+/* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for
+ * MPX.
+ * inputInfo is needed to pass the core pointer as the default argument into
+ * the cursor functions.
+ * 
+ * Externing inputInfo is not the nice way to do it but it works.
+ */
+#include "inputstr.h"
+extern InputInfo inputInfo;
+
 int xf86CursorScreenIndex = -1;
 static unsigned long xf86CursorGeneration = 0;
 
 /* sprite functions */
 
-static Bool xf86CursorRealizeCursor(ScreenPtr, CursorPtr);
-static Bool xf86CursorUnrealizeCursor(ScreenPtr, CursorPtr);
-static void xf86CursorSetCursor(ScreenPtr, CursorPtr, int, int);
-static void xf86CursorMoveCursor(ScreenPtr, int, int);
+static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
+static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
+static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int);
+static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int);
 
 static miPointerSpriteFuncRec xf86CursorSpriteFuncs = {
    xf86CursorRealizeCursor,
@@ -194,14 +204,17 @@ xf86CursorEnableDisableFBAccess(
     int index,
     Bool enable)
 {
+    DeviceIntPtr pDev = inputInfo.pointer;
+
     ScreenPtr pScreen = screenInfo.screens[index];
     xf86CursorScreenPtr ScreenPriv =
 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
 
     if (!enable && ScreenPriv->CurrentCursor != NullCursor) {
 	ScreenPriv->SavedCursor = ScreenPriv->CurrentCursor;
-	xf86CursorSetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
-	ScreenPriv->isUp = FALSE;
+        xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x,
+                ScreenPriv->y); 
+        ScreenPriv->isUp = FALSE;
 	ScreenPriv->SWCursor = TRUE;
     }
 
@@ -214,7 +227,7 @@ xf86CursorEnableDisableFBAccess(
 	 * Re-set current cursor so drivers can react to FB access having been
 	 * temporarily disabled.
 	 */
-	xf86CursorSetCursor(pScreen, ScreenPriv->SavedCursor,
+	xf86CursorSetCursor(pDev, pScreen, ScreenPriv->SavedCursor,
 			    ScreenPriv->x, ScreenPriv->y);
 	ScreenPriv->SavedCursor = NULL;
     }
@@ -251,7 +264,7 @@ xf86CursorSwitchMode(int index, DisplayModePtr mode, int flags)
 /****** miPointerSpriteFunctions *******/
 
 static Bool
-xf86CursorRealizeCursor(ScreenPtr pScreen, CursorPtr pCurs)
+xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs)
 {
     xf86CursorScreenPtr ScreenPriv =
 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
@@ -259,11 +272,12 @@ xf86CursorRealizeCursor(ScreenPtr pScreen, CursorPtr pCurs)
     if (pCurs->refcnt <= 1)
 	pCurs->devPriv[pScreen->myNum] = NULL;
 
-    return (*ScreenPriv->spriteFuncs->RealizeCursor)(pScreen, pCurs);
+    return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs);
 }
 
 static Bool
-xf86CursorUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCurs)
+xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                          CursorPtr pCurs)
 {
     xf86CursorScreenPtr ScreenPriv =
 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
@@ -273,11 +287,12 @@ xf86CursorUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCurs)
 	pCurs->devPriv[pScreen->myNum] = NULL;
     }
 
-    return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pScreen, pCurs);
+    return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs);
 }
 
 static void
-xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
+xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, 
+                    int x, int y)
 {
     xf86CursorScreenPtr ScreenPriv =
 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
@@ -294,8 +309,10 @@ xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
 
     if (pCurs == NullCursor) {	/* means we're supposed to remove the cursor */
 	if (ScreenPriv->SWCursor)
-	    (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, NullCursor, x, y);
-	else if (ScreenPriv->isUp) {
+            (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor,
+                                                  x, y); 
+        else if
+                (ScreenPriv->isUp) {
 	    xf86SetCursor(pScreen, NullCursor, x, y);
 	    ScreenPriv->isUp = FALSE;
 	}
@@ -319,7 +336,7 @@ xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
     {
 
 	if (ScreenPriv->SWCursor)	/* remove the SW cursor */
-	      (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, NullCursor, x, y);
+	      (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y);
 
 	xf86SetCursor(pScreen, pCurs, x, y);
 	ScreenPriv->SWCursor = FALSE;
@@ -344,11 +361,11 @@ xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
 
     if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent)
 	pCurs = NullCursor;
-    (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, pCurs, x, y);
+    (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, pCurs, x, y);
 }
 
 static void
-xf86CursorMoveCursor(ScreenPtr pScreen, int x, int y)
+xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     xf86CursorScreenPtr ScreenPriv =
 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
@@ -357,10 +374,10 @@ xf86CursorMoveCursor(ScreenPtr pScreen, int x, int y)
     ScreenPriv->y = y;
 
     if (ScreenPriv->CursorToRestore)
-	xf86CursorSetCursor(pScreen, ScreenPriv->CursorToRestore,
+	xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore,
 			    ScreenPriv->x, ScreenPriv->y);
     else if (ScreenPriv->SWCursor)
-	(*ScreenPriv->spriteFuncs->MoveCursor)(pScreen, x, y);
+	(*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y);
     else if (ScreenPriv->isUp)
 	xf86MoveCursor(pScreen, x, y);
 }
@@ -368,6 +385,8 @@ xf86CursorMoveCursor(ScreenPtr pScreen, int x, int y)
 void
 xf86ForceHWCursor (ScreenPtr pScreen, Bool on)
 {
+    DeviceIntPtr pDev = inputInfo.pointer;
+
     xf86CursorScreenPtr ScreenPriv =
 	pScreen->devPrivates[xf86CursorScreenIndex].ptr;
 
@@ -378,7 +397,7 @@ xf86ForceHWCursor (ScreenPtr pScreen, Bool on)
 	    if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor)
 	    {
 		ScreenPriv->HWCursorForced = TRUE;
-		xf86CursorSetCursor (pScreen, ScreenPriv->CurrentCursor,
+		xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor,
 				     ScreenPriv->x, ScreenPriv->y);
 	    }
 	    else
@@ -390,7 +409,7 @@ xf86ForceHWCursor (ScreenPtr pScreen, Bool on)
 	if (--ScreenPriv->ForceHWCursorCount == 0)
 	{
 	    if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor)
-		xf86CursorSetCursor (pScreen, ScreenPriv->CurrentCursor,
+		xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor,
 				     ScreenPriv->x, ScreenPriv->y);
 	}
     }
diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c
index 91caea0..b76b800 100644
--- a/hw/xfree86/ramdac/xf86HWCurs.c
+++ b/hw/xfree86/ramdac/xf86HWCurs.c
@@ -73,6 +73,13 @@ static unsigned char* RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
 Bool
 xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
 {
+
+#ifdef MPX
+    /* Graphics cards cannot render multiple cursors in hardware. We have to
+       software render them. */
+    return FALSE;
+#endif
+
     if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
 	return FALSE;
 
diff --git a/include/inputstr.h b/include/inputstr.h
index 231dffc..6f6b676 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -288,9 +288,6 @@ 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 */
-#ifdef MPX
-    Bool        isMPDev;                /* TRUE if multipointer device */
-#endif
     GrabPtr	grab;			/* the grabber - used by DIX */
     struct {
 	Bool		frozen;
@@ -332,6 +329,9 @@ typedef struct _DeviceIntRec {
     DevUnion		*devPrivates;
     int			nPrivates;
     DeviceUnwrapProc    unwrapProc;
+#ifdef MPX
+    Bool        isMPDev;                /* TRUE if multipointer device */
+#endif
 } DeviceIntRec;
 
 typedef struct {
diff --git a/mi/mipointer.c b/mi/mipointer.c
index dbe2aae..7d5d18f 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -27,6 +27,15 @@ Except as contained in this notice, the name of The Open Group 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 Open Group.
 */
+#ifdef MPX
+ /* 
+  * MPX additions:
+  * Copyright © 2006 Peter Hutterer
+  * License see above.
+  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
+  *
+  */
+#endif
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -58,6 +67,11 @@ static unsigned long miPointerGeneration = 0;
 
 static miPointerRec miPointer;
 
+#ifdef MPX
+/* Multipointers */
+static miPointerRec miMPPointers[MAX_DEVICES];
+#endif
+
 static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
@@ -77,6 +91,9 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     miPointerScreenFuncPtr  screenFuncs;
     Bool		    waitForUpdate;
 {
+#ifdef MPX
+    int mpPtrIdx = 0; /* loop counter */
+#endif
     miPointerScreenPtr	pScreenPriv;
 
     if (miPointerGeneration != serverGeneration)
@@ -128,6 +145,28 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
     miPointer.confined = FALSE;
     miPointer.x = 0;
     miPointer.y = 0;
+
+#ifdef MPX
+    /*
+     * Set up pointer objects for multipointer devices.
+     */
+    while(mpPtrIdx < MAX_DEVICES)
+    {
+        miMPPointers[mpPtrIdx].pScreen = NULL;
+        miMPPointers[mpPtrIdx].pSpriteScreen = NULL;
+        miMPPointers[mpPtrIdx].pCursor = NULL;
+        miMPPointers[mpPtrIdx].pSpriteCursor = NULL;
+        miMPPointers[mpPtrIdx].limits.x1 = 0;
+        miMPPointers[mpPtrIdx].limits.x2 = 32767;
+        miMPPointers[mpPtrIdx].limits.y1 = 0;
+        miMPPointers[mpPtrIdx].limits.y2 = 32767;
+        miMPPointers[mpPtrIdx].confined = FALSE;
+        miMPPointers[mpPtrIdx].x = 0;
+        miMPPointers[mpPtrIdx].y = 0;
+        mpPtrIdx++;
+    }
+#endif
+
     return TRUE;
 }
 
@@ -156,9 +195,11 @@ miPointerRealizeCursor (pScreen, pCursor)
     ScreenPtr	pScreen;
     CursorPtr	pCursor;
 {
+    DeviceIntPtr pDev = inputInfo.pointer;
+
     SetupScreen(pScreen);
 
-    return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor);
+    return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
 }
 
 static Bool
@@ -166,9 +207,10 @@ miPointerUnrealizeCursor (pScreen, pCursor)
     ScreenPtr	pScreen;
     CursorPtr	pCursor;
 {
+    DeviceIntPtr pDev = inputInfo.pointer;
     SetupScreen(pScreen);
 
-    return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor);
+    return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
 }
 
 static Bool
@@ -236,6 +278,8 @@ miPointerWarpCursor (pScreen, x, y)
     ScreenPtr	pScreen;
     int		x, y;
 {
+    DeviceIntPtr pDev = inputInfo.pointer;
+
     SetupScreen (pScreen);
 
     if (miPointer.pScreen != pScreen)
@@ -243,7 +287,7 @@ miPointerWarpCursor (pScreen, x, y)
 
     if (GenerateEvent)
     {
-	miPointerMove (pScreen, x, y, GetTimeInMillis()); 
+	miPointerMoved (pDev, pScreen, x, y, GetTimeInMillis()); 
     }
     else
     {
@@ -254,7 +298,7 @@ miPointerWarpCursor (pScreen, x, y)
 	    miPointer.devx = x;
 	    miPointer.devy = y;
 	    if(!miPointer.pCursor->bits->emptyMask)
-		(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
+		(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     	}
 	miPointer.x = x;
 	miPointer.y = y;
@@ -313,13 +357,13 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
 	    if (miPointer.pCursor)
 	    {
 	    	(*pOldPriv->spriteFuncs->SetCursor)
-			    	(miPointer.pSpriteScreen, NullCursor, 0, 0);
+			    	(pDev, miPointer.pSpriteScreen, NullCursor, 0, 0);
 	    }
 	    (*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE);
 	}
 	(*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
 	(*pScreenPriv->spriteFuncs->SetCursor)
-				(pScreen, miPointer.pCursor, x, y);
+				(pDev, pScreen, miPointer.pCursor, x, y);
 	miPointer.devx = x;
 	miPointer.devy = y;
 	miPointer.pSpriteCursor = miPointer.pCursor;
@@ -333,7 +377,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
 	pCursor = miPointer.pCursor;
 	if (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)
 	    pCursor = NullCursor;
-	(*pScreenPriv->spriteFuncs->SetCursor) (pScreen, pCursor, x, y);
+	(*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
 
 	miPointer.devx = x;
 	miPointer.devy = y;
@@ -344,7 +388,7 @@ miPointerUpdateSprite (DeviceIntPtr pDev)
 	miPointer.devx = x;
 	miPointer.devy = y;
 	if(!miPointer.pCursor->bits->emptyMask)
-	    (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
+	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     }
 }
 
@@ -413,7 +457,12 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
     if (!pScreen)
 	return;	    /* called before ready */
 
+#ifdef MPX
+    if (!pDev || 
+            !(pDev->coreEvents || pDev == inputInfo.pointer || pDev->isMPDev))
+#else
     if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer))
+#endif
         return;
 
     if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
@@ -482,7 +531,7 @@ miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
 	miPointer.devx = x;
 	miPointer.devy = y;
 	if(!miPointer.pCursor->bits->emptyMask)
-	    (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
+	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
     }
 
     miPointer.x = x;
diff --git a/mi/mipointer.h b/mi/mipointer.h
index 30e8944..8e66ae6 100644
--- a/mi/mipointer.h
+++ b/mi/mipointer.h
@@ -37,20 +37,24 @@ in this Software without prior written authorization from The Open Group.
 
 typedef struct _miPointerSpriteFuncRec {
     Bool	(*RealizeCursor)(
+                    DeviceIntPtr /* pDev */,
                     ScreenPtr /* pScr */,
                     CursorPtr /* pCurs */
                     );
     Bool	(*UnrealizeCursor)(
+                    DeviceIntPtr /* pDev */,
                     ScreenPtr /* pScr */,
                     CursorPtr /* pCurs */
                     );
     void	(*SetCursor)(
+                    DeviceIntPtr /* pDev */,
                     ScreenPtr /* pScr */,
                     CursorPtr /* pCurs */,
                     int  /* x */,
                     int  /* y */
                     );
     void	(*MoveCursor)(
+                    DeviceIntPtr /* pDev */,
                     ScreenPtr /* pScr */,
                     int  /* x */,
                     int  /* y */
diff --git a/mi/misprite.c b/mi/misprite.c
index 286c755..cc7ab95 100644
--- a/mi/misprite.c
+++ b/mi/misprite.c
@@ -29,6 +29,15 @@ Except as contained in this notice, the name of The Open Group 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 Open Group.
 */
+#ifdef MPX
+ /* 
+  * MPX additions:
+  * Copyright © 2006 Peter Hutterer
+  * License see above.
+  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
+  *
+  */
+#endif
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -105,11 +114,14 @@ static void	    miSpriteComputeSaved(ScreenPtr pScreen);
  * pointer-sprite method table
  */
 
-static Bool miSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
-static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor,
-			      int x, int y);
-static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y);
+static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
+                                  CursorPtr pCursor); 
+static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                                    CursorPtr pCursor);
+static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                              CursorPtr pCursor, int x, int y);
+static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 
+                               int x, int y);
 
 _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = {
     miSpriteRealizeCursor,
@@ -603,7 +615,8 @@ miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
 #define SPRITE_PAD  8
 
 static Bool
-miSpriteRealizeCursor (pScreen, pCursor)
+miSpriteRealizeCursor (pDev, pScreen, pCursor)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
     CursorPtr	pCursor;
 {
@@ -616,7 +629,8 @@ miSpriteRealizeCursor (pScreen, pCursor)
 }
 
 static Bool
-miSpriteUnrealizeCursor (pScreen, pCursor)
+miSpriteUnrealizeCursor (pDev, pScreen, pCursor)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
     CursorPtr	pCursor;
 {
@@ -627,7 +641,8 @@ miSpriteUnrealizeCursor (pScreen, pCursor)
 }
 
 static void
-miSpriteSetCursor (pScreen, pCursor, x, y)
+miSpriteSetCursor (pDev, pScreen, pCursor, x, y)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
     CursorPtr	pCursor;
     int		x;
@@ -729,14 +744,15 @@ miSpriteSetCursor (pScreen, pCursor, x, y)
 }
 
 static void
-miSpriteMoveCursor (pScreen, x, y)
+miSpriteMoveCursor (pDev, pScreen, x, y)
+    DeviceIntPtr pDev;
     ScreenPtr	pScreen;
     int		x, y;
 {
     miSpriteScreenPtr	pScreenPriv;
 
     pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
-    miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
+    miSpriteSetCursor (pDev, pScreen, pScreenPriv->pCursor, x, y);
 }
 
 /*
commit 5388423eb05daefcc71067b6ab96b6e57c44ef5c
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 16 20:43:27 2006 +1030

    mieq:  EQ processing handles MP devices
    
    global: MPX define added to xorg-server.h.in
    
    xfree86/common: small fix to avoid byte overflow

diff --git a/Changelog b/Changelog
index 3b5e9ad..87501fb 100644
--- a/Changelog
+++ b/Changelog
@@ -37,3 +37,15 @@ Files:
         hw/xfree86/common/xf86Xinput.c
         include/inputstr.h
         mi/mieq.c
+
+
+mieq:  EQ processing handles MP devices 
+
+global: MPX define added to xorg-server.h.in
+
+xfree86/common: small fix to avoid byte overflow
+
+Files:
+        mi/mieq.c
+        hw/xfree86/common/xf86Xinput.c
+        include/xserver-config.h.in
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 888ad42..2cb1441 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -215,7 +215,10 @@ xf86ActivateDevice(LocalDevicePtr local)
 
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
 #ifdef MPX
-        dev->isMPDev = local->flags & XI86_MP_DEVICE;
+        if (local->flags & XI86_MP_DEVICE)
+            dev->isMPDev = TRUE;
+        else
+            dev->isMPDev = FALSE;
 #endif
         RegisterOtherDevice(dev);
 
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 48196d8..c58e2b3 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -142,6 +142,9 @@
 /* Support X Input extension */
 #undef XINPUT
 
+/* Support MPX multipointer extension */
+#undef MPX
+
 /* Build XKB */
 #undef XKB
 
diff --git a/mi/mieq.c b/mi/mieq.c
index b901fbc..d199335 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -24,6 +24,15 @@ in this Software without prior written authorization from The Open Group.
  *
  * Author:  Keith Packard, MIT X Consortium
  */
+#ifdef MPX
+ /* 
+  * MPX additions:
+  * Copyright © 2006 Peter Hutterer
+  * License see above.
+  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
+  *
+  */
+#endif
 
 /*
  * mieq.c
@@ -218,13 +227,28 @@ mieqProcessInputEvents()
             else if (e->event[0].u.u.type == MotionNotify ||
                      e->event[0].u.u.type == ButtonPress ||
                      e->event[0].u.u.type == ButtonRelease) {
-                SwitchCorePointer(e->pDev);
+#ifdef MPX
+                if (!e->pDev->isMPDev)
+#endif
+                    SwitchCorePointer(e->pDev);
                 dev = inputInfo.pointer;
+
             }
             else {
                 dev = e->pDev;
             }
 
+#ifdef MPX
+            /* MPX devices send both core and Xi events. Depending on what
+             * event we have, dev is set to either the core pointer or the
+             * device. This gives us the right processing function but we need
+             * to pass the right device in too.
+             * Any device that is not a MP device is processed as usual.
+             */
+            if (e->pDev->isMPDev)
+                dev->public.processInputProc(e->event, e->pDev, e->nevents);
+            else
+#endif
             dev->public.processInputProc(e->event, dev, e->nevents);
         }
     }
commit c957a16180810fbd58526e1a670d82384fb4a61d
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 16 15:11:14 2006 +1030

    dix:    added isMPdev field to _DeviceIntRec, is used in GetPointerEvents()
    
    mieq:   avoid merging events from different devices in mieqEnqueue()
    
    xfree86/common
            isMPdev field used from xf86ActivateDevice(), xf86PostMotionEvent()
            and xf86PostButtonEvent()

diff --git a/Changelog b/Changelog
index d8f9300..3b5e9ad 100644
--- a/Changelog
+++ b/Changelog
@@ -23,3 +23,17 @@ Files:
         configure.ac
         include/dix-config.h.in
 
+
+dix:    added isMPdev field to _DeviceIntRec, is used in GetPointerEvents()
+
+mieq:   avoid merging events from different devices in mieqEnqueue()
+
+xfree86/common
+        isMPdev field used from xf86ActivateDevice(), xf86PostMotionEvent()
+        and xf86PostButtonEvent()
+
+Files:
+        dix/getevents.c
+        hw/xfree86/common/xf86Xinput.c
+        include/inputstr.h
+        mi/mieq.c
diff --git a/dix/getevents.c b/dix/getevents.c
index eb3c2a5..9c7b723 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -636,7 +636,12 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
                                    num_valuators, valuators);
     }
 
+#ifdef MPX
+    /* MPX devices always send core events */
+    if (pDev->coreEvents || pDev->isMPDev) {
+#else
     if (pDev->coreEvents) {
+#endif
         events->u.u.type = type;
         events->u.keyButtonPointer.time = ms;
         events->u.keyButtonPointer.rootX = x;
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 0dc392a..888ad42 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -215,7 +215,7 @@ xf86ActivateDevice(LocalDevicePtr local)
 
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
 #ifdef MPX
-        dev->coreEvents |= local->flags & XI86_MP_DEVICE;
+        dev->isMPDev = local->flags & XI86_MP_DEVICE;
 #endif
         RegisterOtherDevice(dev);
 
@@ -464,7 +464,7 @@ xf86PostMotionEvent(DeviceIntPtr	device,
         flags = POINTER_RELATIVE | POINTER_ACCELERATE;
 
 #ifdef MPX
-    if (device->coreEvents & XI86_MP_DEVICE)
+    if (device->isMPDev)
         flags |= POINTER_MULTIPOINTER;
 #endif
     
@@ -541,7 +541,7 @@ xf86PostButtonEvent(DeviceIntPtr	device,
         flags = POINTER_RELATIVE;
 
 #ifdef MPX
-    if (device->coreEvents & XI86_MP_DEVICE)
+    if (device->isMPDev)
         flags |= POINTER_MULTIPOINTER;
 #endif
     
diff --git a/include/inputstr.h b/include/inputstr.h
index ada94e6..231dffc 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -288,6 +288,9 @@ 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 */
+#ifdef MPX
+    Bool        isMPDev;                /* TRUE if multipointer device */
+#endif
     GrabPtr	grab;			/* the grabber - used by DIX */
     struct {
 	Bool		frozen;
diff --git a/mi/mieq.c b/mi/mieq.c
index 80915fd..b901fbc 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -101,6 +101,12 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
     deviceKeyButtonPointer *lastkbp = (deviceKeyButtonPointer *)
                                       &laste->event[0];
 
+#ifdef MPX
+    /* avoid merging events from different devices */
+    if (e->u.u.type == MotionNotify && pDev->isMPDev)
+        isMotion = pDev->id;
+    else
+#endif
     if (e->u.u.type == MotionNotify)
         isMotion = inputInfo.pointer->id;
     else if (e->u.u.type == DeviceMotionNotify)
commit 7ce2dc57844872cc340b60387d4d1cb3d982633e
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 16 12:51:08 2006 +1030

    dix:
            merge with code cleanup from master
            GetPointerEvents treats events in the same way as XINPUT devices when flag
            has POINTER_MULTIPOINTER set.
    
    xfree86/common:
        added XI86_MP_DEVICE flag and parsing in xf86ProcessCommonOptions
        added POINTER_MULTIPOINTER define. Is used in xf86PostMotionEvent and
        xf86PostButtonEvent for the flags that are passed into GetPointerEvents()
    
    global:
        added flags to configure.ac to enable/disable MPX define
        added flags to dix-config.h.in to define MPX

diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..d8f9300
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,25 @@
+MPX Changelog file
+
+== 16.11.06 ==
+dix: 
+        merge with code cleanup from master
+        GetPointerEvents treats events in the same way as XINPUT devices when flag
+        has POINTER_MULTIPOINTER set.
+
+xfree86/common:
+    added XI86_MP_DEVICE flag and parsing in xf86ProcessCommonOptions
+    added POINTER_MULTIPOINTER define. Is used in xf86PostMotionEvent and
+    xf86PostButtonEvent for the flags that are passed into GetPointerEvents()
+
+global:
+    added flags to configure.ac to enable/disable MPX define
+    added flags to dix-config.h.in to #define MPX
+
+Files:
+        dix/getevents.c
+        hw/xfree86/common/xf86Xinput.c
+        hw/xfree86/common/xf86Xinput.h
+        include/input.h
+        configure.ac
+        include/dix-config.h.in
+
diff --git a/configure.ac b/configure.ac
index 2108db4..706df91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -421,6 +421,7 @@ AC_ARG_ENABLE(builtin-fonts,  AS_HELP_STRING([--enable-builtin-fonts], [Use only
 AC_ARG_ENABLE(null-root-cursor, AS_HELP_STRING([--enable-null-root-cursor], [Use an empty root cursor (default: use core cursor)]),
                                  [NULL_ROOT_CURSOR=$enableval],
                                  [NULL_ROOT_CURSOR=no])
+AC_ARG_ENABLE(mpx,            AS_HELP_STRING([--disable-mpx], [Disable MPX multipointer support (Default: enabled)]), [MPX=$enableval], [MPX=yes])
 
 dnl Extensions.
 AC_ARG_ENABLE(composite,      AS_HELP_STRING([--disable-composite], [Build Composite extension (default: enabled)]), [COMPOSITE=$enableval], [COMPOSITE=yes])
@@ -783,6 +784,14 @@ AC_DEFINE(XINPUT, 1, [Support X Input extension])
 XI_LIB='$(top_builddir)/Xi/libXi.la'
 XI_INC='-I$(top_srcdir)/Xi'
 
+dnl Enable MPX multipointer  extension
+AC_MSG_CHECKING([whether to use MPX extension])
+AC_MSG_RESULT([$MPX])
+AM_CONDITIONAL(MPX, [test "x$MPX" = xyes])
+
+if test "x$MPX" = xyes; then
+    AC_DEFINE(MPX, 1, [Support MPX multipointer extension])
+fi
 AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes)
 
 AC_DEFINE(SHAPE, 1, [Support SHAPE extension])
diff --git a/dix/getevents.c b/dix/getevents.c
index 2077ce2..eb3c2a5 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -21,6 +21,15 @@
  *
  * Author: Daniel Stone <daniel at fooishbar.org>
  */
+#ifdef MPX
+ /* 
+  * MPX additions:
+  * Copyright © 2006 Peter Hutterer
+  * License see above.
+  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
+  *
+  */
+#endif
 
 #ifdef HAVE_DIX_CONFIG_H
 #include <dix-config.h>
@@ -480,6 +489,11 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
  * The DDX is responsible for allocating the event structure in the first
  * place via GetMaximumEventsNum(), and for freeing it.
  */
+#ifdef MPX
+ /* In MPX, flags can be set to POINTER_MULTIPOINTER to indicate that the
+  * device is a multipointer device. MP devices always send core events.
+  */
+#endif
 _X_EXPORT int
 GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
                  int flags, int first_valuator, int num_valuators,
@@ -525,6 +539,11 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     kbp->time = ms;
     kbp->deviceid = pDev->id;
 
+#ifdef MPX
+    if (flags & POINTER_MULTIPOINTER)
+        pointer = pDev;
+    else
+#endif
     if (pDev->coreEvents)
         pointer = inputInfo.pointer;
     else
@@ -581,6 +600,12 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
 
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
+#ifdef MPX
+    if (flags & POINTER_MULTIPOINTER)
+    {
+        // noop, just to fit MPX in easier with the following if
+    } else
+#endif
     if (pDev->coreEvents) {
         /* set the virtual core pointer's coordinates */
         pointer->valuator->lastx = x;
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 50df566..0dc392a 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -47,6 +47,17 @@
  */
 /* $XConsortium: xf86Xinput.c /main/14 1996/10/27 11:05:25 kaleb $ */
 
+#ifdef MPX
+ /* 
+  * MPX additions:
+  * Copyright © 2006 Peter Hutterer
+  * License see above.
+  * Author: Peter Hutterer <peter at cs.unisa.edu.au>
+  *
+  */
+#endif
+
+
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
 #endif
@@ -133,6 +144,13 @@ xf86ProcessCommonOptions(LocalDevicePtr local,
         xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name);
     }
 
+#ifdef MPX
+    if (xf86SetBoolOption(list, "IsMPDevice", 0)) {
+        local->flags |= XI86_MP_DEVICE;
+        xf86Msg(X_CONFIG, "%s: is MP device\n", local->name);
+    }
+#endif
+
     if (xf86SetBoolOption(list, "SendDragEvents", 1)) {
         local->flags |= XI86_SEND_DRAG_EVENTS;
     } else {
@@ -196,6 +214,9 @@ xf86ActivateDevice(LocalDevicePtr local)
         xf86XinputFinalizeInit(dev);
 
         dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
+#ifdef MPX
+        dev->coreEvents |= local->flags & XI86_MP_DEVICE;
+#endif
         RegisterOtherDevice(dev);
 
         if (serverGeneration == 1) 
@@ -441,6 +462,11 @@ xf86PostMotionEvent(DeviceIntPtr	device,
         flags = POINTER_ABSOLUTE;
     else
         flags = POINTER_RELATIVE | POINTER_ACCELERATE;
+
+#ifdef MPX
+    if (device->coreEvents & XI86_MP_DEVICE)
+        flags |= POINTER_MULTIPOINTER;
+#endif
     
     valuators = xcalloc(sizeof(int), num_valuators);
 
@@ -507,6 +533,17 @@ xf86PostButtonEvent(DeviceIntPtr	device,
     va_list var;
     int *valuators = NULL;
     int i = 0, nevents = 0;
+    int flags = 0;
+
+    if (is_absolute)
+        flags = POINTER_ABSOLUTE;
+    else
+        flags = POINTER_RELATIVE;
+
+#ifdef MPX
+    if (device->coreEvents & XI86_MP_DEVICE)
+        flags |= POINTER_MULTIPOINTER;
+#endif
     
     valuators = xcalloc(sizeof(int), num_valuators);
 
@@ -522,8 +559,7 @@ xf86PostButtonEvent(DeviceIntPtr	device,
 
     nevents = GetPointerEvents(xf86Events, device,
                                is_down ? ButtonPress : ButtonRelease, button,
-                               is_absolute ? POINTER_ABSOLUTE :
-                                             POINTER_RELATIVE,
+                               flags,
                                first_valuator, num_valuators, valuators);
 
     for (i = 0; i < nevents; i++)
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index fe65643..4c752cd 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -83,6 +83,10 @@
 #define XI86_POINTER_CAPABLE	0x40 /* capable of being a core pointer */
 #define XI86_KEYBOARD_CAPABLE	0x80 /* capable of being a core keyboard */
 
+#ifdef MPX
+#define XI86_MP_DEVICE 0x100 /* device is multipointer device */
+#endif
+
 #define XI_PRIVATE(dev) \
 	(((LocalDevicePtr)((dev)->public.devicePrivate))->private)
 
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 1120337..ed7a3d7 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -347,6 +347,9 @@
 /* Support X Input extension */
 #undef XINPUT
 
+/* Support MPX multipointer extension */
+#undef MPX
+
 /* Build XKB */
 #undef XKB
 
diff --git a/include/input.h b/include/input.h
index e7017cb..c7b2dfe 100644
--- a/include/input.h
+++ b/include/input.h
@@ -62,6 +62,9 @@ SOFTWARE.
 #define POINTER_RELATIVE (1 << 1)
 #define POINTER_ABSOLUTE (1 << 2)
 #define POINTER_ACCELERATE (1 << 3)
+#ifdef MPX
+#define POINTER_MULTIPOINTER (1 << 4)
+#endif
 
 #define MAP_LENGTH	256
 #define DOWN_LENGTH	32	/* 256/8 => number of bytes to hold 256 bits */
commit 4d07b503727ba86315b90d6f45b06ed6185724b2
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Thu Nov 16 10:55:15 2006 +1030

    dix: cleaned up GetPointerEvents() to avoid code duplication.

diff --git a/dix/getevents.c b/dix/getevents.c
index a888df6..2077ce2 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -488,7 +488,7 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     CARD32 ms = 0;
     deviceKeyButtonPointer *kbp = NULL;
     Bool sendValuators = (type == MotionNotify || flags & POINTER_ABSOLUTE);
-    DeviceIntPtr cp = inputInfo.pointer;
+    DeviceIntPtr pointer = NULL;
     int x = 0, y = 0;
 
     /* Sanity checks. */
@@ -525,6 +525,11 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     kbp->time = ms;
     kbp->deviceid = pDev->id;
 
+    if (pDev->coreEvents)
+        pointer = inputInfo.pointer;
+    else
+        pointer = pDev;
+
     /* Set x and y based on whether this is absolute or relative, and
      * accelerate if we need to. */
     if (flags & POINTER_ABSOLUTE) {
@@ -532,20 +537,14 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
             x = valuators[0];
         }
         else {
-            if (pDev->coreEvents)
-                x = cp->valuator->lastx;
-            else
-                x = pDev->valuator->lastx;
+            x = pointer->valuator->lastx;
         }
 
         if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) {
             y = valuators[1 - first_valuator];
         }
         else {
-            if (pDev->coreEvents)
-                x = cp->valuator->lasty;
-            else
-                y = pDev->valuator->lasty;
+                y = pointer->valuator->lasty;
         }
     }
     else {
@@ -553,28 +552,15 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
             acceleratePointer(pDev, first_valuator, num_valuators,
                               valuators);
 
-        if (pDev->coreEvents) {
-            if (first_valuator == 0 && num_valuators >= 1)
-                x = cp->valuator->lastx + valuators[0];
-            else
-                x = cp->valuator->lastx;
+        if (first_valuator == 0 && num_valuators >= 1)
+            x = pointer->valuator->lastx + valuators[0];
+        else
+            x = pointer->valuator->lastx;
 
-            if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-                y = cp->valuator->lasty + valuators[1 - first_valuator];
-            else
-                y = cp->valuator->lasty;
-        }
-        else {
-            if (first_valuator == 0 && num_valuators >= 1)
-                x = pDev->valuator->lastx + valuators[0];
-            else
-                x = pDev->valuator->lastx;
-
-            if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-                y = pDev->valuator->lasty + valuators[1 - first_valuator];
-            else
-                y = pDev->valuator->lasty;
-        }
+        if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
+            y = pointer->valuator->lasty + valuators[1 - first_valuator];
+        else
+            y = pointer->valuator->lasty;
     }
 
     /* Clip both x and y to the defined limits (usually co-ord space limit). */
@@ -596,8 +582,9 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons,
     updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators);
 
     if (pDev->coreEvents) {
-        cp->valuator->lastx = x;
-        cp->valuator->lasty = y;
+        /* set the virtual core pointer's coordinates */
+        pointer->valuator->lastx = x;
+        pointer->valuator->lasty = y;
     }
     pDev->valuator->lastx = x;
     pDev->valuator->lasty = y;
commit bffb1f9b67c8d3d264c0c3fd703cf7e57dcdf7b7
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 15 17:53:13 2006 +1030

    removed unused variables drag and local from xf86PostMotionEvent

diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index be3368d..50df566 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -434,8 +434,6 @@ xf86PostMotionEvent(DeviceIntPtr	device,
 {
     va_list var;
     int i = 0, nevents = 0;
-    Bool drag = xf86SendDragEvents(device);
-    LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate;
     int *valuators = NULL;
     int flags = 0;
 
commit f737cd925efe452787443b039ae65b8d85081bb3
Author: Peter Hutterer <peter at cs.unisa.edu.au>
Date:   Wed Nov 15 17:50:02 2006 +1030

    o fix minor error in comment for GetPointerEvents()

diff --git a/dix/getevents.c b/dix/getevents.c
index c1b8840..a888df6 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -473,7 +473,7 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type,
 
 
 /**
- * Generate a series of xEvents (returned in xE) representing pointer
+ * Generate a series of xEvents (returned in events) representing pointer
  * motion, or button presses.  Xi and XKB-aware.
  *
  * events is not NULL-terminated; the return value is the number of events.


More information about the xorg-commit mailing list