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 compati