File xserver-NOMAD.diff of Package xorg-x11-server-dmx

diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c
index b690593..b0a16cf 100644
--- a/Xext/panoramiX.c
+++ b/Xext/panoramiX.c
@@ -53,9 +53,18 @@ Equipment Corporation.
 #include "globals.h"
 #include "servermd.h"
 #include "resource.h"
+#ifdef MITSHM
+#include "shmint.h"
+#endif
 #ifdef RENDER
 #include "picturestr.h"
 #endif
+#ifdef XFIXES
+#include "xfixesint.h"
+#endif
+#ifdef COMPOSITE
+#include "compint.h"
+#endif
 #include "modinit.h"
 
 
@@ -577,9 +586,19 @@ void PanoramiXExtensionInit(int argc, char *argv[])
     ProcVector[X_StoreColors] = PanoramiXStoreColors;    
     ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor;    
 
+#ifdef MITSHM
+    PanoramiXShmInit ();
+#endif
 #ifdef RENDER
     PanoramiXRenderInit ();
 #endif
+#ifdef XFIXES
+    PanoramiXFixesInit ();
+#endif
+#ifdef COMPOSITE
+    PanoramiXCompositeInit ();
+#endif
+
 }
 
 extern Bool CreateConnectionBlock(void);
@@ -888,6 +907,9 @@ static void PanoramiXResetProc(ExtensionEntry* extEntry)
 #ifdef RENDER
     PanoramiXRenderReset ();
 #endif
+#ifdef XFIXES
+    PanoramiXFixesReset ();
+#endif
     screenInfo.numScreens = PanoramiXNumScreens;
     for (i = 256; i--; )
 	ProcVector[i] = SavedProcVector[i];
diff --git a/Xext/panoramiX.h b/Xext/panoramiX.h
index 89c7547..c4928b2 100644
--- a/Xext/panoramiX.h
+++ b/Xext/panoramiX.h
@@ -69,7 +69,8 @@ typedef struct {
 	} pix;
 #ifdef RENDER
 	struct {
-	    Bool root;
+	    char root;
+	    char sourcePict;
 	} pict;
 #endif
 	char raw_data[4];
diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
index 38199a5..7518927 100644
--- a/Xext/panoramiXprocs.c
+++ b/Xext/panoramiXprocs.c
@@ -981,18 +981,20 @@ int PanoramiXCopyArea(ClientPtr client)
     Bool		srcIsRoot = FALSE;
     Bool		dstIsRoot = FALSE;
     Bool		srcShared, dstShared;
+    Bool		getImageData = FALSE;
+    DrawablePtr		srcDrawables[MAXSCREENS];
     REQUEST(xCopyAreaReq);
 
     REQUEST_SIZE_MATCH(xCopyAreaReq);
 
     if(!(src = (PanoramiXRes *)SecurityLookupIDByClass(
-		client, stuff->srcDrawable, XRC_DRAWABLE, DixReadAccess)))
+	     client, stuff->srcDrawable, XRC_DRAWABLE, DixReadAccess)))
 	return BadDrawable;
 
     srcShared = IS_SHARED_PIXMAP(src);
 
     if(!(dst = (PanoramiXRes *)SecurityLookupIDByClass(
-		client, stuff->dstDrawable, XRC_DRAWABLE, DixWriteAccess)))
+	     client, stuff->dstDrawable, XRC_DRAWABLE, DixWriteAccess)))
 	return BadDrawable;
 
     dstShared = IS_SHARED_PIXMAP(dst);
@@ -1000,6 +1002,17 @@ int PanoramiXCopyArea(ClientPtr client)
     if(dstShared && srcShared)
 	return (* SavedProcVector[X_CopyArea])(client);
 
+    if (stuff->dstDrawable != stuff->srcDrawable) {
+	int rc;
+
+	FOR_NSCREENS(j) {
+	    rc = dixLookupDrawable(srcDrawables+j, src->info[j].id, client, 0,
+				   DixGetAttrAccess);
+	    if (rc != Success)
+		return rc;
+	}
+    }
+
     if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
 		client, stuff->gc, XRT_GC, DixReadAccess)))
 	return BadGC;
@@ -1011,32 +1024,34 @@ int PanoramiXCopyArea(ClientPtr client)
 
     srcx = stuff->srcX; srcy = stuff->srcY;
     dstx = stuff->dstX; dsty = stuff->dstY;
+
     if((dst->type == XRT_PIXMAP) && (src->type == XRT_WINDOW)) {
-	DrawablePtr drawables[MAXSCREENS];
+	WindowPtr pWin = (WindowPtr) srcDrawables[0];
+
+	/* no need to use GetImageData if window is redirected */
+	for (getImageData = TRUE; pWin && getImageData; pWin = pWin->parent)
+	    if (pWin->redirectDraw != RedirectDrawNone)
+		getImageData = FALSE;
+    }
+
+    if(getImageData) {
 	DrawablePtr pDst;
 	GCPtr pGC;
         char *data;
-	int pitch, rc;
-
-	FOR_NSCREENS(j) {
-	    rc = dixLookupDrawable(drawables+j, src->info[j].id, client, 0,
-				   DixGetAttrAccess);
-	    if (rc != Success)
-		return rc;
-	}
+	int pitch;
 
-	pitch = PixmapBytePad(stuff->width, drawables[0]->depth); 
+	pitch = PixmapBytePad(stuff->width, srcDrawables[0]->depth); 
 	if(!(data = xcalloc(1, stuff->height * pitch)))
 	    return BadAlloc;
 
-	XineramaGetImageData(drawables, srcx, srcy, 
+	XineramaGetImageData(srcDrawables, srcx, srcy, 
 		stuff->width, stuff->height, ZPixmap, ~0, data, pitch, 
 		srcIsRoot);
 
 	FOR_NSCREENS_BACKWARD(j) {
 	    stuff->gc = gc->info[j].id;
 	    VALIDATE_DRAWABLE_AND_GC(dst->info[j].id, pDst, DixWriteAccess);
-	    if(drawables[0]->depth != pDst->depth) {
+	    if(srcDrawables[0]->depth != pDst->depth) {
 		client->errorValue = stuff->dstDrawable;
 		xfree(data);
 		return (BadMatch);
@@ -1056,7 +1071,6 @@ int PanoramiXCopyArea(ClientPtr client)
 	DrawablePtr pDst = NULL, pSrc = NULL;
 	GCPtr pGC = NULL;
 	RegionPtr pRgn[MAXSCREENS];
-	int rc;
 
 	FOR_NSCREENS_BACKWARD(j) {
 	    stuff->dstDrawable = dst->info[j].id;
@@ -1074,11 +1088,7 @@ int PanoramiXCopyArea(ClientPtr client)
 	    VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
 
 	    if (stuff->dstDrawable != stuff->srcDrawable) {
-		rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
-				       DixReadAccess);
-		if (rc != Success)
-		    return rc;
-
+		pSrc = srcDrawables[j];
 		if ((pDst->pScreen != pSrc->pScreen) || 
 		    (pDst->depth != pSrc->depth)) {
 			client->errorValue = stuff->dstDrawable;
@@ -1749,6 +1759,7 @@ int PanoramiXGetImage(ClientPtr client)
 {
     DrawablePtr 	drawables[MAXSCREENS];
     DrawablePtr 	pDraw;
+    WindowPtr		pWin;
     PanoramiXRes	*draw;
     xGetImageReply	xgi;
     Bool		isRoot;
@@ -1782,6 +1793,11 @@ int PanoramiXGetImage(ClientPtr client)
     if(!((WindowPtr)pDraw)->realized)
 	return(BadMatch);
 
+    /* bits for redirected windows are available on all screens */
+    for (pWin = (WindowPtr) pDraw; pWin; pWin = pWin->parent)
+	if (pWin->redirectDraw != RedirectDrawNone)
+	    return (*SavedProcVector[X_GetImage])(client);
+
     x = stuff->x;
     y = stuff->y;
     w = stuff->width;
diff --git a/Xext/shm.c b/Xext/shm.c
index 6465edb..f22496c 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -90,16 +90,9 @@ in this Software without prior written authorization from The Open Group.
 #include "panoramiXsrv.h"
 #endif
 
-#include "modinit.h"
+int (*PanoramiXSaveShmVector[ShmNumberRequests])(ClientPtr);
 
-typedef struct _ShmDesc {
-    struct _ShmDesc *next;
-    int shmid;
-    int refcnt;
-    char *addr;
-    Bool writable;
-    unsigned long size;
-} ShmDescRec, *ShmDescPtr;
+#include "modinit.h"
 
 static void miShmPutImage(XSHM_PUT_IMAGE_ARGS);
 static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS);
@@ -132,7 +125,25 @@ static DISPATCH_PROC(SProcShmGetImage);
 static DISPATCH_PROC(SProcShmPutImage);
 static DISPATCH_PROC(SProcShmQueryVersion);
 
-static unsigned char ShmReqCode;
+int (*ProcShmVector[ShmNumberRequests])(ClientPtr) = {
+    ProcShmQueryVersion,
+    ProcShmAttach,
+    ProcShmDetach,
+    ProcShmPutImage,
+    ProcShmGetImage,
+    ProcShmCreatePixmap
+};
+
+int (*SProcShmVector[ShmNumberRequests])(ClientPtr) = {
+    SProcShmQueryVersion,
+    SProcShmAttach,
+    SProcShmDetach,
+    SProcShmPutImage,
+    SProcShmGetImage,
+    SProcShmCreatePixmap
+};
+
+_X_EXPORT unsigned char ShmReqCode;
 _X_EXPORT int ShmCompletionCode;
 _X_EXPORT int BadShmSegCode;
 _X_EXPORT RESTYPE ShmSegType;
@@ -146,37 +157,6 @@ static DevPrivateKey shmPixmapPrivate = &shmPixmapPrivate;
 static ShmFuncs miFuncs = {NULL, miShmPutImage};
 static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage};
 
-#define VERIFY_SHMSEG(shmseg,shmdesc,client) \
-{ \
-    shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \
-    if (!shmdesc) \
-    { \
-	client->errorValue = shmseg; \
-	return BadShmSegCode; \
-    } \
-}
-
-#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
-{ \
-    VERIFY_SHMSEG(shmseg, shmdesc, client); \
-    if ((offset & 3) || (offset > shmdesc->size)) \
-    { \
-	client->errorValue = offset; \
-	return BadValue; \
-    } \
-    if (needwrite && !shmdesc->writable) \
-	return BadAccess; \
-}
-
-#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \
-{ \
-    if ((offset + len) > shmdesc->size) \
-    { \
-	return BadAccess; \
-    } \
-}
-
-
 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
 #include <sys/signal.h>
 
@@ -591,7 +571,7 @@ ProcPanoramiXShmPutImage(ClientPtr client)
     orig_y = stuff->dstY;
     sendEvent = stuff->sendEvent;
     stuff->sendEvent = 0;
-    FOR_NSCREENS(j) {
+    FOR_NSCREENS_BACKWARD(j) {
 	if(!j) stuff->sendEvent = sendEvent;
 	stuff->drawable = draw->info[j].id;
 	stuff->gc = gc->info[j].id;
@@ -599,7 +579,7 @@ ProcPanoramiXShmPutImage(ClientPtr client)
 	    stuff->dstX = orig_x - panoramiXdataPtr[j].x;
 	    stuff->dstY = orig_y - panoramiXdataPtr[j].y;
 	}
-	result = ProcShmPutImage(client);
+	result = (*PanoramiXSaveShmVector[X_ShmPutImage])(client);
 	if(result != client->noClientException) break;
     }
     return(result);
@@ -611,6 +591,7 @@ ProcPanoramiXShmGetImage(ClientPtr client)
     PanoramiXRes	*draw;
     DrawablePtr 	drawables[MAXSCREENS];
     DrawablePtr 	pDraw;
+    WindowPtr		pWin;
     xShmGetImageReply	xgi;
     ShmDescPtr		shmdesc;
     int         	i, x, y, w, h, format, rc;
@@ -632,13 +613,18 @@ ProcPanoramiXShmGetImage(ClientPtr client)
 	return BadDrawable;
 
     if (draw->type == XRT_PIXMAP)
-	return ProcShmGetImage(client);
+	return (*PanoramiXSaveShmVector[X_ShmGetImage])(client);
 
     rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
 			   DixReadAccess);
     if (rc != Success)
 	return rc;
 
+    /* bits for redirected windows are available on all screens */
+    for (pWin = (WindowPtr) pDraw; pWin; pWin = pWin->parent)
+	if (pWin->redirectDraw != RedirectDrawNone)
+	    return (*PanoramiXSaveShmVector[X_ShmGetImage])(client);
+
     VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
 
     x = stuff->x;
@@ -1160,35 +1146,11 @@ static int
 ProcShmDispatch (ClientPtr client)
 {
     REQUEST(xReq);
-    switch (stuff->data)
-    {
-    case X_ShmQueryVersion:
-	return ProcShmQueryVersion(client);
-    case X_ShmAttach:
-	return ProcShmAttach(client);
-    case X_ShmDetach:
-	return ProcShmDetach(client);
-    case X_ShmPutImage:
-#ifdef PANORAMIX
-        if ( !noPanoramiXExtension )
-	   return ProcPanoramiXShmPutImage(client);
-#endif
-	return ProcShmPutImage(client);
-    case X_ShmGetImage:
-#ifdef PANORAMIX
-        if ( !noPanoramiXExtension )
-	   return ProcPanoramiXShmGetImage(client);
-#endif
-	return ProcShmGetImage(client);
-    case X_ShmCreatePixmap:
-#ifdef PANORAMIX
-        if ( !noPanoramiXExtension )
-	   return ProcPanoramiXShmCreatePixmap(client);
-#endif
-	   return ProcShmCreatePixmap(client);
-    default:
+
+    if (stuff->data < ShmNumberRequests)
+	return (*ProcShmVector[stuff->data]) (client);
+    else
 	return BadRequest;
-    }
 }
 
 static void
@@ -1210,7 +1172,7 @@ SProcShmQueryVersion(ClientPtr client)
     REQUEST(xShmQueryVersionReq);
 
     swaps(&stuff->length, n);
-    return ProcShmQueryVersion(client);
+    return (*ProcShmVector[stuff->shmReqType])(client);
 }
 
 static int
@@ -1222,7 +1184,7 @@ SProcShmAttach(ClientPtr client)
     REQUEST_SIZE_MATCH(xShmAttachReq);
     swapl(&stuff->shmseg, n);
     swapl(&stuff->shmid, n);
-    return ProcShmAttach(client);
+    return (*ProcShmVector[stuff->shmReqType])(client);
 }
 
 static int
@@ -1233,7 +1195,7 @@ SProcShmDetach(ClientPtr client)
     swaps(&stuff->length, n);
     REQUEST_SIZE_MATCH(xShmDetachReq);
     swapl(&stuff->shmseg, n);
-    return ProcShmDetach(client);
+    return (*ProcShmVector[stuff->shmReqType])(client);
 }
 
 static int
@@ -1255,7 +1217,7 @@ SProcShmPutImage(ClientPtr client)
     swaps(&stuff->dstY, n);
     swapl(&stuff->shmseg, n);
     swapl(&stuff->offset, n);
-    return ProcShmPutImage(client);
+    return (*ProcShmVector[stuff->shmReqType])(client);
 }
 
 static int
@@ -1273,7 +1235,7 @@ SProcShmGetImage(ClientPtr client)
     swapl(&stuff->planeMask, n);
     swapl(&stuff->shmseg, n);
     swapl(&stuff->offset, n);
-    return ProcShmGetImage(client);
+    return (*ProcShmVector[stuff->shmReqType])(client);
 }
 
 static int
@@ -1289,28 +1251,45 @@ SProcShmCreatePixmap(ClientPtr client)
     swaps(&stuff->height, n);
     swapl(&stuff->shmseg, n);
     swapl(&stuff->offset, n);
-    return ProcShmCreatePixmap(client);
+    return (*ProcShmVector[stuff->shmReqType])(client);
 }
 
 static int
 SProcShmDispatch (ClientPtr client)
 {
     REQUEST(xReq);
-    switch (stuff->data)
-    {
-    case X_ShmQueryVersion:
-	return SProcShmQueryVersion(client);
-    case X_ShmAttach:
-	return SProcShmAttach(client);
-    case X_ShmDetach:
-	return SProcShmDetach(client);
-    case X_ShmPutImage:
-	return SProcShmPutImage(client);
-    case X_ShmGetImage:
-	return SProcShmGetImage(client);
-    case X_ShmCreatePixmap:
-	return SProcShmCreatePixmap(client);
-    default:
+
+    if (stuff->data < ShmNumberRequests)
+	return (*SProcShmVector[stuff->data]) (client);
+    else
 	return BadRequest;
-    }
 }
+
+#ifdef PANORAMIX
+
+void
+PanoramiXShmInit (void)
+{
+    int i;
+    
+    for (i = 0; i < ShmNumberRequests; i++)
+	PanoramiXSaveShmVector[i] = ProcShmVector[i];
+
+    /*
+     * Stuff in Xinerama aware request processing hooks
+     */
+    ProcShmVector[X_ShmPutImage]     = ProcPanoramiXShmPutImage;
+    ProcShmVector[X_ShmGetImage]     = ProcPanoramiXShmGetImage;
+    ProcShmVector[X_ShmCreatePixmap] = ProcPanoramiXShmCreatePixmap;
+}
+
+void
+PanoramiXShmReset (void)
+{
+    int i;
+
+    for (i = 0; i < ShmNumberRequests; i++)
+	ProcShmVector[i] = PanoramiXSaveShmVector[i];
+}
+
+#endif	/* PANORAMIX */
diff --git a/Xext/shmint.h b/Xext/shmint.h
index 33ab6a4..eb7c0f5 100644
--- a/Xext/shmint.h
+++ b/Xext/shmint.h
@@ -30,6 +30,54 @@
 #include "pixmap.h"
 #include "gc.h"
 
+#ifndef ShmNumberRequests
+#define ShmNumberRequests (X_ShmCreatePixmap + 1)
+#endif
+
+typedef struct _ShmDesc {
+    struct _ShmDesc *next;
+    int shmid;
+    int refcnt;
+    char *addr;
+    Bool writable;
+    unsigned long size;
+} ShmDescRec, *ShmDescPtr;
+
+extern unsigned char ShmReqCode;
+extern int ShmCompletionCode;
+extern int BadShmSegCode;
+extern RESTYPE ShmSegType;
+
+#define VERIFY_SHMSEG(shmseg,shmdesc,client) \
+{ \
+    shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \
+    if (!shmdesc) \
+    { \
+	client->errorValue = shmseg; \
+	return BadShmSegCode; \
+    } \
+}
+
+#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
+{ \
+    VERIFY_SHMSEG(shmseg, shmdesc, client); \
+    if ((offset & 3) || (offset > shmdesc->size)) \
+    { \
+	client->errorValue = offset; \
+	return BadValue; \
+    } \
+    if (needwrite && !shmdesc->writable) \
+	return BadAccess; \
+}
+
+#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \
+{ \
+    if ((offset + len) > shmdesc->size) \
+    { \
+	return BadAccess; \
+    } \
+}
+
 void
 ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
 
@@ -42,4 +90,9 @@ fbShmPutImage(XSHM_PUT_IMAGE_ARGS);
 void
 ShmRegisterFbFuncs(ScreenPtr pScreen);
 
+#ifdef PANORAMIX
+void PanoramiXShmInit (void);
+void PanoramiXShmReset (void);
+#endif
+
 #endif /* _SHMINT_H_ */
diff --git a/composite/compext.c b/composite/compext.c
index 154f719..341e002 100644
--- a/composite/compext.c
+++ b/composite/compext.c
@@ -143,6 +143,7 @@ ProcCompositeRedirectWindow (ClientPtr client)
     REQUEST(xCompositeRedirectWindowReq);
 
     REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
+
     rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, client,
 			   DixSetAttrAccess|DixManageAccess|DixBlendAccess);
     if (rc != Success)
@@ -161,6 +162,7 @@ ProcCompositeRedirectSubwindows (ClientPtr client)
     REQUEST(xCompositeRedirectSubwindowsReq);
 
     REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
+
     rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, client,
 			   DixSetAttrAccess|DixManageAccess|DixBlendAccess);
     if (rc != Success)
@@ -178,6 +180,7 @@ ProcCompositeUnredirectWindow (ClientPtr client)
     REQUEST(xCompositeUnredirectWindowReq);
 
     REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
+
     pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
     if (!pWin)
     {
@@ -194,6 +197,7 @@ ProcCompositeUnredirectSubwindows (ClientPtr client)
     REQUEST(xCompositeUnredirectSubwindowsReq);
 
     REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
+
     pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
     if (!pWin)
     {
@@ -249,6 +253,7 @@ ProcCompositeNameWindowPixmap (ClientPtr client)
     REQUEST(xCompositeNameWindowPixmapReq);
 
     REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
+
     rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, client,
 			   DixGetAttrAccess);
     if (rc != Success)
@@ -297,6 +302,7 @@ ProcCompositeGetOverlayWindow (ClientPtr client)
     int rc;
 
     REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
+
     rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, client,
 			   DixGetAttrAccess);
     if (rc != Success)
@@ -359,6 +365,7 @@ ProcCompositeReleaseOverlayWindow (ClientPtr client)
     CompOverlayClientPtr pOc;
 
     REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
+
     pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
     if (!pWin)
     {
@@ -381,7 +388,7 @@ ProcCompositeReleaseOverlayWindow (ClientPtr client)
     return client->noClientException;
 }
 
-static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
+int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
     ProcCompositeQueryVersion,
     ProcCompositeRedirectWindow,
     ProcCompositeRedirectSubwindows,
@@ -565,13 +572,6 @@ CompositeExtensionInit (void)
 	if (GetPictureScreenIfSet(pScreen) == NULL)
 	    return;
     }
-#ifdef PANORAMIX
-    /* Xinerama's rewriting of window drawing before Composite gets to it
-     * breaks Composite.
-     */
-    if (!noPanoramiXExtension)
-	return;
-#endif
 
     CompositeClientWindowType = CreateNewResourceType (FreeCompositeClientWindow);
     if (!CompositeClientWindowType)
@@ -607,3 +607,357 @@ CompositeExtensionInit (void)
     /* Initialization succeeded */
     noCompositeExtension = FALSE;
 }
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+extern unsigned long XRT_PIXMAP;
+extern unsigned long XRT_WINDOW;
+extern int           PanoramiXNumScreens;
+
+int (*PanoramiXSaveCompositeVector[CompositeNumberRequests]) (ClientPtr);
+
+static int
+PanoramiXCompositeRedirectWindow (ClientPtr client)
+{
+    PanoramiXRes *win;
+    int rc = 0, j;
+    REQUEST(xCompositeRedirectWindowReq);
+
+    REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
+
+    if(!(win = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->window, XRT_WINDOW, DixUnknownAccess)))
+	return BadWindow;
+
+    FOR_NSCREENS_FORWARD(j) {
+	stuff->window = win->info[j].id;
+	rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
+	if (rc != Success) break;
+    }
+
+    return (rc);
+}
+
+static int
+PanoramiXCompositeRedirectSubwindows (ClientPtr client)
+{
+    PanoramiXRes *win;
+    int rc = 0, j;
+    REQUEST(xCompositeRedirectSubwindowsReq);
+
+    REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
+
+    if(!(win = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->window, XRT_WINDOW, DixUnknownAccess)))
+	return BadWindow;
+
+    FOR_NSCREENS_FORWARD(j) {
+	stuff->window = win->info[j].id;
+	rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
+	if (rc != Success) break;
+    }
+
+    return (rc);
+}
+
+static int
+PanoramiXCompositeUnredirectWindow (ClientPtr client)
+{
+    PanoramiXRes *win;
+    int rc = 0, j;
+    REQUEST(xCompositeUnredirectWindowReq);
+
+    REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
+
+    if(!(win = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->window, XRT_WINDOW, DixUnknownAccess)))
+	return BadWindow;
+
+    FOR_NSCREENS_FORWARD(j) {
+	stuff->window = win->info[j].id;
+	rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
+	if (rc != Success) break;
+    }
+
+    return (rc);
+}
+
+static int
+PanoramiXCompositeUnredirectSubwindows (ClientPtr client)
+{
+    PanoramiXRes *win;
+    int rc = 0, j;
+    REQUEST(xCompositeUnredirectSubwindowsReq);
+
+    REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
+
+    if(!(win = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->window, XRT_WINDOW, DixUnknownAccess)))
+	return BadWindow;
+
+    FOR_NSCREENS_FORWARD(j) {
+	rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client);
+	if (rc != Success) break;
+    }
+
+    return (rc);
+}
+
+static int
+PanoramiXCompositeNameWindowPixmap (ClientPtr client)
+{
+    WindowPtr	    pWin;
+    CompWindowPtr   cw;
+    PixmapPtr	    pPixmap;
+    int rc;
+    PanoramiXRes *win, *newPix;
+    int i;
+    REQUEST(xCompositeNameWindowPixmapReq);
+
+    REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
+
+    if(!(win = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->window, XRT_WINDOW, DixUnknownAccess)))
+    {
+	client->errorValue = stuff->window;
+	return BadWindow;
+    }
+
+    if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes))))
+	return BadAlloc;
+
+    LEGAL_NEW_RESOURCE (stuff->pixmap, client);
+
+    newPix->type = XRT_PIXMAP;
+    newPix->u.pix.shared = FALSE;
+    newPix->info[0].id = stuff->pixmap;
+
+    for (i = 1; i < PanoramiXNumScreens; i++)
+	newPix->info[i].id = FakeClientID (client->index);
+
+    FOR_NSCREENS(i) {
+	rc = dixLookupResource ((pointer *) &pWin,
+				win->info[i].id, RT_WINDOW, client,
+				DixGetAttrAccess);
+	if (rc != Success)
+	{
+	    client->errorValue = stuff->window;
+	    xfree (newPix);
+	    return (rc == BadValue) ? BadWindow : rc;
+	}
+
+	if (!pWin->viewable)
+	{
+	    xfree (newPix);
+	    return BadMatch;
+	}
+
+	cw = GetCompWindow (pWin);
+	if (!cw)
+	{
+	    xfree (newPix);
+	    return BadMatch;
+	}
+
+	pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+	if (!pPixmap)
+	{
+	    xfree (newPix);
+	    return BadMatch;
+	}
+
+	if (!AddResource (newPix->info[i].id, RT_PIXMAP,
+			  (pointer) pPixmap))
+	    return BadAlloc;
+
+	++pPixmap->refcnt;
+    }
+
+    if (!AddResource (stuff->pixmap, XRT_PIXMAP, (pointer) newPix))
+	return BadAlloc;
+
+    return (client->noClientException);
+}
+
+
+static int
+PanoramiXCompositeGetOverlayWindow (ClientPtr client)
+{
+    REQUEST(xCompositeGetOverlayWindowReq);
+    xCompositeGetOverlayWindowReply rep;
+    WindowPtr pWin;
+    ScreenPtr pScreen;
+    CompScreenPtr cs;
+    CompOverlayClientPtr pOc;
+    int rc;
+    PanoramiXRes *win, *overlayWin = NULL;
+    int i;
+
+    REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
+
+    if(!(win = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->window, XRT_WINDOW, DixUnknownAccess)))
+    {
+	client->errorValue = stuff->window;
+	return BadWindow;
+    }
+
+    cs = GetCompScreen(screenInfo.screens[0]);
+    if (!cs->pOverlayWin)
+    {
+	if(!(overlayWin = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes))))
+	    return BadAlloc;
+
+	overlayWin->type = XRT_WINDOW;
+	overlayWin->u.win.root = FALSE;
+    }
+
+    FOR_NSCREENS_BACKWARD(i) {
+	rc = dixLookupResource((pointer *)&pWin, win->info[i].id,
+			       RT_WINDOW, client,
+			       DixGetAttrAccess);
+	if (rc != Success)
+	{
+	    client->errorValue = stuff->window;
+	    return (rc == BadValue) ? BadWindow : rc;
+	}
+	pScreen = pWin->drawable.pScreen;
+
+	/*
+	 * Create an OverlayClient structure to mark this client's
+	 * interest in the overlay window
+	 */
+	pOc = compCreateOverlayClient(pScreen, client);
+	if (pOc == NULL)
+	    return BadAlloc;
+
+	/*
+	 * Make sure the overlay window exists
+	 */
+	cs = GetCompScreen(pScreen);
+	if (cs->pOverlayWin == NULL)
+	    if (!compCreateOverlayWindow(pScreen))
+	    {
+		FreeResource (pOc->resource, RT_NONE);
+		return BadAlloc;
+	    }
+
+	rc = XaceHook(XACE_RESOURCE_ACCESS, client,
+		      cs->pOverlayWin->drawable.id,
+		      RT_WINDOW, cs->pOverlayWin, RT_NONE, NULL,
+		      DixGetAttrAccess);
+	if (rc != Success)
+	{
+	    FreeResource (pOc->resource, RT_NONE);
+	    return rc;
+	}
+    }
+
+    if (overlayWin)
+    {
+	FOR_NSCREENS(i) {
+	    cs = GetCompScreen(screenInfo.screens[i]);
+	    overlayWin->info[i].id = cs->pOverlayWin->drawable.id;
+	}
+
+	AddResource(overlayWin->info[0].id, XRT_WINDOW, overlayWin);
+    }
+
+    cs = GetCompScreen(screenInfo.screens[0]);
+
+    rep.type = X_Reply;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    rep.overlayWin = cs->pOverlayWin->drawable.id;
+
+    if (client->swapped)
+    {
+	int n;
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.overlayWin, n);
+    }
+    (void) WriteToClient(client, sz_xCompositeGetOverlayWindowReply, (char *)&rep);
+
+    return client->noClientException;
+}
+
+static int
+PanoramiXCompositeReleaseOverlayWindow (ClientPtr client)
+{
+    REQUEST(xCompositeReleaseOverlayWindowReq);
+    WindowPtr pWin;
+    ScreenPtr pScreen;
+    CompOverlayClientPtr pOc;
+    PanoramiXRes *win;
+    int i;
+
+    REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
+
+    if(!(win = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->window, XRT_WINDOW, DixUnknownAccess)))
+    {
+	client->errorValue = stuff->window;
+	return BadWindow;
+    }
+
+    FOR_NSCREENS_BACKWARD(i) {
+	pWin = (WindowPtr) LookupIDByType (win->info[i].id, RT_WINDOW);
+	if (!pWin)
+	{
+	    client->errorValue = stuff->window;
+	    return BadWindow;
+	}
+	pScreen = pWin->drawable.pScreen;
+
+	/*
+	 * Has client queried a reference to the overlay window
+	 * on this screen? If not, generate an error.
+	 */
+	pOc = compFindOverlayClient (pWin->drawable.pScreen, client);
+	if (pOc == NULL)
+	    return BadMatch;
+
+	/* The delete function will free the client structure */
+	FreeResource (pOc->resource, RT_NONE);
+    }
+
+    return client->noClientException;
+}
+
+void
+PanoramiXCompositeInit (void)
+{
+    int i;
+
+    for (i = 0; i < CompositeNumberRequests; i++)
+	PanoramiXSaveCompositeVector[i] = ProcCompositeVector[i];
+    /*
+     * Stuff in Xinerama aware request processing hooks
+     */
+    ProcCompositeVector[X_CompositeRedirectWindow] =
+	PanoramiXCompositeRedirectWindow;
+    ProcCompositeVector[X_CompositeRedirectSubwindows] =
+	PanoramiXCompositeRedirectSubwindows;
+    ProcCompositeVector[X_CompositeUnredirectWindow] =
+	PanoramiXCompositeUnredirectWindow;
+    ProcCompositeVector[X_CompositeUnredirectSubwindows] =
+	PanoramiXCompositeUnredirectSubwindows;
+    ProcCompositeVector[X_CompositeNameWindowPixmap] =
+	PanoramiXCompositeNameWindowPixmap;
+    ProcCompositeVector[X_CompositeGetOverlayWindow] =
+	PanoramiXCompositeGetOverlayWindow;
+    ProcCompositeVector[X_CompositeReleaseOverlayWindow] =
+	PanoramiXCompositeReleaseOverlayWindow;
+}
+
+void
+PanoramiXCompositeReset (void)
+{
+    int i;
+
+    for (i = 0; i < CompositeNumberRequests; i++)
+	ProcCompositeVector[i] = PanoramiXSaveCompositeVector[i];
+}
+
+#endif
diff --git a/composite/compint.h b/composite/compint.h
index 1c19ccd..ee6727a 100644
--- a/composite/compint.h
+++ b/composite/compint.h
@@ -319,4 +319,9 @@ CompositeRealChildHead (WindowPtr pWin);
 int
 DeleteWindowNoInputDevices(pointer value, XID wid);
 
+#ifdef PANORAMIX
+void PanoramiXCompositeInit (void);
+void PanoramiXCompositeReset (void);
+#endif
+
 #endif /* _COMPINT_H_ */
diff --git a/composite/compoverlay.c b/composite/compoverlay.c
index 94e5b03..ed5fe38 100644
--- a/composite/compoverlay.c
+++ b/composite/compoverlay.c
@@ -47,6 +47,10 @@
 #include "compint.h"
 #include "xace.h"
 
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+#endif
+
 /* 
  * Delete the given overlay client list element from its screen list.
  */
@@ -127,10 +131,20 @@ compCreateOverlayWindow (ScreenPtr pScreen)
     WindowPtr	    pWin;
     XID		    overrideRedirect = TRUE;
     int		    result;
+    int		    w = pScreen->width;
+    int		    h = pScreen->height;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	w = PanoramiXPixWidth;
+	h = PanoramiXPixHeight;
+    }
+#endif
 
     pWin = cs->pOverlayWin = 
 	CreateWindow (cs->overlayWid, pRoot,
-		      0, 0, pScreen->width, pScreen->height, 0, 
+		      0, 0, w, h, 0,
 		      InputOutput, CWOverrideRedirect, &overrideRedirect,
 		      pRoot->drawable.depth, 
 		      serverClient, pScreen->rootVisual, &result);
diff --git a/composite/compwindow.c b/composite/compwindow.c
index c1657bd..072f99e 100644
--- a/composite/compwindow.c
+++ b/composite/compwindow.c
@@ -46,6 +46,10 @@
 
 #include "compint.h"
 
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+#endif
+
 #ifdef COMPOSITE_DEBUG
 static int
 compCheckWindow (WindowPtr pWin, pointer data)
@@ -171,16 +175,26 @@ updateOverlayWindow(ScreenPtr pScreen)
 	CompScreenPtr cs;
 	WindowPtr pWin; /* overlay window */
 	XID vlist[2];
+	int w = pScreen->width;
+	int h = pScreen->height;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    w = PanoramiXPixWidth;
+	    h = PanoramiXPixHeight;
+	}
+#endif
 
 	cs = GetCompScreen(pScreen);
 	if ((pWin = cs->pOverlayWin) != NULL) {
-		if ((pWin->drawable.width == pScreen->width) &&
-			(pWin->drawable.height == pScreen->height))
+		if ((pWin->drawable.width == w) &&
+			(pWin->drawable.height == h))
 			return Success;
 
 		/* Let's resize the overlay window. */
-		vlist[0] = pScreen->width;
-		vlist[1] = pScreen->height;
+		vlist[0] = w;
+		vlist[1] = h;
 		return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin));
 	}
 
diff --git a/config/dbus-core.c b/config/dbus-core.c
index b349c6e..8b97e24 100644
--- a/config/dbus-core.c
+++ b/config/dbus-core.c
@@ -85,7 +85,7 @@ teardown(void)
      * completeness.  But then it gets awkward, given that you can't
      * guarantee that they'll be called ... */
     if (bus_info.connection)
-        dbus_connection_unref(bus_info.connection);
+        dbus_connection_close(bus_info.connection);
 
     RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, &bus_info);
     if (bus_info.fd != -1)
@@ -140,7 +140,7 @@ connect_to_bus(void)
     struct config_dbus_core_hook *hook;
 
     dbus_error_init(&error);
-    bus_info.connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+    bus_info.connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
     if (!bus_info.connection || dbus_error_is_set(&error)) {
         DebugF("[config/dbus-core] error connecting to system bus: %s (%s)\n",
                error.name, error.message);
diff --git a/configure.ac b/configure.ac
index 570a688..d816561 100644
--- a/configure.ac
+++ b/configure.ac
@@ -544,6 +544,7 @@ AC_ARG_ENABLE(dpms,           AS_HELP_STRING([--disable-dpms], [Build DPMS exten
 AC_ARG_ENABLE(config-dbus,    AS_HELP_STRING([--enable-config-dbus], [Build D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=no])
 AC_ARG_ENABLE(config-hal,     AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto])
 AC_ARG_ENABLE(xfree86-utils,     AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes])
+AC_ARG_ENABLE(avahi,   AS_HELP_STRING([--disable-avahi], [Build Avahi support (default: auto)]), [AVAHI=$enableval], [AVAHI=no])
 
 dnl DDXes.
 AC_ARG_ENABLE(xorg,    	      AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -707,6 +708,12 @@ fi
 AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes])
 CONFIG_LIB='$(top_builddir)/config/libconfig.a'
 
+PKG_CHECK_MODULES(AVAHI, avahi-client, [HAVE_AVAHI=yes], [HAVE_AVAHI=no])
+if test "x$HAVE_AVAHI" = xyes; then
+        AC_DEFINE(HAVE_AVAHI, 1, [Have Avahi suppport])
+fi
+AM_CONDITIONAL(HAVE_AVAHI, [test "x$HAVE_AVAHI" = xyes])
+
 AC_MSG_CHECKING([for glibc...])
 AC_PREPROC_IFELSE([
 #include <features.h>
@@ -1565,8 +1572,7 @@ AM_CONDITIONAL(XQUARTZ, [test "x$XQUARTZ" = xyes])
 
 dnl DMX DDX
 
-PKG_CHECK_MODULES([DMXMODULES], [xmuu xext x11 xrender xfixes xfont xi dmxproto xau $XDMCP_MODULES], [have_dmx=yes], [have_dmx=no])
-AC_MSG_CHECKING([whether to build Xdmx DDX])
+PKG_CHECK_MODULES([DMXMODULES], [xmuu xext x11 xrender xfixes xfont xi >= 1.1.99.1 dmxproto xau xcomposite xrandr xv x11-xcb xcb-randr xcb-xinput xcb-aux >= 0.2.1 xcb-image xcb-shape $XDMCP_MODULES], [have_dmx=yes], [have_dmx=no])
 if test "x$DMX" = xauto; then
 	DMX="$have_dmx"
 	case $host_os in
@@ -1584,24 +1590,14 @@ if test "x$DMX" = xyes; then
 	fi
 	DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
 	XDMX_CFLAGS="$DMXMODULES_CFLAGS"
-	XDMX_LIBS="$XEXT_LIB $FB_LIB $CONFIG_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB"
+	XDMX_LIBS="$DIX_LIB $CONFIG_LIB $COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $FB_LIB $RENDER_LIB $RANDR_LIB $RECORD_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $OS_LIB $MI_LIB"
 	XDMX_SYS_LIBS="$DMXMODULES_LIBS"
 	AC_SUBST([XDMX_CFLAGS])
 	AC_SUBST([XDMX_LIBS])
 	AC_SUBST([XDMX_SYS_LIBS])
-
-dnl USB sources in DMX require <linux/input.h>
-	AC_CHECK_HEADER([linux/input.h], DMX_BUILD_USB="yes",
-			DMX_BUILD_USB="no")
-dnl Linux sources in DMX require <linux/keyboard.h>
-	AC_CHECK_HEADER([linux/keyboard.h], DMX_BUILD_LNX="yes",
-			DMX_BUILD_LNX="no")
 	if test "x$GLX" = xyes; then
 		PKG_CHECK_MODULES([GL], [glproto])
 	fi
-	PKG_CHECK_MODULES([XDMXCONFIG_DEP], [xaw7 xmu xt xpm x11])
-	AC_SUBST(XDMXCONFIG_DEP_CFLAGS)
-	AC_SUBST(XDMXCONFIG_DEP_LIBS)
 	PKG_CHECK_MODULES([DMXEXAMPLES_DEP], [dmx xext x11])
 	AC_SUBST(DMXEXAMPLES_DEP_LIBS)
 	PKG_CHECK_MODULES([DMXXMUEXAMPLES_DEP], [dmx xmu xext x11])
@@ -1614,9 +1610,10 @@ dnl Linux sources in DMX require <linux/keyboard.h>
 	AC_SUBST(XRESEXAMPLES_DEP_LIBS)
 	PKG_CHECK_MODULES([X11EXAMPLES_DEP], [xext x11])
 	AC_SUBST(X11EXAMPLES_DEP_LIBS)
+	PKG_CHECK_MODULES([DBUSEXAMPLES_DEP], [dbus-1 xcb])
+        AC_SUBST(DBUSEXAMPLES_DEP_CFLAGS)
+	AC_SUBST(DBUSEXAMPLES_DEP_LIBS)
 fi
-AM_CONDITIONAL([DMX_BUILD_LNX], [test "x$DMX_BUILD_LNX" = xyes])
-AM_CONDITIONAL([DMX_BUILD_USB], [test "x$DMX_BUILD_USB" = xyes])
 
 dnl kdrive DDX
 
@@ -1864,10 +1861,8 @@ hw/xfree86/xf8_16bpp/Makefile
 hw/xfree86/utils/Makefile
 hw/xfree86/utils/cvt/Makefile
 hw/xfree86/utils/gtf/Makefile
-hw/dmx/config/Makefile
 hw/dmx/doc/Makefile
 hw/dmx/examples/Makefile
-hw/dmx/input/Makefile
 hw/dmx/glxProxy/Makefile
 hw/dmx/Makefile
 hw/vfb/Makefile
diff --git a/dix/events.c b/dix/events.c
index d6b3ecb..d4e5a35 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -647,6 +647,7 @@ XineramaCheckVirtualMotion(
 static Bool
 XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 {
+    INT16     *rootX, *rootY;
     WindowPtr prevSpriteWin;
     SpritePtr pSprite = pDev->spriteInfo->sprite;
 
@@ -654,15 +655,38 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 
     if (xE && !syncEvents.playingEvents)
     {
+	/* GetPointerEvents() guarantees that pointer events have the correct
+           rootX/Y set already. */
+        switch(xE->u.u.type)
+        {
+            case ButtonPress:
+            case ButtonRelease:
+            case MotionNotify:
+                rootX = &XE_KBPTR.rootX;
+                rootY = &XE_KBPTR.rootY;
+                break;
+            default:
+                if (xE->u.u.type == DeviceButtonPress ||
+		    xE->u.u.type == DeviceButtonRelease ||
+		    xE->u.u.type == DeviceMotionNotify)
+                {
+                    rootX = &((deviceKeyButtonPointer*)xE)->root_x;
+                    rootY = &((deviceKeyButtonPointer*)xE)->root_y;
+                    break;
+                }
+                /* all other events return FALSE */
+                return FALSE;
+        }
+
 	/* Motion events entering DIX get translated to Screen 0
 	   coordinates.  Replayed events have already been
 	   translated since they've entered DIX before */
-	XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
-			  panoramiXdataPtr[0].x;
-	XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y -
-			  panoramiXdataPtr[0].y;
-	pSprite->hot.x = XE_KBPTR.rootX;
-	pSprite->hot.y = XE_KBPTR.rootY;
+	*rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
+	    panoramiXdataPtr[0].x;
+	*rootY += panoramiXdataPtr[pSprite->screen->myNum].y -
+	    panoramiXdataPtr[0].y;
+	pSprite->hot.x = *rootX;
+        pSprite->hot.y = *rootY;
 	if (pSprite->hot.x < pSprite->physLimits.x1)
 	    pSprite->hot.x = pSprite->physLimits.x1;
 	else if (pSprite->hot.x >= pSprite->physLimits.x2)
@@ -676,14 +700,14 @@ XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
 	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
 
 	pSprite->hotPhys = pSprite->hot;
-	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
-	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
+	if ((pSprite->hotPhys.x != *rootX) ||
+	    (pSprite->hotPhys.y != *rootY))
 	{
 	    XineramaSetCursorPosition(
 			pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
 	}
-	XE_KBPTR.rootX = pSprite->hot.x;
-	XE_KBPTR.rootY = pSprite->hot.y;
+	*rootX = pSprite->hot.x;
+	*rootY = pSprite->hot.y;
     }
 
 #ifdef XEVIE
diff --git a/dix/window.c b/dix/window.c
index 14fccab..2487e27 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -2719,7 +2719,7 @@ EnableMapUnmapEvents(WindowPtr pWin)
     windowDisableMapUnmapEvents = NULL;
 }
 
-static Bool
+Bool
 MapUnmapEventsEnabled(WindowPtr pWin)
 {
     return pWin != windowDisableMapUnmapEvents;
diff --git a/hw/dmx/Makefile.am b/hw/dmx/Makefile.am
index 8457aea..53c1027 100644
--- a/hw/dmx/Makefile.am
+++ b/hw/dmx/Makefile.am
@@ -1,6 +1,6 @@
-DIST_SUBDIRS = input config glxProxy examples doc
+DIST_SUBDIRS = glxProxy examples doc
 
-SUBDIRS = input config examples
+SUBDIRS = examples
 bin_PROGRAMS = Xdmx
 
 if XINERAMA
@@ -20,11 +20,25 @@ if BUILDDOCS
 SUBDIRS += doc
 endif
 
+if CONFIG_DBUS_API
+DBUS_SRCS = dmxdbus.c dmxdbus.h
+DBUS_INCS = -I$(top_srcdir)/config
+DBUS_DEFS = @DBUS_CFLAGS@
+endif
+
+if HAVE_AVAHI
+AVAHI_SRCS = dmxavahi.c dmxavahi.h
+AVAHI_DEFS = @AVAHI_CFLAGS@
+endif
+
 AM_CFLAGS = \
       -DHAVE_DMX_CONFIG_H \
       $(DIX_CFLAGS) \
       $(GLX_INCS) \
       $(GLX_DEFS) \
+      $(DBUS_INCS) \
+      $(DBUS_DEFS) \
+      $(AVAHI_DEFS) \
       $(DMX_CFLAGS) \
       @DMXMODULES_CFLAGS@
 
@@ -62,8 +76,6 @@ Xdmx_SOURCES = dmx.c \
                dmxprop.h \
                dmxscrinit.c \
                dmxscrinit.h \
-               dmxshadow.c \
-               dmxshadow.h \
                dmxstat.c \
                dmxstat.h \
                dmxsync.c \
@@ -72,9 +84,29 @@ Xdmx_SOURCES = dmx.c \
                dmxvisual.h \
                dmxwindow.c \
                dmxwindow.h \
+               dmxatom.c \
+               dmxatom.h \
+               dmxlaunch.c \
+               dmxlaunch.h \
+               dmxshm.c \
+               dmxshm.h \
+               dmxcomp.c \
+               dmxcomp.h \
+               dmxrandr.c \
+               dmxrandr.h \
+               dmxxv.c \
+               dmxxv.h \
+               dmxgrab.c \
+               dmxgrab.h \
+               dmxselection.c \
+               dmxselection.h \
+               dmxdnd.c \
+               dmxdnd.h \
                $(top_srcdir)/mi/miinitext.c \
                $(top_srcdir)/fb/fbcmap_mi.c \
-               $(GLX_SRCS) 
+               $(GLX_SRCS) \
+               $(DBUS_SRCS) \
+               $(AVAHI_SRCS)
 
 
 #if COMPOSITE
@@ -84,9 +116,7 @@ Xdmx_SOURCES = dmx.c \
 XDMX_LIBS = \
 	@XDMX_LIBS@ \
 	$(GLX_LIBS) \
-        input/libdmxinput.a \
-        config/libdmxconfig.a \
-	$(XSERVER_LIBS)
+        $(AVAHI_LIBS)
 
 Xdmx_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
 Xdmx_DEPENDENCIES= $(XDMX_LIBS)
diff --git a/hw/dmx/dmx-config.h b/hw/dmx/dmx-config.h
index 5b7b605..2cfcd6f 100644
--- a/hw/dmx/dmx-config.h
+++ b/hw/dmx/dmx-config.h
@@ -74,15 +74,10 @@
 
 /* Disable the extensions that are not currently supported */
 #undef MULTIBUFFER
-#undef XV
 #undef DBE
 #undef XF86VIDMODE
 #undef XFreeXDGA
 #undef XF86DRI
 #undef SCREENSAVER
-#undef RANDR
-#undef XFIXES
-#undef DAMAGE
-#undef COMPOSITE
 
 #endif /* DMX_CONFIG_H */
diff --git a/hw/dmx/dmx.c b/hw/dmx/dmx.c
index 10d9e22..ae4be98 100644
--- a/hw/dmx/dmx.c
+++ b/hw/dmx/dmx.c
@@ -63,10 +63,21 @@
 
 #ifdef PANORAMIX
 #include "panoramiX.h"
+extern unsigned long XRC_DRAWABLE;
 extern unsigned long XRT_WINDOW;
 extern int           PanoramiXNumScreens;
 #endif
 
+#ifdef RANDR
+#include "randrstr.h"
+#endif
+
+#include "dmxdbus.h"
+
+#ifdef HAVE_AVAHI
+#include "dmxavahi.h"
+#endif
+
 extern void DMXExtensionInit(void);
 
 static unsigned char DMXCode;
@@ -113,19 +124,41 @@ static int _DMXXineramaActive(void)
     return 0;
 }
 
+static void DMXResetProc(ExtensionEntry *extEntry)
+{
+
+#ifdef HAVE_AVAHI
+    dmx_avahi_fini ();
+#endif
+
+#ifdef CONFIG_DBUS_API
+    dmx_dbus_fini ();
+#endif
+
+}
+
 /** Initialize the extension. */
 void DMXExtensionInit(void)
 {
     ExtensionEntry *extEntry;
-    
+
     if ((extEntry = AddExtension(DMX_EXTENSION_NAME, 0, 0,
                                  ProcDMXDispatch, SProcDMXDispatch,
-                                 NULL, StandardMinorOpcode)))
+                                 DMXResetProc, StandardMinorOpcode)))
 	DMXCode = extEntry->base;
+
+#ifdef CONFIG_DBUS_API
+    dmx_dbus_init ();
+#endif
+
+#ifdef HAVE_AVAHI
+    dmx_avahi_init ();
+#endif
+
 }
 
 static void dmxSetScreenAttribute(int bit, DMXScreenAttributesPtr attr,
-                                  CARD32 value)
+				  CARD32 value)
 {
     switch (1 << bit) {
     case DMXScreenWindowWidth:   attr->screenWindowWidth   = value; break;
@@ -142,25 +175,25 @@ static void dmxSetScreenAttribute(int bit, DMXScreenAttributesPtr attr,
 }
 
 static int dmxFetchScreenAttributes(unsigned int mask,
-                                    DMXScreenAttributesPtr attr,
-                                    CARD32 *value_list)
+				    DMXScreenAttributesPtr attr,
+				    CARD32 *value_list)
 {
     int    i;
     CARD32 *value = value_list;
     int    count  = 0;
-        
+
     for (i = 0; i < 32; i++) {
-        if (mask & (1 << i)) {
-            dmxSetScreenAttribute(i, attr, *value);
-            ++value;
-            ++count;
-        }
+	if (mask & (1 << i)) {
+	    dmxSetScreenAttribute(i, attr, *value);
+	    ++value;
+	    ++count;
+	}
     }
     return count;
 }
 
 static void dmxSetDesktopAttribute(int bit, DMXDesktopAttributesPtr attr,
-                                   CARD32 value)
+				   CARD32 value)
 {
     switch (1 << bit) {
     case DMXDesktopWidth:  attr->width  = value; break;
@@ -171,25 +204,25 @@ static void dmxSetDesktopAttribute(int bit, DMXDesktopAttributesPtr attr,
 }
 
 static int dmxFetchDesktopAttributes(unsigned int mask,
-                                     DMXDesktopAttributesPtr attr,
-                                     CARD32 *value_list)
+				     DMXDesktopAttributesPtr attr,
+				     CARD32 *value_list)
 {
     int    i;
     CARD32 *value = value_list;
     int    count  = 0;
-        
+
     for (i = 0; i < 32; i++) {
-        if (mask & (1 << i)) {
-            dmxSetDesktopAttribute(i, attr, *value);
+	if (mask & (1 << i)) {
+	    dmxSetDesktopAttribute(i, attr, *value);
 	    ++value;
-            ++count;
-        }
+	    ++count;
+	}
     }
     return count;
 }
 
 static void dmxSetInputAttribute(int bit, DMXInputAttributesPtr attr,
-                                 CARD32 value)
+				 CARD32 value)
 {
     switch (1 << bit) {
     case DMXInputType:           attr->inputType      = value;   break;
@@ -199,19 +232,19 @@ static void dmxSetInputAttribute(int bit, DMXInputAttributesPtr attr,
 }
 
 static int dmxFetchInputAttributes(unsigned int mask,
-                                   DMXInputAttributesPtr attr,
-                                   CARD32 *value_list)
+				   DMXInputAttributesPtr attr,
+				   CARD32 *value_list)
 {
     int    i;
     CARD32 *value = value_list;
     int    count  = 0;
 
     for (i = 0; i < 32; i++) {
-        if (mask & (1 << i)) {
-            dmxSetInputAttribute(i, attr, *value);
-            ++value;
-            ++count;
-        }
+	if (mask & (1 << i)) {
+	    dmxSetInputAttribute(i, attr, *value);
+	    ++value;
+	    ++count;
+	}
     }
     return count;
 }
@@ -231,7 +264,7 @@ static int ProcDMXQueryVersion(ClientPtr client)
     rep.patchVersion   = DMX_EXTENSION_PATCH;
     if (client->swapped) {
     	swaps(&rep.sequenceNumber, n);
-        swapl(&rep.length, n);
+	swapl(&rep.length, n);
 	swapl(&rep.majorVersion, n);
 	swapl(&rep.minorVersion, n);
 	swapl(&rep.patchVersion, n);
@@ -254,9 +287,9 @@ static int ProcDMXSync(ClientPtr client)
     rep.length         = 0;
     rep.status         = 0;
     if (client->swapped) {
-        swaps(&rep.sequenceNumber, n);
-        swapl(&rep.length, n);
-        swapl(&rep.status, n);
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.status, n);
     }
     WriteToClient(client, sizeof(xDMXSyncReply), (char *)&rep);
     return client->noClientException;
@@ -273,27 +306,27 @@ static int ProcDMXForceWindowCreation(ClientPtr client)
 
 #ifdef PANORAMIX
     if (!noPanoramiXExtension) {
-        PanoramiXRes *win;
-        int          i;
+	PanoramiXRes *win;
+	int          i;
 
-        if (!(win = SecurityLookupIDByType(client, stuff->window, XRT_WINDOW,
-                                           DixReadAccess)))
-            return -1;           /* BadWindow */
+	if (!(win = SecurityLookupIDByType(client, stuff->window, XRT_WINDOW,
+					   DixReadAccess)))
+	    return -1;           /* BadWindow */
 
-        FOR_NSCREENS(i) {
-            if (Success != dixLookupWindow(&pWin, win->info[i].id, client,
+	FOR_NSCREENS(i) {
+	    if (Success != dixLookupWindow(&pWin, win->info[i].id, client,
 					   DixReadAccess))
-                return -1;       /* BadWindow */
+		return -1;       /* BadWindow */
 
-            dmxForceWindowCreation(pWin);
-        }
-        goto doreply;
+	    dmxForceWindowCreation(pWin);
+	}
+	goto doreply;
     }
 #endif
 
     if (Success != dixLookupWindow(&pWin, stuff->window, client,
 				   DixReadAccess))
-        return -1;               /* BadWindow */
+	return -1;               /* BadWindow */
 
     dmxForceWindowCreation(pWin);
   doreply:
@@ -303,9 +336,9 @@ static int ProcDMXForceWindowCreation(ClientPtr client)
     rep.length         = 0;
     rep.status         = 0;
     if (client->swapped) {
-        swaps(&rep.sequenceNumber, n);
-        swapl(&rep.length, n);
-        swapl(&rep.status, n);
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.status, n);
     }
     WriteToClient(client, sizeof(xDMXForceWindowCreationReply), (char *)&rep);
     return Success;
@@ -324,8 +357,8 @@ static int ProcDMXGetScreenCount(ClientPtr client)
     rep.screenCount    = dmxGetNumScreens();
     if (client->swapped) {
     	swaps(&rep.sequenceNumber, n);
-        swapl(&rep.length, n);
-        swapl(&rep.screenCount, n);
+	swapl(&rep.length, n);
+	swapl(&rep.screenCount, n);
     }
     WriteToClient(client, sizeof(xDMXGetScreenCountReply), (char *)&rep);
     return client->noClientException;
@@ -343,10 +376,10 @@ static int ProcDMXGetScreenAttributes(ClientPtr client)
     REQUEST_SIZE_MATCH(xDMXGetScreenAttributesReq);
 
     if (stuff->physicalScreen < 0
-        || stuff->physicalScreen >= dmxGetNumScreens()) return BadValue;
+	|| stuff->physicalScreen >= dmxGetNumScreens()) return BadValue;
 
     if (!dmxGetScreenAttributes(stuff->physicalScreen, &attr))
-        return BadValue;
+	return BadValue;
 
     rep.logicalScreen       = attr.logicalScreen;
     rep.screenWindowWidth   = attr.screenWindowWidth;
@@ -359,7 +392,7 @@ static int ProcDMXGetScreenAttributes(ClientPtr client)
     rep.rootWindowYoffset   = attr.rootWindowYoffset;
     rep.rootWindowXorigin   = attr.rootWindowXorigin;
     rep.rootWindowYorigin   = attr.rootWindowYorigin;
-                                 
+
     length                  = attr.displayName ? strlen(attr.displayName) : 0;
     paddedLength            = (length + 3) & ~3;
     rep.type                = X_Reply;
@@ -369,19 +402,19 @@ static int ProcDMXGetScreenAttributes(ClientPtr client)
 
     if (client->swapped) {
     	swaps(&rep.sequenceNumber, n);
-        swapl(&rep.length, n);
-        swapl(&rep.displayNameLength, n);
-        swapl(&rep.logicalScreen, n);
-        swaps(&rep.screenWindowWidth, n);
-        swaps(&rep.screenWindowHeight, n);
-        swaps(&rep.screenWindowXoffset, n);
-        swaps(&rep.screenWindowYoffset, n);
-        swaps(&rep.rootWindowWidth, n);
-        swaps(&rep.rootWindowHeight, n);
-        swaps(&rep.rootWindowXoffset, n);
-        swaps(&rep.rootWindowYoffset, n);
-        swaps(&rep.rootWindowXorigin, n);
-        swaps(&rep.rootWindowYorigin, n);
+	swapl(&rep.length, n);
+	swapl(&rep.displayNameLength, n);
+	swapl(&rep.logicalScreen, n);
+	swaps(&rep.screenWindowWidth, n);
+	swaps(&rep.screenWindowHeight, n);
+	swaps(&rep.screenWindowXoffset, n);
+	swaps(&rep.screenWindowYoffset, n);
+	swaps(&rep.rootWindowWidth, n);
+	swaps(&rep.rootWindowHeight, n);
+	swaps(&rep.rootWindowXoffset, n);
+	swaps(&rep.rootWindowYoffset, n);
+	swaps(&rep.rootWindowXorigin, n);
+	swaps(&rep.rootWindowYorigin, n);
     }
     WriteToClient(client, sizeof(xDMXGetScreenAttributesReply), (char *)&rep);
     if (length) WriteToClient(client, length, (char *)attr.displayName);
@@ -403,12 +436,12 @@ static int ProcDMXChangeScreensAttributes(ClientPtr client)
     int                              errorScreen = 0;
     unsigned int                     len;
     int                              ones = 0;
-    
+
 
     REQUEST_AT_LEAST_SIZE(xDMXChangeScreensAttributesReq);
     len = client->req_len - (sizeof(xDMXChangeScreensAttributesReq) >> 2);
     if (len < stuff->screenCount + stuff->maskCount)
-        return BadLength;
+	return BadLength;
 
     screen_list = (CARD32 *)(stuff + 1);
     mask_list   = &screen_list[stuff->screenCount];
@@ -416,28 +449,21 @@ static int ProcDMXChangeScreensAttributes(ClientPtr client)
 
     for (i = 0; i < stuff->maskCount; i++) ones += Ones(mask_list[i]);
     if (len != stuff->screenCount + stuff->maskCount + ones)
-        return BadLength;
-    
+	return BadLength;
+
     if (!_DMXXineramaActive()) goto noxinerama;
 
     if (!(attribs = xalloc(stuff->screenCount * sizeof(*attribs))))
-        return BadAlloc;
+	return BadAlloc;
 
     for (i = 0; i < stuff->screenCount; i++) {
-        int count;
-        
-        if (i < stuff->maskCount) mask = mask_list[i];
-        dmxGetScreenAttributes(screen_list[i], &attribs[i]);
-        count = dmxFetchScreenAttributes(mask, &attribs[i], value_list);
-        value_list += count;
-    }
+	int count;
 
-#if PANORAMIX
-    status = dmxConfigureScreenWindows(stuff->screenCount,
-				       screen_list,
-				       attribs,
-				       &errorScreen);
-#endif
+	if (i < stuff->maskCount) mask = mask_list[i];
+	dmxGetScreenAttributes(screen_list[i], &attribs[i]);
+	count = dmxFetchScreenAttributes(mask, &attribs[i], value_list);
+	value_list += count;
+    }
 
     xfree(attribs);
 
@@ -450,14 +476,14 @@ static int ProcDMXChangeScreensAttributes(ClientPtr client)
     rep.status         = status;
     rep.errorScreen    = errorScreen;
     if (client->swapped) {
-        swaps(&rep.sequenceNumber, n);
-        swapl(&rep.length, n);
-        swapl(&rep.status, n);
-        swapl(&rep.errorScreen, n);
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swapl(&rep.status, n);
+	swapl(&rep.errorScreen, n);
     }
     WriteToClient(client,
-                  sizeof(xDMXChangeScreensAttributesReply),
-                  (char *)&rep);
+		  sizeof(xDMXChangeScreensAttributesReply),
+		  (char *)&rep);
     return client->noClientException;
 }
 
@@ -478,20 +504,25 @@ static int ProcDMXAddScreen(ClientPtr client)
     paddedLength = (stuff->displayNameLength + 3) & ~3;
     len          = client->req_len - (sizeof(xDMXAddScreenReq) >> 2);
     if (len != Ones(stuff->valueMask) + paddedLength/4)
-        return BadLength;
+	return BadLength;
 
     memset(&attr, 0, sizeof(attr));
-    dmxGetScreenAttributes(stuff->physicalScreen, &attr);
+    /*dmxGetScreenAttributes(stuff->physicalScreen, &attr); */
     value_list = (CARD32 *)(stuff + 1);
     count      = dmxFetchScreenAttributes(stuff->valueMask, &attr, value_list);
-    
+
     if (!(name = xalloc(stuff->displayNameLength + 1 + 4)))
-        return BadAlloc;
+	return BadAlloc;
     memcpy(name, &value_list[count], stuff->displayNameLength);
     name[stuff->displayNameLength] = '\0';
     attr.displayName = name;
+    
+    status = dmxAttachScreen(stuff->physicalScreen,
+			     &attr, 0, NULL, 0, NULL, 0, NULL,
+			     0, 0);
 
-    status = dmxAttachScreen(stuff->physicalScreen, &attr);
+    if (status == Success)
+	dmxEnableScreen(stuff->physicalScreen);
 
     xfree(name);
 
@@ -544,28 +575,32 @@ static int dmxPopulatePanoramiX(ClientPtr client, Window window,
                                 CARD32 *screens, CARD32 *windows,
                                 xRectangle *pos, xRectangle *vis)
 {
-    WindowPtr              pWin;
-    PanoramiXRes           *win;
+    DrawablePtr            pDraw;
+    PanoramiXRes           *res;
     int                    i;
     int                    count = 0;
     DMXWindowAttributesRec attr;
     
-    if (!(win = SecurityLookupIDByType(client, window, XRT_WINDOW,
-                                       DixReadAccess)))
-        return -1;               /* BadWindow */
+
+    if(!(res = (PanoramiXRes *) SecurityLookupIDByClass(
+	     client, window, XRC_DRAWABLE, DixReadAccess)))
+	return -1;               /* BadDrawable */
     
     FOR_NSCREENS(i) {
-        if (Success != dixLookupWindow(&pWin, win->info[i].id, client,
-				       DixReadAccess))
-            return -1;          /* BadWindow */
-        if (dmxGetWindowAttributes(pWin, &attr)) {
-            screens[count] = attr.screen;
-            windows[count] = attr.window;
-            pos[count]     = attr.pos;
-            vis[count]     = attr.vis;
-            ++count;            /* Only count existing windows */
-        }
+	if (Success == dixLookupDrawable (&pDraw, res->info[i].id, client,
+					  M_ANY, DixUnknownAccess))
+	{
+	    if (dmxGetDrawableAttributes (pDraw, &attr))
+	    {
+		screens[count] = attr.screen;
+		windows[count] = attr.window;
+		pos[count]     = attr.pos;
+		vis[count]     = attr.vis;
+		++count;            /* Only count existing windows */
+	    }
+	}
     }
+
     return count;
 }
 #endif
@@ -573,7 +608,7 @@ static int dmxPopulatePanoramiX(ClientPtr client, Window window,
 static int dmxPopulate(ClientPtr client, Window window, CARD32 *screens,
                        CARD32 *windows, xRectangle *pos, xRectangle *vis)
 {
-    WindowPtr              pWin;
+    DrawablePtr            pDraw;
     DMXWindowAttributesRec attr;
 
 #ifdef PANORAMIX
@@ -582,14 +617,21 @@ static int dmxPopulate(ClientPtr client, Window window, CARD32 *screens,
                                     pos, vis);
 #endif
     
-    if (Success != dixLookupWindow(&pWin, window, client, DixReadAccess))
-        return -1;               /* BadWindow */
+    if (Success != dixLookupDrawable (&pDraw, window, client, 0,
+				      DixReadAccess))
+	return -1;
+
+    if (!dmxGetDrawableAttributes (pDraw, &attr))
+	return -1;
 
-    dmxGetWindowAttributes(pWin, &attr);
     *screens = attr.screen;
     *windows = attr.window;
     *pos     = attr.pos;
     *vis     = attr.vis;
+
+    if (!attr.window)
+	abort ();
+
     return 1;
 }
 
@@ -735,9 +777,6 @@ static int ProcDMXChangeDesktopAttributes(ClientPtr client)
     dmxGetDesktopAttributes(&attr);
     dmxFetchDesktopAttributes(stuff->valueMask, &attr, value_list);
 
-#if PANORAMIX
-    status = dmxConfigureDesktop(&attr);
-#endif
     if (status == BadValue) return status;
 
   noxinerama:
diff --git a/hw/dmx/dmx.h b/hw/dmx/dmx.h
index 00200a8..1cdfce4 100644
--- a/hw/dmx/dmx.h
+++ b/hw/dmx/dmx.h
@@ -71,6 +71,13 @@
 #include <GL/glxint.h>
 #endif
 
+#include <xcb/xcb.h>
+#include <xcb/xcbext.h>
+
+#include <X11/Xlib-xcb.h>
+
+#include "dmxxlibio.h"
+
 typedef enum {
     PosNone = -1,
     PosAbsolute = 0,
@@ -81,21 +88,81 @@ typedef enum {
     PosRelative
 } PositionType;
 
-/** Provide the typedef globally, but keep the contents opaque outside
- * of the input routines.  \see dmxinput.h */
-typedef struct _DMXInputInfo DMXInputInfo;
+typedef struct _DMXAtom {
+    Atom                     atom;
+    xcb_intern_atom_cookie_t cookie;
+} DMXAtom;
+
+typedef struct _DMXSequence {
+    struct _DMXSequence *next;
+    unsigned long       sequence;
+} DMXSequence;
+
+typedef struct _DMXQueue {
+    DMXSequence *head;
+    DMXSequence **tail;
+} DMXQueue;
+
+typedef void (*ReplyProcPtr) (ScreenPtr           pScreen,
+			      unsigned int        sequence,
+			      xcb_generic_reply_t *reply,
+			      xcb_generic_error_t *error,
+			      void                *data);
+
+typedef struct _DMXRequest {
+    DMXSequence  base;
+    ReplyProcPtr reply;
+    void         *data;
+} DMXRequest;
+
+typedef struct _DMXPropTrans {
+    const char *name;
+    const char *format;
+    Atom       type;
+} DMXPropTrans;
+
+typedef struct _DMXSelectionMap {
+    const char *name;
+    Atom       atom;
+    Atom       beAtom;
+} DMXSelectionMap;
+
+#define DMX_DETACHED 0xff
 
 /** Provide the typedef globally, but keep the contents opaque outside
  * of the XSync statistic routines.  \see dmxstat.c */
 typedef struct _DMXStatInfo DMXStatInfo;
 
+typedef struct _DMXInputInfo {
+    DeviceIntPtr *devs;
+    int          numDevs;
+    int          eventBase;
+} DMXInputInfo;
+
+typedef struct _DMXDnDChild DMXDnDChild;
+
 /** Global structure containing information about each backend screen. */
 typedef struct _DMXScreenInfo {
-    const char   *name;           /**< Name from command line or config file */
+    DMXInputInfo input;
+
+    char          *name;          /**< Name that uniquely identifies screen  */
+    char          *display;       /**< Name from command line or config file */
     int           index;          /**< Index into dmxScreens global          */
 
     /*---------- Back-end X server information ----------*/
 
+    int fd;
+    int inDispatch;
+
+    xcb_connection_t             *connection;
+    xcb_get_input_focus_cookie_t sync;
+
+    Atom *atomTable;
+    int  atomTableSize;
+
+    DMXAtom *beAtomTable;
+    int     beAtomTableSize;
+
     Display      *beDisplay;      /**< Back-end X server's display */
     int           beWidth;        /**< Width of BE display */
     int           beHeight;       /**< Height of BE display */
@@ -106,6 +173,8 @@ typedef struct _DMXScreenInfo {
 
     int           beNumDepths;    /**< Number of depths on BE server */
     int          *beDepths;       /**< Depths from BE server */
+    int           alive;
+    int           broken;
 
     int           beNumPixmapFormats; /**< Number of pixmap formats on BE */
     XPixmapFormatValues *bePixmapFormats; /**< Pixmap formats on BE */
@@ -120,15 +189,34 @@ typedef struct _DMXScreenInfo {
     Pixel         beBlackPixel;   /**< Default black pixel for BE */
     Pixel         beWhitePixel;   /**< Default white pixel for BE */
 
+    int           beShapeEventBase;
+
+#ifdef RANDR
+    Bool          beRandr;        /**< Use RANDR support on BE server */
+    Bool          beRandrPending;
+    int           beRandrEventBase;
+#endif
+
+#ifdef MITSHM
+    Bool          beShm;          /**< Use MIT-SHM support on BE server */
+    int           beShmEventBase;
+#endif
+
+    Display      *beAttachedDisplay; /**< Disabled X server's display */
+
+    char          *authType;
+    int           authTypeLen;
+    char          *authData;
+    int           authDataLen;
+
+    int           virtualFb;
+
     /*---------- Screen window information ----------*/
 
     Window        scrnWin;        /**< "Screen" window on backend display */
-    int           scrnX;          /**< X offset of "screen" WRT BE display */
-    int           scrnY;          /**< Y offset of "screen" WRT BE display */
     int           scrnWidth;      /**< Width of "screen" */
     int           scrnHeight;     /**< Height of "screen" */
-    int           scrnXSign;      /**< X offset sign of "screen" */
-    int           scrnYSign;      /**< Y offset sign of "screen" */
+    int           scrnEventMask;
 
                                   /** Default drawables for "screen" */
     Drawable      scrnDefDrawables[MAXFORMATS];
@@ -141,38 +229,61 @@ typedef struct _DMXScreenInfo {
     Window        rootWin;        /**< "Root" window on backend display */
     int           rootX;          /**< X offset of "root" window WRT "screen"*/
     int           rootY;          /**< Y offset of "root" window WRT "screen"*/
-    int           rootWidth;      /**< Width of "root" window */
-    int           rootHeight;     /**< Height of "root" window */
-
-    int           rootXOrigin;    /**< Global X origin of "root" window */
-    int           rootYOrigin;    /**< Global Y origin of "root" window */
-
-    /*---------- Shadow framebuffer information ----------*/
-
-    void         *shadow;         /**< Shadow framebuffer data (if enabled) */
-    XlibGC        shadowGC;       /**< Default GC used by shadow FB code */
-    XImage       *shadowFBImage;  /**< Screen image used by shadow FB code */
+    int           rootEventMask;
+
+    /*---------- Input overlay ----------*/
+    XID                              inputOverlayWid;
+    WindowPtr                        pInputOverlayWin;
+
+    /*---------- Selection information ----------*/
+    Atom                             beSelectionAtom;
+    Window                           selectionOwner;
+    xcb_get_selection_owner_cookie_t getSelectionOwner;
+    Window                           getSelectionOwnerResult;
+    Atom                             multipleAtom;
+    Atom                             atomPairAtom;
+    Atom                             incrAtom;
+
+    /*---------- DnD information ----------*/
+    Atom                               wmStateAtom;
+    Atom                               xdndProxyAtom;
+    Atom                               xdndAwareAtom;
+    Atom                               xdndSelectionAtom;
+    Atom                               xdndEnterAtom;
+    Atom                               xdndPositionAtom;
+    Atom                               xdndStatusAtom;
+    Atom                               xdndLeaveAtom;
+    Atom                               xdndDropAtom;
+    Atom                               xdndFinishedAtom;
+    Atom                               xdndTypeListAtom;
+    Atom                               xdndActionAskAtom;
+    Atom                               xdndActionListAtom;
+    Atom                               xdndActionDescriptionAtom;
+    Bool                               dndHasTypeProp;
+    XID                                dndWid;
+    XID                                dndSource;
+    XID                                dndTarget;
+    int                                dndStatus;
+    XID                                dndWindow;
+    Atom                               dndAction;
+    Atom                               dndAcceptedAction;
+    int                                dndVersion;
+    Atom                               dndType[3];
+    RegionRec                          dndBox;
+    int                                dndX;
+    int                                dndY;
+    int                                dndXPos;
+    int                                dndYPos;
+    xcb_translate_coordinates_cookie_t translateCoordinates;
+    xcb_get_property_cookie_t          getTypeProp;
+    xcb_get_property_cookie_t          getActionListProp;
+    xcb_get_property_cookie_t          getActionDescriptionProp;
+    DMXDnDChild                        *dndChildren;
+    int                                dndNChildren;
+    xcb_query_tree_cookie_t            queryTree;
 
     /*---------- Other related information ----------*/
 
-    int           shared;         /**< Non-zero if another Xdmx is running */
-
-    Bool          WMRunningOnBE;
-
-    Cursor        noCursor;
-    Cursor        curCursor;
-                                /* Support for cursors on overlapped
-                                 * backend displays. */
-    CursorPtr     cursor;
-    int           cursorVisible;
-    int           cursorNotShared; /* for overlapping screens on a backend */
-
-    PositionType  where;            /**< Relative layout information */
-    int           whereX;           /**< Relative layout information */
-    int           whereY;           /**< Relative layout information */
-    int           whereRefScreen;   /**< Relative layout information */
-
-    int           savedTimeout;     /**< Original screen saver timeout */
     int           dpmsCapable;      /**< Non-zero if backend is DPMS capable */
     int           dpmsEnabled;      /**< Non-zero if DPMS enabled */
     int           dpmsStandby;      /**< Original DPMS standby value  */
@@ -182,6 +293,9 @@ typedef struct _DMXScreenInfo {
     DMXStatInfo  *stat;             /**< Statistics about XSync  */
     Bool          needsSync;        /**< True if an XSync is pending  */
 
+    DMXQueue ignore;
+    DMXQueue request;
+
 #ifdef GLXEXT
                                   /** Visual information for glxProxy */
     int           numGlxVisuals;
@@ -212,10 +326,15 @@ typedef struct _DMXScreenInfo {
     CopyWindowProcPtr              CopyWindow;
 
     ResizeWindowProcPtr            ResizeWindow;
+    HandleExposuresProcPtr         HandleExposures;
     ReparentWindowProcPtr          ReparentWindow;
 
     ChangeBorderWidthProcPtr       ChangeBorderWidth;
 
+    ModifyPixmapHeaderProcPtr	   ModifyPixmapHeader;
+
+    SetWindowPixmapProcPtr         SetWindowPixmap;
+
     GetImageProcPtr                GetImage;
     GetSpansProcPtr                GetSpans;
 
@@ -254,15 +373,16 @@ typedef struct _DMXScreenInfo {
     TrianglesProcPtr               Triangles;
     TriStripProcPtr                TriStrip;
     TriFanProcPtr                  TriFan;
+
+    RealizeGlyphProcPtr            RealizeGlyph;
+    UnrealizeGlyphProcPtr          UnrealizeGlyph;
 #endif
 } DMXScreenInfo;
 
 /* Global variables available to all Xserver/hw/dmx routines. */
 extern int              dmxNumScreens;          /**< Number of dmxScreens */
 extern DMXScreenInfo   *dmxScreens;             /**< List of outputs */
-extern int              dmxShadowFB;            /**< Non-zero if using
-                                                 * shadow frame-buffer
-                                                 * (deprecated) */
+
 extern XErrorEvent      dmxLastErrorEvent;      /**< Last error that
                                                  * occurred */
 extern Bool             dmxErrorOccurred;       /**< True if an error
@@ -315,6 +435,23 @@ extern Bool             dmxIgnoreBadFontPaths;  /**< True if bad font
 extern Bool             dmxAddRemoveScreens;    /**< True if add and
 						 * remove screens support
 						 * is enabled */
+#ifdef RANDR
+extern int             xRROutputsPerScreen;
+extern int             xRRCrtcsPerScreen;
+#endif
+
+extern DMXPropTrans     *dmxPropTrans;
+extern int              dmxPropTransNum;
+
+extern DMXSelectionMap  *dmxSelectionMap;
+extern int              dmxSelectionMapNum;
+
+#ifdef XV
+extern char             **dmxXvImageFormats;
+extern int              dmxXvImageFormatsNum;
+#endif
+
+extern char             dmxDigest[64];
 
 /** Wrap screen or GC function pointer */
 #define DMX_WRAP(_entry, _newfunc, _saved, _actual)			\
@@ -370,4 +507,6 @@ do {									\
 #define MAXSCREENSCALLOC_FATAL(o,m)     _MAXSCREENSALLOCF(o,MAXSCREENS*(m),1)
 #endif
 
+char *dmxMemDup (const char *data, int Len);
+
 #endif /* DMX_H */
diff --git a/hw/dmx/dmxatom.c b/hw/dmx/dmxatom.c
new file mode 100644
index 0000000..bfbc30d
--- /dev/null
+++ b/hw/dmx/dmxatom.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmxatom.h"
+#include "dmxsync.h"
+#include "dmxscrinit.h"
+
+static void
+dmxAddAtom (DMXScreenInfo *dmxScreen,
+	    Atom          atom,
+	    Atom          beAtom)
+{
+    int i;
+
+    if (atom >= dmxScreen->beAtomTableSize)
+    {
+	DMXAtom *table;
+
+	table = xrealloc (dmxScreen->beAtomTable,
+			  sizeof (DMXAtom) * (atom + 1));
+	if (table)
+	{
+	    for (i = dmxScreen->beAtomTableSize; i < atom; i++)
+	    {
+		table[i].atom            = None;
+		table[i].cookie.sequence = 0;
+	    }
+
+	    table[atom].atom            = beAtom;
+	    table[atom].cookie.sequence = 0;
+
+	    dmxScreen->beAtomTable     = table;
+	    dmxScreen->beAtomTableSize = atom + 1;
+	}
+    }
+    else
+    {
+	dmxScreen->beAtomTable[atom].atom = beAtom;
+    }
+
+    if (beAtom)
+    {
+	if (beAtom >= dmxScreen->atomTableSize)
+	{
+	    Atom *table;
+
+	    table = xrealloc (dmxScreen->atomTable,
+			      sizeof (Atom) * (beAtom + 1));
+	    if (table)
+	    {
+		for (i = dmxScreen->atomTableSize; i < beAtom; i++)
+		    table[i] = None;
+
+		table[beAtom] = atom;
+
+		dmxScreen->atomTable     = table;
+		dmxScreen->atomTableSize = beAtom + 1;
+	    }
+	}
+	else
+	{
+	    dmxScreen->atomTable[beAtom] = atom;
+	}
+    }
+}
+
+static void
+dmxInternAtomReply (ScreenPtr           pScreen,
+		    unsigned int        sequence,
+		    xcb_generic_reply_t *reply,
+		    xcb_generic_error_t *error,
+		    void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    Atom          atom = (Atom) data;
+
+    dmxScreen->beAtomTable[atom].cookie.sequence = 0;
+
+    if (reply)
+    {
+	xcb_intern_atom_reply_t *xatom = (xcb_intern_atom_reply_t *) reply;
+
+	dmxAddAtom (dmxScreen, atom, xatom->atom);
+    }
+}
+
+static unsigned int
+dmxBERequestAtom (DMXScreenInfo *dmxScreen,
+		  Atom	        atom)
+{
+    if (atom < dmxScreen->beAtomTableSize)
+	if (dmxScreen->beAtomTable[atom].atom)
+	    return 0;
+
+    if (atom <= XA_LAST_PREDEFINED)
+    {
+	dmxAddAtom (dmxScreen, atom, atom);
+    }
+    else
+    {
+	char *name;
+
+	dmxAddAtom (dmxScreen, atom, None);
+
+	name = NameForAtom (atom);
+	if (name && atom < dmxScreen->beAtomTableSize)
+	{
+	    dmxScreen->beAtomTable[atom].cookie =
+		xcb_intern_atom (dmxScreen->connection,
+				 FALSE,
+				 strlen (name),
+				 name);
+	    
+	    return dmxScreen->beAtomTable[atom].cookie.sequence;
+	}
+    }
+
+    return 0;
+}
+
+Atom
+dmxAtom (DMXScreenInfo *dmxScreen,
+	 Atom	       beAtom)
+{
+    if (beAtom < dmxScreen->atomTableSize)
+	if (dmxScreen->atomTable[beAtom])
+	    return dmxScreen->atomTable[beAtom];
+
+    if (beAtom <= XA_LAST_PREDEFINED)
+    {
+	dmxAddAtom (dmxScreen, beAtom, beAtom);
+    }
+    else
+    {
+	xcb_get_atom_name_reply_t *reply;
+	Atom                      atom;
+
+	reply = xcb_get_atom_name_reply
+	    (dmxScreen->connection,
+	     xcb_get_atom_name (dmxScreen->connection,
+				beAtom),
+	     NULL);
+	if (!reply)
+	    return None;
+
+	atom = MakeAtom ((char *) (reply + 1), reply->name_len, TRUE);
+
+	free (reply);
+
+	if (!atom)
+	    return None;
+
+	dmxAddAtom (dmxScreen, atom, beAtom);
+    }
+
+    if (beAtom < dmxScreen->atomTableSize)
+	return dmxScreen->atomTable[beAtom];
+
+    return None;
+}
+
+Atom
+dmxBEAtom (DMXScreenInfo *dmxScreen,
+	   Atom		 atom)
+{
+    xcb_intern_atom_cookie_t cookie = { 0 };
+
+    if (atom < dmxScreen->beAtomTableSize)
+    {
+	if (dmxScreen->beAtomTable[atom].atom)
+	    return dmxScreen->beAtomTable[atom].atom;
+
+	cookie = dmxScreen->beAtomTable[atom].cookie;
+    }
+
+    if (!cookie.sequence)
+	cookie.sequence = dmxBERequestAtom (dmxScreen, atom);
+    
+    if (cookie.sequence)
+    {
+	xcb_intern_atom_reply_t *reply;
+
+	reply = xcb_intern_atom_reply (dmxScreen->connection, cookie, NULL);
+
+	dmxInternAtomReply (screenInfo.screens[dmxScreen->index],
+			    cookie.sequence,
+			    (xcb_generic_reply_t *) reply,
+			    NULL,
+			    (void *) atom);
+    }
+
+    if (atom < dmxScreen->beAtomTableSize)
+	return dmxScreen->beAtomTable[atom].atom;
+
+    return None;
+}
+
+void
+dmxBEPrefetchAtom (DMXScreenInfo *dmxScreen,
+		   Atom	         atom)
+{
+    unsigned int sequence;
+
+    sequence = dmxBERequestAtom (dmxScreen, atom);
+    if (sequence)
+	dmxAddRequest (&dmxScreen->request,
+		       dmxInternAtomReply,
+		       sequence,
+		       (void *) atom);
+}
diff --git a/hw/dmx/dmxatom.h b/hw/dmx/dmxatom.h
new file mode 100644
index 0000000..88416b3
--- /dev/null
+++ b/hw/dmx/dmxatom.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXATOM_H
+#define DMXATOM_H
+
+#include "dmx.h"
+
+extern Atom dmxAtom (DMXScreenInfo *dmxScreen, Atom beAtom);
+extern Atom dmxBEAtom (DMXScreenInfo *dmxScreen, Atom atom);
+extern void dmxBEPrefetchAtom (DMXScreenInfo *dmxScreen, Atom atom);
+
+#endif /* DMXATOM_H */
diff --git a/hw/dmx/dmxavahi.c b/hw/dmx/dmxavahi.c
new file mode 100644
index 0000000..9dfb85e
--- /dev/null
+++ b/hw/dmx/dmxavahi.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * 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.
+ *
+ * Authors: Hubert Figuiere <hfiguiere@novell.com>
+ *          David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-common/watch.h>
+
+#include "dix.h"
+#include "os.h"
+#include "opaque.h"
+#include "dmxavahi.h"
+
+typedef struct _DMXAvahiPoll DMXAvahiPoll;
+
+struct AvahiWatch {
+    struct AvahiWatch *next;
+
+    int                fd;
+    AvahiWatchEvent    event;
+    AvahiWatchCallback callback;
+    void               *userdata;
+
+    DMXAvahiPoll *p;
+};
+
+struct AvahiTimeout {
+    struct AvahiTimeout *next;
+
+    AvahiTimeoutCallback callback;
+    void                 *userdata;
+	
+    DMXAvahiPoll *p;
+    OsTimerPtr   timer;
+};
+
+struct _DMXAvahiPoll {
+    AvahiPoll base;
+
+    AvahiWatch   *watches;
+    AvahiTimeout *timeouts;
+};
+
+static DMXAvahiPoll    avahi_poll;
+static AvahiClient     *avahi_client;
+static AvahiEntryGroup *avahi_group;
+
+static const char * _service_name = "DMX service on %s";
+
+static AvahiWatch *
+dmx_avahi_watch_new (const AvahiPoll    *api,
+		     int		fd,
+		     AvahiWatchEvent    event,
+		     AvahiWatchCallback callback,
+		     void		*userdata)
+{
+    DMXAvahiPoll *p = (DMXAvahiPoll *) api;
+    AvahiWatch   *w;
+
+    w = xalloc (sizeof (AvahiWatch));
+    if (!w)
+	return NULL;
+
+    w->fd       = fd;
+    w->event    = event;
+    w->callback = callback;
+    w->userdata = userdata;
+    w->p        = p;
+
+    w->next = p->watches;
+    p->watches = w;
+
+    if (w->event & AVAHI_WATCH_IN)
+	AddEnabledDevice (fd);
+
+    return w;
+}
+
+static void
+dmx_avahi_watch_update (AvahiWatch      *w,
+			AvahiWatchEvent event)
+{
+    if (event & AVAHI_WATCH_IN)
+    {
+	if (!(w->event & AVAHI_WATCH_IN))
+	    AddEnabledDevice (w->fd);
+    }
+    else
+    {
+	if (w->event & AVAHI_WATCH_IN)
+	    RemoveEnabledDevice (w->fd);
+    }
+
+    w->event = event;
+}
+
+static AvahiWatchEvent
+dmx_avahi_watch_get_events (AvahiWatch *w)
+{
+    return AVAHI_WATCH_IN;
+}
+
+static void
+dmx_avahi_watch_free (AvahiWatch *w)
+{
+    DMXAvahiPoll *p = w->p;
+    AvahiWatch   *prev;
+
+    for (prev = p->watches; prev; prev = prev->next)
+	if (prev->next == w)
+	    break;
+
+    if (prev)
+	prev->next = w->next;
+    else
+	p->watches = w->next;
+
+    if (w->event & AVAHI_WATCH_IN)
+	RemoveEnabledDevice (w->fd);
+
+    free (w);
+}
+
+static CARD32
+avahi_poll_timeout (OsTimerPtr timer,
+		    CARD32     time,
+		    pointer    arg)
+{
+    AvahiTimeout *t = (AvahiTimeout *) arg;
+
+    (*t->callback) (t, t->userdata);
+
+    return 0;
+}
+
+static AvahiTimeout *
+dmx_avahi_timeout_new (const AvahiPoll      *api,
+		       const struct timeval *tv,
+		       AvahiTimeoutCallback callback,
+		       void                 *userdata)
+{
+    DMXAvahiPoll *p = (DMXAvahiPoll *) api;
+    AvahiTimeout *t;
+
+    t = xalloc (sizeof (AvahiTimeout));
+    if (!t)
+	return NULL;
+
+    t->callback = callback;
+    t->userdata = userdata;
+    t->timer    = NULL;
+    t->p        = p;
+    
+    t->next = p->timeouts;
+    p->timeouts = t;
+
+    if (tv)
+	t->timer = TimerSet (NULL,
+			     0,
+			     ((CARD16) tv->tv_sec) * 1000 + tv->tv_usec / 1000,
+			     avahi_poll_timeout,
+			     t);
+
+    return t;
+}
+
+static void
+dmx_avahi_timeout_update (AvahiTimeout         *t,
+			  const struct timeval *tv)
+{
+    if (tv)
+	t->timer = TimerSet (t->timer,
+			     0,
+			     ((CARD16) tv->tv_sec) * 1000 + tv->tv_usec / 1000,
+			     avahi_poll_timeout,
+			     t);
+    else
+	TimerCancel (t->timer);
+}
+
+static void
+dmx_avahi_timeout_free (AvahiTimeout *t)
+{
+    DMXAvahiPoll *p = t->p;
+    AvahiTimeout *prev;
+
+    for (prev = p->timeouts; prev; prev = prev->next)
+	if (prev->next == t)
+	    break;
+
+    if (prev)
+	prev->next = t->next;
+    else
+	p->timeouts = t->next;
+
+    TimerFree (t->timer);
+
+    free (t);
+}
+
+static void
+avahi_poll_block_handler (pointer   blockData,
+			  OSTimePtr pTimeout,
+			  pointer   pReadMask)
+{
+}
+
+static void
+avahi_poll_wakeup_handler (pointer blockData,
+			   int     result,
+			   pointer pReadMask)
+{
+    DMXAvahiPoll *p = (DMXAvahiPoll *) blockData;
+    AvahiWatch   *w = p->watches;
+    fd_set       *fds = (fd_set *) pReadMask;
+
+    while (w)
+    {
+	AvahiWatch *next = w->next;
+
+	if (FD_ISSET (w->fd, fds))
+	    (*w->callback) (w, w->fd, AVAHI_WATCH_IN, w->userdata);
+
+	w = next;
+    }
+}
+
+static void
+dmx_avahi_poll_init (DMXAvahiPoll *p)
+{
+    p->base.watch_new        = dmx_avahi_watch_new;
+    p->base.watch_update     = dmx_avahi_watch_update;
+    p->base.watch_get_events = dmx_avahi_watch_get_events;
+    p->base.watch_free       = dmx_avahi_watch_free;
+    p->base.timeout_new      = dmx_avahi_timeout_new;
+    p->base.timeout_update   = dmx_avahi_timeout_update;
+    p->base.timeout_free     = dmx_avahi_timeout_free;
+
+    RegisterBlockAndWakeupHandlers (avahi_poll_block_handler,
+				    avahi_poll_wakeup_handler,
+				    p);
+}
+
+static void
+dmx_avahi_poll_fini (DMXAvahiPoll *p)
+{
+    while (p->timeouts)
+	dmx_avahi_timeout_free (p->timeouts);
+
+    while (p->watches)
+	dmx_avahi_watch_free (p->watches);
+
+    RemoveBlockAndWakeupHandlers (avahi_poll_block_handler,
+				  avahi_poll_wakeup_handler,
+				  p);
+}
+
+static void
+avahi_client_callback (AvahiClient      *c,
+		       AvahiClientState state,
+		       void             *userdata)
+{
+    switch (state) {
+    case AVAHI_CLIENT_S_RUNNING: {
+	char hname[512], name[576];
+
+	if (gethostname (hname, sizeof (hname)))
+	    break;
+
+	sprintf (name, _service_name, hname);
+
+	avahi_group = avahi_entry_group_new (c, 0, 0);
+	if (avahi_group)
+	{
+	    avahi_entry_group_add_service (avahi_group,
+					   AVAHI_IF_UNSPEC,
+					   AVAHI_PROTO_UNSPEC,
+					   0, 
+					   name,
+					   "_dmx._tcp",
+					   0,
+					   0,
+					   6000 + atoi (display),
+					   NULL);
+
+	    avahi_entry_group_commit (avahi_group);
+	}
+    } break;
+    case AVAHI_CLIENT_FAILURE:
+    case AVAHI_CLIENT_S_COLLISION:
+    case AVAHI_CLIENT_CONNECTING:
+	break;
+    case AVAHI_CLIENT_S_REGISTERING:
+	if (avahi_group)
+	    avahi_entry_group_reset (avahi_group);
+    default:
+	break;
+    }
+}
+
+void
+dmx_avahi_init (void)
+{
+    dmx_avahi_poll_init (&avahi_poll);
+	
+    avahi_group  = NULL;
+    avahi_client = avahi_client_new (&avahi_poll.base,
+				     0, 
+				     avahi_client_callback,
+				     NULL,
+				     NULL);
+}
+
+void
+dmx_avahi_fini (void)
+{
+    if (avahi_group)
+    {
+	avahi_entry_group_free (avahi_group);
+	avahi_group = NULL;
+    }
+
+    if (avahi_client)
+    {
+	avahi_client_free (avahi_client);
+	avahi_client = NULL;
+    }
+
+    dmx_avahi_poll_fini (&avahi_poll);
+}
diff --git a/hw/dmx/dmxavahi.h b/hw/dmx/dmxavahi.h
new file mode 100644
index 0000000..881a37c
--- /dev/null
+++ b/hw/dmx/dmxavahi.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * 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.
+ *
+ * Authors: Hubert Figuiere <hfiguiere@novell.com>
+ *          David Reveman <davidr@novell.com>
+ */
+
+
+#ifndef DMX_AVAHI_H
+#define DMX_AVAHI_H
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#ifdef HAVE_AVAHI
+extern void dmx_avahi_init (void);
+extern void dmx_avahi_fini (void);
+#endif
+
+#endif
diff --git a/hw/dmx/dmxcb.c b/hw/dmx/dmxcb.c
index 2ecfe22..47139f3 100644
--- a/hw/dmx/dmxcb.c
+++ b/hw/dmx/dmxcb.c
@@ -42,6 +42,7 @@
 #include "dmxcb.h"
 #include "dmxinput.h"
 #include "dmxlog.h"
+#include "dmxwindow.h"
 
 extern char    *ConnectionInfo;
 extern int     connBlockScreenStart;
@@ -50,6 +51,8 @@ extern int     connBlockScreenStart;
 extern int     PanoramiXPixWidth;
 extern int     PanoramiXPixHeight;
 extern int     PanoramiXNumScreens;
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
 #endif
 
        int     dmxGlobalWidth, dmxGlobalHeight;
@@ -64,46 +67,100 @@ void dmxSetWidthHeight(int width, int height)
     dmxGlobalHeight = height;
 }
 
-/** Computes the global bounding box for DMX.  This may be larger than
- * the one computed by Xinerama because of the DMX configuration
- * file. */
-void dmxComputeWidthHeight(DMXRecomputeFlag flag)
+void dmxComputeWidthHeight(void)
 {
-    int           i;
-    DMXScreenInfo *dmxScreen;
-    int           w = 0;
-    int           h = 0;
+    int       i;
+    ScreenPtr pScreen;
+    int       w = 0;
+    int       h = 0;
     
     for (i = 0; i < dmxNumScreens; i++) {
-                                /* Don't use root* here because this is
-                                 * the global bounding box. */
-        dmxScreen = &dmxScreens[i];
-        if (w < dmxScreen->scrnWidth + dmxScreen->rootXOrigin)
-            w = dmxScreen->scrnWidth + dmxScreen->rootXOrigin;
-        if (h < dmxScreen->scrnHeight + dmxScreen->rootYOrigin)
-            h = dmxScreen->scrnHeight + dmxScreen->rootYOrigin;
+	pScreen = screenInfo.screens[i];
+        if (w < pScreen->width)
+            w = pScreen->width;
+        if (h < pScreen->height)
+            h = pScreen->height;
     }
-    if (!dmxGlobalWidth && !dmxGlobalHeight) {
-        dmxLog(dmxInfo, "Using %dx%d as global bounding box\n", w, h);
-    } else {
-        switch (flag) {
-        case DMX_NO_RECOMPUTE_BOUNDING_BOX:
-            dmxLog(dmxInfo,
-                   "Using old bounding box (%dx%d) instead of new (%dx%d)\n",
-                   dmxGlobalWidth, dmxGlobalHeight, w, h);
-            w = dmxGlobalWidth;
-            h = dmxGlobalHeight;
-            break;
-        case DMX_RECOMPUTE_BOUNDING_BOX:
-            dmxLog(dmxInfo,
-                   "Using %dx%d as global bounding box, instead of %dx%d\n",
-                   w, h, dmxGlobalWidth, dmxGlobalHeight);
-            break;
-        }
+
+    dmxSetWidthHeight (w, h);
+}
+
+static Bool
+dmxCreateInputOverlayWindow (void)
+{
+    WindowPtr pWin;
+    XID       inputOverlayWid;
+    XID       overrideRedirect = TRUE;
+    int	      result;
+    Atom      xdndVersion = 5;
+
+    if (dmxScreens[0].inputOverlayWid)
+	return TRUE;
+
+    inputOverlayWid = FakeClientID (0);
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	PanoramiXRes *newWin;
+	int          j;
+
+	if (!(newWin = (PanoramiXRes *) xalloc (sizeof (PanoramiXRes))))
+	    return BadAlloc;
+
+	newWin->type = XRT_WINDOW;
+	newWin->u.win.visibility = VisibilityNotViewable;
+	newWin->u.win.class = InputOnly;
+	newWin->u.win.root = FALSE;
+	newWin->info[0].id = inputOverlayWid;
+	for(j = 1; j < PanoramiXNumScreens; j++)
+	    newWin->info[j].id = FakeClientID (0);
+
+	FOR_NSCREENS_BACKWARD(j) {
+	    pWin = CreateWindow (newWin->info[j].id, WindowTable[j],
+				 -1, -1, 1, 1, 0, InputOnly, 
+				 CWOverrideRedirect, &overrideRedirect,
+				 0, serverClient, CopyFromParent, 
+				 &result);
+	    if (result != Success)
+		return FALSE;
+	    if (!AddResource (pWin->drawable.id, RT_WINDOW, pWin))
+		return FALSE;
+
+	    dmxScreens[j].inputOverlayWid = inputOverlayWid;
+	    dmxScreens[j].pInputOverlayWin = pWin;
+	}
+
+	AddResource (newWin->info[0].id, XRT_WINDOW, newWin);
     }
-        
-    dmxGlobalWidth  = w;
-    dmxGlobalHeight = h;
+    else
+#endif
+	
+    {
+	pWin = CreateWindow (inputOverlayWid, WindowTable[0],
+			     -1, -1, 1, 1, 0, InputOnly, 
+			     CWOverrideRedirect, &overrideRedirect,
+			     0, serverClient, CopyFromParent, 
+			     &result);
+	if (result != Success)
+	    return FALSE;
+	if (!AddResource (pWin->drawable.id, RT_WINDOW, pWin))
+	    return FALSE;
+
+	dmxScreens[0].inputOverlayWid = inputOverlayWid;
+	dmxScreens[0].pInputOverlayWin = pWin;
+    }
+
+    ChangeWindowProperty (dmxScreens[0].pInputOverlayWin,
+			  dmxScreens[0].xdndAwareAtom,
+			  XA_ATOM,
+			  32,
+			  PropModeReplace,
+			  1,
+			  &xdndVersion,
+			  TRUE);
+
+    return TRUE;
 }
 
 /** A callback routine that hooks into Xinerama and provides a
@@ -198,7 +255,6 @@ void dmxConnectionBlockCallback(void)
         offset = voffset + depth->nVisuals * sizeof(xVisualType);
     }
 
-    dmxInputLogDevices();
     dmxLog(dmxInfo, "===== End of Summary =====\n");
 
 #ifdef PANORAMIX
@@ -220,4 +276,7 @@ void dmxConnectionBlockCallback(void)
     }
 #endif
     MAXSCREENSFREE(found);
+
+    if (!dmxCreateInputOverlayWindow ())
+	dmxLog (dmxFatal, "dmxCreateInputOverlayWindow: failed");
 }
diff --git a/hw/dmx/dmxcb.h b/hw/dmx/dmxcb.h
index fa334db..6f90830 100644
--- a/hw/dmx/dmxcb.h
+++ b/hw/dmx/dmxcb.h
@@ -40,14 +40,7 @@
 /** The cursor position, in global coordinates. */
 extern int  dmxGlobalWidth, dmxGlobalHeight;
 
-/** #dmxComputeWidthHeight can either recompute the global bounding box
- * or not. */
-typedef enum {
-    DMX_RECOMPUTE_BOUNDING_BOX,
-    DMX_NO_RECOMPUTE_BOUNDING_BOX
-} DMXRecomputeFlag;
-
 extern void dmxSetWidthHeight(int width, int height);
-extern void dmxComputeWidthHeight(DMXRecomputeFlag flag);
+extern void dmxComputeWidthHeight(void);
 extern void dmxConnectionBlockCallback(void);
 #endif
diff --git a/hw/dmx/dmxclient.h b/hw/dmx/dmxclient.h
index f0c3608..4673409 100644
--- a/hw/dmx/dmxclient.h
+++ b/hw/dmx/dmxclient.h
@@ -72,6 +72,11 @@ typedef XID           KeySym64;
 #define Colormap      Colormap64
 #define GContext      GContext64
 #define KeySym        KeySym64
+#ifdef RANDR
+#define RRMode        RRMode64
+#define RROutput      RROutput64
+#define RRCrtc        RRCrtc64
+#endif
 #endif
 
 #include <X11/Xlib.h>
@@ -91,16 +96,25 @@ typedef XID           KeySym64;
 #undef PictFormatType
 #endif
 
+#ifdef RANDR
+#include <X11/extensions/Xrandr.h>
+#endif
+
 #ifdef XKB
 #include <X11/extensions/XKB.h>
 #include <X11/extensions/XKBstr.h>
 #endif
 
+#ifdef XV
+#include <X11/extensions/Xvlib.h>
+#endif
+
 #include <X11/extensions/XI.h>
 
 /* Always include these, since we query them even if we don't export XINPUT. */
 #include <X11/extensions/XInput.h> /* For XDevice */
 #include <X11/extensions/Xext.h>
+#include <X11/extensions/Xcomposite.h>
 
 #undef GC
 
@@ -119,6 +133,11 @@ typedef XID           KeySym64;
 #undef Colormap
 #undef GContext
 #undef KeySym
+#ifdef RANDR
+#undef RRMode
+#undef RROutput
+#undef RRCrtc
+#endif
 #endif
 
 /* These are in exglobals.h, but that conflicts with xkbsrv.h */
diff --git a/hw/dmx/dmxcmap.c b/hw/dmx/dmxcmap.c
index 4aa586a..eed5e33 100644
--- a/hw/dmx/dmxcmap.c
+++ b/hw/dmx/dmxcmap.c
@@ -70,12 +70,15 @@ Bool dmxBECreateColormap(ColormapPtr pColormap)
     Visual             *visual    = dmxLookupVisual(pScreen, pVisual);
 
     if (visual) {
-       pCmapPriv->cmap = XCreateColormap(dmxScreen->beDisplay,
-                                         dmxScreen->scrnWin,
-                                         visual,
-                                         (pVisual->class & DynamicClass ?
-                                          AllocAll : AllocNone));
-       return (pCmapPriv->cmap != 0);
+	pCmapPriv->cmap = 0;
+	XLIB_PROLOGUE (dmxScreen);
+	pCmapPriv->cmap = XCreateColormap(dmxScreen->beDisplay,
+					  dmxScreen->scrnWin,
+					  visual,
+					  (pVisual->class & DynamicClass ?
+					   AllocAll : AllocNone));
+	XLIB_EPILOGUE (dmxScreen);
+	return (pCmapPriv->cmap != 0);
     }
     else {
        dmxLog(dmxWarning, "dmxBECreateColormap: No visual found\n");
@@ -115,7 +118,9 @@ Bool dmxBEFreeColormap(ColormapPtr pColormap)
     dmxColormapPrivPtr  pCmapPriv = DMX_GET_COLORMAP_PRIV(pColormap);
 
     if (pCmapPriv->cmap) {
+	XLIB_PROLOGUE (dmxScreen);
 	XFreeColormap(dmxScreen->beDisplay, pCmapPriv->cmap);
+	XLIB_EPILOGUE (dmxScreen);
 	pCmapPriv->cmap = (Colormap)0;
 	return TRUE;
     }
@@ -156,7 +161,9 @@ void dmxInstallColormap(ColormapPtr pColormap)
     DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
 
     if (dmxScreen->beDisplay) {
+	XLIB_PROLOGUE (dmxScreen);
 	XInstallColormap(dmxScreen->beDisplay, pCmapPriv->cmap);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 }
@@ -182,7 +189,9 @@ void dmxStoreColors(ColormapPtr pColormap, int ndef, xColorItem *pdef)
                 color[i].flags = pdef[i].flags;
                 color[i].pad   = pdef[i].pad;
             }
+	    XLIB_PROLOGUE (dmxScreen);
             XStoreColors(dmxScreen->beDisplay, pCmapPriv->cmap, color, ndef);
+	    XLIB_EPILOGUE (dmxScreen);
             xfree(color);
         } else {                /* xalloc failed, so fallback */
             XColor c;
@@ -193,7 +202,9 @@ void dmxStoreColors(ColormapPtr pColormap, int ndef, xColorItem *pdef)
                 c.green = pdef[i].green;
                 c.flags = pdef[i].flags;
                 c.pad   = pdef[i].pad;
+		XLIB_PROLOGUE (dmxScreen);
                 XStoreColor(dmxScreen->beDisplay, pCmapPriv->cmap, &c);
+		XLIB_EPILOGUE (dmxScreen);
             }
         }
 	dmxSync(dmxScreen, FALSE);
diff --git a/hw/dmx/dmxcomp.c b/hw/dmx/dmxcomp.c
new file mode 100644
index 0000000..debd97d
--- /dev/null
+++ b/hw/dmx/dmxcomp.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxcomp.h"
+#include "compint.h"
+
+extern int (*ProcCompositeVector[CompositeNumberRequests]) (ClientPtr);
+static int (*dmxSaveCompositeVector[CompositeNumberRequests]) (ClientPtr);
+
+unsigned long DMX_CLIENTWINDOW;
+unsigned long DMX_CLIENTSUBWINDOWS;
+
+static int
+dmxProcCompositeRedirectWindow (ClientPtr client)
+{
+    WindowPtr	pWin;
+    int rc;
+    REQUEST(xCompositeRedirectWindowReq);
+
+    REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
+
+    rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, client,
+			   DixSetAttrAccess|DixManageAccess|DixBlendAccess);
+    if (rc != Success)
+    {
+	client->errorValue = stuff->window;
+	return (rc == BadValue) ? BadWindow : rc;
+    }
+
+    /* Add implicit CompositeRedirectManual. This prevents clients
+       from using CompositeRedirectManual and composite extension from
+       handling window updates. Window updates are handled by
+       back-end servers. */
+    if (!GetCompWindow (pWin))
+    {
+	rc = compRedirectWindow (serverClient, pWin, CompositeRedirectManual);
+	if (rc != Success)
+	    return rc;
+    }
+
+    rc = compRedirectWindow (client, pWin, stuff->update);
+    if (rc == Success)
+    {
+	AddResource (GetCompWindow (pWin)->clients->id,
+		     DMX_CLIENTWINDOW,
+		     pWin);
+    }
+    else
+    {
+	if (!GetCompWindow (pWin)->clients->next)
+	    compUnredirectWindow (serverClient, pWin, CompositeRedirectManual);
+    }
+
+    return rc;
+}
+
+static int
+dmxProcCompositeRedirectSubwindows (ClientPtr client)
+{
+    WindowPtr	pWin;
+    int rc;
+    REQUEST(xCompositeRedirectSubwindowsReq);
+
+    REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
+
+    rc = dixLookupResource((pointer *)&pWin, stuff->window, RT_WINDOW, client,
+			   DixSetAttrAccess|DixManageAccess|DixBlendAccess);
+    if (rc != Success)
+    {
+	client->errorValue = stuff->window;
+	return (rc == BadValue) ? BadWindow : rc;
+    }
+
+    if (!GetCompSubwindows (pWin))
+    {
+	rc = compRedirectSubwindows (serverClient, pWin,
+				     CompositeRedirectManual);
+	if (rc != Success)
+	    return rc;
+    }
+
+    rc = compRedirectSubwindows (client, pWin, stuff->update);
+    if (rc == Success)
+    {
+	AddResource (GetCompSubwindows (pWin)->clients->id,
+		     DMX_CLIENTSUBWINDOWS,
+		     pWin);
+    }
+    else
+    {
+	if (!GetCompSubwindows (pWin)->clients->next)
+	    compUnredirectSubwindows (serverClient, pWin,
+				      CompositeRedirectManual);
+    }
+
+    return rc;
+}
+
+static int
+dmxFreeCompositeClientWindow (pointer value, XID ccwid)
+{
+    WindowPtr	        pWin = value;
+    CompWindowPtr	cw = GetCompWindow (pWin);
+    CompClientWindowPtr	ccw;
+    int		        count = 0;
+
+    for (ccw = cw->clients; ccw; ccw = ccw->next)
+	if (ccw->update != CompositeRedirectManual)
+	    count++;
+
+    /* free our implicit manual redirect if that's the only one left */
+    if (count <= 1)
+	compUnredirectWindow (serverClient, pWin, CompositeRedirectManual);
+
+    return Success;
+}
+
+static int
+dmxFreeCompositeClientSubwindows (pointer value, XID ccwid)
+{
+    WindowPtr	        pWin = value;
+    CompSubwindowsPtr   csw = GetCompSubwindows (pWin);
+    CompClientWindowPtr	ccw;
+    int		        count = 0;
+
+    for (ccw = csw->clients; ccw; ccw = ccw->next)
+	if (ccw->update != CompositeRedirectManual)
+	    count++;
+
+    /* free our implicit manual redirect if that's the only one left */
+    if (count <= 1)
+	compUnredirectSubwindows (serverClient, pWin,
+				  CompositeRedirectManual);
+
+    return Success;
+}
+
+/** Initialize the Proc Vector for the Composite extension.  The functions
+ *  here cannot be handled by the mi layer Composite hooks either because
+ *  the required information is no longer available when it reaches the
+ *  mi layer or no mi layer hooks exist.  This function is called from
+ *  InitOutput() since it should be initialized only once per server
+ *  generation. */
+void
+dmxInitComposite (void)
+{
+    int i;
+
+    DMX_CLIENTWINDOW = CreateNewResourceType (dmxFreeCompositeClientWindow);
+    DMX_CLIENTSUBWINDOWS =
+	CreateNewResourceType (dmxFreeCompositeClientSubwindows);
+
+    for (i = 0; i < CompositeNumberRequests; i++)
+        dmxSaveCompositeVector[i] = ProcCompositeVector[i];
+
+    ProcCompositeVector[X_CompositeRedirectWindow]
+	= dmxProcCompositeRedirectWindow;
+    ProcCompositeVector[X_CompositeRedirectSubwindows]
+	= dmxProcCompositeRedirectSubwindows;
+}
+
+/** Reset the Proc Vector for the Composite extension back to the original
+ *  functions.  This function is called from dmxCloseScreen() during the
+ *  server reset (only for screen #0). */
+void
+dmxResetComposite (void)
+{
+    int i;
+
+    for (i = 0; i < CompositeNumberRequests; i++)
+        ProcCompositeVector[i] = dmxSaveCompositeVector[i];
+}
diff --git a/hw/dmx/dmxcomp.h b/hw/dmx/dmxcomp.h
new file mode 100644
index 0000000..f9bffbf
--- /dev/null
+++ b/hw/dmx/dmxcomp.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXCOMP_H
+#define DMXCOMP_H
+
+void
+dmxInitComposite (void);
+
+void
+dmxResetComposite (void);
+
+#endif /* DMXCOMP_H */
diff --git a/hw/dmx/dmxcursor.c b/hw/dmx/dmxcursor.c
index 6218dc3..24cc7ee 100644
--- a/hw/dmx/dmxcursor.c
+++ b/hw/dmx/dmxcursor.c
@@ -33,548 +33,86 @@
  *
  */
 
-/** \file
- * This file contains code than supports cursor movement, including the
- * code that initializes and reinitializes the screen positions and
- * computes screen overlap.
- *
- * "This code is based very closely on the XFree86 equivalent
- * (xfree86/common/xf86Cursor.c)."  --David Dawes.
- *
- * "This code was then extensively re-written, as explained here."
- * --Rik Faith
- *
- * The code in xf86Cursor.c used edge lists to implement the
- * CursorOffScreen function.  The edge list computation was complex
- * (especially in the face of arbitrarily overlapping screens) compared
- * with the speed savings in the CursorOffScreen function.  The new
- * implementation has erred on the side of correctness, readability, and
- * maintainability over efficiency.  For the common (non-edge) case, the
- * dmxCursorOffScreen function does avoid a loop over all the screens.
- * When the cursor has left the screen, all the screens are searched,
- * and the first screen (in dmxScreens order) containing the cursor will
- * be returned.  If run-time profiling shows that this routing is a
- * performance bottle-neck, then an edge list may have to be
- * reimplemented.  An edge list algorithm is O(edges) whereas the new
- * algorithm is O(dmxNumScreens).  Since edges is usually 1-3 and
- * dmxNumScreens may be 30-60 for large backend walls, this trade off
- * may be compelling.
- *
- * The xf86InitOrigins routine uses bit masks during the computation and
- * is therefore limited to the length of a word (e.g., 32 or 64 bits)
- * screens.  Because Xdmx is expected to be used with a large number of
- * backend displays, this limitation was removed.  The new
- * implementation has erred on the side of readability over efficiency,
- * using the dmxSL* routines to manage a screen list instead of a
- * bitmap, and a function call to decrease the length of the main
- * routine.  Both algorithms are of the same order, and both are called
- * only at server generation time, so trading clarity and long-term
- * maintainability for efficiency does not seem justified in this case.
- */
-
 #ifdef HAVE_DMX_CONFIG_H
 #include <dmx-config.h>
 #endif
 
-#define DMX_CURSOR_DEBUG 0
-
 #include "dmx.h"
 #include "dmxsync.h"
 #include "dmxcursor.h"
 #include "dmxlog.h"
 #include "dmxprop.h"
 #include "dmxinput.h"
+#include "dmxgrab.h"
 
 #include "mipointer.h"
 #include "windowstr.h"
 #include "globals.h"
 #include "cursorstr.h"
-#include "dixevents.h"          /* For GetSpriteCursor() */
-
-#if DMX_CURSOR_DEBUG
-#define DMXDBG0(f)               dmxLog(dmxDebug,f)
-#define DMXDBG1(f,a)             dmxLog(dmxDebug,f,a)
-#define DMXDBG2(f,a,b)           dmxLog(dmxDebug,f,a,b)
-#define DMXDBG3(f,a,b,c)         dmxLog(dmxDebug,f,a,b,c)
-#define DMXDBG4(f,a,b,c,d)       dmxLog(dmxDebug,f,a,b,c,d)
-#define DMXDBG5(f,a,b,c,d,e)     dmxLog(dmxDebug,f,a,b,c,d,e)
-#define DMXDBG6(f,a,b,c,d,e,g)   dmxLog(dmxDebug,f,a,b,c,d,e,g)
-#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
-#else
-#define DMXDBG0(f)
-#define DMXDBG1(f,a)
-#define DMXDBG2(f,a,b)
-#define DMXDBG3(f,a,b,c)
-#define DMXDBG4(f,a,b,c,d)
-#define DMXDBG5(f,a,b,c,d,e)
-#define DMXDBG6(f,a,b,c,d,e,g)
-#define DMXDBG7(f,a,b,c,d,e,g,h)
-#endif
-
-static int dmxCursorDoMultiCursors = 1;
 
-/** Turn off support for displaying multiple cursors on overlapped
-    back-end displays.  See #dmxCursorDoMultiCursors. */
-void dmxCursorNoMulti(void)
+Bool
+dmxInitCursor (ScreenPtr pScreen)
 {
-    dmxCursorDoMultiCursors = 0;
-}
+    if (!dixRequestPrivate(pScreen, sizeof(dmxCursorPrivRec)))
+	return FALSE;
 
-static Bool dmxCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
-{
-    DMXScreenInfo *dmxScreen;
-    int           i;
-    int           localX = *x;
-    int           localY = *y;
-    int           globalX;
-    int           globalY;
-    
-    if (screenInfo.numScreens == 1)
-        return FALSE;
-
-                                /* On current screen? */
-    dmxScreen = &dmxScreens[(*ppScreen)->myNum];
-    if (localX >= 0
-        && localX < dmxScreen->rootWidth
-        && localY >= 0
-        && localY < dmxScreen->rootHeight)
-        return FALSE;
-
-                                /* Convert to global coordinate space */
-    globalX = dmxScreen->rootXOrigin + localX;
-    globalY = dmxScreen->rootYOrigin + localY;
-
-                                /* Is cursor on the current screen?
-                                 * This efficiently exits this routine
-                                 * for the most common case. */
-    if (ppScreen && *ppScreen) {
-        dmxScreen = &dmxScreens[(*ppScreen)->myNum];
-        if (globalX >= dmxScreen->rootXOrigin
-            && globalX < dmxScreen->rootXOrigin + dmxScreen->rootWidth
-            && globalY >= dmxScreen->rootYOrigin
-            && globalY < dmxScreen->rootYOrigin + dmxScreen->rootHeight)
-            return FALSE;
-    }
+    if (!dixRequestPrivate (dmxDevicePrivateKey, sizeof (dmxDevicePrivRec)))
+	return FALSE;
 
-                                /* Find first screen cursor is on */
-    for (i = 0; i < dmxNumScreens; i++) {
-        dmxScreen = &dmxScreens[i];
-        if (globalX >= dmxScreen->rootXOrigin
-            && globalX < dmxScreen->rootXOrigin + dmxScreen->rootWidth
-            && globalY >= dmxScreen->rootYOrigin
-            && globalY < dmxScreen->rootYOrigin + dmxScreen->rootHeight) {
-            if (dmxScreen->index == (*ppScreen)->myNum)
-                return FALSE;
-            *ppScreen = screenInfo.screens[dmxScreen->index];
-            *x        = globalX - dmxScreen->rootXOrigin;
-            *y        = globalY - dmxScreen->rootYOrigin;
-            return TRUE;
-        }
-    }
-    return FALSE;
+    return TRUE;
 }
 
-static void dmxCrossScreen(ScreenPtr pScreen, Bool entering)
+static Bool
+dmxCursorOffScreen (ScreenPtr *ppScreen,
+		    int       *x,
+		    int       *y)
 {
+    return FALSE;
 }
 
-static void dmxWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+static void
+dmxCrossScreen (ScreenPtr pScreen,
+		Bool      entering)
 {
-    DMXDBG3("dmxWarpCursor(%d,%d,%d)\n", pScreen->myNum, x, y);
-#if 11 /*BP*/
-    /* This call is depracated.  Replace with???? */
-    miPointerWarpCursor(pDev, pScreen, x, y);
-#else
-    pScreen->SetCursorPosition(pDev, pScreen, x, y, FALSE);
-#endif
 }
 
-miPointerScreenFuncRec dmxPointerCursorFuncs =
+static void
+dmxWarpCursor (DeviceIntPtr pDev,
+	       ScreenPtr    pScreen,
+	       int          x,
+	       int          y)
 {
-    dmxCursorOffScreen,
-    dmxCrossScreen,
-    dmxWarpCursor,
-    dmxeqEnqueue,        /*XXX incompatible type/function! */
-    dmxeqSwitchScreen
-};
-
-
-/** Create a list of screens that we'll manipulate. */
-static int *dmxSLCreate(void)
-{
-    int *list = malloc(dmxNumScreens * sizeof(*list));
     int i;
-    
-    for (i = 0; i < dmxNumScreens; i++)
-        list[i] = 1;
-    return list;
-}
 
-/** Free list. */
-static void dmxSLFree(int *list)
-{
-    free(list);
-}
-
-/** Find next uninitialized entry in list. */
-static int dmxSLFindNext(int *list)
-{
-    int i;
     for (i = 0; i < dmxNumScreens; i++)
-        if (list[i])
-            return i;
-    return -1;
-}
-
-/** Make one pass over all the screens and return the number updated. */
-static int dmxTryComputeScreenOrigins(int *screensLeft)
-{
-    ScreenPtr       pScreen;
-    DMXScreenInfo   *screen;
-    int             i, ref;
-    int             changed = 0;
-
-    for (i = 0; i < dmxNumScreens; i++) {
-        if (!screensLeft[i])
-            continue;
-        screen  = &dmxScreens[i];
-        switch (screen->where) {
-        case PosAbsolute:
-            dixScreenOrigins[i].x = screen->whereX;
-            dixScreenOrigins[i].y = screen->whereY;
-            ++changed, screensLeft[i] = 0;
-            break;
-        case PosRelative:
-            ref = screen->whereRefScreen;
-            if (screensLeft[ref])
-                break;
-            dixScreenOrigins[i].x = dixScreenOrigins[ref].x + screen->whereX;
-            dixScreenOrigins[i].y = dixScreenOrigins[ref].y + screen->whereY;
-            ++changed, screensLeft[i] = 0;
-            break;
-        case PosRightOf:
-            ref = screen->whereRefScreen;
-            if (screensLeft[ref])
-                break;
-            pScreen = screenInfo.screens[ref];
-            dixScreenOrigins[i].x = dixScreenOrigins[ref].x + pScreen->width;
-            dixScreenOrigins[i].y = dixScreenOrigins[ref].y;
-            ++changed, screensLeft[i] = 0;
-            break;
-        case PosLeftOf:
-            ref = screen->whereRefScreen;
-            if (screensLeft[ref])
-                break;
-            pScreen = screenInfo.screens[i];
-            dixScreenOrigins[i].x = dixScreenOrigins[ref].x - pScreen->width;
-            dixScreenOrigins[i].y = dixScreenOrigins[ref].y;
-            ++changed, screensLeft[i] = 0;
-            break;
-        case PosBelow:
-            ref = screen->whereRefScreen;
-            if (screensLeft[ref])
-                break;
-            pScreen = screenInfo.screens[ref];
-            dixScreenOrigins[i].x = dixScreenOrigins[ref].x;
-            dixScreenOrigins[i].y = dixScreenOrigins[ref].y + pScreen->height;
-            ++changed, screensLeft[i] = 0;
-            break;
-        case PosAbove:
-            ref = screen->whereRefScreen;
-            if (screensLeft[ref])
-                break;
-            pScreen = screenInfo.screens[i];
-            dixScreenOrigins[i].x = dixScreenOrigins[ref].x;
-            dixScreenOrigins[i].y = dixScreenOrigins[ref].y - pScreen->height;
-            ++changed, screensLeft[i] = 0;
-            break;
-        case PosNone:
-            dmxLog(dmxFatal, "No position information for screen %d\n", i);
-        }
-    }
-    return changed;
-}
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
 
-static void dmxComputeScreenOrigins(void)
-{
-    int             *screensLeft;
-    int             i, ref;
-    int             minX, minY;
-
-                                /* Compute origins based on
-                                 * configuration information. */
-    screensLeft = dmxSLCreate();
-    while ((i = dmxSLFindNext(screensLeft)) >= 0) {
-        while (dmxTryComputeScreenOrigins(screensLeft));
-        if ((i = dmxSLFindNext(screensLeft)) >= 0) {
-	    /* All of the remaining screens are referencing each other.
-	     * Assign a value to one of them and go through again.  This
-	     * guarantees that we will eventually terminate.
-	     */
-	    ref                     = dmxScreens[i].whereRefScreen;
-	    dixScreenOrigins[ref].x = dixScreenOrigins[ref].y = 0;
-            screensLeft[ref]        = 0;
-	}
-    }
-    dmxSLFree(screensLeft);
-
-
-                                /* Justify the topmost and leftmost to
-                                 * (0,0). */
-    minX = dixScreenOrigins[0].x;
-    minY = dixScreenOrigins[0].y;
-    for (i = 1; i < dmxNumScreens; i++) { /* Compute minX, minY */
-	if (dixScreenOrigins[i].x < minX)
-            minX = dixScreenOrigins[i].x;
-	if (dixScreenOrigins[i].y < minY)
-            minY = dixScreenOrigins[i].y;
-    }
-    if (minX || minY) {
-	for (i = 0; i < dmxNumScreens; i++) {
-	    dixScreenOrigins[i].x -= minX;
-	    dixScreenOrigins[i].y -= minY;
-	}
-    }
-}
+	if (!dmxScreen->beDisplay)
+	    continue;
 
-/** Recompute origin information in the #dmxScreens list.  This is
- * either called from #dmxInitOrigins() or from #dmxReconfig(). */
-void dmxReInitOrigins(void)
-{
-    int        i;
-
-    if (dmxNumScreens > MAXSCREENS)
-        dmxLog(dmxFatal, "dmxNumScreens = %d > MAXSCREENS = %d\n",
-               dmxNumScreens, MAXSCREENS);
-
-    for (i = 0; i < dmxNumScreens; i++) {
-        DMXScreenInfo    *dmxScreen  = &dmxScreens[i];
-        dmxLogOutput(dmxScreen,
-                     "s=%dx%d%+d%+d r=%dx%d%+d%+d @%d,%d"
-                     " (be=%dx%d depth=%d bpp=%d)\n",
-                     dmxScreen->scrnWidth, dmxScreen->scrnHeight,
-                     dmxScreen->scrnX, dmxScreen->scrnY,
-
-                     dmxScreen->rootWidth, dmxScreen->rootHeight,
-                     dmxScreen->rootX, dmxScreen->rootY,
-                     
-                     dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
-                     dmxScreen->beWidth, dmxScreen->beHeight,
-                     dmxScreen->beDepth, dmxScreen->beBPP);
+	dmxInputWarpPointer (&dmxScreen->input, pDev, x, y);
     }
 }
 
-/** Initialize screen origins (and relative position).  This is called
- * for each server generation.  For dynamic reconfiguration, use
- * #dmxReInitOrigins() instead. */
-void dmxInitOrigins(void)
-{
-    int  i;
-
-    if (dmxNumScreens > MAXSCREENS)
-        dmxLog(dmxFatal, "dmxNumScreens = %d > MAXSCREENS = %d\n",
-               dmxNumScreens, MAXSCREENS);
-
-    for (i = 0; i < dmxNumScreens; i++) {
-        DMXScreenInfo    *dmxScreen  = &dmxScreens[i];
-        dmxLogOutput(dmxScreen,
-                     "(request) s=%dx%d%+d%+d r=%dx%d%+d%+d @%d,%d (%d)"
-                     " (be=%dx%d depth=%d bpp=%d)\n",
-                     dmxScreen->scrnWidth, dmxScreen->scrnHeight,
-                     dmxScreen->scrnX, dmxScreen->scrnY,
-
-                     dmxScreen->rootWidth, dmxScreen->rootHeight,
-                     dmxScreen->rootX, dmxScreen->rootY,
-
-                     dmxScreen->whereX, dmxScreen->whereY,
-                     dmxScreen->where,
-
-                     dmxScreen->beWidth, dmxScreen->beHeight,
-                     dmxScreen->beDepth, dmxScreen->beBPP);
-    }
-
-    dmxComputeScreenOrigins();
+miPointerScreenFuncRec dmxPointerCursorFuncs = {
+    dmxCursorOffScreen,
+    dmxCrossScreen,
+    dmxWarpCursor
+};
 
-    for (i = 0; i < dmxNumScreens; i++) {
-        DMXScreenInfo  *dmxScreen = &dmxScreens[i];
-        dmxScreen->rootXOrigin = dixScreenOrigins[i].x;
-        dmxScreen->rootYOrigin = dixScreenOrigins[i].y;
-    }
+#ifdef ARGB_CURSOR
 
-    dmxReInitOrigins();
-}
+static Cursor
+dmxCreateARGBCursor (ScreenPtr pScreen,
+		     CursorPtr pCursor);
 
-/** Returns non-zero if the global \a x, \a y coordinate is on the
- * screen window of the \a dmxScreen. */
-int dmxOnScreen(int x, int y, DMXScreenInfo *dmxScreen)
-{
-#if DMX_CURSOR_DEBUG > 1
-    dmxLog(dmxDebug,
-           "dmxOnScreen %d %d,%d (r=%dx%d%+d%+d@%d,%d s=%dx%d%+d%+d)\n",
-           dmxScreen->index, x, y,
-           dmxScreen->rootWidth, dmxScreen->rootHeight,
-           dmxScreen->rootX, dmxScreen->rootY,
-           dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
-           dmxScreen->scrnWidth, dmxScreen->scrnHeight,
-           dmxScreen->scrnX, dmxScreen->scrnY);
 #endif
-    if (x >= dmxScreen->rootXOrigin
-        && x < dmxScreen->rootXOrigin + dmxScreen->rootWidth
-        && y >= dmxScreen->rootYOrigin
-        && y < dmxScreen->rootYOrigin + dmxScreen->rootHeight) return 1;
-    return 0;
-}
-
-/** Returns non-zero if \a a overlaps \a b. */
-static int dmxDoesOverlap(DMXScreenInfo *a, DMXScreenInfo *b)
-{
-    if (dmxOnScreen(a->rootXOrigin,
-                    a->rootYOrigin,                 b))
-        return 1;
-
-    if (dmxOnScreen(a->rootXOrigin,
-                    a->rootYOrigin + a->scrnWidth,  b))
-        return 1;
-
-    if (dmxOnScreen(a->rootXOrigin + a->scrnHeight,
-                    a->rootYOrigin,                 b))
-        return 1;
-
-    if (dmxOnScreen(a->rootXOrigin + a->scrnHeight,
-                    a->rootYOrigin + a->scrnWidth,  b))
-        return 1;
-
-    if (dmxOnScreen(b->rootXOrigin,
-                    b->rootYOrigin,                 a))
-        return 1;
-
-    if (dmxOnScreen(b->rootXOrigin,
-                    b->rootYOrigin + b->scrnWidth,  a))
-        return 1;
-
-    if (dmxOnScreen(b->rootXOrigin + b->scrnHeight,
-                    b->rootYOrigin,                 a))
-        return 1;
-
-    if (dmxOnScreen(b->rootXOrigin + b->scrnHeight,
-                    b->rootYOrigin + b->scrnWidth,  a))
-        return 1;
-
-    return 0;
-}
-
-/** Used with #dmxInterateOverlap to print out a list of screens which
- * overlap each other. */
-static void *dmxPrintOverlap(DMXScreenInfo *dmxScreen, void *closure)
-{
-    DMXScreenInfo *a = closure;
-    if (dmxScreen != a) {
-        if (dmxScreen->cursorNotShared)
-            dmxLogOutputCont(a, " [%d/%s]", dmxScreen->index, dmxScreen->name);
-        else
-            dmxLogOutputCont(a, " %d/%s", dmxScreen->index, dmxScreen->name);
-    }
-    return NULL;
-}
-
-/** Iterate over the screens which overlap with the \a start screen,
- * calling \a f with the \a closure for each argument.  Often used with
- * #dmxPrintOverlap. */
-static void *dmxIterateOverlap(DMXScreenInfo *start,
-                               void *(*f)(DMXScreenInfo *dmxScreen, void *),
-                               void *closure)
-{
-    DMXScreenInfo *pt;
-
-    if (!start->over) return f(start, closure);
-
-    for (pt = start->over; /* condition at end of loop */; pt = pt->over) {
-        void *retval;
-        if ((retval = f(pt, closure))) return retval;
-        if (pt == start) break;
-    }
-    return NULL;
-}
-
-/** Used with #dmxPropertyIterate to determine if screen \a a is the
- * same as the screen \a closure. */
-static void *dmxTestSameDisplay(DMXScreenInfo *a, void *closure)
-{
-    DMXScreenInfo *b = closure;
-
-    if (a == b)
-        return a;
-    return NULL;
-}
-
-/** Detects overlapping dmxScreens and creates circular lists.  This
- * uses an O(dmxNumScreens^2) algorithm, but dmxNumScreens is < 100 and
- * the computation only needs to be performed for every server
- * generation or dynamic reconfiguration . */
-void dmxInitOverlap(void)
-{
-    int           i, j;
-    DMXScreenInfo *a, *b, *pt;
-
-    for (i = 0; i < dmxNumScreens; i++)
-        dmxScreens[i].over = NULL;
-
-    for (i = 0; i < dmxNumScreens; i++) {
-        a = &dmxScreens[i];
-        
-        for (j = i+1; j < dmxNumScreens; j++) {
-            b = &dmxScreens[j];
-            if (b->over)
-                continue;
-            
-            if (dmxDoesOverlap(a, b)) {
-                DMXDBG6("%d overlaps %d: a=%p %p b=%p %p\n",
-                        a->index, b->index, a, a->over, b, b->over);
-                b->over = (a->over ? a->over : a);
-                a->over = b;
-            }
-        }
-    }
-
-    for (i = 0; i < dmxNumScreens; i++) {
-        a = &dmxScreens[i];
-        
-        if (!a->over)
-            continue;
-        
-                                /* Flag all pairs that are on same display */
-        for (pt = a->over; pt != a; pt = pt->over) {
-            if (dmxPropertyIterate(a, dmxTestSameDisplay, pt)) {
-                /* The ->over sets contain the transitive set of screens
-                 * that overlap.  For screens that are on the same
-                 * backend display, we only want to exclude pairs of
-                 * screens that mutually overlap on the backend display,
-                 * so we call dmxDoesOverlap, which is stricter than the
-                 * ->over set. */
-                if (!dmxDoesOverlap(a, pt))
-                    continue;
-                a->cursorNotShared  = 1;
-                pt->cursorNotShared = 1;
-                dmxLog(dmxInfo,
-                       "Screen %d and %d overlap on %s\n",
-                       a->index, pt->index, a->name);
-            }
-        }
-    }
-
-    for (i = 0; i < dmxNumScreens; i++) {
-        a = &dmxScreens[i];
-        
-        if (a->over) {
-            dmxLogOutput(a, "Overlaps");
-            dmxIterateOverlap(a, dmxPrintOverlap, a);
-            dmxLogOutputCont(a, "\n");
-        }
-    }
-}
 
 /** Create \a pCursor on the back-end associated with \a pScreen. */
-void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor)
+void
+dmxBECreateCursor (ScreenPtr pScreen,
+		   CursorPtr pCursor)
 {
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
     dmxCursorPrivPtr  pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
@@ -587,9 +125,49 @@ void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor)
     unsigned long     m;
     int               i;
 
-    if (!pCursorPriv)
+    if (pCursorPriv->cursor)
 	return;
 
+    if (IsAnimCur (pCursor))
+    {
+	AnimCurPtr  ac = GetAnimCur (pCursor);
+	XAnimCursor *cursors;
+	int         i;
+
+	cursors = xalloc (sizeof (*cursors) * ac->nelt);
+	if (!cursors)
+	    return;
+
+	for (i = 0; i < ac->nelt; i++)
+	{
+	    dmxCursorPrivPtr pEltPriv = DMX_GET_CURSOR_PRIV (ac->elts[i].pCursor,
+							     pScreen);
+
+	    dmxBECreateCursor (pScreen, ac->elts[i].pCursor);
+
+	    cursors[i].cursor = pEltPriv->cursor;
+	    cursors[i].delay  = ac->elts[i].delay;
+	}
+
+	pCursorPriv->cursor = XRenderCreateAnimCursor (dmxScreen->beDisplay,
+						       ac->nelt,
+						       cursors);
+
+	xfree (cursors);
+
+	if (pCursorPriv->cursor)
+	    return;
+    }
+
+#ifdef ARGB_CURSOR
+    if (pCursor->bits->argb)
+    {
+	pCursorPriv->cursor = dmxCreateARGBCursor (pScreen, pCursor);
+	if (pCursorPriv->cursor)
+	    return;
+    }
+#endif
+
     m = GCFunction | GCPlaneMask | GCForeground | GCBackground | GCClipMask;
     v.function = GXcopy;
     v.plane_mask = AllPlanes;
@@ -600,14 +178,18 @@ void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor)
     for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
 	if (dmxScreen->bePixmapFormats[i].depth == 1) {
 	    /* Create GC in the back-end servers */
+	    XLIB_PROLOGUE (dmxScreen);
 	    gc = XCreateGC(dmxScreen->beDisplay, dmxScreen->scrnDefDrawables[i],
 			   m, &v);
+	    XLIB_EPILOGUE (dmxScreen);
 	    break;
 	}
     }
     if (!gc)
         dmxLog(dmxFatal, "dmxRealizeCursor: gc not initialized\n");
 
+    XLIB_PROLOGUE (dmxScreen);
+
     src = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
 			pBits->width, pBits->height, 1);
     msk = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
@@ -652,329 +234,113 @@ void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor)
     XFreePixmap(dmxScreen->beDisplay, msk);
     XFreeGC(dmxScreen->beDisplay, gc);
 
-    dmxSync(dmxScreen, FALSE);
+    XLIB_EPILOGUE (dmxScreen);
 }
 
-static Bool _dmxRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+static Bool
+_dmxRealizeCursor (ScreenPtr pScreen,
+		   CursorPtr pCursor)
 {
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
-    dmxCursorPrivPtr  pCursorPriv;
-
-    DMXDBG2("_dmxRealizeCursor(%d,%p)\n", pScreen->myNum, pCursor);
-
-    DMX_SET_CURSOR_PRIV(pCursor, pScreen, xalloc(sizeof(*pCursorPriv)));
-    if (!DMX_GET_CURSOR_PRIV(pCursor, pScreen))
-	return FALSE;
+    dmxCursorPrivPtr pCursorPriv;
 
-    pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
-    pCursorPriv->cursor = (Cursor)0;
+    pCursorPriv = DMX_GET_CURSOR_PRIV (pCursor, pScreen);
+    pCursorPriv->cursor = (Cursor) 0;
 
-    if (!dmxScreen->beDisplay)
-	return TRUE;
+    if (dmxScreen->beDisplay)
+	dmxBECreateCursor (pScreen, pCursor);
 
-    dmxBECreateCursor(pScreen, pCursor);
     return TRUE;
 }
 
 /** Free \a pCursor on the back-end associated with \a pScreen. */
-Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor)
-{
-    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
-    dmxCursorPrivPtr  pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
-
-    if (pCursorPriv) {
-	XFreeCursor(dmxScreen->beDisplay, pCursorPriv->cursor);
-	pCursorPriv->cursor = (Cursor)0;
-	return TRUE;
-    }
-
-    return FALSE;
-}
-
-static Bool _dmxUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+Bool
+dmxBEFreeCursor (ScreenPtr pScreen,
+		 CursorPtr pCursor)
 {
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
+    dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV (pCursor, pScreen);
 
-    DMXDBG2("_dmxUnrealizeCursor(%d,%p)\n",
-            pScreen->myNum, pCursor);
-
-    if (dmxScreen->beDisplay) {
-	if (dmxBEFreeCursor(pScreen, pCursor))
-	    xfree(DMX_GET_CURSOR_PRIV(pCursor, pScreen));
-    }
-    DMX_SET_CURSOR_PRIV(pCursor, pScreen, NULL);
+    if (pCursorPriv->cursor)
+    {
+	XLIB_PROLOGUE (dmxScreen);
+	XFreeCursor (dmxScreen->beDisplay, pCursorPriv->cursor);
+	XLIB_EPILOGUE (dmxScreen);
 
-    return TRUE;
-}
+	pCursorPriv->cursor = (Cursor) 0;
 
-static void _dmxMoveCursor(ScreenPtr pScreen, int x, int y)
-{
-    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
-    int           newX       = x + dmxScreen->rootX;
-    int           newY       = y + dmxScreen->rootY;
-
-    if (newX < 0) newX = 0;
-    if (newY < 0) newY = 0;
-
-    DMXDBG5("_dmxMoveCursor(%d,%d,%d) -> %d,%d\n",
-            pScreen->myNum, x, y, newX, newY);
-    if (dmxScreen->beDisplay) {
-	XWarpPointer(dmxScreen->beDisplay, None, dmxScreen->scrnWin,
-		     0, 0, 0, 0, newX, newY);
-	dmxSync(dmxScreen, TRUE);
-    }
-}
-
-static void _dmxSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
-{
-    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
+	if (IsAnimCur (pCursor))
+	{
+	    AnimCurPtr ac = GetAnimCur (pCursor);
+	    int        i;
 
-    DMXDBG4("_dmxSetCursor(%d,%p,%d,%d)\n", pScreen->myNum, pCursor, x, y);
-
-    if (pCursor) {
-	dmxCursorPrivPtr  pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
-	if (pCursorPriv && dmxScreen->curCursor != pCursorPriv->cursor) {
-	    if (dmxScreen->beDisplay)
-		XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
-			      pCursorPriv->cursor);
-            dmxScreen->cursor        = pCursor;
-	    dmxScreen->curCursor     = pCursorPriv->cursor;
-            dmxScreen->cursorVisible = 1;
+	    for (i = 0; i < ac->nelt; i++)
+		dmxBEFreeCursor (pScreen, ac->elts[i].pCursor);
 	}
-	_dmxMoveCursor(pScreen, x, y);
-    } else {
-	if (dmxScreen->beDisplay)
-	    XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
-			  dmxScreen->noCursor);
-        dmxScreen->cursor        = NULL;
-	dmxScreen->curCursor     = (Cursor)0;
-        dmxScreen->cursorVisible = 0;
-    }
-    if (dmxScreen->beDisplay) dmxSync(dmxScreen, TRUE);
-}
 
-static Bool dmxRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
-    DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
-    DMXScreenInfo *pt;
-
-    if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared)
-        return _dmxRealizeCursor(pScreen, pCursor);
-
-    for (pt = start->over; /* condition at end of loop */; pt = pt->over) {
-        if (pt->cursorNotShared)
-            continue;
-        _dmxRealizeCursor(screenInfo.screens[pt->index], pCursor);
-        if (pt == start)
-            break;
+	return TRUE;
     }
-    return TRUE;
-}
 
-static Bool dmxUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
-    DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
-    DMXScreenInfo *pt;
-
-    if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared)
-        return _dmxUnrealizeCursor(pScreen, pCursor);
-
-    for (pt = start->over; /* condition at end of loop */; pt = pt->over) {
-        if (pt->cursorNotShared)
-            continue;
-        _dmxUnrealizeCursor(screenInfo.screens[pt->index], pCursor);
-        if (pt == start)
-            break;
-    }
-    return TRUE;
+    return FALSE;
 }
 
-static CursorPtr dmxFindCursor(DMXScreenInfo *start)
+static Bool
+_dmxUnrealizeCursor (ScreenPtr pScreen,
+		     CursorPtr pCursor)
 {
-    DMXScreenInfo *pt;
-
-    if (!start || !start->over)
-        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(inputInfo.pointer);
+    dmxBEFreeCursor (pScreen, pCursor);
+    return TRUE;
 }
 
-/** Move the cursor to coordinates (\a x, \a y)on \a pScreen.  This
- * function is usually called via #dmxPointerSpriteFuncs, except during
- * reconfiguration when the cursor is repositioned to force an update on
- * newley overlapping screens and on screens that no longer overlap.
- *
- * The coords (x,y) are in global coord space.  We'll loop over the
- * 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(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
+static Bool
+dmxRealizeCursor (DeviceIntPtr pDev,
+		  ScreenPtr    pScreen,
+		  CursorPtr    pCursor)
 {
-    DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
-    DMXScreenInfo *pt;
-
-    DMXDBG3("dmxMoveCursor(%d,%d,%d)\n", pScreen->myNum, x, y);
-
-    if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) {
-        _dmxMoveCursor(pScreen, x, y);
-        return;
-    }
+    if (pDev == inputInfo.pointer)
+	return _dmxRealizeCursor (pScreen, pCursor);
 
-    for (pt = start->over; /* condition at end of loop */; pt = pt->over) {
-        if (pt->cursorNotShared)
-            continue;
-        if (dmxOnScreen(x + start->rootXOrigin, y + start->rootYOrigin, pt)) {
-            if (/* pt != start && */ !pt->cursorVisible) {
-                if (!pt->cursor) {
-                                /* This only happens during
-                                 * reconfiguration when a new overlap
-                                 * occurs. */
-                    CursorPtr pCursor;
-                    
-                    if ((pCursor = dmxFindCursor(start)))
-                        _dmxRealizeCursor(screenInfo.screens[pt->index],
-                                          pt->cursor = pCursor);
-                    
-                }
-                _dmxSetCursor(screenInfo.screens[pt->index],
-                              pt->cursor,
-                              x + start->rootXOrigin - pt->rootXOrigin,
-                              y + start->rootYOrigin - pt->rootYOrigin);
-            }
-            _dmxMoveCursor(screenInfo.screens[pt->index],
-                           x + start->rootXOrigin - pt->rootXOrigin,
-                           y + start->rootYOrigin - pt->rootYOrigin);
-        } else if (/* pt != start && */ pt->cursorVisible) {
-            _dmxSetCursor(screenInfo.screens[pt->index],
-                          NULL,
-                          x + start->rootXOrigin - pt->rootXOrigin,
-                          y + start->rootYOrigin - pt->rootYOrigin);
-        }
-        if (pt == start)
-            break;
-    }
+    return TRUE;
 }
 
-static void dmxSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+static Bool
+dmxUnrealizeCursor (DeviceIntPtr pDev,
+		    ScreenPtr    pScreen,
+		    CursorPtr    pCursor)
 {
-    DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
-    DMXScreenInfo *pt;
-    int           GX, GY, gx, gy;
-
-    DMXDBG5("dmxSetCursor(%d %p, %p,%d,%d)\n",
-            pScreen->myNum, start, pCursor, x, y);
-
-                                /* We do this check here because of two cases:
-                                 *
-                                 * 1) if a client calls XWarpPointer()
-                                 * and Xinerama is not running, we can
-                                 * have mi's notion of the pointer
-                                 * position out of phase with DMX's
-                                 * notion.
-                                 *
-                                 * 2) if a down button is held while the
-                                 * cursor moves outside the root window,
-                                 * mi's notion of the pointer position
-                                 * is out of phase with DMX's notion and
-                                 * the cursor can remain visible when it
-                                 * shouldn't be. */
-
-    dmxGetGlobalPosition(&GX, &GY);
-    gx = start->rootXOrigin + x;
-    gy = start->rootYOrigin + y;
-    if (x && y && (GX != gx || GY != gy))
-        dmxCoreMotion(NULL, gx, gy, 0, DMX_NO_BLOCK);
-    
-    if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) {
-        _dmxSetCursor(pScreen, pCursor, x, y);
-        return;
-    }
+    if (pDev == inputInfo.pointer)
+	return _dmxUnrealizeCursor (pScreen, pCursor);
 
-    for (pt = start->over; /* condition at end of loop */; pt = pt->over) {
-        if (pt->cursorNotShared)
-            continue;
-        if (dmxOnScreen(x + start->rootXOrigin, y + start->rootYOrigin, pt)) {
-            _dmxSetCursor(screenInfo.screens[pt->index], pCursor,
-                          x + start->rootXOrigin - pt->rootXOrigin,
-                          y + start->rootYOrigin - pt->rootYOrigin);
-        } else {
-            _dmxSetCursor(screenInfo.screens[pt->index], NULL,
-                          x + start->rootXOrigin - pt->rootXOrigin,
-                          y + start->rootYOrigin - pt->rootYOrigin);
-        }
-        if (pt == start)
-            break;
-    }
+    return TRUE;
 }
 
-
-/** This routine is used by the backend input routines to hide the
- * cursor on a screen that is being used for relative input.  \see
- * dmxbackend.c */
-void dmxHideCursor(DMXScreenInfo *dmxScreen)
+static void
+dmxMoveCursor (DeviceIntPtr pDev,
+	       ScreenPtr    pScreen,
+	       int          x,
+	       int          y)
 {
-    int       x, y;
-    ScreenPtr pScreen = screenInfo.screens[dmxScreen->index];
-
-    dmxGetGlobalPosition(&x, &y);
-    _dmxSetCursor(pScreen, NULL, x, y);
 }
 
-/** This routine is called during reconfiguration to make sure the
- * cursor is visible. */
-void dmxCheckCursor(void)
+static void
+dmxSetCursor (DeviceIntPtr pDev,
+	      ScreenPtr    pScreen,
+	      CursorPtr    pCursor,
+	      int          x,
+	      int          y)
 {
-    int           i;
-    int           x, y;
-    ScreenPtr     pScreen;
-    DMXScreenInfo *firstScreen;
-
-    dmxGetGlobalPosition(&x, &y);
-    firstScreen = dmxFindFirstScreen(x, y);
-
-    DMXDBG2("dmxCheckCursor %d %d\n", x, y);
-    for (i = 0; i < dmxNumScreens; i++) {
-        DMXScreenInfo *dmxScreen = &dmxScreens[i];
-        pScreen                  = screenInfo.screens[dmxScreen->index];
-
-        if (!dmxOnScreen(x, y, dmxScreen)) {
-#if 00
-            if (firstScreen && i == miPointerCurrentScreen()->myNum)
-                miPointerSetNewScreen(firstScreen->index, x, y);
-#else
-            if (firstScreen && i == miPointerGetScreen(inputInfo.pointer)->myNum)
-                miPointerSetScreen(inputInfo.pointer, firstScreen->index, x, y);
-#endif
-            _dmxSetCursor(pScreen, NULL,
-                          x - dmxScreen->rootXOrigin,
-                          y - dmxScreen->rootYOrigin);
-        } else {
-            if (!dmxScreen->cursor) {
-                CursorPtr pCursor;
-                
-                if ((pCursor = dmxFindCursor(dmxScreen))) {
-                    _dmxRealizeCursor(pScreen, dmxScreen->cursor = pCursor);
-                }
-            }
-            _dmxSetCursor(pScreen, dmxScreen->cursor,
-                          x - dmxScreen->rootXOrigin,
-                          y - dmxScreen->rootYOrigin);
-        }
-    }
-    DMXDBG2("   leave dmxCheckCursor %d %d\n", x, y);
 }
 
-static Bool dmxDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr)
+static Bool
+dmxDeviceCursorInitialize (DeviceIntPtr pDev,
+			   ScreenPtr    pScr)
 {
     return TRUE;
 }
 
-static void dmxDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr)
+static void
+dmxDeviceCursorCleanup (DeviceIntPtr pDev,
+			ScreenPtr    pScr)
 {
 }
 
@@ -987,3 +353,62 @@ miPointerSpriteFuncRec dmxPointerSpriteFuncs =
     dmxDeviceCursorInitialize,
     dmxDeviceCursorCleanup
 };
+
+#ifdef ARGB_CURSOR
+
+#include <X11/extensions/Xrender.h>
+
+static Cursor
+dmxCreateARGBCursor (ScreenPtr pScreen,
+		     CursorPtr pCursor)
+{
+    Pixmap	      xpixmap;
+    XlibGC	      xgc;
+    XImage	      *ximage;
+    XRenderPictFormat *xformat;
+    Picture	      xpicture;
+    Cursor	      cursor = None;
+    DMXScreenInfo     *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    XLIB_PROLOGUE (dmxScreen);
+
+    xpixmap = XCreatePixmap (dmxScreen->beDisplay,
+			     dmxScreen->scrnWin,
+			     pCursor->bits->width,
+			     pCursor->bits->height,
+			     32);
+
+    xgc = XCreateGC (dmxScreen->beDisplay, xpixmap, 0, NULL);
+
+    ximage = XCreateImage (dmxScreen->beDisplay,
+			   DefaultVisual (dmxScreen->beDisplay, 0),
+			   32, ZPixmap, 0,
+			   (char *) pCursor->bits->argb,
+			   pCursor->bits->width,
+			   pCursor->bits->height,
+			   32, pCursor->bits->width * 4);
+
+    XPutImage (dmxScreen->beDisplay, xpixmap, xgc, ximage,
+	       0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
+
+    XFree (ximage);
+    XFreeGC (dmxScreen->beDisplay, xgc);
+
+    xformat = XRenderFindStandardFormat (dmxScreen->beDisplay,
+					 PictStandardARGB32);
+    xpicture = XRenderCreatePicture (dmxScreen->beDisplay, xpixmap,
+				     xformat, 0, 0);
+
+    cursor = XRenderCreateCursor (dmxScreen->beDisplay, xpicture,
+				  pCursor->bits->xhot,
+				  pCursor->bits->yhot);
+
+    XRenderFreePicture (dmxScreen->beDisplay, xpicture);
+    XFreePixmap (dmxScreen->beDisplay, xpixmap);
+
+    XLIB_EPILOGUE (dmxScreen);
+
+    return cursor;
+}
+
+#endif
diff --git a/hw/dmx/dmxcursor.h b/hw/dmx/dmxcursor.h
index da8ea5e..19c596b 100644
--- a/hw/dmx/dmxcursor.h
+++ b/hw/dmx/dmxcursor.h
@@ -1,3 +1,4 @@
+/* $XFree86$ */
 /*
  * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
  *
@@ -51,22 +52,11 @@ extern miPointerScreenFuncRec dmxPointerCursorFuncs;
 /** Sprite functions for mi layer. \see dmxcursor.c \see dmxscrinit.c */
 extern miPointerSpriteFuncRec dmxPointerSpriteFuncs;
 
-extern void dmxReInitOrigins(void);
-extern void dmxInitOrigins(void);
-extern void dmxInitOverlap(void);
-extern void dmxCursorNoMulti(void);
-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);
+extern Bool dmxInitCursor(ScreenPtr pScreen);
 
 extern void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor);
 extern Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor);
 
 #define DMX_GET_CURSOR_PRIV(_pCursor, _pScreen) \
     ((dmxCursorPrivPtr)dixLookupPrivate(&(_pCursor)->devPrivates, _pScreen))
-
-#define DMX_SET_CURSOR_PRIV(_pCursor, _pScreen, v) \
-    dixSetPrivate(&(_pCursor)->devPrivates, _pScreen, v)
-
 #endif /* DMXCURSOR_H */
diff --git a/hw/dmx/dmxdbus.c b/hw/dmx/dmxdbus.c
new file mode 100644
index 0000000..0ea4628
--- /dev/null
+++ b/hw/dmx/dmxdbus.c
@@ -0,0 +1,549 @@
+/*
+ * Copyright © 2006-2007 Daniel Stone
+ * Copyright © 2008 Novell, Inc.
+ *
+ * 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: Daniel Stone <daniel@fooishbar.org>
+ *         David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "config-backends.h"
+#include "dixstruct.h"
+#include "opaque.h" /* for 'display': there should be a better way. */
+#include "dmxdbus.h"
+#include "dmxextension.h"
+
+#define API_VERSION 3
+
+#define MATCH_RULE "type='method_call',interface='org.x.config.dmx'"
+#define MALFORMED_MSG "[dmx/dbus] malformed message, dropping"
+
+struct connection_info {
+    char           busobject[32];
+    char           busname[64];
+    DBusConnection *connection;
+};
+
+static void
+reset_info (struct connection_info *info)
+{
+    info->connection = NULL;
+    info->busname[0] = '\0';
+    info->busobject[0] = '\0';
+}
+
+static int
+enable_screen (DBusMessage *message,
+	       DBusMessage *reply,
+	       DBusError   *error)
+{
+    DMXScreenAttributesRec attr;
+    uint32_t               screen;
+
+    if (!dbus_message_get_args (message, error,
+				DBUS_TYPE_UINT32,
+				&screen,
+				DBUS_TYPE_INVALID))
+    {
+	DebugF (MALFORMED_MSG ": %s, %s", error->name, error->message);
+	return BadValue;
+    }
+
+    if (screen >= dmxGetNumScreens ())
+    {
+	dbus_set_error (error,
+			DMX_ERROR_INVALID_SCREEN,
+			"Screen %d does not exist", screen);
+	return BadValue;
+    }
+
+    dmxGetScreenAttributes (screen, &attr);
+
+    if (!attr.name || !*attr.name)
+    {
+	dbus_set_error (error,
+			DBUS_ERROR_FAILED,
+			"No back-end server attached to screen %d",
+			screen);
+	return BadValue;
+    }
+
+    dmxEnableScreen(screen);
+
+    return Success;
+}
+
+static int
+disable_screen (DBusMessage *message,
+		DBusMessage *reply,
+		DBusError   *error)
+{
+    DMXScreenAttributesRec attr;
+    uint32_t               screen;
+
+    if (!dbus_message_get_args (message, error,
+				DBUS_TYPE_UINT32,
+				&screen,
+				DBUS_TYPE_INVALID))
+    {
+	DebugF (MALFORMED_MSG ": %s, %s", error->name, error->message);
+	return BadValue;
+    }
+
+    if (screen >= dmxGetNumScreens ())
+    {
+	dbus_set_error (error,
+			DMX_ERROR_INVALID_SCREEN,
+			"Screen %d does not exist", screen);
+	return BadValue;
+    }
+
+    dmxGetScreenAttributes (screen, &attr);
+
+    if (!attr.name || !*attr.name)
+    {
+	dbus_set_error (error,
+			DBUS_ERROR_FAILED,
+			"No back-end server attached to screen %d",
+			screen);
+	return BadValue;
+    }
+
+    dmxDisableScreen(screen);
+
+    return Success;
+}
+
+static int
+attach_screen (DBusMessage *message,
+	       DBusMessage *reply,
+	       DBusError   *error)
+{
+    DMXScreenAttributesRec attr;
+    uint32_t               window, screen, auth_type_len, auth_data_len;
+    char                   *display, *auth_type, *auth_data, *name;
+    int                    ret;
+
+    if (!dbus_message_get_args (message, error,
+				DBUS_TYPE_UINT32,
+				&screen,
+				DBUS_TYPE_STRING,
+				&display,
+				DBUS_TYPE_STRING,
+				&name,
+				DBUS_TYPE_UINT32,
+				&window,
+				DBUS_TYPE_ARRAY,  DBUS_TYPE_BYTE,
+				&auth_type, &auth_type_len,
+				DBUS_TYPE_ARRAY,  DBUS_TYPE_BYTE,
+				&auth_data, &auth_data_len,
+				DBUS_TYPE_INVALID))
+    {
+	DebugF (MALFORMED_MSG ": %s, %s", error->name, error->message);
+	return BadValue;
+    }
+
+    if (!*name)
+    {
+	dbus_set_error (error,
+			DBUS_ERROR_FAILED,
+			"Cannot use empty string for screen name");
+	return BadValue;
+    }
+
+    if (screen >= dmxGetNumScreens ())
+    {
+	dbus_set_error (error,
+			DMX_ERROR_INVALID_SCREEN,
+			"Screen %d does not exist", screen);
+	return BadValue;
+    }
+
+    dmxGetScreenAttributes (screen, &attr);
+
+    if (attr.name && *attr.name)
+    {
+	dbus_set_error (error,
+			DMX_ERROR_SCREEN_IN_USE,
+			"Back-end server already attached to screen %d",
+			screen);
+	return BadValue;
+    }
+
+    memset (&attr, 0, sizeof (attr));
+
+    attr.name        = name;
+    attr.displayName = display;
+
+    ret = dmxAttachScreen (screen,
+			   &attr,
+			   window,
+			   auth_type,
+			   auth_type_len,
+			   auth_data,
+			   auth_data_len,
+			   (dmxErrorSetProcPtr) dbus_set_error,
+			   error,
+			   DBUS_ERROR_FAILED);
+
+    if (ret != Success)
+    {
+        DebugF ("[dmx/dbus] dmxAttachScreen failed\n");
+        return ret;
+    }
+
+    return Success;
+}
+
+static int
+detach_screen (DBusMessage *message,
+	       DBusMessage *reply,
+	       DBusError   *error)
+{
+    uint32_t screen;
+    int      ret;
+
+    if (!dbus_message_get_args (message, error,
+				DBUS_TYPE_UINT32,
+				&screen,
+				DBUS_TYPE_INVALID))
+   { 
+       DebugF (MALFORMED_MSG ": %s, %s", error->name, error->message);
+       return BadValue;
+    }
+
+    ret = dmxDetachScreen (screen);
+    if (ret != Success)
+    {
+        DebugF ("[dmx/dbus] dmxDetachScreen failed\n");
+        return ret;
+    }
+
+    return Success;
+}
+
+static int
+add_input (DBusMessage *message,
+	   DBusMessage *reply,
+	   DBusError   *error)
+{
+    DMXInputAttributesRec attr;
+    DBusMessageIter       iter;
+    uint32_t              screen, id;
+    dbus_bool_t           core;
+    int                   input_id, ret;
+
+    dbus_message_iter_init_append (reply, &iter);
+
+    if (!dbus_message_get_args (message, error,
+				DBUS_TYPE_UINT32,
+				&screen,
+				DBUS_TYPE_BOOLEAN,
+				&core,
+				DBUS_TYPE_INVALID))
+    {
+	DebugF (MALFORMED_MSG ": %s, %s", error->name, error->message);
+	return BadValue;
+    }
+
+    memset (&attr, 0, sizeof (attr));
+
+    attr.physicalScreen = screen;
+    attr.inputType      = 2;
+
+    ret = dmxAddInput (&attr, &input_id);
+    if (ret != Success)
+    {
+	DebugF ("[dmx/dbus] dmxAddInput failed\n");
+	return ret;
+    }
+
+    id = input_id;
+
+    if (!dbus_message_iter_append_basic (&iter,
+					 DBUS_TYPE_UINT32,
+					 &id))
+    {
+	ErrorF ("[dmx/dbus] couldn't append to iterator\n");
+	dmxRemoveInput (id);
+	return BadAlloc;
+    }
+
+    return Success;
+}
+
+static int
+remove_input (DBusMessage *message,
+	      DBusMessage *reply,
+	      DBusError   *error)
+{
+    uint32_t id;
+    int      ret;
+
+    if (!dbus_message_get_args (message, error,
+				DBUS_TYPE_UINT32,
+				&id,
+				DBUS_TYPE_INVALID))
+    {
+	DebugF (MALFORMED_MSG ": %s, %s", error->name, error->message);
+	return BadValue;
+    }
+
+    ret = dmxRemoveInput (id);
+    if (ret != Success)
+    {
+	DebugF ("[dmx/dbus] dmxRemoveInput failed\n");
+	return ret;
+    }
+
+    return Success;
+}
+
+static int
+list_screens (DBusMessage *message,
+	      DBusMessage *reply,
+	      DBusError   *error)
+{
+    DBusMessageIter iter, subiter;
+    int		    screen;
+
+    dbus_message_iter_init_append (reply, &iter);
+
+    for (screen = 0; screen < dmxGetNumScreens (); screen++)
+    {
+	DMXScreenAttributesRec attribs;
+
+	dmxGetScreenAttributes (screen, &attribs);
+
+	if (!attribs.name || !*attribs.name)
+	    continue;
+
+        if (!dbus_message_iter_open_container (&iter,
+					       DBUS_TYPE_STRUCT,
+					       NULL,
+					       &subiter))
+	{
+            ErrorF ("[dmx/dbus] couldn't init container\n");
+            return BadAlloc;
+        }
+
+        if (!dbus_message_iter_append_basic (&subiter,
+					     DBUS_TYPE_UINT32,
+					     &screen))
+	{
+            ErrorF ("[dmx/dbus] couldn't append to iterator\n");
+            return BadAlloc;
+        }
+
+        if (!dbus_message_iter_append_basic (&subiter,
+					     DBUS_TYPE_STRING,
+					     &attribs.name))
+	{
+            ErrorF("[dmx/dbus] couldn't append to iterator\n");
+            return BadAlloc;
+        }
+
+        if (!dbus_message_iter_close_container (&iter, &subiter))
+	{
+            ErrorF ("[dmx/dbus] couldn't close container\n");
+            return BadAlloc;
+        }
+    }
+
+    return Success;
+}
+
+static int
+get_version (DBusMessage *message,
+	     DBusMessage *reply,
+	     DBusError   *error)
+{
+    DBusMessageIter iter;
+    unsigned int    version = API_VERSION;
+
+    dbus_message_iter_init_append (reply, &iter);
+
+    if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &version))
+    {
+        ErrorF ("[dmx/dbus] couldn't append version\n");
+        return BadAlloc;
+    }
+
+    return Success;
+}
+
+static DBusHandlerResult
+message_handler (DBusConnection *connection,
+		 DBusMessage    *message,
+		 void           *data)
+{
+    struct connection_info *info = data;
+    DBusMessage            *reply;
+    DBusError              error;
+
+    /* ret is the overall D-Bus handler result, whereas err is the internal
+     * X error from our individual functions. */
+    int                    err, ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    DebugF ("[dmx/dbus] received a message for %s\n",
+	    dbus_message_get_interface (message));
+
+    dbus_error_init (&error);
+
+    reply = dbus_message_new_method_return (message);
+    if (!reply)
+    {
+        ErrorF ("[dmx/dbus] failed to create reply\n");
+        ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
+        goto err_start;
+    }
+
+    if (strcmp (dbus_message_get_member (message), "enableScreen") == 0)
+        err = enable_screen (message, reply, &error);
+    else if (strcmp (dbus_message_get_member (message), "disableScreen") == 0)
+        err = disable_screen (message, reply, &error);
+    else if (strcmp (dbus_message_get_member (message), "attachScreen") == 0)
+        err = attach_screen (message, reply, &error);
+    else if (strcmp (dbus_message_get_member (message), "detachScreen") == 0)
+        err = detach_screen (message, reply, &error);
+    else if (strcmp (dbus_message_get_member (message), "addInput") == 0)
+        err = add_input (message, reply, &error);
+    else if (strcmp (dbus_message_get_member (message), "removeInput") == 0)
+        err = remove_input (message, reply, &error);
+    else if (strcmp (dbus_message_get_member (message), "listScreens") == 0)
+        err = list_screens (message, reply, &error);
+    else if (strcmp (dbus_message_get_member (message), "version") == 0)
+        err = get_version (message, reply, &error);
+    else
+        goto err_reply;
+
+    /* Failure to allocate is a special case. */
+    if (err == BadAlloc)
+    {
+        ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
+        goto err_reply;
+    }
+
+    if (err != Success)
+    {
+	dbus_message_unref (reply);
+
+	reply = dbus_message_new_error_printf (message,
+					       error.name,
+					       error.message);
+
+	if (!reply)
+	{
+	    ErrorF ("[dmx/dbus] failed to create reply\n");
+	    ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
+	    goto err_start;
+	}
+    }
+
+    /* While failure here is always an OOM, we don't return that,
+     * since that would result in devices being double-added/removed. */
+    if (dbus_connection_send (info->connection, reply, NULL))
+	dbus_connection_flush (info->connection);
+    else
+        ErrorF ("[dmx/dbus] failed to send reply\n");
+
+    ret = DBUS_HANDLER_RESULT_HANDLED;
+
+err_reply:
+    dbus_message_unref (reply);
+err_start:
+    dbus_error_free (&error);
+
+    return ret;
+}
+
+static void
+connect_hook (DBusConnection *connection,
+	      void           *data)
+{
+    DBusObjectPathVTable   vtable = { .message_function = message_handler };
+    DBusError              error;
+    struct connection_info *info = data;
+
+    info->connection = connection;
+
+    dbus_error_init (&error);
+
+    /* blocks until we get a reply. */
+    dbus_bus_add_match (info->connection, MATCH_RULE, &error);
+    if (!dbus_error_is_set (&error))
+    {
+	if (dbus_connection_register_object_path (info->connection,
+						  info->busobject,
+						  &vtable,
+						  info))
+	{
+	    DebugF ("[dbus] registered %s, %s\n", info->busname,
+		    info->busobject);
+	}
+	else
+	{
+	    ErrorF ("[dmx/dbus] couldn't register object path\n");
+	    dbus_bus_remove_match (info->connection, MATCH_RULE, &error);
+	    reset_info (info);
+	}
+    }
+    else
+    {
+        ErrorF ("[dmx/dbus] couldn't add match: %s (%s)\n", error.name,
+		error.message);
+	reset_info (info);
+    }
+
+    dbus_error_free (&error);
+}
+
+static void
+disconnect_hook (void *data)
+{
+}
+
+static struct connection_info connection_data;
+static struct config_dbus_core_hook core_hook = {
+    .connect    = connect_hook,
+    .disconnect = disconnect_hook,
+    .data       = &connection_data
+};
+
+int
+dmx_dbus_init (void)
+{
+    snprintf (connection_data.busobject, sizeof (connection_data.busobject),
+	      "/org/x/config/dmx/%d", atoi (display));
+
+    return config_dbus_core_add_hook (&core_hook);
+}
+
+void
+dmx_dbus_fini (void)
+{
+    config_dbus_core_remove_hook (&core_hook);
+    reset_info (&connection_data);
+}
diff --git a/hw/dmx/dmxdbus.h b/hw/dmx/dmxdbus.h
new file mode 100644
index 0000000..1905685
--- /dev/null
+++ b/hw/dmx/dmxdbus.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2008 David Reveman
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * David Reveman not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * David Reveman makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DAVID REVEMAN 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMX_DBUS_H
+#define DMX_DBUS_H
+
+#define DMX_ERROR_INVALID_SCREEN "org.x.config.dmx.InvalidScreen"
+#define DMX_ERROR_SCREEN_IN_USE  "org.x.config.dmx.ScreenInUse"
+
+#ifdef CONFIG_DBUS_API
+int  dmx_dbus_init (void);
+void dmx_dbus_fini (void);
+#endif
+
+#endif
diff --git a/hw/dmx/dmxdnd.c b/hw/dmx/dmxdnd.c
new file mode 100644
index 0000000..0841db6
--- /dev/null
+++ b/hw/dmx/dmxdnd.c
@@ -0,0 +1,1870 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxlog.h"
+#include "dmxatom.h"
+#include "dmxwindow.h"
+#include "dmxscrinit.h"
+#include "dmxsync.h"
+#include "dmxinput.h"
+#include "dmxselection.h"
+#include "dmxdnd.h"
+
+#include "selection.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#include <xcb/xinput.h>
+#include <xcb/shape.h>
+
+struct _DMXDnDChild {
+    Window    target;
+    Window    wid;
+    BoxRec    box;
+    RegionPtr boundingShape;
+    RegionPtr inputShape;
+    int       map_state;
+    int       version;
+};
+
+void
+dmxBEDnDRootWindowUpdate (ScreenPtr pScreen,
+			  Window    window)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    xcb_atom_t    version = 5;
+
+    xcb_change_property (dmxScreen->connection,
+			 XCB_PROP_MODE_REPLACE,
+			 window,
+			 dmxBEAtom (dmxScreen, dmxScreen->xdndAwareAtom),
+			 XA_ATOM,
+			 32,
+			 1,
+			 &version);
+    xcb_change_property (dmxScreen->connection,
+			 XCB_PROP_MODE_REPLACE,
+			 window,
+			 dmxBEAtom (dmxScreen, dmxScreen->xdndProxyAtom),
+			 XA_WINDOW,
+			 32,
+			 1,
+			 &window);
+}
+
+static void
+dmxDnDSendDeclineStatus (void)
+{
+    WindowPtr pWin;
+
+    if (!dmxScreens[0].dndWindow)
+	return;
+
+    if (dixLookupWindow (&pWin,
+			 dmxScreens[0].dndWindow,
+			 serverClient,
+			 DixReadAccess) == Success)
+    {
+	xEvent x;
+
+	x.u.u.type                   = ClientMessage | 0x80;
+	x.u.u.detail                 = 32;
+	x.u.clientMessage.window     = dmxScreens[0].dndWindow;
+	x.u.clientMessage.u.l.type   = dmxScreens[0].xdndStatusAtom;
+	x.u.clientMessage.u.l.longs0 = dmxScreens[0].inputOverlayWid;
+	x.u.clientMessage.u.l.longs1 = 0;
+	x.u.clientMessage.u.l.longs2 = 0;
+	x.u.clientMessage.u.l.longs3 = 0;
+	x.u.clientMessage.u.l.longs4 = 0;
+
+	DeliverEventsToWindow (PickPointer (serverClient),
+			       pWin,
+			       &x,
+			       1,
+			       NoEventMask,
+			       NullGrab, 0);
+    }
+}
+
+static void
+dmxBEDnDUpdateTarget (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    Window        target = None;
+    Window        wid = None;
+    int           version = 0;
+
+    if (!dmxScreens[0].dndWindow || !dmxScreen->dndSource)
+	return;
+
+    if (dmxScreen->dndStatus)
+    {
+	int n;
+
+	n = dmxScreen->dndNChildren;
+	while (n--)
+	{
+	    if (dmxScreen->dndChildren[n].map_state != XCB_MAP_STATE_VIEWABLE)
+		continue;
+
+	    if (dmxScreen->dndChildren[n].box.x1 <= dmxScreen->dndX &&
+		dmxScreen->dndChildren[n].box.y1 <= dmxScreen->dndY &&
+		dmxScreen->dndChildren[n].box.x2 >  dmxScreen->dndX &&
+		dmxScreen->dndChildren[n].box.y2 >  dmxScreen->dndY)
+	    {
+		BoxRec box;
+
+		if ((!dmxScreen->dndChildren[n].boundingShape ||
+		     POINT_IN_REGION (pScreen,
+				      dmxScreen->dndChildren[n].boundingShape,
+				      dmxScreen->dndX -
+				      dmxScreen->dndChildren[n].box.x1,
+				      dmxScreen->dndY -
+				      dmxScreen->dndChildren[n].box.y1,
+				      &box)) &&
+		    (!dmxScreen->dndChildren[n].inputShape ||
+		     POINT_IN_REGION (pScreen,
+				      dmxScreen->dndChildren[n].inputShape,
+				      dmxScreen->dndX -
+				      dmxScreen->dndChildren[n].box.x1,
+				      dmxScreen->dndY -
+				      dmxScreen->dndChildren[n].box.y1,
+				      &box)))
+		    break;
+	    }
+	}
+
+	if (n >= 0 && dmxScreen->dndChildren[n].version >= 3)
+	{
+	    target  = dmxScreen->dndChildren[n].target;
+	    wid     = dmxScreen->dndChildren[n].wid;
+	    version = dmxScreen->dndChildren[n].version < 5 ?
+		dmxScreen->dndChildren[n].version : 5;
+	}
+    }
+
+    if (target != dmxScreen->dndTarget)
+    {
+	if (dmxScreen->dndTarget)
+	{
+	    xcb_client_message_event_t xevent;
+
+	    xevent.response_type = XCB_CLIENT_MESSAGE;
+	    xevent.format        = 32;
+
+	    xevent.type   = dmxBEAtom (dmxScreen, dmxScreen->xdndLeaveAtom);
+	    xevent.window = dmxScreen->dndTarget;
+
+	    xevent.data.data32[0] = dmxScreen->dndSource;
+	    xevent.data.data32[1] = 0;
+	    xevent.data.data32[2] = 0;
+	    xevent.data.data32[3] = 0;
+	    xevent.data.data32[4] = 0;
+
+	    xcb_send_event (dmxScreen->connection,
+			    FALSE,
+			    dmxScreen->dndWid,
+			    0,
+			    (const char *) &xevent);
+	}
+
+	if (target)
+	{
+	    xcb_client_message_event_t xevent;
+	    int                        i;
+
+	    xevent.response_type = XCB_CLIENT_MESSAGE;
+	    xevent.format        = 32;
+
+	    xevent.type   = dmxBEAtom (dmxScreen, dmxScreen->xdndEnterAtom);
+	    xevent.window = target;
+
+	    xevent.data.data32[0] = dmxScreen->dndSource;
+	    xevent.data.data32[1] = version << 24;
+	    xevent.data.data32[2] = 0;
+	    xevent.data.data32[3] = 0;
+	    xevent.data.data32[4] = 0;
+
+	    if (dmxScreen->dndHasTypeProp)
+		xevent.data.data32[1] |= 1;
+
+	    for (i = 0; i < 3; i++)
+		if (ValidAtom (dmxScreen->dndType[i]))
+		    xevent.data.data32[i + 2] =
+			dmxBEAtom (dmxScreen, dmxScreen->dndType[i]);
+
+	    xcb_send_event (dmxScreen->connection,
+			    FALSE,
+			    wid,
+			    0,
+			    (const char *) &xevent);
+
+	    dmxScreen->dndXPos = -1;
+	    dmxScreen->dndYPos = -1;
+	}
+	else if (dmxScreen->dndStatus)
+	{
+	    dmxDnDSendDeclineStatus ();
+	}
+
+	dmxScreen->dndTarget = target;
+	dmxScreen->dndWid    = wid;
+    }
+
+    if (dmxScreen->dndTarget)
+    {
+	if (dmxScreen->dndX != dmxScreen->dndXPos ||
+	    dmxScreen->dndY != dmxScreen->dndYPos)
+	{
+	    xcb_client_message_event_t xevent;
+
+	    xevent.response_type = XCB_CLIENT_MESSAGE;
+	    xevent.format        = 32;
+
+	    xevent.type   = dmxBEAtom (dmxScreen, dmxScreen->xdndPositionAtom);
+	    xevent.window = dmxScreen->dndTarget;
+
+	    xevent.data.data32[0] = dmxScreen->dndSource;
+	    xevent.data.data32[1] = 0;
+	    xevent.data.data32[2] = (dmxScreen->dndX << 16) | dmxScreen->dndY;
+	    xevent.data.data32[3] = 0; /* XXX: need time stamp */
+	    xevent.data.data32[4] = dmxBEAtom (dmxScreen,
+					       dmxScreen->dndAction);
+
+	    xcb_send_event (dmxScreen->connection,
+			    FALSE,
+			    dmxScreen->dndWid,
+			    0,
+			    (const char *) &xevent);
+
+	    dmxScreen->dndXPos = dmxScreen->dndX;
+	    dmxScreen->dndYPos = dmxScreen->dndY;
+	}
+    }
+}
+
+static void
+dmxDnDAwarePropertyReply (ScreenPtr           pScreen,
+			  unsigned int        sequence,
+			  xcb_generic_reply_t *reply,
+			  xcb_generic_error_t *error,
+			  void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           n = (int) data;
+
+     if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+	return;
+
+    if (reply)
+    {
+	xcb_get_property_reply_t *xproperty =
+	    (xcb_get_property_reply_t *) reply;
+
+	if (xproperty->format == 32)
+	{
+	    uint32_t *data = xcb_get_property_value (xproperty);
+	    int      length = xcb_get_property_value_length (xproperty);
+
+	    if (length)
+		dmxScreen->dndChildren[n].version = *data;
+	}
+    }
+}
+
+static void
+dmxDnDProxyPropertyReply (ScreenPtr           pScreen,
+			  unsigned int        sequence,
+			  xcb_generic_reply_t *reply,
+			  xcb_generic_error_t *error,
+			  void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           n = (int) data;
+
+    if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+	return;
+
+    if (reply)
+    {
+	xcb_get_property_reply_t *xproperty =
+	    (xcb_get_property_reply_t *) reply;
+
+	if (xproperty->format == 32)
+	{
+	    uint32_t *data = xcb_get_property_value (xproperty);
+	    int      length = xcb_get_property_value_length (xproperty);
+
+	    if (length)
+	    {
+		xcb_get_property_cookie_t prop;
+
+		dmxScreen->dndChildren[n].wid = *data;
+
+		/* ignore previous xdndAware property reply */
+		dmxScreen->dndChildren[n].version = 0;
+
+		prop = xcb_get_property (dmxScreen->connection,
+					 xFalse,
+					 dmxScreen->dndChildren[n].wid,
+					 dmxBEAtom (dmxScreen,
+						    dmxScreen->xdndAwareAtom),
+					 XCB_GET_PROPERTY_TYPE_ANY,
+					 0,
+					 1);
+		dmxAddRequest (&dmxScreen->request,
+			       dmxDnDAwarePropertyReply,
+			       prop.sequence,
+			       (void *) n);
+	    }
+	}
+    }
+}
+
+static void
+dmxDnDGeometryReply (ScreenPtr           pScreen,
+		     unsigned int        sequence,
+		     xcb_generic_reply_t *reply,
+		     xcb_generic_error_t *error,
+		     void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           n = (int) data;
+
+    if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+	return;
+
+    if (reply)
+    {
+	xcb_get_geometry_reply_t *xgeometry =
+	    (xcb_get_geometry_reply_t *) reply;
+
+	dmxScreen->dndChildren[n].box.x1 = xgeometry->x;
+	dmxScreen->dndChildren[n].box.y1 = xgeometry->y;
+	dmxScreen->dndChildren[n].box.x2 = xgeometry->x + xgeometry->width;
+	dmxScreen->dndChildren[n].box.y2 = xgeometry->y + xgeometry->height;
+    }
+}
+
+typedef struct dmx_xcb_shape_get_rectangles_reply_t {
+    uint8_t  response_type;
+    uint8_t  ordering;
+    uint16_t sequence;
+    uint32_t length;
+    uint32_t rectangles_len;
+    uint32_t pad1;
+    uint32_t pad2;
+    uint32_t pad3;
+    uint32_t pad4;
+    uint32_t pad5;
+} dmx_xcb_shape_get_rectangles_reply_t;
+
+static void
+dmxDnDBoundingShapeReply (ScreenPtr           pScreen,
+			  unsigned int        sequence,
+			  xcb_generic_reply_t *reply,
+			  xcb_generic_error_t *error,
+			  void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           n = (int) data;
+    RegionPtr     pRegion;
+
+    if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+	return;
+
+    if (reply)
+    {
+	dmx_xcb_shape_get_rectangles_reply_t *xshape =
+	    (dmx_xcb_shape_get_rectangles_reply_t *) reply;
+
+	pRegion = RECTS_TO_REGION (pScreen,
+				   xshape->rectangles_len,
+				   (xRectangle *) (xshape + 1),
+				   xshape->ordering);
+
+	if (dmxScreen->dndChildren[n].boundingShape)
+	    REGION_DESTROY (pScreen, dmxScreen->dndChildren[n].boundingShape);
+
+	dmxScreen->dndChildren[n].boundingShape = pRegion;
+    }
+}
+
+static void
+dmxDnDInputShapeReply (ScreenPtr           pScreen,
+		       unsigned int        sequence,
+		       xcb_generic_reply_t *reply,
+		       xcb_generic_error_t *error,
+		       void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           n = (int) data;
+    RegionPtr     pRegion;
+
+    if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+	return;
+
+    if (reply)
+    {
+	dmx_xcb_shape_get_rectangles_reply_t *xshape =
+	    (dmx_xcb_shape_get_rectangles_reply_t *) reply;
+
+	pRegion = RECTS_TO_REGION (pScreen,
+				   xshape->rectangles_len,
+				   (xRectangle *) (xshape + 1),
+				   xshape->ordering);
+
+	if (dmxScreen->dndChildren[n].inputShape)
+	    REGION_DESTROY (pScreen, dmxScreen->dndChildren[n].inputShape);
+
+	dmxScreen->dndChildren[n].inputShape = pRegion;
+    }
+}
+
+static void
+dmxDnDBoundingShapeUpdateReply (ScreenPtr           pScreen,
+				unsigned int        sequence,
+				xcb_generic_reply_t *reply,
+				xcb_generic_error_t *error,
+				void                *data)
+{
+    dmxDnDBoundingShapeReply (pScreen, sequence, reply, error, data);
+    dmxBEDnDUpdateTarget (pScreen);
+}
+
+static void
+dmxDnDInputShapeUpdateReply (ScreenPtr           pScreen,
+			     unsigned int        sequence,
+			     xcb_generic_reply_t *reply,
+			     xcb_generic_error_t *error,
+			     void                *data)
+{
+    dmxDnDInputShapeReply (pScreen, sequence, reply, error, data);
+    dmxBEDnDUpdateTarget (pScreen);
+}
+
+static void
+dmxDnDWindowAttributesReply (ScreenPtr           pScreen,
+			     unsigned int        sequence,
+			     xcb_generic_reply_t *reply,
+			     xcb_generic_error_t *error,
+			     void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           n = (int) data;
+
+    if (!dmxScreen->dndChildren || n >= dmxScreen->dndNChildren)
+	return;
+
+    if (reply)
+    {
+	xcb_get_window_attributes_reply_t *xattrib =
+	    (xcb_get_window_attributes_reply_t *) reply;
+
+	dmxScreen->dndChildren[n].map_state = xattrib->map_state;
+
+	if (xattrib->map_state == XCB_MAP_STATE_VIEWABLE)
+	    dmxBEDnDUpdateTarget (pScreen);
+    }
+}
+
+/* XXX: back-end server DND target lookup method is efficient but
+   doesn't support reparenting window managers */
+static void
+dmxDnDQueryTreeReply (ScreenPtr           pScreen,
+		      unsigned int        sequence,
+		      xcb_generic_reply_t *reply,
+		      xcb_generic_error_t *error,
+		      void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (sequence != dmxScreen->queryTree.sequence)
+	return;
+
+    assert (!dmxScreen->dndChildren);
+
+    if (reply)
+    {
+	xcb_query_tree_reply_t *xquery = (xcb_query_tree_reply_t *) reply;
+	DMXDnDChild            *children;
+	xcb_window_t           *c;
+	int                    n;
+
+	c = xcb_query_tree_children (xquery);
+	n = xcb_query_tree_children_length (xquery);
+
+	children = xalloc (n * sizeof (DMXDnDChild));
+	if (!children)
+	    return;
+
+	dmxScreen->dndChildren  = children;
+	dmxScreen->dndNChildren = n;
+
+	while (n--)
+	{
+	    xcb_get_property_cookie_t          prop;
+	    xcb_get_geometry_cookie_t          geometry;
+	    xcb_shape_get_rectangles_cookie_t  shape;
+	    xcb_get_window_attributes_cookie_t attr;
+
+	    children[n].box.x1        = 0;
+	    children[n].box.y1        = 0;
+	    children[n].box.x2        = 0;
+	    children[n].box.y2        = 0;
+	    children[n].boundingShape = NULL;
+	    children[n].inputShape    = NULL;
+	    children[n].version       = 0;
+	    children[n].target        = c[n];
+	    children[n].wid           = c[n];
+
+	    prop = xcb_get_property (dmxScreen->connection,
+				     xFalse,
+				     c[n],
+				     dmxBEAtom (dmxScreen,
+						dmxScreen->xdndAwareAtom),
+				     XCB_GET_PROPERTY_TYPE_ANY,
+				     0,
+				     1);
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxDnDAwarePropertyReply,
+			   prop.sequence,
+			   (void *) n);
+
+	    prop = xcb_get_property (dmxScreen->connection,
+				     xFalse,
+				     c[n],
+				     dmxBEAtom (dmxScreen,
+						dmxScreen->xdndProxyAtom),
+				     XCB_GET_PROPERTY_TYPE_ANY,
+				     0,
+				     1);
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxDnDProxyPropertyReply,
+			   prop.sequence,
+			   (void *) n);
+
+	    geometry = xcb_get_geometry (dmxScreen->connection, c[n]);
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxDnDGeometryReply,
+			   geometry.sequence,
+			   (void *) n);
+
+	    xcb_shape_select_input (dmxScreen->connection, c[n], 1);
+
+	    shape = xcb_shape_get_rectangles (dmxScreen->connection, c[n],
+					      ShapeBounding);
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxDnDBoundingShapeReply,
+			   shape.sequence,
+			   (void *) n);
+
+	    shape = xcb_shape_get_rectangles (dmxScreen->connection, c[n],
+					      ShapeInput);
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxDnDInputShapeReply,
+			   shape.sequence,
+			   (void *) n);
+
+	    attr = xcb_get_window_attributes (dmxScreen->connection, c[n]);
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxDnDWindowAttributesReply,
+			   attr.sequence,
+			   (void *) n);
+	}
+    }
+}
+
+static void
+dmxBEDnDUpdatePosition (ScreenPtr pScreen,
+			int       x,
+			int       y)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           i;
+
+    for (i = 0; i < dmxNumScreens; i++)
+	dmxScreens[i].dndStatus = 0;
+
+    dmxScreen->dndX      = x;
+    dmxScreen->dndY      = y;
+    dmxScreen->dndStatus = 1;
+
+    if (!dmxScreen->dndChildren)
+    {
+	if (!dmxScreen->queryTree.sequence)
+	{
+	    Window root = DefaultRootWindow (dmxScreen->beDisplay);
+
+	    XSelectInput (dmxScreen->beDisplay, root,
+			  dmxScreen->scrnEventMask |
+			  StructureNotifyMask | SubstructureNotifyMask);
+
+	    dmxScreen->queryTree = xcb_query_tree (dmxScreen->connection,
+						   root);
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxDnDQueryTreeReply,
+			   dmxScreen->queryTree.sequence,
+			   0);
+	}
+    }
+
+    for (i = 0; i < dmxNumScreens; i++)
+	dmxBEDnDUpdateTarget (screenInfo.screens[i]);
+}
+
+static void
+dmxDnDFreeChildren (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (dmxScreen->dndChildren)
+    {
+	int i;
+
+	for (i = 0; i < dmxScreen->dndNChildren; i++)
+	{
+	    if (dmxScreen->dndChildren[i].boundingShape)
+		REGION_DESTROY (pScreen,
+				dmxScreen->dndChildren[i].boundingShape);
+
+	    if (dmxScreen->dndChildren[i].inputShape)
+		REGION_DESTROY (pScreen,
+				dmxScreen->dndChildren[i].inputShape);
+
+	    xcb_shape_select_input (dmxScreen->connection,
+				    dmxScreen->dndChildren[i].target,
+				    0);
+	}
+
+	xfree (dmxScreen->dndChildren);
+
+	dmxScreen->dndChildren  = NULL;
+	dmxScreen->dndNChildren = 0;
+    }
+}
+
+static void
+dmxBEDnDHideProxyWindow (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    WindowPtr     pProxyWin = dmxScreen->pInputOverlayWin;
+
+    if (!pProxyWin->mapped)
+	return;
+
+    dmxScreen->dndStatus = 0;
+    dmxBEDnDUpdateTarget (pScreen);
+
+    UnmapWindow (pProxyWin, FALSE);
+
+    if (dmxScreen->dndChildren || dmxScreen->queryTree.sequence)
+	XSelectInput (dmxScreen->beDisplay,
+		      DefaultRootWindow (dmxScreen->beDisplay),
+		      dmxScreen->scrnEventMask);
+
+    dmxDnDFreeChildren (pScreen);
+
+    dmxScreen->dndSource = None;
+    dmxScreen->queryTree.sequence = 0;
+}
+
+void
+dmxBEDnDSpriteUpdate (ScreenPtr pScreen,
+		      Window    event,
+		      int       rootX,
+		      int       rootY)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    WindowPtr     pProxyWin = dmxScreen->pInputOverlayWin;
+
+    if (event != dmxScreen->rootWin)
+    {
+	if (!pProxyWin->mapped)
+	{
+	    Selection *pSel;
+	    XID       vlist[5];
+
+	    if (dixLookupSelection (&pSel,
+				    dmxScreen->xdndSelectionAtom,
+				    serverClient,
+				    DixReadAccess) != Success)
+		return;
+
+	    if (!pSel->window)
+		return;
+
+	    vlist[0] = 0;
+	    vlist[1] = 0;
+	    vlist[2] = WindowTable[pScreen->myNum]->drawable.width;
+	    vlist[3] = WindowTable[pScreen->myNum]->drawable.height;
+	    vlist[4] = Above;
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		int j;
+
+		FOR_NSCREENS_BACKWARD(j) {
+		    ConfigureWindow (dmxScreens[j].pInputOverlayWin,
+				     CWX | CWY | CWWidth | CWHeight |
+				     CWStackMode,
+				     vlist,
+				     serverClient);
+		    MapWindow (dmxScreens[j].pInputOverlayWin, serverClient);
+
+		    dmxScreens[j].dndSource = None;
+		    dmxScreens[j].dndTarget = None;
+		}
+	    }
+	    else
+#endif
+	
+	    {
+		ConfigureWindow (pProxyWin,
+				 CWX | CWY | CWWidth | CWHeight | CWStackMode,
+				 vlist,
+				 serverClient);
+		MapWindow (pProxyWin, serverClient);
+
+		dmxScreen->dndSource = None;
+		dmxScreen->dndTarget = None;
+	    }
+	}
+
+	dmxBEDnDUpdatePosition (pScreen, rootX, rootY);
+    }
+    else
+    {
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    int j;
+
+	    FOR_NSCREENS_BACKWARD(j) {
+		dmxBEDnDHideProxyWindow (screenInfo.screens[j]);
+	    }
+	}
+	else
+#endif
+
+	    dmxBEDnDHideProxyWindow (pScreen);
+    }
+}
+
+static void
+dmxDnDUpdatePosition (DMXScreenInfo *dmxScreen,
+		      WindowPtr     pWin,
+		      int           x,
+		      int           y)
+{
+    WindowPtr pDst = NullWindow;
+    BoxRec    box;
+    XID       targetId = None;
+    xEvent    event;
+    int       version = 0;
+
+    event.u.u.type   = ClientMessage | 0x80;
+    event.u.u.detail = 32;
+    
+    event.u.clientMessage.u.l.longs0 = dmxScreens[0].inputOverlayWid;
+
+    if (pWin)
+    {
+	if (!dmxFakeMotion (&dmxScreen->input, x, y))
+	    pWin = NullWindow;
+    }
+    else
+    {
+	dmxEndFakeMotion (&dmxScreen->input);
+    }
+
+    while (pWin)
+    {
+	if ((pWin->mapped) &&
+	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
+	    (x < pWin->drawable.x + (int) pWin->drawable.width +
+	     wBorderWidth(pWin)) &&
+	    (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
+	    (y < pWin->drawable.y + (int) pWin->drawable.height +
+	     wBorderWidth (pWin))
+	    /* When a window is shaped, a further check
+	     * is made to see if the point is inside
+	     * borderSize
+	     */
+	    && (!wBoundingShape (pWin) ||
+		POINT_IN_REGION (pWin->drawable.pScreen, 
+				 &pWin->borderSize, x, y, &box))
+	
+	    && (!wInputShape (pWin) ||
+		POINT_IN_REGION (pWin->drawable.pScreen,
+				 wInputShape (pWin),
+				 x - pWin->drawable.x,
+				 y - pWin->drawable.y, &box)))
+	{
+	    WindowPtr   pProxy = NullWindow;
+	    PropertyPtr pProp;
+
+	    if (dixLookupProperty (&pProp,
+				   pWin,
+				   dmxScreen->xdndProxyAtom,
+				   serverClient,
+				   DixReadAccess) == Success)
+	    {
+		if (pProp->format == 32 && pProp->size == 1)
+		    dixLookupWindow (&pProxy,
+				     *((XID *) pProp->data),
+				     serverClient,
+				     DixReadAccess);
+	    }
+
+	    if (dixLookupProperty (&pProp,
+				   pProxy ? pProxy : pWin,
+				   dmxScreen->xdndAwareAtom,
+				   serverClient,
+				   DixReadAccess) == Success)
+	    {
+		if (pProp->format == 32 && pProp->size == 1)
+		{
+		    Atom v;
+
+		    v = *((Atom *) pProp->data);
+		    if (v >= 3)
+		    {
+			pDst = pProxy ? pProxy : pWin;
+			targetId = pWin->drawable.id;
+			version = v;
+			if (version > 5)
+			    version = 5;
+		    }
+		}
+	    }
+
+	    if (dixLookupProperty (&pProp,
+				   pWin,
+				   dmxScreen->wmStateAtom,
+				   serverClient,
+				   DixReadAccess) == Success)
+		break;
+
+	    pWin = pWin->firstChild;
+	}
+	else
+	    pWin = pWin->nextSib;
+    }
+
+    if (dmxScreen->dndTarget != targetId)
+    {
+	if (dmxScreen->dndWindow)
+	{
+	    event.u.clientMessage.window   = dmxScreen->dndTarget;
+	    event.u.clientMessage.u.l.type = dmxScreen->xdndLeaveAtom;
+
+	    event.u.clientMessage.u.l.longs1 = 0;
+	    event.u.clientMessage.u.l.longs2 = 0;
+	    event.u.clientMessage.u.l.longs3 = 0;
+	    event.u.clientMessage.u.l.longs4 = 0;
+
+	    if (dixLookupWindow (&pWin,
+				 dmxScreen->dndWindow,
+				 serverClient,
+				 DixReadAccess) == Success)
+		DeliverEventsToWindow (PickPointer (serverClient),
+				       pWin,
+				       &event,
+				       1,
+				       NoEventMask,
+				       NullGrab, 0);
+
+	    dmxScreen->dndStatus = 0;
+	    dmxScreen->dndTarget = None;
+	    dmxScreen->dndWindow = None;
+	}
+
+	if (pDst)
+	{
+	    event.u.clientMessage.window   = targetId;
+	    event.u.clientMessage.u.l.type = dmxScreen->xdndEnterAtom;
+
+	    event.u.clientMessage.u.l.longs1 = version << 24;
+	    event.u.clientMessage.u.l.longs2 = dmxScreen->dndType[0];
+	    event.u.clientMessage.u.l.longs3 = dmxScreen->dndType[1];
+	    event.u.clientMessage.u.l.longs4 = dmxScreen->dndType[2];
+
+	    if (dmxScreen->dndHasTypeProp)
+		event.u.clientMessage.u.l.longs1 |= 1;
+
+	    DeliverEventsToWindow (PickPointer (serverClient),
+				   pDst,
+				   &event,
+				   1,
+				   NoEventMask,
+				   NullGrab, 0);
+
+	    dmxScreen->dndStatus         = 0;
+	    dmxScreen->dndWindow         = pDst->drawable.id;
+	    dmxScreen->dndTarget         = targetId;
+	    dmxScreen->dndXPos           = -1;
+	    dmxScreen->dndYPos           = -1;
+	    dmxScreen->dndAcceptedAction = None;
+	    dmxScreen->dndVersion        = version;
+
+	    REGION_EMPTY (pScreen, &dmxScreen->dndBox);
+	}
+    }
+
+    if (pDst && !POINT_IN_REGION (pScreen,
+				  &dmxScreen->dndBox,
+				  x, y, &box))
+    {
+	event.u.clientMessage.window   = dmxScreen->dndTarget;
+	event.u.clientMessage.u.l.type = dmxScreen->xdndPositionAtom;
+
+	event.u.clientMessage.u.l.longs1 = 0;
+	event.u.clientMessage.u.l.longs2 = (x << 16) | y;
+	event.u.clientMessage.u.l.longs3 = currentTime.milliseconds;
+	event.u.clientMessage.u.l.longs4 = dmxScreen->dndAction;
+
+	DeliverEventsToWindow (PickPointer (serverClient),
+			       pDst,
+			       &event,
+			       1,
+			       NoEventMask,
+			       NullGrab, 0);
+
+	dmxScreen->dndXPos = x;
+	dmxScreen->dndYPos = y;
+
+	box.x1 = SHRT_MIN;
+	box.y1 = SHRT_MIN;
+	box.x2 = SHRT_MAX;
+	box.y2 = SHRT_MAX;
+
+	REGION_RESET (pScreen, &dmxScreen->dndBox, &box);
+    }
+}
+
+static void
+dmxDnDTranslateCoordinatesReply (ScreenPtr           pScreen,
+				 unsigned int        sequence,
+				 xcb_generic_reply_t *reply,
+				 xcb_generic_error_t *error,
+				 void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (reply)
+    {
+	xcb_translate_coordinates_reply_t *xcoord =
+	    (xcb_translate_coordinates_reply_t *) reply;
+
+	dmxScreen->dndX = xcoord->dst_x;
+	dmxScreen->dndY = xcoord->dst_y;
+
+	if (dmxScreen->dndSource)
+	{
+	    WindowPtr                  pWin = WindowTable[pScreen->myNum];
+	    xcb_client_message_event_t xevent;
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+		pWin = WindowTable[0];
+#endif
+
+	    if (!dmxScreen->getTypeProp.sequence)
+		dmxDnDUpdatePosition (dmxScreen,
+				      pWin,
+				      dmxScreen->dndX,
+				      dmxScreen->dndY);
+
+	    xevent.response_type = XCB_CLIENT_MESSAGE;
+	    xevent.format        = 32;
+
+	    xevent.type   = dmxBEAtom (dmxScreen, dmxScreen->xdndStatusAtom);
+	    xevent.window = dmxScreen->dndSource;
+
+	    xevent.data.data32[0] = dmxScreen->dndWid;
+	    xevent.data.data32[1] = dmxScreen->dndStatus;
+	    xevent.data.data32[2] = 0;
+	    xevent.data.data32[3] = 0;
+	    xevent.data.data32[4] = 0;
+
+	    if (ValidAtom (dmxScreen->dndAcceptedAction))
+		xevent.data.data32[4] =
+		    dmxBEAtom (dmxScreen, dmxScreen->dndAcceptedAction);
+
+	    xcb_send_event (dmxScreen->connection,
+			    FALSE,
+			    dmxScreen->dndSource,
+			    0,
+			    (const char *) &xevent);
+	}
+    }
+}
+
+static void
+dmxDnDGetTypePropReply (ScreenPtr           pScreen,
+			unsigned int        sequence,
+			xcb_generic_reply_t *reply,
+			xcb_generic_error_t *error,
+			void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (reply)
+    {
+	xcb_get_property_reply_t *xproperty =
+	    (xcb_get_property_reply_t *) reply;
+	    
+	if (xproperty->format                    == 32 &&
+	    dmxAtom (dmxScreen, xproperty->type) == XA_ATOM)
+	{
+	    uint32_t *data = xcb_get_property_value (xproperty);
+	    int      i;
+
+	    for (i = 0; i < xcb_get_property_value_length (xproperty); i++)
+		data[i] = dmxAtom (dmxScreen, data[i]);
+
+	    ChangeWindowProperty (dmxScreens[0].pInputOverlayWin,
+				  dmxScreen->xdndTypeListAtom,
+				  XA_ATOM,
+				  32,
+				  PropModeReplace,
+				  xcb_get_property_value_length (xproperty),
+				  data,
+				  TRUE);
+
+	    dmxScreen->dndHasTypeProp = TRUE;
+	}
+	    
+	if (dmxScreen->dndX != -1 && dmxScreen->dndY != -1)
+	{
+	    WindowPtr pWin = WindowTable[pScreen->myNum];
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+		pWin = WindowTable[0];
+#endif
+
+	    dmxDnDUpdatePosition (dmxScreen,
+				  pWin,
+				  dmxScreen->dndX,
+				  dmxScreen->dndY);
+	}
+    }
+
+    dmxScreen->getTypeProp.sequence = 0;
+}
+
+static void
+dmxDnDGetActionListPropReply (ScreenPtr           pScreen,
+			      unsigned int        sequence,
+			      xcb_generic_reply_t *reply,
+			      xcb_generic_error_t *error,
+			      void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (reply)
+    {
+	xcb_get_property_reply_t *xproperty =
+	    (xcb_get_property_reply_t *) reply;
+	    
+	if (xproperty->format                    == 32 &&
+	    dmxAtom (dmxScreen, xproperty->type) == XA_ATOM)
+	{
+	    uint32_t *data = xcb_get_property_value (xproperty);
+	    int      i;
+
+	    for (i = 0; i < xcb_get_property_value_length (xproperty); i++)
+		data[i] = dmxAtom (dmxScreen, data[i]);
+
+	    ChangeWindowProperty (dmxScreens[0].pInputOverlayWin,
+				  dmxScreen->xdndActionListAtom,
+				  XA_ATOM,
+				  32,
+				  PropModeReplace,
+				  xcb_get_property_value_length (xproperty),
+				  data,
+				  TRUE);
+	}
+    }
+
+    dmxScreen->getActionListProp.sequence = 0;
+}
+
+static void
+dmxDnDGetActionDescriptionPropReply (ScreenPtr           pScreen,
+				     unsigned int        sequence,
+				     xcb_generic_reply_t *reply,
+				     xcb_generic_error_t *error,
+				     void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (reply)
+    {
+	xcb_get_property_reply_t *xproperty =
+	    (xcb_get_property_reply_t *) reply;
+	    
+	if (xproperty->format                    == 8 &&
+	    dmxAtom (dmxScreen, xproperty->type) == XA_STRING)
+	{
+	    ChangeWindowProperty (dmxScreens[0].pInputOverlayWin,
+				  dmxScreen->xdndActionDescriptionAtom,
+				  XA_STRING,
+				  8,
+				  PropModeReplace,
+				  xcb_get_property_value_length (xproperty),
+				  xcb_get_property_value (xproperty),
+				  TRUE);
+	}
+    }
+
+    dmxScreen->getActionDescriptionProp.sequence = 0;
+}
+
+static void
+dmxDnDPositionMessage (ScreenPtr pScreen,
+		       Window    source,
+		       int       xRoot,
+		       int       yRoot,
+		       Time      time,
+		       Atom      action)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (action)
+	dmxScreen->dndAction = dmxAtom (dmxScreen, action);
+
+    if (dmxScreen->dndAction == dmxScreen->xdndActionAskAtom)
+    {
+	dmxScreen->getActionListProp =
+	    xcb_get_property (dmxScreen->connection,
+			      xFalse,
+			      source,
+			      dmxBEAtom (dmxScreen,
+					 dmxScreen->xdndActionListAtom),
+			      XCB_GET_PROPERTY_TYPE_ANY,
+			      0,
+			      0xffffffff);
+
+	dmxAddRequest (&dmxScreen->request,
+		       dmxDnDGetActionListPropReply,
+		       dmxScreen->getActionListProp.sequence,
+		       0);
+
+	dmxScreen->getActionDescriptionProp =
+	    xcb_get_property (dmxScreen->connection,
+			      xFalse,
+			      source,
+			      dmxBEAtom (dmxScreen,
+					 dmxScreen->xdndActionDescriptionAtom),
+			      XCB_GET_PROPERTY_TYPE_ANY,
+			      0,
+			      0xffffffff);
+
+	dmxAddRequest (&dmxScreen->request,
+		       dmxDnDGetActionDescriptionPropReply,
+		       dmxScreen->getActionDescriptionProp.sequence,
+		       0);
+    }
+
+    dmxScreen->translateCoordinates =
+	xcb_translate_coordinates (dmxScreen->connection,
+				   DefaultRootWindow (dmxScreen->beDisplay),
+				   dmxScreen->rootWin,
+				   xRoot,
+				   yRoot);
+    	dmxAddRequest (&dmxScreen->request,
+		       dmxDnDTranslateCoordinatesReply,
+		       dmxScreen->translateCoordinates.sequence,
+		       0);
+}
+
+static void
+dmxDnDEnterMessage (ScreenPtr pScreen,
+		    Window    target,
+		    Window    source,
+		    Atom      type0,
+		    Atom      type1,
+		    Atom      type2,
+		    Bool      hasTypeProp,
+		    int       version)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    dmxScreen->dndWid            = target;
+    dmxScreen->dndSource         = source;
+    dmxScreen->dndAction         = None;
+    dmxScreen->dndAcceptedAction = None;
+    dmxScreen->dndType[0]        = type0;
+    dmxScreen->dndType[1]        = type1;
+    dmxScreen->dndType[2]        = type2;
+    dmxScreen->dndHasTypeProp    = FALSE;
+
+    if (hasTypeProp)
+    {
+	dmxScreen->getTypeProp =
+	    xcb_get_property (dmxScreen->connection,
+			      xFalse,
+			      source,
+			      dmxBEAtom (dmxScreen,
+					 dmxScreen->xdndTypeListAtom),
+			      XCB_GET_PROPERTY_TYPE_ANY,
+			      0,
+			      0xffffffff);
+
+	if (dmxScreen->getTypeProp.sequence)
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxDnDGetTypePropReply,
+			   dmxScreen->getTypeProp.sequence,
+			   0);
+    }
+}
+
+static void
+dmxDnDLeaveMessage (ScreenPtr pScreen,
+		    Window    source)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    dmxDnDUpdatePosition (dmxScreen, NullWindow, 0, 0);
+
+    dmxScreen->dndWid    = None;
+    dmxScreen->dndSource = None;
+    dmxScreen->dndStatus = 0;
+    dmxScreen->dndXPos   = -1;
+    dmxScreen->dndYPos   = -1;
+    dmxScreen->dndX      = -1;
+    dmxScreen->dndY      = -1;
+}
+
+static void
+dmxDnDDropMessage (ScreenPtr pScreen,
+		   Window    source,
+		   Time      time)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    dmxEndFakeMotion (&dmxScreen->input);
+
+    if (dmxScreen->dndWindow)
+    {
+	WindowPtr pWin;
+	xEvent    event;
+	BoxRec    box;
+
+	event.u.u.type   = ClientMessage | 0x80;
+	event.u.u.detail = 32;
+
+	event.u.clientMessage.window   = dmxScreen->dndTarget;
+	event.u.clientMessage.u.l.type = dmxScreen->xdndDropAtom;
+
+	event.u.clientMessage.u.l.longs0 = dmxScreens[0].inputOverlayWid;
+	event.u.clientMessage.u.l.longs1 = 0;
+	event.u.clientMessage.u.l.longs2 = currentTime.milliseconds;
+	event.u.clientMessage.u.l.longs3 = 0;
+	event.u.clientMessage.u.l.longs4 = 0;
+
+	if (dixLookupWindow (&pWin,
+			     dmxScreen->dndWindow,
+			     serverClient,
+			     DixReadAccess) == Success)
+	    DeliverEventsToWindow (PickPointer (serverClient),
+				   pWin,
+				   &event,
+				   1,
+				   NoEventMask,
+				   NullGrab, 0);
+
+	box.x1 = SHRT_MIN;
+	box.y1 = SHRT_MIN;
+	box.x2 = SHRT_MAX;
+	box.y2 = SHRT_MAX;
+
+	REGION_RESET (pScreen, &dmxScreen->dndBox, &box);
+    }
+    else
+    {
+	xcb_client_message_event_t xevent;
+
+	dmxDnDLeaveMessage (pScreen, source);
+
+	xevent.response_type = XCB_CLIENT_MESSAGE;
+	xevent.format        = 32;
+
+	xevent.type   = dmxBEAtom (dmxScreen, dmxScreen->xdndFinishedAtom);
+	xevent.window = dmxScreen->dndSource;
+
+	xevent.data.data32[0] = dmxScreen->dndWid;
+	xevent.data.data32[1] = 0;
+	xevent.data.data32[2] = 0;
+	xevent.data.data32[3] = 0;
+	xevent.data.data32[4] = 0;
+
+	xcb_send_event (dmxScreen->connection,
+			FALSE,
+			dmxScreen->dndSource,
+			0,
+			(const char *) &xevent);
+
+	dmxScreen->dndWid    = None;
+	dmxScreen->dndSource = None;
+    }
+}
+
+static void
+dmxDnDStatusMessage (ScreenPtr pScreen,
+		     Window    target,
+		     int       status,
+		     Atom      action)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    WindowPtr     pWin;
+
+    if (!dmxScreens[0].dndWindow)
+	return;
+
+    if (!dmxScreen->dndStatus)
+	return;
+
+    if (target != dmxScreen->dndTarget)
+	return;
+
+    if (dixLookupWindow (&pWin,
+			 dmxScreens[0].dndWindow,
+			 serverClient,
+			 DixReadAccess) == Success)
+    {
+	xEvent x;
+
+	x.u.u.type                   = ClientMessage | 0x80;
+	x.u.u.detail                 = 32;
+	x.u.clientMessage.window     = dmxScreens[0].dndWindow;
+	x.u.clientMessage.u.l.type   = dmxScreens[0].xdndStatusAtom;
+	x.u.clientMessage.u.l.longs0 = dmxScreens[0].inputOverlayWid;
+	x.u.clientMessage.u.l.longs1 = 0;
+	x.u.clientMessage.u.l.longs2 = 0;
+	x.u.clientMessage.u.l.longs3 = 0;
+	x.u.clientMessage.u.l.longs4 = 0;
+
+	if (status)
+	{
+	    x.u.clientMessage.u.l.longs1 = 1;
+	    x.u.clientMessage.u.l.longs4 = dmxAtom (dmxScreen, action);
+	}
+
+	DeliverEventsToWindow (PickPointer (serverClient),
+			       pWin,
+			       &x,
+			       1,
+			       NoEventMask,
+			       NullGrab, 0);
+    }
+}
+
+static void
+dmxDnDFinishedMessage (ScreenPtr pScreen,
+		       Window    target,
+		       int       status,
+		       Atom      action)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    WindowPtr     pWin;
+
+    if (!dmxScreens[0].dndWindow)
+	return;
+
+    if (target != dmxScreen->dndTarget)
+	return;
+
+    if (dixLookupWindow (&pWin,
+			 dmxScreens[0].dndWindow,
+			 serverClient,
+			 DixReadAccess) == Success)
+    {
+	xEvent x;
+
+	x.u.u.type                   = ClientMessage | 0x80;
+	x.u.u.detail                 = 32;
+	x.u.clientMessage.window     = dmxScreens[0].dndWindow;
+	x.u.clientMessage.u.l.type   = dmxScreens[0].xdndFinishedAtom;
+	x.u.clientMessage.u.l.longs0 = dmxScreens[0].inputOverlayWid;
+	x.u.clientMessage.u.l.longs1 = 0;
+	x.u.clientMessage.u.l.longs2 = 0;
+	x.u.clientMessage.u.l.longs3 = 0;
+	x.u.clientMessage.u.l.longs4 = 0;
+
+	if (status)
+	{
+	    x.u.clientMessage.u.l.longs1 = 1;
+	    x.u.clientMessage.u.l.longs2 = dmxAtom (dmxScreen, action);
+	}
+
+	DeliverEventsToWindow (PickPointer (serverClient),
+			       pWin,
+			       &x,
+			       1,
+			       NoEventMask,
+			       NullGrab, 0);
+    }
+}
+
+Bool
+dmxScreenEventCheckDnD (ScreenPtr           pScreen,
+			xcb_generic_event_t *event)
+{
+    DMXScreenInfo          *dmxScreen = &dmxScreens[pScreen->myNum];
+    xcb_map_notify_event_t *xmap = (xcb_map_notify_event_t *) event;
+    int                    reltype, type = event->response_type & 0x7f;
+
+    switch (type) {
+    case XCB_MAP_NOTIFY:
+	if (xmap->window == dmxScreen->rootWin)
+	    return FALSE;
+
+	/* fall-through */
+    case XCB_UNMAP_NOTIFY:
+    case XCB_CONFIGURE_NOTIFY:
+	if (xmap->event != DefaultRootWindow (dmxScreen->beDisplay))
+	    return FALSE;
+
+	dmxDnDFreeChildren (pScreen);
+
+	dmxScreen->queryTree.sequence = 0;
+
+	if (dmxScreen->dndStatus)
+	    dmxBEDnDUpdatePosition (pScreen, dmxScreen->dndX, dmxScreen->dndY);
+	break;
+    case XCB_CLIENT_MESSAGE: {
+	xcb_client_message_event_t *xclient =
+	    (xcb_client_message_event_t *) event;
+	xcb_atom_t                 type = xclient->type;
+
+	if (dmxAtom (dmxScreen, type) == dmxScreen->xdndPositionAtom)
+	{
+	    dmxDnDPositionMessage (pScreen,
+				   xclient->data.data32[0],
+				   xclient->data.data32[2] >> 16,
+				   xclient->data.data32[2] & 0xffff,
+				   xclient->data.data32[3],
+				   xclient->data.data32[4]);
+	}
+	else if (dmxAtom (dmxScreen, type) == dmxScreen->xdndEnterAtom)
+	{
+	    dmxDnDEnterMessage (pScreen,
+				xclient->window,
+				xclient->data.data32[0],
+				xclient->data.data32[2],
+				xclient->data.data32[3],
+				xclient->data.data32[4],
+				((xclient->data.data32[1] & 1) != 0),
+				(xclient->data.data32[1] & 0xff000000) >> 24);
+	}
+	else if (dmxAtom (dmxScreen, type) == dmxScreen->xdndLeaveAtom)
+	{
+	    dmxDnDLeaveMessage (pScreen, xclient->data.data32[0]);
+	}
+	else if (dmxAtom (dmxScreen, type) == dmxScreen->xdndDropAtom)
+	{
+	    dmxDnDDropMessage (pScreen,
+			       xclient->data.data32[0],
+			       xclient->data.data32[2]);
+	}
+	else if (dmxAtom (dmxScreen, type) == dmxScreen->xdndStatusAtom)
+	{
+	    dmxDnDStatusMessage (pScreen,
+				 xclient->data.data32[0],
+				 ((xclient->data.data32[1] & 1) != 0),
+				 xclient->data.data32[4]);
+	}
+	else if (dmxAtom (dmxScreen, type) == dmxScreen->xdndFinishedAtom)
+	{
+	    dmxDnDFinishedMessage (pScreen,
+				   xclient->data.data32[0],
+				   ((xclient->data.data32[1] & 1) != 0),
+				   xclient->data.data32[2]);
+	}
+	else
+	{
+	    return FALSE;
+	}
+    } break;
+    default:
+	reltype = type - dmxScreen->beShapeEventBase;
+
+	switch (reltype) {
+	case XCB_SHAPE_NOTIFY: {
+	    xcb_shape_notify_event_t *xshape =
+		(xcb_shape_notify_event_t *) event;
+	    int                      i;
+
+	    for (i = 0; i < dmxScreen->dndNChildren; i++)
+		if (dmxScreen->dndChildren[i].target == xshape->affected_window)
+		    break;
+
+	    if (i < dmxScreen->dndNChildren)
+	    {
+		xcb_shape_get_rectangles_cookie_t shape;
+
+		switch (xshape->shape_kind) {
+		case ShapeBounding:
+		    shape = xcb_shape_get_rectangles (dmxScreen->connection,
+						      xshape->affected_window,
+						      ShapeBounding);
+		    dmxAddRequest (&dmxScreen->request,
+				   dmxDnDBoundingShapeUpdateReply,
+				   shape.sequence,
+				   (void *) i);
+
+		case ShapeInput:
+		    shape = xcb_shape_get_rectangles (dmxScreen->connection,
+						      xshape->affected_window,
+						      ShapeInput);
+		    dmxAddRequest (&dmxScreen->request,
+				   dmxDnDInputShapeUpdateReply,
+				   shape.sequence,
+				   (void *) i);
+		default:
+		    break;
+		}
+	    }
+	    else
+	    {
+		return FALSE;
+	    }
+	} break;
+	default:
+	    return FALSE;
+	}
+    }
+
+    return TRUE;
+}
+
+void
+dmxDnDClientMessageEvent (xEvent *event)
+{
+    Atom type = event->u.clientMessage.u.l.type;
+    int  i;
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	if (type == dmxScreens[0].xdndStatusAtom)
+	{
+	    int  dndStatus = event->u.clientMessage.u.l.longs1 & 1;
+	    Atom dndAcceptedAction = event->u.clientMessage.u.l.longs4;
+
+	    if (!dmxScreen->dndSource)
+		continue;
+
+	    if (event->u.clientMessage.u.l.longs0 != dmxScreen->dndTarget)
+		continue;
+
+	    if (dmxScreen->dndStatus         != dndStatus ||
+		dmxScreen->dndAcceptedAction != dndAcceptedAction)
+	    {
+		xcb_client_message_event_t xevent;
+
+		dmxScreen->dndStatus         = dndStatus;
+		dmxScreen->dndAcceptedAction = dndAcceptedAction;
+
+		xevent.response_type = XCB_CLIENT_MESSAGE;
+		xevent.format        = 32;
+
+		xevent.type   = dmxBEAtom (dmxScreen,
+					   dmxScreen->xdndStatusAtom);
+		xevent.window = dmxScreen->dndSource;
+
+		xevent.data.data32[0] = dmxScreen->dndWid;
+		xevent.data.data32[1] = dmxScreen->dndStatus;
+		xevent.data.data32[2] = 0;
+		xevent.data.data32[3] = 0;
+		xevent.data.data32[4] = 0;
+
+		if (ValidAtom (dmxScreen->dndAcceptedAction))
+		    xevent.data.data32[4] =
+			dmxBEAtom (dmxScreen,
+				   dmxScreen->dndAcceptedAction);
+
+		xcb_send_event (dmxScreen->connection,
+				FALSE,
+				dmxScreen->dndSource,
+				0,
+				(const char *) &xevent);
+	    }
+
+	    REGION_EMPTY (pScreen, &dmxScreen->dndBox);
+
+	    if (dmxScreen->dndStatus & 2)
+	    {
+		BoxRec box;
+
+		box.x1 = event->u.clientMessage.u.l.longs2 >> 16;
+		box.y1 = event->u.clientMessage.u.l.longs2 & 0xffff;
+		box.x2 = box.x1 +
+		    (event->u.clientMessage.u.l.longs3 >> 16);
+		box.y2 = box.y1 +
+		    (event->u.clientMessage.u.l.longs3 & 0xffff);
+
+		REGION_RESET (pScreen, &dmxScreen->dndBox, &box);
+	    }
+
+	    if (dmxScreen->dndX != dmxScreen->dndXPos ||
+		dmxScreen->dndY != dmxScreen->dndYPos)
+	    {
+		WindowPtr pWin = WindowTable[i];
+#ifdef PANORAMIX
+		if (!noPanoramiXExtension)
+		    pWin = WindowTable[0];
+#endif
+
+		dmxDnDUpdatePosition (dmxScreen,
+				      pWin,
+				      dmxScreen->dndX,
+				      dmxScreen->dndY);
+	    }
+	}
+	else if (type == dmxScreen->xdndFinishedAtom)
+	{
+	    xcb_client_message_event_t xevent;
+
+	    if (!dmxScreen->dndSource)
+		continue;
+
+	    if (event->u.clientMessage.u.l.longs0 != dmxScreen->dndTarget)
+		continue;
+
+	    xevent.response_type = XCB_CLIENT_MESSAGE;
+	    xevent.format        = 32;
+
+	    xevent.type   = dmxBEAtom (dmxScreen, dmxScreen->xdndFinishedAtom);
+	    xevent.window = dmxScreen->dndSource;
+
+	    xevent.data.data32[0] = dmxScreen->dndWid;
+	    xevent.data.data32[1] = 0;
+	    xevent.data.data32[2] = 0;
+	    xevent.data.data32[3] = 0;
+	    xevent.data.data32[4] = 0;
+
+	    if (dmxScreen->dndVersion >= 5)
+	    {
+		xevent.data.data32[1] = event->u.clientMessage.u.l.longs1 & 1;
+		xevent.data.data32[2] = event->u.clientMessage.u.l.longs2;
+	    }
+
+	    xcb_send_event (dmxScreen->connection,
+			    FALSE,
+			    dmxScreen->dndSource,
+			    0,
+			    (const char *) &xevent);
+
+	    dmxScreen->dndTarget = None;
+	    dmxScreen->dndWindow = None;
+		
+	    dmxDnDLeaveMessage (screenInfo.screens[i], dmxScreen->dndSource);
+
+	    dmxScreen->dndWid    = None;
+	    dmxScreen->dndSource = None;
+	}
+	else if (type == dmxScreen->xdndEnterAtom)
+	{
+	    dmxScreen->dndAction      = None;
+	    dmxScreen->dndType[0]     = event->u.clientMessage.u.l.longs2;
+	    dmxScreen->dndType[1]     = event->u.clientMessage.u.l.longs3;
+	    dmxScreen->dndType[2]     = event->u.clientMessage.u.l.longs4;
+	    dmxScreen->dndHasTypeProp =
+		((event->u.clientMessage.u.l.longs1 & 1) != 0);
+	}
+	else if (type == dmxScreen->xdndLeaveAtom)
+	{
+	    dmxBEDnDHideProxyWindow (screenInfo.screens[i]);
+	}
+	else if (type == dmxScreen->xdndPositionAtom)
+	{
+	    WindowPtr pWin = NullWindow;
+	    Window    dndSource = dmxScreen->dndSource;
+
+#ifdef PANORAMIX
+	    PanoramiXRes *win = NULL;
+
+	    if (!noPanoramiXExtension)
+	    {
+		win = (PanoramiXRes *)
+		    SecurityLookupIDByType (serverClient,
+					    event->u.clientMessage.u.l.longs0,
+					    XRT_WINDOW,
+					    DixReadAccess);
+		if (win)
+		    dixLookupWindow (&pWin, win->info[i].id,
+				     serverClient, DixReadAccess);
+	    }
+	    else
+#endif
+		dixLookupWindow (&pWin, event->u.clientMessage.u.l.longs0,
+				 serverClient, DixReadAccess);
+
+	    if (pWin)
+		dmxScreen->dndSource = DMX_GET_WINDOW_PRIV (pWin)->window;
+
+	    dmxScreen->dndWindow = event->u.clientMessage.u.l.longs0;
+	    dmxScreen->dndAction = event->u.clientMessage.u.l.longs4;
+	    dmxScreen->dndXPos   = -1;
+	    dmxScreen->dndXPos   = -1;
+
+	    if (dmxScreen->dndStatus)
+	    {
+		if (dmxScreen->dndSource != dndSource)
+		    dmxDnDSendDeclineStatus ();
+
+		dmxBEDnDUpdatePosition (screenInfo.screens[i],
+					dmxScreen->dndX,
+					dmxScreen->dndY);
+	    }
+	}
+	else if (type == dmxScreen->xdndDropAtom)
+	{
+	    Window target = None;
+	    int    status = 0;
+	    
+	    if (dmxScreen->dndStatus)
+	    {
+		if (dmxScreen->dndTarget)
+		{
+		    xcb_client_message_event_t xevent;
+
+		    xevent.response_type = XCB_CLIENT_MESSAGE;
+		    xevent.format        = 32;
+
+		    xevent.type   = dmxBEAtom (dmxScreen,
+					       dmxScreen->xdndDropAtom);
+		    xevent.window = dmxScreen->dndTarget;
+
+		    xevent.data.data32[0] = dmxScreen->dndSource;
+		    xevent.data.data32[1] = 0;
+		    xevent.data.data32[2] = 0; /* XXX: need time stamp */
+		    xevent.data.data32[3] = 0;
+		    xevent.data.data32[4] = 0;
+
+		    xcb_send_event (dmxScreen->connection,
+				    FALSE,
+				    dmxScreen->dndWid,
+				    0,
+				    (const char *) &xevent);
+
+		    status = 1;
+		    target = dmxScreen->dndTarget;
+
+		    dmxScreen->dndTarget = None;
+		}
+		else
+		{
+		    WindowPtr pWin;
+		    xEvent    x;
+
+		    x.u.u.type                   = ClientMessage | 0x80;
+		    x.u.u.detail                 = 32;
+		    x.u.clientMessage.window     = dmxScreens[0].dndWindow;
+		    x.u.clientMessage.u.l.type   =
+			dmxScreens[0].xdndFinishedAtom;
+		    x.u.clientMessage.u.l.longs0 =
+			dmxScreens[0].inputOverlayWid;
+		    x.u.clientMessage.u.l.longs1 = 0;
+		    x.u.clientMessage.u.l.longs2 = 0;
+		    x.u.clientMessage.u.l.longs3 = 0;
+		    x.u.clientMessage.u.l.longs4 = 0;
+
+		    if (dixLookupWindow (&pWin,
+					 dmxScreens[0].dndWindow,
+					 serverClient,
+					 DixReadAccess) == Success)
+			DeliverEventsToWindow (PickPointer (serverClient),
+					       pWin,
+					       &x,
+					       1,
+					       NoEventMask,
+					       NullGrab, 0);
+		}
+	    }
+
+	    dmxBEDnDHideProxyWindow (screenInfo.screens[i]);
+
+	    dmxScreen->dndTarget = target;
+	    dmxScreen->dndStatus = status;
+	}
+    }
+}
+
+#define MAKE_DND_ATOM(name)				\
+    MakeAtom ("Xdnd" name, strlen ("Xdnd" name), TRUE)
+
+Bool
+dmxDnDScreenInit (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    
+    dmxScreen->wmStateAtom = MakeAtom ("WM_STATE", strlen ("WM_STATE"), TRUE);
+
+    dmxScreen->xdndProxyAtom = MAKE_DND_ATOM ("Proxy");
+    dmxScreen->xdndAwareAtom = MAKE_DND_ATOM ("Aware");
+    dmxScreen->xdndSelectionAtom = MAKE_DND_ATOM ("Selection");
+    dmxScreen->xdndEnterAtom = MAKE_DND_ATOM ("Enter");
+    dmxScreen->xdndPositionAtom = MAKE_DND_ATOM ("Position");
+    dmxScreen->xdndStatusAtom = MAKE_DND_ATOM ("Status");
+    dmxScreen->xdndLeaveAtom = MAKE_DND_ATOM ("Leave");
+    dmxScreen->xdndDropAtom = MAKE_DND_ATOM ("Drop");
+    dmxScreen->xdndFinishedAtom = MAKE_DND_ATOM ("Finished");
+    dmxScreen->xdndTypeListAtom = MAKE_DND_ATOM ("TypeList");
+    dmxScreen->xdndActionAskAtom = MAKE_DND_ATOM ("ActionAsk");
+    dmxScreen->xdndActionListAtom = MAKE_DND_ATOM ("ActionList");
+    dmxScreen->xdndActionDescriptionAtom = MAKE_DND_ATOM ("ActionDescription");
+
+    dmxScreen->dndXPos = -1;
+    dmxScreen->dndYPos = -1;
+
+    REGION_INIT (pScreen, &dmxScreen->dndBox, NullBox, 0);
+
+    return TRUE;
+}
+
+void
+dmxDnDScreenFini (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    REGION_UNINIT (pScreen, &dmxScreen->dndBox);
+}
diff --git a/hw/dmx/dmxdnd.h b/hw/dmx/dmxdnd.h
new file mode 100644
index 0000000..6c6d975
--- /dev/null
+++ b/hw/dmx/dmxdnd.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXDND_H
+#define DMXDND_H
+
+#include "dmx.h"
+
+void
+dmxBEDnDRootWindowUpdate (ScreenPtr pScreen,
+			  Window    window);
+
+void
+dmxBEDnDSpriteUpdate (ScreenPtr pScreen,
+		      Window    window,
+		      int       rootX,
+		      int       rootY);
+
+Bool
+dmxScreenEventCheckDnD (ScreenPtr           pScreen,
+			xcb_generic_event_t *event);
+
+void
+dmxDnDClientMessageEvent (xEvent *event);
+
+Bool
+dmxDnDScreenInit (ScreenPtr pScreen);
+
+void
+dmxDnDScreenFini (ScreenPtr pScreen);
+
+#endif /* DMXDND_H */
diff --git a/hw/dmx/dmxdpms.c b/hw/dmx/dmxdpms.c
index 2af1605..0498cf4 100644
--- a/hw/dmx/dmxdpms.c
+++ b/hw/dmx/dmxdpms.c
@@ -56,13 +56,17 @@
 static unsigned long dpmsGeneration = 0;
 static Bool          dpmsSupported  = TRUE;
 
-static void _dmxDPMSInit(DMXScreenInfo *dmxScreen)
+/** Initialize DPMS support.  We save the current settings and turn off
+ * DPMS.  The settings are restored in #dmxDPMSTerm. */
+void dmxBEDPMSScreenInit(ScreenPtr pScreen)
 {
-    int        event_base, error_base;
-    int        major, minor;
-    CARD16     level, standby, suspend, off;
-    BOOL       state;
-    const char *monitor;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           event_base, error_base;
+    int           major, minor;
+    CARD16        level, standby, suspend, off;
+    BOOL          state;
+    const char    *monitor;
+    int           status = 1;
 
     if (dpmsGeneration != serverGeneration) {
         dpmsSupported  = TRUE;  /* On unless a backend doesn't support it */
@@ -74,37 +78,52 @@ static void _dmxDPMSInit(DMXScreenInfo *dmxScreen)
 #endif
 
     dmxScreen->dpmsCapable = 0;
-    
+
     if (!dmxScreen->beDisplay) {
         dmxLogOutput(dmxScreen,
 		     "Cannot determine if DPMS supported (detached screen)\n");
-        dpmsSupported = FALSE;
         return;
     }
 
-    if (!DPMSQueryExtension(dmxScreen->beDisplay,
-                            &event_base, &error_base)) {
-        dmxLogOutput(dmxScreen, "DPMS not supported\n");
-        dpmsSupported = FALSE;
-        return;
-    }
-    if (!DPMSGetVersion(dmxScreen->beDisplay, &major, &minor)) {
-        dmxLogOutput(dmxScreen, "DPMS not supported\n");
-        dpmsSupported = FALSE;
+    if (dmxScreen->scrnWin != DefaultRootWindow (dmxScreen->beDisplay)) {
+        dmxLogOutput(dmxScreen,
+		     "Cannot use DPMS in window mode\n");
         return;
     }
-    if (!DPMSCapable(dmxScreen->beDisplay)) {
-        dmxLogOutput(dmxScreen, "DPMS %d.%d (not DPMS capable)\n",
-                     major, minor);
-        dpmsSupported = FALSE;
-        return;
+
+    dpmsSupported = FALSE;
+
+    XLIB_PROLOGUE (dmxScreen);
+
+    if (!(status = DPMSQueryExtension(dmxScreen->beDisplay,
+				      &event_base, &error_base)))
+	dmxLogOutput(dmxScreen, "DPMS not supported\n");
+
+    if (status)
+	if (!(status = DPMSGetVersion(dmxScreen->beDisplay, &major, &minor)))
+	    dmxLogOutput(dmxScreen, "DPMS not supported\n");
+
+    if (status)
+	if (!(status = DPMSCapable(dmxScreen->beDisplay)))
+	    dmxLogOutput(dmxScreen, "DPMS %d.%d (not DPMS capable)\n",
+			 major, minor);
+
+    if (status)
+    {
+	DPMSInfo(dmxScreen->beDisplay, &level, &state);
+	DPMSGetTimeouts(dmxScreen->beDisplay, &standby, &suspend, &off);
+	DPMSSetTimeouts(dmxScreen->beDisplay, 0, 0, 0);
+	DPMSEnable(dmxScreen->beDisplay);
+	DPMSForceLevel(dmxScreen->beDisplay, DPMSModeOn);
+
+	dpmsSupported = TRUE;
     }
 
-    DPMSInfo(dmxScreen->beDisplay, &level, &state);
-    DPMSGetTimeouts(dmxScreen->beDisplay, &standby, &suspend, &off);
-    DPMSSetTimeouts(dmxScreen->beDisplay, 0, 0, 0);
-    DPMSEnable(dmxScreen->beDisplay);
-    DPMSForceLevel(dmxScreen->beDisplay, DPMSModeOn);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!dpmsSupported)
+	return;
+
     dmxScreen->dpmsCapable = 1;
     dmxScreen->dpmsEnabled = !!state;
     dmxScreen->dpmsStandby = standby;
@@ -125,49 +144,26 @@ static void _dmxDPMSInit(DMXScreenInfo *dmxScreen)
                  standby, suspend, off);
 }
 
-/** Initialize DPMS support.  We save the current settings and turn off
- * DPMS.  The settings are restored in #dmxDPMSTerm. */
-void dmxDPMSInit(DMXScreenInfo *dmxScreen)
-{
-    int    interval, preferBlanking, allowExposures;
-
-                                /* Turn off DPMS */
-    _dmxDPMSInit(dmxScreen);
-
-    if (!dmxScreen->beDisplay)
-	return;
-
-                                /* Turn off screen saver */
-    XGetScreenSaver(dmxScreen->beDisplay, &dmxScreen->savedTimeout, &interval,
-		    &preferBlanking, &allowExposures);
-    XSetScreenSaver(dmxScreen->beDisplay, 0, interval,
-		    preferBlanking, allowExposures);
-    XResetScreenSaver(dmxScreen->beDisplay);
-    dmxSync(dmxScreen, FALSE);
-}
-
 /** Terminate DPMS support on \a dmxScreen.  We restore the settings
  * saved in #dmxDPMSInit. */
-void dmxDPMSTerm(DMXScreenInfo *dmxScreen)
+void dmxBEDPMSScreenFini(ScreenPtr pScreen)
 {
-    int    timeout, interval, preferBlanking, allowExposures;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 
     if (!dmxScreen->beDisplay)
 	return;
 
-    XGetScreenSaver(dmxScreen->beDisplay, &timeout, &interval,
-		    &preferBlanking, &allowExposures);
-    XSetScreenSaver(dmxScreen->beDisplay, dmxScreen->savedTimeout, interval,
-		    preferBlanking, allowExposures);
     if (dmxScreen->dpmsCapable) {
                                 /* Restore saved state */
+	XLIB_PROLOGUE (dmxScreen);
         DPMSForceLevel(dmxScreen->beDisplay, DPMSModeOn);
         DPMSSetTimeouts(dmxScreen->beDisplay, dmxScreen->dpmsStandby,
                         dmxScreen->dpmsSuspend, dmxScreen->dpmsOff);
         if (dmxScreen->dpmsEnabled) DPMSEnable(dmxScreen->beDisplay);
         else                        DPMSDisable(dmxScreen->beDisplay);
+	XLIB_EPILOGUE (dmxScreen);
+	dmxSync(dmxScreen, FALSE);
     }
-    dmxSync(dmxScreen, FALSE);
 }
 
 /** Called when activity is detected so that DPMS power-saving mode can
@@ -203,8 +199,10 @@ int DPMSSet(ClientPtr client, int level)
 
     for (i = 0; i < dmxNumScreens; i++) {
         DMXScreenInfo *dmxScreen = &dmxScreens[i];
-	if (dmxScreen->beDisplay) {
+	if (dmxScreen->beDisplay && dmxScreen->dpmsCapable) {
+	    XLIB_PROLOGUE (dmxScreen);
 	    DPMSForceLevel(dmxScreen->beDisplay, level);
+	    XLIB_EPILOGUE (dmxScreen);
 	    dmxSync(dmxScreen, FALSE);
 	}
     }
diff --git a/hw/dmx/dmxdpms.h b/hw/dmx/dmxdpms.h
index e3eee98..5be9a39 100644
--- a/hw/dmx/dmxdpms.h
+++ b/hw/dmx/dmxdpms.h
@@ -36,7 +36,7 @@
 
 #ifndef _DMXDPMS_H_
 #define _DMXDPMS_H_
-extern void dmxDPMSInit(DMXScreenInfo *dmxScreen);
-extern void dmxDPMSTerm(DMXScreenInfo *dmxScreen);
+extern void dmxBEDPMSScreenInit(ScreenPtr pScreen);
+extern void dmxBEDPMSScreenFini(ScreenPtr pScreen);
 extern void dmxDPMSWakeup(void); /* Call when input is processed */
 #endif
diff --git a/hw/dmx/dmxextension.c b/hw/dmx/dmxextension.c
index aaa50d5..a3eef48 100644
--- a/hw/dmx/dmxextension.c
+++ b/hw/dmx/dmxextension.c
@@ -51,18 +51,38 @@
 #include "dmxgc.h"
 #include "dmxfont.h"
 #include "dmxcmap.h"
+#include "dmxshm.h"
 #ifdef RENDER
 #include "dmxpict.h"
 #endif
+#ifdef RANDR
+#include "dmxrandr.h"
+#endif
 #include "dmxinput.h"
+#include "dmxlog.h"
+#include "dmxgrab.h"
 #include "dmxsync.h"
 #include "dmxscrinit.h"
-#include "input/dmxinputinit.h"
+#ifdef XV
+#include "dmxxv.h"
+#endif
 
 #include "windowstr.h"
 #include "inputstr.h"                 /* For DeviceIntRec */
 #include <X11/extensions/dmxproto.h>  /* For DMX_BAD_* */
 #include "cursorstr.h"
+#include "propertyst.h"
+
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+#endif
+
+#define dmxErrorSet(set, error, name, fmt, ...)       \
+    if (set) (*set) (error, name, fmt, ##__VA_ARGS__)
+
+#define dmxLogErrorSet(type, set, error, name, fmt, ...) \
+    dmxLog (type, fmt "\n", ##__VA_ARGS__);		 \
+    dmxErrorSet (set, error, name, fmt, ##__VA_ARGS__)
 
 /* The default font is declared in dix/globals.c, but is not included in
  * _any_ header files. */
@@ -77,7 +97,8 @@ Bool dmxGetScreenAttributes(int physical, DMXScreenAttributesPtr attr)
     if (physical < 0 || physical >= dmxNumScreens) return FALSE;
 
     dmxScreen = &dmxScreens[physical];
-    attr->displayName         = dmxScreen->name;
+    attr->name                = dmxScreen->name;
+    attr->displayName         = dmxScreen->display;
 #ifdef PANORAMIX
     attr->logicalScreen       = noPanoramiXExtension ? dmxScreen->index : 0;
 #else
@@ -86,16 +107,25 @@ Bool dmxGetScreenAttributes(int physical, DMXScreenAttributesPtr attr)
 
     attr->screenWindowWidth   = dmxScreen->scrnWidth;
     attr->screenWindowHeight  = dmxScreen->scrnHeight;
-    attr->screenWindowXoffset = dmxScreen->scrnX;
-    attr->screenWindowYoffset = dmxScreen->scrnY;
+    attr->screenWindowXoffset = 0;
+    attr->screenWindowYoffset = 0;
+
+    attr->rootWindowWidth     = WindowTable[physical]->drawable.width;
+    attr->rootWindowHeight    = WindowTable[physical]->drawable.height;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	attr->rootWindowWidth  = PanoramiXPixWidth;
+	attr->rootWindowHeight = PanoramiXPixHeight;
+    }
+#endif
 
-    attr->rootWindowWidth     = dmxScreen->rootWidth;
-    attr->rootWindowHeight    = dmxScreen->rootHeight;
     attr->rootWindowXoffset   = dmxScreen->rootX;
     attr->rootWindowYoffset   = dmxScreen->rootY;
 
-    attr->rootWindowXorigin   = dmxScreen->rootXOrigin;
-    attr->rootWindowYorigin   = dmxScreen->rootYOrigin;
+    attr->rootWindowXorigin   = 0;
+    attr->rootWindowYorigin   = 0;
 
     return TRUE;
 }
@@ -156,6 +186,76 @@ Bool dmxGetWindowAttributes(WindowPtr pWindow, DMXWindowAttributesPtr attr)
     return TRUE;
 }
 
+/** This routine provides information to the DMX protocol extension
+ * about a particular window. */
+Bool dmxGetDrawableAttributes(DrawablePtr pDraw, DMXWindowAttributesPtr attr)
+{
+    if ((pDraw->type == UNDRAWABLE_WINDOW) || (pDraw->type == DRAWABLE_WINDOW))
+    {
+	WindowPtr pWindow = (WindowPtr) pDraw;
+	dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pWindow);
+
+	attr->screen         = pWindow->drawable.pScreen->myNum;
+	attr->window         = pWinPriv->window;
+
+	attr->pos.x          = pWindow->drawable.x;
+	attr->pos.y          = pWindow->drawable.y;
+	attr->pos.width      = pWindow->drawable.width;
+	attr->pos.height     = pWindow->drawable.height;
+
+	if (!pWinPriv->window || pWinPriv->offscreen) {
+	    attr->vis.x      = 0;
+	    attr->vis.y      = 0;
+	    attr->vis.height = 0;
+	    attr->vis.width  = 0;
+	    return pWinPriv->window ? TRUE : FALSE;
+	}
+
+	/* Compute display-relative coordinates */
+	attr->vis.x          = pWindow->drawable.x;
+	attr->vis.y          = pWindow->drawable.y;
+	attr->vis.width      = pWindow->drawable.width;
+	attr->vis.height     = pWindow->drawable.height;
+
+	if (attr->pos.x < 0) {
+	    attr->vis.x     -= attr->pos.x;
+	    attr->vis.width  = attr->pos.x + attr->pos.width - attr->vis.x;
+	}
+	if (attr->pos.x + attr->pos.width > pWindow->drawable.pScreen->width) {
+	    if (attr->pos.x < 0)
+		attr->vis.width  = pWindow->drawable.pScreen->width;
+	    else
+		attr->vis.width  = pWindow->drawable.pScreen->width - attr->pos.x;
+	}
+	if (attr->pos.y < 0) {
+	    attr->vis.y     -= attr->pos.y;
+	    attr->vis.height = attr->pos.y + attr->pos.height - attr->vis.y;
+	}
+	if (attr->pos.y + attr->pos.height > pWindow->drawable.pScreen->height) {
+	    if (attr->pos.y < 0)
+		attr->vis.height = pWindow->drawable.pScreen->height;
+	    else
+		attr->vis.height = pWindow->drawable.pScreen->height - attr->pos.y;
+	}
+
+	/* Convert to window-relative coordinates */
+	attr->vis.x -= attr->pos.x;
+	attr->vis.y -= attr->pos.y;
+    }
+    else
+    {
+	PixmapPtr pPixmap = (PixmapPtr) pDraw;
+	dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV (pPixmap);
+	xRectangle empty = { 0, 0, 0, 0 };
+
+	attr->screen = pDraw->pScreen->myNum;
+	attr->window = pPixPriv->pixmap;
+	attr->pos = attr->vis = empty;
+    }
+
+    return TRUE;
+}
+
 void dmxGetDesktopAttributes(DMXDesktopAttributesPtr attr)
 {
     attr->width  = dmxGlobalWidth;
@@ -171,7 +271,9 @@ int dmxGetInputCount(void)
 {
     int i, total;
     
-    for (total = i = 0; i < dmxNumInputs; i++) total += dmxInputs[i].numDevs;
+    for (total = i = 0; i < dmxNumScreens; i++)
+	total += dmxScreens[i].input.numDevs;
+
     return total;
 }
 
@@ -185,89 +287,83 @@ int dmxGetInputAttributes(int deviceId, DMXInputAttributesPtr attr)
     DMXInputInfo *dmxInput;
 
     if (deviceId < 0) return -1;
-    for (i = 0; i < dmxNumInputs; i++) {
-        dmxInput = &dmxInputs[i];
+    for (i = 0; i < dmxNumScreens; i++) {
+        dmxInput = &dmxScreens[i].input;
         for (j = 0; j < dmxInput->numDevs; j++) {
-            DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
-            if (deviceId != dmxLocal->pDevice->id) continue;
-            attr->isCore             = !!dmxLocal->isCore;
-            attr->sendsCore          = !!dmxLocal->sendsCore;
-            attr->detached           = !!dmxInput->detached;
-            attr->physicalScreen     = -1;
-            attr->physicalId         = -1;
-            attr->name               = NULL;
-            switch (dmxLocal->extType) {
-            case DMX_LOCAL_TYPE_LOCAL:
-                attr->inputType      = 0;
-                break;
-            case DMX_LOCAL_TYPE_CONSOLE:
-                attr->inputType      = 1;
-                attr->name           = dmxInput->name;
-                attr->physicalId     = dmxLocal->deviceId;
-                break;
-            case DMX_LOCAL_TYPE_BACKEND:
-            case DMX_LOCAL_TYPE_COMMON:
-                attr->inputType      = 2;
-                attr->physicalScreen = dmxInput->scrnIdx;
-                attr->name           = dmxInput->name;
-                attr->physicalId     = dmxLocal->deviceId;
-                break;
-            }
-            return 0;           /* Success */
+            if (deviceId != dmxInput->devs[i]->id) continue;
+            attr->isCore         = FALSE;
+            attr->sendsCore      = TRUE;
+            attr->detached       = FALSE;
+	    attr->inputType      = 2;
+	    attr->physicalScreen = i;
+	    attr->name           = dmxInput->devs[i]->name;
+	    attr->physicalId     = deviceId;
+	    return 0;           /* Success */
         }
     }
     return -1;                  /* Failure */
 }
 
-/** Reinitialized the cursor boundaries. */
-static void dmxAdjustCursorBoundaries(void)
-{
-    int           i;
-
-    dmxReInitOrigins();
-    dmxInitOverlap();
-    dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
-    dmxConnectionBlockCallback();
-    for (i = 0; i < dmxNumInputs; i++) {
-        DMXInputInfo *dmxInput = &dmxInputs[i];
-	if (!dmxInput->detached) dmxInputReInit(dmxInput);
-    }
-
-    dmxCheckCursor();
-
-    for (i = 0; i < dmxNumInputs; i++) {
-        DMXInputInfo *dmxInput = &dmxInputs[i];
-	if (!dmxInput->detached) dmxInputLateReInit(dmxInput);
-    }
-}
-
 /** Add an input with the specified attributes.  If the input is added,
  * the physical id is returned in \a deviceId. */
 int dmxAddInput(DMXInputAttributesPtr attr, int *id)
 {
-    int retcode = BadValue;
+    if (attr->physicalScreen < 0 || attr->physicalScreen >= dmxNumScreens)
+	return BadValue;
 
-    if (attr->inputType == 1)   /* console */
-        retcode = dmxInputAttachConsole(attr->name, attr->sendsCore, id);
-    else if (attr->inputType == 2)   /* backend */
-        retcode = dmxInputAttachBackend(attr->physicalScreen,
-                                        attr->sendsCore,id);
+    if (attr->inputType == 2)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[attr->physicalScreen];
+	int           ret;
 
-    if (retcode == Success) {
-        /* Adjust the cursor boundaries */
-        dmxAdjustCursorBoundaries();
+	if (dmxScreen->beDisplay)
+	{
+	    ret = dmxInputAttach (&dmxScreen->input);
+	    if (ret != Success)
+		return ret;
 
-        /* Force completion of the changes */
-        dmxSync(NULL, TRUE);
+	    dmxInputEnable (&dmxScreen->input);
+	}
+	else
+	{
+	    dmxScreen->beDisplay = dmxScreen->beAttachedDisplay;
+	    ret = dmxInputAttach (&dmxScreen->input);
+	    dmxScreen->beDisplay = NULL;
+	
+	    if (ret != Success)
+		return ret;
+	}
+
+	*id = attr->physicalScreen;
+
+	return ret;
     }
 
-    return retcode;
+    return BadValue;
 }
 
 /** Remove the input with physical id \a id. */
 int dmxRemoveInput(int id)
 {
-    return dmxInputDetachId(id);
+    int ret;
+
+    if (id < 0 || id >= dmxNumScreens)
+	return BadValue;
+
+    if (dmxScreens[id].beDisplay)
+    {
+	dmxInputDisable (&dmxScreens[id].input);
+	ret = dmxInputDetach (&dmxScreens[id].input);
+    }
+    else
+    {
+	dmxScreens[id].beDisplay = dmxScreens[id].beAttachedDisplay;
+	ret = dmxInputDetach (&dmxScreens[id].input);
+	dmxScreens[id].beDisplay = NULL;
+
+    }
+
+    return ret;
 }
 
 /** Return the value of #dmxNumScreens -- the total number of backend
@@ -370,307 +466,6 @@ void dmxUpdateScreenResources(ScreenPtr pScreen, int x, int y, int w, int h)
     }
 }
 
-#ifdef PANORAMIX
-#include "panoramiXsrv.h"
-
-/** Change the "screen" window attributes by resizing the actual window
- *  on the back-end display (if necessary). */
-static void dmxConfigureScreenWindow(int idx,
-				     int x, int y, int w, int h)
-{
-    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-    ScreenPtr      pScreen   = screenInfo.screens[idx];
-
-    /* Resize "screen" window */
-    if (dmxScreen->scrnX      != x ||
-	dmxScreen->scrnY      != y ||
-	dmxScreen->scrnWidth  != w ||
-	dmxScreen->scrnHeight != h) {
-	dmxResizeScreenWindow(pScreen, x, y, w, h);
-    }
-
-    /* Change "screen" window values */
-    dmxScreen->scrnX      = x;
-    dmxScreen->scrnY      = y;
-    dmxScreen->scrnWidth  = w;
-    dmxScreen->scrnHeight = h;
-}
-				     
-/** Change the "root" window position and size by resizing the actual
- *  window on the back-end display (if necessary) and updating all of
- *  DMX's resources by calling #dmxUpdateScreenResources. */
-static void dmxConfigureRootWindow(int idx, int x, int y, int w, int h)
-{
-    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-    WindowPtr      pRoot     = WindowTable[idx];
-
-    /* NOTE: Either this function or the ones that it calls must handle
-     * the case where w == 0 || h == 0.  Currently, the functions that
-     * this one calls handle that case. */
-
-    /* 1. Resize "root" window */
-    if (dmxScreen->rootX      != x ||
-	dmxScreen->rootY      != y ||
-	dmxScreen->rootWidth  != w ||
-	dmxScreen->rootHeight != h) {
-	dmxResizeRootWindow(pRoot, x, y, w, h);
-    }
-
-    /* 2. Update all of the screen's resources associated with this root
-     *    window */
-    if (dmxScreen->rootWidth  != w ||
-	dmxScreen->rootHeight != h) {
-	dmxUpdateScreenResources(screenInfo.screens[idx], x, y, w, h);
-    }
-
-    /* Change "root" window values */
-    dmxScreen->rootX      = x;
-    dmxScreen->rootY      = y;
-    dmxScreen->rootWidth  = w;
-    dmxScreen->rootHeight = h;
-}
-
-/** Change the "root" window's origin by updating DMX's internal data
- *  structures (dix and Xinerama) to use the new origin and adjust the
- *  positions of windows that overlap this "root" window. */
-static void dmxSetRootWindowOrigin(int idx, int x, int y)
-{
-    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-    ScreenPtr      pScreen   = screenInfo.screens[idx];
-    WindowPtr      pRoot     = WindowTable[idx];
-    WindowPtr      pChild;
-    int            xoff;
-    int            yoff;
-
-    /* Change "root" window's origin */
-    dmxScreen->rootXOrigin = x;
-    dmxScreen->rootYOrigin = y;
-
-    /* Compute offsets here in case <x,y> has been changed above */
-    xoff = x - dixScreenOrigins[idx].x;
-    yoff = y - dixScreenOrigins[idx].y;
-
-    /* Adjust the root window's position in dixScreenOrigins */
-    dixScreenOrigins[idx].x = dmxScreen->rootXOrigin;
-    dixScreenOrigins[idx].y = dmxScreen->rootYOrigin;
-
-    /* Recalculate the Xinerama regions and data structs */
-    XineramaReinitData(pScreen);
-
-    /* Adjust each of the root window's children */
-    if (!idx) ReinitializeRootWindow(WindowTable[0], xoff, yoff);
-    pChild = pRoot->firstChild;
-    while (pChild) {
-	/* Adjust child window's position */
-	pScreen->MoveWindow(pChild,
-			    pChild->origin.x - wBorderWidth(pChild) - xoff,
-			    pChild->origin.y - wBorderWidth(pChild) - yoff,
-			    pChild->nextSib,
-			    VTMove);
-
-	/* Note that the call to MoveWindow will eventually call
-	 * dmxPositionWindow which will automatically create a
-	 * window if it is now exposed on screen (for lazy window
-	 * creation optimization) and it will properly set the
-	 * offscreen flag.
-	 */
-
-	pChild = pChild->nextSib;
-    }
-}
-
-/** Configure the attributes of each "screen" and "root" window. */
-int dmxConfigureScreenWindows(int nscreens,
-			      CARD32 *screens,
-			      DMXScreenAttributesPtr attribs,
-			      int *errorScreen)
-{
-    int           i;
-
-    for (i = 0; i < nscreens; i++) {
-	DMXScreenAttributesPtr  attr      = &attribs[i];
-	int                     idx       = screens[i];
-	DMXScreenInfo          *dmxScreen = &dmxScreens[idx];
-
-	if (errorScreen) *errorScreen = i;
-
-	if (!dmxScreen->beDisplay) return DMX_BAD_VALUE;
-
-	/* Check for illegal values */
-	if (idx < 0 || idx >= dmxNumScreens) return BadValue;
-
-	/* The "screen" and "root" windows must have valid sizes */
-	if (attr->screenWindowWidth <= 0 || attr->screenWindowHeight <= 0 ||
-	    attr->rootWindowWidth   <  0 || attr->rootWindowHeight   <  0)
-	    return DMX_BAD_VALUE;
-
-	/* The "screen" window must fit entirely within the BE display */
-	if (attr->screenWindowXoffset < 0 ||
-	    attr->screenWindowYoffset < 0 ||
-	    attr->screenWindowXoffset
-	    + attr->screenWindowWidth  > (unsigned)dmxScreen->beWidth ||
-	    attr->screenWindowYoffset
-	    + attr->screenWindowHeight > (unsigned)dmxScreen->beHeight)
-	    return DMX_BAD_VALUE;
-
-	/* The "root" window must fit entirely within the "screen" window */
-	if (attr->rootWindowXoffset < 0 ||
-	    attr->rootWindowYoffset < 0 ||
-	    attr->rootWindowXoffset
-	    + attr->rootWindowWidth  > attr->screenWindowWidth ||
-	    attr->rootWindowYoffset
-	    + attr->rootWindowHeight > attr->screenWindowHeight)
-	    return DMX_BAD_VALUE;
-
-	/* The "root" window must not expose unaddressable coordinates */
-	if (attr->rootWindowXorigin < 0 ||
-	    attr->rootWindowYorigin < 0 ||
-	    attr->rootWindowXorigin + attr->rootWindowWidth  > 32767 ||
-	    attr->rootWindowYorigin + attr->rootWindowHeight > 32767)
-	    return DMX_BAD_VALUE;
-
-	/* The "root" window must fit within the global bounding box */
-	if (attr->rootWindowXorigin
-	    + attr->rootWindowWidth > (unsigned)dmxGlobalWidth ||
-	    attr->rootWindowYorigin
-	    + attr->rootWindowHeight > (unsigned)dmxGlobalHeight)
-	    return DMX_BAD_VALUE;
-
-	/* FIXME: Handle the rest of the illegal value checking */
-    }
-
-    /* No illegal values found */
-    if (errorScreen) *errorScreen = 0;
-
-    for (i = 0; i < nscreens; i++) {
-	DMXScreenAttributesPtr  attr      = &attribs[i];
-	int                     idx       = screens[i];
-	DMXScreenInfo          *dmxScreen = &dmxScreens[idx];
-
-	dmxLog(dmxInfo, "Changing screen #%d attributes "
-	       "from %dx%d+%d+%d %dx%d+%d+%d +%d+%d "
-	       "to %dx%d+%d+%d %dx%d+%d+%d +%d+%d\n",
-	       idx,
-	       dmxScreen->scrnWidth,      dmxScreen->scrnHeight,
-	       dmxScreen->scrnX,          dmxScreen->scrnY,
-	       dmxScreen->rootWidth,      dmxScreen->rootHeight,
-	       dmxScreen->rootX,          dmxScreen->rootY,
-	       dmxScreen->rootXOrigin,    dmxScreen->rootYOrigin,
-	       attr->screenWindowWidth,   attr->screenWindowHeight,
-	       attr->screenWindowXoffset, attr->screenWindowYoffset,
-	       attr->rootWindowWidth,     attr->rootWindowHeight,
-	       attr->rootWindowXoffset,   attr->rootWindowYoffset,
-	       attr->rootWindowXorigin,   attr->rootWindowYorigin);
-
-	/* Configure "screen" window */
-	dmxConfigureScreenWindow(idx,
-				 attr->screenWindowXoffset,
-				 attr->screenWindowYoffset,
-				 attr->screenWindowWidth,
-				 attr->screenWindowHeight);
-
-	/* Configure "root" window */
-	dmxConfigureRootWindow(idx,
-			       attr->rootWindowXoffset,
-			       attr->rootWindowYoffset,
-			       attr->rootWindowWidth,
-			       attr->rootWindowHeight);
-
-
-	/* Set "root" window's origin */
-	dmxSetRootWindowOrigin(idx,
-			       attr->rootWindowXorigin,
-			       attr->rootWindowYorigin);
-    }
-
-    /* Adjust the cursor boundaries */
-    dmxAdjustCursorBoundaries();
-
-    /* Force completion of the changes */
-    dmxSync(NULL, TRUE);
-
-    return Success;
-}
-
-/** Configure the attributes of the global desktop. */
-int dmxConfigureDesktop(DMXDesktopAttributesPtr attribs)
-{
-    if (attribs->width  <= 0 || attribs->width  >= 32767 ||
-	attribs->height <= 0 || attribs->height >= 32767)
-	return DMX_BAD_VALUE;
-
-    /* If the desktop is shrinking, adjust the "root" windows on each
-     * "screen" window to only show the visible desktop.  Also, handle
-     * the special case where the desktop shrinks such that the it no
-     * longer overlaps an portion of a "screen" window. */
-    if (attribs->width < dmxGlobalWidth || attribs->height < dmxGlobalHeight) {
-	int   i;
-	for (i = 0; i < dmxNumScreens; i++) {
-	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
-	    if (dmxScreen->rootXOrigin
-		+ dmxScreen->rootWidth  > attribs->width ||
-		dmxScreen->rootYOrigin
-		+ dmxScreen->rootHeight > attribs->height) {
-		int  w, h;
-		if ((w = attribs->width  - dmxScreen->rootXOrigin) < 0) w = 0;
-		if ((h = attribs->height - dmxScreen->rootYOrigin) < 0) h = 0;
-		if (w > dmxScreen->scrnWidth)  w = dmxScreen->scrnWidth;
-		if (h > dmxScreen->scrnHeight) h = dmxScreen->scrnHeight;
-		if (w > dmxScreen->rootWidth)  w = dmxScreen->rootWidth;
-		if (h > dmxScreen->rootHeight) h = dmxScreen->rootHeight;
-		dmxConfigureRootWindow(i,
-				       dmxScreen->rootX,
-				       dmxScreen->rootY,
-				       w, h);
-	    }
-	}
-    }
-
-    /* Set the global width/height */
-    dmxSetWidthHeight(attribs->width, attribs->height);
-
-    /* Handle shift[XY] changes */
-    if (attribs->shiftX || attribs->shiftY) {
-	int   i;
-	for (i = 0; i < dmxNumScreens; i++) {
-	    ScreenPtr  pScreen = screenInfo.screens[i];
-	    WindowPtr  pChild  = WindowTable[i]->firstChild;
-	    while (pChild) {
-		/* Adjust child window's position */
-		pScreen->MoveWindow(pChild,
-				    pChild->origin.x - wBorderWidth(pChild)
-				    - attribs->shiftX,
-				    pChild->origin.y - wBorderWidth(pChild)
-				    - attribs->shiftY,
-				    pChild->nextSib,
-				    VTMove);
-
-		/* Note that the call to MoveWindow will eventually call
-		 * dmxPositionWindow which will automatically create a
-		 * window if it is now exposed on screen (for lazy
-		 * window creation optimization) and it will properly
-		 * set the offscreen flag.
-		 */
-
-		pChild = pChild->nextSib;
-	    }
-	}
-    }
-
-    /* Update connection block, Xinerama, etc. -- these appears to
-     * already be handled in dmxConnectionBlockCallback(), which is
-     * called from dmxAdjustCursorBoundaries() [below]. */
-
-    /* Adjust the cursor boundaries */
-    dmxAdjustCursorBoundaries();
-
-    /* Force completion of the changes */
-    dmxSync(NULL, TRUE);
-
-    return Success;
-}
-#endif
-
 /** Create the scratch GCs per depth. */
 static void dmxBECreateScratchGCs(int scrnNum)
 {
@@ -685,6 +480,8 @@ static void dmxBECreateScratchGCs(int scrnNum)
 #ifdef PANORAMIX
 static Bool FoundPixImage;
 
+extern unsigned long	XRT_PICTURE;
+
 /** Search the Xinerama XRT_PIXMAP resources for the pixmap that needs
  *  to have its image restored.  When it is found, see if there is
  *  another screen with the same image.  If so, copy the pixmap image
@@ -692,46 +489,128 @@ static Bool FoundPixImage;
 static void dmxBERestorePixmapImage(pointer value, XID id, RESTYPE type,
 				    pointer p)
 {
+    PixmapPtr pSrc = NULL;
+    PixmapPtr pDst = (PixmapPtr) p;
+    int       idx      = pDst->drawable.pScreen->myNum;
+    int       i;
+
     if ((type & TypeMask) == (XRT_PIXMAP & TypeMask)) {
-	PixmapPtr      pDst     = (PixmapPtr)p;
 	int            idx      = pDst->drawable.pScreen->myNum;
 	PanoramiXRes  *pXinPix  = (PanoramiXRes *)value;
 	PixmapPtr      pPix;
-	int            i;
 
 	pPix = (PixmapPtr)LookupIDByType(pXinPix->info[idx].id, RT_PIXMAP);
 	if (pPix != pDst) return; /* Not a match.... Next! */
 
-	for (i = 0; i < PanoramiXNumScreens; i++) {
-	    PixmapPtr      pSrc;
-	    dmxPixPrivPtr  pSrcPriv = NULL;
-
+	for (i = 0; i < PanoramiXNumScreens; i++)
+	{
 	    if (i == idx) continue; /* Self replication is bad */
 
 	    pSrc =
 		(PixmapPtr)LookupIDByType(pXinPix->info[i].id, RT_PIXMAP);
-	    pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
-	    if (pSrcPriv->pixmap) {
-		DMXScreenInfo *dmxSrcScreen = &dmxScreens[i];
-		DMXScreenInfo *dmxDstScreen = &dmxScreens[idx];
-		dmxPixPrivPtr  pDstPriv = DMX_GET_PIXMAP_PRIV(pDst);
-		XImage        *img;
-		int            j;
-		XlibGC         gc = NULL;
-
-		/* This should never happen, but just in case.... */
-		if (pSrc->drawable.width  != pDst->drawable.width ||
-		    pSrc->drawable.height != pDst->drawable.height)
-		    return;
-
-		/* Copy from src pixmap to dst pixmap */
-		img = XGetImage(dmxSrcScreen->beDisplay,
-				pSrcPriv->pixmap,
-				0, 0,
-				pSrc->drawable.width, pSrc->drawable.height,
-				-1,
-				ZPixmap);
+	    break;
+	}
+    }
+
+#ifdef RENDER
+    else if ((type & TypeMask) == (XRT_PICTURE & TypeMask))
+    {
+	int           idx      = pDst->drawable.pScreen->myNum;
+	PanoramiXRes  *pXinPic  = (PanoramiXRes *) value;
+	PicturePtr    pPic;
+
+	pPic = (PicturePtr) LookupIDByType (pXinPic->info[idx].id,
+					    PictureType);
+
+	/* Not a match.... Next! */
+	if (!pPic || !pPic->pDrawable) return;
+	if (pPic->pDrawable->type != DRAWABLE_PIXMAP) return;
+	if (pPic->pDrawable != (DrawablePtr) pDst) return;
+
+	for (i = 0; i < PanoramiXNumScreens; i++)
+	{
+	    if (i == idx) continue; /* Self replication is bad */
+
+	    pPic = (PicturePtr) LookupIDByType (pXinPic->info[i].id,
+						PictureType);
+	    pSrc = (PixmapPtr) pPic->pDrawable;
+	    break;
+	}
+    }
+#endif
+
+    else if ((type & TypeMask) == (XRT_WINDOW & TypeMask))
+    {
+	PixmapPtr      pDst     = (PixmapPtr)p;
+	int            idx      = pDst->drawable.pScreen->myNum;
+	PanoramiXRes  *pXinWin  = (PanoramiXRes *) value;
+	Bool	      border;
+	WindowPtr     pWin;
 
+	pWin = (WindowPtr) LookupIDByType (pXinWin->info[idx].id, RT_WINDOW);
+
+	if (!pWin) return;
+	if (!pWin->borderIsPixel && pWin->border.pixmap == pDst)
+	{
+	    border = TRUE;
+	}
+	else if (pWin->backgroundState == BackgroundPixmap &&
+		 pWin->background.pixmap == pDst)
+	{
+	    border = FALSE;
+	}
+	else
+	{
+	    return;
+	}
+
+	for (i = 0; i < PanoramiXNumScreens; i++)
+	{
+	    if (i == idx) continue; /* Self replication is bad */
+
+	    pWin = (WindowPtr) LookupIDByType (pXinWin->info[i].id, RT_WINDOW);
+
+	    if (border)
+		pSrc = pWin->border.pixmap;
+	    else
+		pSrc = pWin->background.pixmap;
+
+	    break;
+	}
+    }
+
+    if (pSrc)
+    {
+	dmxPixPrivPtr pSrcPriv = DMX_GET_PIXMAP_PRIV (pSrc);
+
+	if (pSrcPriv->pixmap)
+	{
+	    DMXScreenInfo *dmxSrcScreen = &dmxScreens[i];
+	    DMXScreenInfo *dmxDstScreen = &dmxScreens[idx];
+	    dmxPixPrivPtr  pDstPriv = DMX_GET_PIXMAP_PRIV(pDst);
+	    XImage        *img = NULL;
+	    int            j;
+	    XlibGC         gc = NULL;
+
+	    /* This should never happen, but just in case.... */
+	    if (pSrc->drawable.width  != pDst->drawable.width ||
+		pSrc->drawable.height != pDst->drawable.height)
+		return;
+
+	    XLIB_PROLOGUE (dmxSrcScreen);
+
+	    /* Copy from src pixmap to dst pixmap */
+	    img = XGetImage(dmxSrcScreen->beDisplay,
+			    pSrcPriv->pixmap,
+			    0, 0,
+			    pSrc->drawable.width, pSrc->drawable.height,
+			    -1,
+			    ZPixmap);
+
+	    XLIB_EPILOGUE (dmxSrcScreen);
+
+	    if (img)
+	    {
 		for (j = 0; j < dmxDstScreen->beNumPixmapFormats; j++) {
 		    if (dmxDstScreen->bePixmapFormats[j].depth == img->depth) {
 			unsigned long  m;
@@ -742,26 +621,31 @@ static void dmxBERestorePixmapImage(pointer value, XID id, RESTYPE type,
 			v.plane_mask = AllPlanes;
 			v.clip_mask = None;
 
+			XLIB_PROLOGUE (dmxDstScreen);
 			gc = XCreateGC(dmxDstScreen->beDisplay,
 				       dmxDstScreen->scrnDefDrawables[j],
 				       m, &v);
+			XLIB_EPILOGUE (dmxDstScreen);
 			break;
 		    }
 		}
 
 		if (gc) {
+		    XLIB_PROLOGUE (dmxDstScreen);
 		    XPutImage(dmxDstScreen->beDisplay,
 			      pDstPriv->pixmap,
 			      gc, img, 0, 0, 0, 0,
 			      pDst->drawable.width, pDst->drawable.height);
 		    XFreeGC(dmxDstScreen->beDisplay, gc);
+		    XLIB_EPILOGUE (dmxDstScreen);
 		    FoundPixImage = True;
 		} else {
 		    dmxLog(dmxWarning, "Could not create GC\n");
 		}
 
 		XDestroyImage(img);
-		return;
+	    } else {
+		dmxLog(dmxWarning, "Could not create image\n");
 	    }
 	}
     }
@@ -810,14 +694,17 @@ static void dmxBERestorePixmap(PixmapPtr pPixmap)
 		    v.plane_mask = AllPlanes;
 		    v.clip_mask = None;
 
+		    XLIB_PROLOGUE (dmxScreen);
 		    gc = XCreateGC(dmxScreen->beDisplay,
 				   dmxScreen->scrnDefDrawables[i],
 				   m, &v);
+		    XLIB_EPILOGUE (dmxScreen);
 		    break;
 		}
 	    }
 
 	    if (gc) {
+		XLIB_PROLOGUE (dmxScreen);
 		XPutImage(dmxScreen->beDisplay,
 			  pPixPriv->pixmap,
 			  gc,
@@ -825,6 +712,7 @@ static void dmxBERestorePixmap(PixmapPtr pPixmap)
 			  0, 0, 0, 0,
 		      pPixmap->drawable.width, pPixmap->drawable.height);
 		XFreeGC(dmxScreen->beDisplay, gc);
+		XLIB_EPILOGUE (dmxScreen);
 	    } else {
 		dmxLog(dmxWarning, "Cannot restore pixmap image\n");
 	    }
@@ -832,7 +720,10 @@ static void dmxBERestorePixmap(PixmapPtr pPixmap)
 	    XDestroyImage(pPixPriv->detachedImage);
 	    pPixPriv->detachedImage = NULL;
 	} else {
-	    dmxLog(dmxWarning, "Cannot restore pixmap image\n");
+	    dmxLog(dmxWarning, "Cannot restore pixmap image: %dx%d - %d\n",
+		   pPixmap->drawable.width,
+		   pPixmap->drawable.height,
+		   pPixmap->drawable.depth);
 	}
     }
 #else
@@ -888,11 +779,17 @@ static void dmxBECreateResources(pointer value, XID id, RESTYPE type,
     } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
 	(void)dmxBELoadFont(pScreen, (FontPtr)value);
     } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
-	dmxBECreateCursor(pScreen, (CursorPtr)value);
+	dmxBECreateCursor (pScreen, (CursorPtr) value);
+    } else if ((type & TypeMask) == (RT_PASSIVEGRAB & TypeMask)) {
+	GrabPtr grab = value;
+	if (grab->cursor)
+	    dmxBECreateCursor (pScreen, grab->cursor);
     } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
 	ColormapPtr  pCmap = value;
 	if (pCmap->pScreen->myNum == scrnNum)
 	    (void)dmxBECreateColormap((ColormapPtr)value);
+    } else if ((type & TypeMask) == (DMX_SHMSEG & TypeMask)) {
+	dmxBEAttachShmSeg (&dmxScreens[scrnNum], (dmxShmSegInfoPtr) value);
 #if 0
 #ifdef RENDER
     /* TODO: Recreate Picture and GlyphSet resources */
@@ -930,9 +827,14 @@ static void dmxBECreateWindowTree(int idx)
 	dmxBERestorePixmap(pRoot->background.pixmap);
     }
 
+    dmxBECreateCursor (screenInfo.screens[idx], pRoot->optional->cursor);
+
     /* Create root window first */
     dmxScreen->rootWin = pWinPriv->window = dmxCreateRootWindow(pRoot);
-    XMapWindow(dmxScreen->beDisplay, dmxScreen->rootWin);
+
+#ifdef RENDER
+    if (pWinPriv->hasPict) dmxCreatePictureList (pRoot);
+#endif
 
     pWin = pRoot->lastChild;
     while (pWin) {
@@ -950,14 +852,17 @@ static void dmxBECreateWindowTree(int idx)
 	    dmxBERestorePixmap(pWin->background.pixmap);
 	}
 
+	if (wUseDefault(pWin, cursor, 0))
+	    dmxBECreateCursor (screenInfo.screens[idx],
+			       pWin->optional->cursor);
+
 	/* Reset the window attributes */
 	dmxGetDefaultWindowAttributes(pWin,
 				      &pWinPriv->cmap,
 				      &pWinPriv->visual);
 
 	/* Create the window */
-	if (pWinPriv->mapped && !pWinPriv->offscreen)
-	    dmxCreateAndRealizeWindow(pWin, TRUE);
+	dmxCreateAndRealizeWindow(pWin, TRUE);
 
 	/* Next, create the bottom-most child */
 	if (pWin->lastChild) {
@@ -980,77 +885,392 @@ static void dmxBECreateWindowTree(int idx)
     }
 }
 
-/* Refresh screen by generating exposure events for all windows */
-static void dmxForceExposures(int idx)
+static void dmxBEMapRootWindow(int idx)
 {
-    ScreenPtr      pScreen   = screenInfo.screens[idx];
-    WindowPtr  pRoot     = WindowTable[idx];
-    Bool       anyMarked = FALSE;
-    WindowPtr  pChild;
+    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
 
-    for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib)
-	anyMarked |= pScreen->MarkOverlappedWindows(pChild, pChild,
-						    (WindowPtr *)NULL);
-    if (anyMarked) {
-	/* If any windows have been marked, set the root window's
-	 * clipList to be broken since it will be recalculated in
-	 * ValidateTree()
-	 */
-	REGION_BREAK(pScreen, &pRoot->clipList);
-	pScreen->ValidateTree(pRoot, NULL, VTBroken);
-	pScreen->HandleExposures(pRoot);
-	if (pScreen->PostValidateTree)
-	    pScreen->PostValidateTree(pRoot, NULL, VTBroken);
+    XLIB_PROLOGUE (dmxScreen);
+    XMapWindow(dmxScreen->beDisplay, dmxScreen->rootWin);
+    XLIB_EPILOGUE (dmxScreen);
+}
+
+static void dmxBECreateWindowProperties (int idx)
+{
+    WindowPtr      pRoot  = WindowTable[idx];
+    WindowPtr      pRoot0 = pRoot;
+    WindowPtr      pWin;
+    WindowPtr      pWin0;
+    PropertyPtr    pProp, pLast;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+	pRoot0 = WindowTable[0];
+#endif
+
+    pWin = pRoot;
+    pWin0 = pRoot0;
+    while (pWin)
+    {
+	pLast = NULL;
+	do
+	{
+	    for (pProp = wUserProps (pWin0); pProp; pProp = pProp->next)
+	    	if (pProp->next == pLast)
+		    break;
+
+	    if (pProp)
+		dmxBESetWindowProperty (pWin, (pLast = pProp));
+	} while (pLast != wUserProps (pWin0));
+
+	/* Next, create the bottom-most child */
+	if (pWin->lastChild) {
+	    pWin = pWin->lastChild;
+	    pWin0 = pWin0->lastChild;
+	    continue;
+	}
+
+	/* If the window has no children, move on to the next higher window */
+	while (!pWin->prevSib && (pWin != pRoot))
+	{
+	    pWin = pWin->parent;
+	    pWin0 = pWin0->parent;
+	}
+
+	if (pWin->prevSib) {
+	    pWin = pWin->prevSib;
+	    pWin0 = pWin0->prevSib;
+	    continue;
+	}
+
+	/* When we reach the root window, we are finished */
+	if (pWin == pRoot)
+	    break;
     }
 }
 
 /** Compare the new and old screens to see if they are compatible. */
-static Bool dmxCompareScreens(DMXScreenInfo *new, DMXScreenInfo *old)
+static Bool dmxCompareScreens(DMXScreenInfo      *new,
+			      DMXScreenInfo      *old,
+			      dmxErrorSetProcPtr errorSet,
+			      void		 *error,
+			      const char         *errorName)
 {
     int i;
 
-    if (new->beWidth != old->beWidth) return FALSE;
-    if (new->beHeight != old->beHeight) return FALSE;
-    if (new->beDepth != old->beDepth) return FALSE;
-    if (new->beBPP != old->beBPP) return FALSE;
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	ScreenPtr pScreen = screenInfo.screens[0];
+	int       j;
+
+	old = dmxScreens; /* each new screen must match the first screen */
+
+	if (new->beDepth != old->beDepth)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "Screen depth is not %d",
+			    old->beDepth);
+	    return FALSE;
+	}
+
+	if (new->beBPP != old->beBPP)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "Screen BPP is not %d",
+			    old->beBPP);
+	    return FALSE;
+	}
+
+	for (i = 0; i < old->beNumDepths; i++)
+	{
+	    for (j = 0; j < new->beNumDepths; j++)
+		if (new->beDepths[j] == old->beDepths[i])
+		    break;
+
+	    if (j == new->beNumDepths)
+	    {
+		dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+				"Screen doesn't support depth %d",
+				old->beDepths[i]);
+		return FALSE;
+	    }
+	}
+
+	for (i = 0; i < old->beNumPixmapFormats; i++)
+	{
+	    for (j = 0; j < new->beNumPixmapFormats; j++)
+		if (new->bePixmapFormats[j].depth ==
+		    old->bePixmapFormats[i].depth &&
+		    new->bePixmapFormats[j].bits_per_pixel ==
+		    old->bePixmapFormats[i].bits_per_pixel &&
+		    new->bePixmapFormats[j].scanline_pad ==
+		    old->bePixmapFormats[i].scanline_pad)
+		    break;
+
+	    if (j == new->beNumPixmapFormats)
+	    {
+		dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+				"Screen doesn't support pixmap format "
+				"depth=%d,bits_per_pixel=%d,scanline_pad=%d\n",
+				old->bePixmapFormats[i].depth,
+				old->bePixmapFormats[i].bits_per_pixel,
+				old->bePixmapFormats[i].scanline_pad);
+		return FALSE;
+	    }
+	}
+
+	for (i = 0; i < pScreen->numVisuals; i++)
+	{
+	    int k;
+
+	    for (k = 0; k < old->beNumVisuals; k++)
+		if (pScreen->visuals[i].class ==
+		    old->beVisuals[k].class &&
+		    pScreen->visuals[i].bitsPerRGBValue ==
+		    old->beVisuals[k].bits_per_rgb &&
+		    pScreen->visuals[i].ColormapEntries ==
+		    old->beVisuals[k].colormap_size &&
+		    pScreen->visuals[i].nplanes ==
+		    old->beVisuals[k].depth &&
+		    pScreen->visuals[i].redMask ==
+		    old->beVisuals[k].red_mask &&
+		    pScreen->visuals[i].greenMask ==
+		    old->beVisuals[k].green_mask &&
+		    pScreen->visuals[i].blueMask ==
+		    old->beVisuals[k].blue_mask)
+		    break;
+
+	    assert (k < old->beNumVisuals);
+
+	    for (j = 0; j < new->beNumVisuals; j++)
+		if (new->beVisuals[j].depth ==
+		    old->beVisuals[k].depth &&
+		    new->beVisuals[j].class ==
+		    old->beVisuals[k].class &&
+		    new->beVisuals[j].red_mask ==
+		    old->beVisuals[k].red_mask &&
+		    new->beVisuals[j].green_mask ==
+		    old->beVisuals[k].green_mask &&
+		    new->beVisuals[j].blue_mask ==
+		    old->beVisuals[k].blue_mask &&
+		    new->beVisuals[j].bits_per_rgb >=
+		    old->beVisuals[k].bits_per_rgb &&
+		    new->beVisuals[j].colormap_size >=
+		    old->beVisuals[k].colormap_size)
+		    break;
+
+	    if (j == new->beNumVisuals)
+	    {
+		dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+				"Screen doesn't support visual: "
+				"class: %s, "
+				"depth: %d planes, "
+				"available colormap entries: %d%s, "
+				"red/green/blue masks: 0x%lx/0x%lx/0x%lx, "
+				"significant bits in color specification: "
+				"%d bits",
+				old->beVisuals[k].class == StaticGray ?
+				"StaticGray" :
+				old->beVisuals[k].class == GrayScale ?
+				"GrayScale" :
+				old->beVisuals[k].class == StaticColor ?
+				"StaticColor" :
+				old->beVisuals[k].class == PseudoColor ?
+				"PseudoColor" :
+				old->beVisuals[k].class == TrueColor ?
+				"TrueColor" :
+				old->beVisuals[k].class == DirectColor ?
+				"DirectColor" :
+				"Unknown Class",
+				old->beVisuals[k].depth,
+				old->beVisuals[k].colormap_size,
+				(old->beVisuals[k].class == TrueColor ||
+				 old->beVisuals[k].class == DirectColor) ?
+				" per subfield" : "",
+				old->beVisuals[k].red_mask,
+				old->beVisuals[k].green_mask,
+				old->beVisuals[k].blue_mask,
+				old->beVisuals[k].bits_per_rgb);
+		return FALSE;
+	    }
+	}
+
+	return TRUE;
+    }
+#endif
+
+    if (new->beWidth != old->beWidth || new->beHeight != old->beHeight)
+    {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Screen dimensions are not %dx%d",
+			old->beWidth, old->beHeight);
+	return FALSE;
+    }
+    if (new->beDepth != old->beDepth)
+    {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Screen depth is not %d",
+			old->beDepth);
+	return FALSE;
+    }
+    if (new->beBPP != old->beBPP)
+    {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Screen BPP is not %dx%d",
+			old->beBPP);
+	return FALSE;
+    }
+    if (new->beNumDepths != old->beNumDepths)
+    {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Screen number of depths is not %d",
+			old->beNumDepths);
+	return FALSE;
+    }
 
-    if (new->beNumDepths != old->beNumDepths) return FALSE;
     for (i = 0; i < old->beNumDepths; i++)
-	if (new->beDepths[i] != old->beDepths[i]) return FALSE;
+	if (new->beDepths[i] != old->beDepths[i])
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "Screen depth index %d is not %d",
+			    i, old->beDepths[i]);
+	    return FALSE;
+	}
 
-    if (new->beNumPixmapFormats != old->beNumPixmapFormats) return FALSE;
+    if (new->beNumPixmapFormats != old->beNumPixmapFormats)
+    {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Screen number of pixmap formats is not %d",
+			old->beNumPixmapFormats);
+	return FALSE;
+    }
     for (i = 0; i < old->beNumPixmapFormats; i++) {
 	if (new->bePixmapFormats[i].depth !=
-	    old->bePixmapFormats[i].depth) return FALSE;
+	    old->bePixmapFormats[i].depth)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "depth of screen pixmap format index %d is not %d",
+			    i, old->bePixmapFormats[i].depth);
+	    return FALSE;
+	}
 	if (new->bePixmapFormats[i].bits_per_pixel !=
-	    old->bePixmapFormats[i].bits_per_pixel) return FALSE;
+	    old->bePixmapFormats[i].bits_per_pixel)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "bits_per_pixel of screen pixmap format "
+			    "index %d is not %d",
+			    i, old->bePixmapFormats[i].bits_per_pixel);
+	    return FALSE;
+	}
 	if (new->bePixmapFormats[i].scanline_pad !=
-	    old->bePixmapFormats[i].scanline_pad) return FALSE;
+	    old->bePixmapFormats[i].scanline_pad)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "scanline_pad of screen pixmap format "
+			    "index %d is not %d",
+			    i, old->bePixmapFormats[i].scanline_pad);
+	    return FALSE;
+	}
     }
 
-    if (new->beNumVisuals != old->beNumVisuals) return FALSE;
+    if (new->beNumVisuals != old->beNumVisuals)
+    {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Screen number of visuals is not %d",
+			old->beNumVisuals);
+	return FALSE;
+    }
     for (i = 0; i < old->beNumVisuals; i++) {
 	if (new->beVisuals[i].visualid !=
-	    old->beVisuals[i].visualid) return FALSE;
+	    old->beVisuals[i].visualid)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "visualid of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].visualid);
+	    return FALSE;
+	}
 	if (new->beVisuals[i].screen !=
-	    old->beVisuals[i].screen) return FALSE;
+	    old->beVisuals[i].screen)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "screen of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].screen);
+	    return FALSE;
+	}
 	if (new->beVisuals[i].depth !=
-	    old->beVisuals[i].depth) return FALSE;
+	    old->beVisuals[i].depth)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "depth of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].depth);
+	    return FALSE;
+	}
 	if (new->beVisuals[i].class !=
-	    old->beVisuals[i].class) return FALSE;
+	    old->beVisuals[i].class)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "class of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].class);
+	    return FALSE;
+	}
 	if (new->beVisuals[i].red_mask !=
-	    old->beVisuals[i].red_mask) return FALSE;
+	    old->beVisuals[i].red_mask)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "red_mask of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].red_mask);
+	    return FALSE;
+	}
 	if (new->beVisuals[i].green_mask !=
-	    old->beVisuals[i].green_mask) return FALSE;
+	    old->beVisuals[i].green_mask)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "green_mask of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].green_mask);
+	    return FALSE;
+	}
 	if (new->beVisuals[i].blue_mask !=
-	    old->beVisuals[i].blue_mask) return FALSE;
+	    old->beVisuals[i].blue_mask)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "blue_mask of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].blue_mask);
+	    return FALSE;
+	}
 	if (new->beVisuals[i].colormap_size !=
-	    old->beVisuals[i].colormap_size) return FALSE;
+	    old->beVisuals[i].colormap_size)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "colormap_size of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].colormap_size);
+	    return FALSE;
+	}
 	if (new->beVisuals[i].bits_per_rgb !=
-	    old->beVisuals[i].bits_per_rgb) return FALSE;
+	    old->beVisuals[i].bits_per_rgb)
+	{
+	    dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			    "bits_per_rgb of screen visual "
+			    "index %d is not %d",
+			    i, old->beVisuals[i].bits_per_rgb);
+	    return FALSE;
+	}
     }
 
-    if (new->beDefVisualIndex != old->beDefVisualIndex) return FALSE;
+    if (new->beDefVisualIndex != old->beDefVisualIndex)
+    {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Screen default visual index is not %d",
+			old->beDefVisualIndex);
+	return FALSE;
+    }
 
     return TRUE;
 }
@@ -1063,20 +1283,23 @@ static void dmxBERestoreRenderPict(pointer value, XID id, pointer n)
     DrawablePtr  pDraw    = pPicture->pDrawable; /* The picture's drawable */
     int          scrnNum  = (int)n;
 
-    if (pDraw->pScreen->myNum != scrnNum) {
-	/* Picture not on the screen we are restoring*/
-	return;
-    }
+    if (pDraw)
+    {
+	if (pDraw->pScreen->myNum != scrnNum) {
+	    /* Picture not on the screen we are restoring*/
+	    return;
+	}
 
-    if (pDraw->type == DRAWABLE_PIXMAP) {
-	PixmapPtr  pPixmap = (PixmapPtr)pDraw;
+	if (pDraw->type == DRAWABLE_PIXMAP) {
+	    PixmapPtr  pPixmap = (PixmapPtr)pDraw;
 	
-	/* Create and restore the pixmap drawable */
-	dmxBECreatePixmap(pPixmap);
-	dmxBERestorePixmap(pPixmap);
+	    /* Create and restore the pixmap drawable */
+	    dmxBECreatePixmap(pPixmap);
+	    dmxBERestorePixmap(pPixmap);
+	}
     }
 
-    dmxBECreatePicture(pPicture);
+    dmxBECreatePicture(scrnNum, pPicture);
 }
 
 /** Restore Render's glyphs */
@@ -1093,7 +1316,7 @@ static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n)
     char            *pos;
     int              beret;
     int              len_images = 0;
-    int              i;
+    int              i, size;
     int              ctr;
 
     if (glyphPriv->glyphSets[scrnNum]) {
@@ -1117,9 +1340,18 @@ static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n)
 	GlyphPtr     gl = gr->glyph;
 
 	if (!gl || gl == DeletedGlyph) continue;
-	len_images += gl->size - sizeof(gl->info);
+
+	size = gl->info.height * PixmapBytePad (gl->info.width,
+						glyphSet->format->depth);
+	if (size & 3)
+	    size += 4 - (size & 3);
+
+	len_images += size;
     }
 
+    if (!len_images)
+	return;
+
     /* Now allocate the memory we need */
     images = xalloc(len_images*sizeof(char));
     gids   = xalloc(glyphSet->hash.tableEntries*sizeof(Glyph));
@@ -1133,6 +1365,7 @@ static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n)
     for (i = 0; i < glyphSet->hash.hashSet->size; i++) {
 	GlyphRefPtr  gr = &table[i];
 	GlyphPtr     gl = gr->glyph;
+	char         *data;
 
 	if (!gl || gl == DeletedGlyph) continue;
 
@@ -1147,32 +1380,62 @@ static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n)
 	glyphs[ctr].xOff   = gl->info.xOff;
 	glyphs[ctr].yOff   = gl->info.yOff;
 
-	/* Copy the images from the DIX's data into the buffer */
-	memcpy(pos, gl+1, gl->size - sizeof(gl->info));
-	pos += gl->size - sizeof(gl->info);
+	size = gl->info.height * PixmapBytePad (gl->info.width,
+						glyphSet->format->depth);
+	if (size & 3)
+	    size += 4 - (size & 3);
+
+	data = dixLookupPrivate (&(gl)->devPrivates, dmxGlyphPrivateKey);
+	if (data)
+	{
+	    memcpy (pos, data, size);
+	}
+	else
+	{
+	    dmxLog (dmxWarning,
+		    "Cannot restore glyph image: %dx%d %d\n",
+		    gl->info.width,
+		    gl->info.height,
+		    glyphSet->format->depth);
+
+	    memset (pos, 0xff, size);
+	}
+
+	pos += size;
 	ctr++;
     }
-    
+
     /* Now restore the glyph data */
+    XLIB_PROLOGUE (dmxScreen);
     XRenderAddGlyphs(dmxScreen->beDisplay, glyphPriv->glyphSets[scrnNum],
-		     gids,glyphs, glyphSet->hash.tableEntries, images,
-		     len_images);
+		     gids, glyphs, ctr, images, len_images);
+    XLIB_EPILOGUE (dmxScreen);
 
     /* Clean up */
-    xfree(len_images);
+    xfree(images);
     xfree(gids);
     xfree(glyphs);    
 }
 #endif
 
 /** Reattach previously detached back-end screen. */
-int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
+int
+dmxAttachScreen (int                    idx,
+		 DMXScreenAttributesPtr attr,
+		 unsigned int		window,
+		 const char             *authType,
+		 int                    authTypeLen,
+		 const char             *authData,
+		 int                    authDataLen,
+		 dmxErrorSetProcPtr     errorSet,
+		 void			*error,
+		 const char             *errorName)
 {
-    ScreenPtr      pScreen;
+    ScreenPtr     pScreen;
     DMXScreenInfo *dmxScreen;
-    CARD32         scrnNum   = idx;
-    DMXScreenInfo  oldDMXScreen;
-    int            i;
+    DMXScreenInfo oldDMXScreen;
+    Bool          beShape = FALSE;
+    int           errorBase;
 
     /* Return failure if dynamic addition/removal of screens is disabled */
     if (!dmxAddRemoveScreens) {
@@ -1184,19 +1447,28 @@ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
 	       "add the \"-addremovescreens\" option either to the command\n");
 	dmxLog(dmxWarning,
 	       "line or in the configuration file.\n");
+	dmxErrorSet (errorSet, error, errorName,
+		     "Screen attach extension has not been enabled");
 	return 1;
     }
 
     /* Cannot add a screen that does not exist */
-    if (idx < 0 || idx >= dmxNumScreens) return 1;
+    if (idx < 0 || idx >= dmxNumScreens)
+    {
+	dmxErrorSet (errorSet, error, errorName,
+		     "Screen %d does not exist", idx);
+	return 1;
+    }
+
     pScreen = screenInfo.screens[idx];
     dmxScreen = &dmxScreens[idx];
 
     /* Cannot attach to a screen that is already opened */
-    if (dmxScreen->beDisplay) {
-	dmxLog(dmxWarning,
-	       "Attempting to add screen #%d but a screen already exists\n",
-	       idx);
+    if (dmxScreen->name && *dmxScreen->name) {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Attempting to attach back-end server to screen #%d "
+			"but back-end server is already attached to this "
+			"screen", idx);
 	return 1;
     }
 
@@ -1205,28 +1477,59 @@ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
     /* Save old info */
     oldDMXScreen = *dmxScreen;
 
-    /* Copy the name to the new screen */
-    dmxScreen->name = strdup(attr->displayName);
+    dmxScreen->scrnWin   = window;
+    dmxScreen->virtualFb = FALSE;
 
     /* Open display and get all of the screen info */
-    if (!dmxOpenDisplay(dmxScreen)) {
-	dmxLog(dmxWarning,
-               "dmxOpenDisplay: Unable to open display %s\n",
-               dmxScreen->name);
+    if (!dmxOpenDisplay(dmxScreen,
+			attr->displayName,
+			authType,
+			authTypeLen,
+			authData,
+			authDataLen)) {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"Can't open display: %s",
+			attr->displayName);
+
+	/* Restore the old screen */
+	*dmxScreen = oldDMXScreen;
+	return 1;
+    }
+
+    XLIB_PROLOGUE (dmxScreen);
+    beShape = XShapeQueryExtension (dmxScreen->beDisplay,
+				    &dmxScreen->beShapeEventBase,
+				    &errorBase);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!beShape)
+    {
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"SHAPE extension missing");
+	dmxCloseDisplay (dmxScreen);
 
 	/* Restore the old screen */
 	*dmxScreen = oldDMXScreen;
 	return 1;
     }
 
+    if (!dmxScreen->scrnWin)
+	dmxScreen->scrnWin = DefaultRootWindow (dmxScreen->beDisplay);
+
+    XLIB_PROLOGUE (dmxScreen);
+    XSelectInput (dmxScreen->beDisplay,
+		  dmxScreen->scrnWin,
+		  StructureNotifyMask);
+    XLIB_EPILOGUE (dmxScreen);
+
     dmxSetErrorHandler(dmxScreen);
-    dmxCheckForWM(dmxScreen);
     dmxGetScreenAttribs(dmxScreen);
 
     if (!dmxGetVisualInfo(dmxScreen)) {
-	dmxLog(dmxWarning, "dmxGetVisualInfo: No matching visuals found\n");
+	dmxLogErrorSet (dmxWarning, errorSet, error, errorName,
+			"No matching visuals found");
 	XFree(dmxScreen->beVisuals);
-	XCloseDisplay(dmxScreen->beDisplay);
+	dmxCloseDisplay (dmxScreen);
 
 	/* Restore the old screen */
 	*dmxScreen = oldDMXScreen;
@@ -1238,28 +1541,82 @@ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
 
     /* Verify that the screen to be added has the same info as the
      * previously added screen. */
-    if (!dmxCompareScreens(dmxScreen, &oldDMXScreen)) {
+    if (!dmxCompareScreens(dmxScreen,
+			   &oldDMXScreen,
+			   errorSet,
+			   error,
+			   errorName))
+    {
 	dmxLog(dmxWarning,
 	       "New screen data (%s) does not match previously\n",
 	       dmxScreen->name);
 	dmxLog(dmxWarning,
-	       "attached screen data (%s)\n",
-	       oldDMXScreen.name);
+	       "attached screen data\n");
 	dmxLog(dmxWarning,
 	       "All data must match in order to attach to screen #%d\n",
 	       idx);
 	XFree(dmxScreen->beVisuals);
 	XFree(dmxScreen->beDepths);
 	XFree(dmxScreen->bePixmapFormats);
-	XCloseDisplay(dmxScreen->beDisplay);
+	dmxCloseDisplay (dmxScreen);
 
 	/* Restore the old screen */
 	*dmxScreen = oldDMXScreen;
 	return 1;
     }
 
+    /* Create the default font */
+    if (!dmxBELoadFont(pScreen, defaultFont))
+    {
+	dmxErrorSet (errorSet, error, errorName,
+		     "Failed to load default font");
+	XFree(dmxScreen->beVisuals);
+	XFree(dmxScreen->beDepths);
+	XFree(dmxScreen->bePixmapFormats);
+	dmxCloseDisplay (dmxScreen);
+
+	/* Restore the old screen */
+	*dmxScreen = oldDMXScreen;
+	return 1;
+    }
+
+    /* We used these to compare the old and new screens.  They are no
+     * longer needed since we have a newly attached screen, so we can
+     * now free the old screen's resources. */
+    if (oldDMXScreen.beVisuals)
+	XFree(oldDMXScreen.beVisuals);
+    if (oldDMXScreen.beDepths)
+	XFree(oldDMXScreen.beDepths);
+    if (oldDMXScreen.bePixmapFormats)
+	XFree(oldDMXScreen.bePixmapFormats);
+
+    if (attr->name)
+	dmxScreen->name = strdup(attr->name);
+    else
+	dmxScreen->name = strdup(attr->displayName);
+
+    dmxScreen->beAttachedDisplay = dmxScreen->beDisplay;
+    dmxScreen->beDisplay = NULL;
+
+    return 0; /* Success */
+}
+
+void
+dmxEnableScreen (int idx)
+{
+    ScreenPtr     pScreen;
+    DMXScreenInfo *dmxScreen;
+    int           i;
+
+    pScreen = screenInfo.screens[idx];
+    dmxScreen = &dmxScreens[idx];
+
+    dmxLogOutput(dmxScreen, "Enable screen #%d\n", idx);
+
+    dmxScreen->beDisplay = dmxScreen->beAttachedDisplay;
+
     /* Initialize the BE screen resources */
-    dmxBEScreenInit(idx, screenInfo.screens[idx]);
+    dmxBEScreenInit(screenInfo.screens[idx]);
 
     /* TODO: Handle GLX visual initialization.  GLXProxy needs to be
      * updated to handle dynamic addition/removal of screens. */
@@ -1271,8 +1628,9 @@ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
     /* Create the scratch GCs */
     dmxBECreateScratchGCs(idx);
 
-    /* Create the default font */
-    (void)dmxBELoadFont(pScreen, defaultFont);
+    /* Create the scratch pixmap */
+    if (pScreen->pScratchPixmap)
+	dmxBECreatePixmap(pScreen->pScratchPixmap);
 
     /* Create all resources that don't depend on windows */
     for (i = currentMaxClients; --i >= 0; )
@@ -1282,6 +1640,7 @@ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
 
     /* Create window hierarchy (top down) */
     dmxBECreateWindowTree(idx);
+    dmxBECreateWindowProperties(idx);
 
 #ifdef RENDER
     /* Restore the picture state for RENDER */
@@ -1297,25 +1656,13 @@ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
 				      dmxBERestoreRenderGlyph,(pointer)idx);
 #endif
 
-    /* Refresh screen by generating exposure events for all windows */
-    dmxForceExposures(idx);
-
-    dmxSync(&dmxScreens[idx], TRUE);
-
-    /* We used these to compare the old and new screens.  They are no
-     * longer needed since we have a newly attached screen, so we can
-     * now free the old screen's resources. */
-    XFree(oldDMXScreen.beVisuals);
-    XFree(oldDMXScreen.beDepths);
-    XFree(oldDMXScreen.bePixmapFormats);
-    /* TODO: should oldDMXScreen.name be freed?? */
+    dmxBEMapRootWindow(idx);
 
-#ifdef PANORAMIX
-    if (!noPanoramiXExtension)
-	return dmxConfigureScreenWindows(1, &scrnNum, attr, NULL);
-    else
+#ifdef RANDR
+    RRGetInfo (screenInfo.screens[0]);
 #endif
-	return 0; /* Success */
+
+    dmxInputEnable (&dmxScreen->input);
 }
 
 /*
@@ -1373,6 +1720,7 @@ static void dmxBEFindPixmapImage(pointer value, XID id, RESTYPE type,
 	int            i;
 
 	pPix = (PixmapPtr)LookupIDByType(pXinPix->info[idx].id, RT_PIXMAP);
+
 	if (pPix != pDst) return; /* Not a match.... Next! */
 
 	for (i = 0; i < PanoramiXNumScreens; i++) {
@@ -1383,6 +1731,7 @@ static void dmxBEFindPixmapImage(pointer value, XID id, RESTYPE type,
 
 	    pSrc =
 		(PixmapPtr)LookupIDByType(pXinPix->info[i].id, RT_PIXMAP);
+
 	    pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
 	    if (pSrcPriv->pixmap) {
 		FoundPixImage = True;
@@ -1390,6 +1739,87 @@ static void dmxBEFindPixmapImage(pointer value, XID id, RESTYPE type,
 	    }
 	}
     }
+
+#ifdef RENDER
+    else if ((type & TypeMask) == (XRT_PICTURE & TypeMask))
+    {
+	PixmapPtr     pDst     = (PixmapPtr) p;
+	int           idx      = pDst->drawable.pScreen->myNum;
+	PanoramiXRes  *pXinPic  = (PanoramiXRes *) value;
+	PicturePtr    pPic;
+	int           i;
+
+	pPic = (PicturePtr) LookupIDByType (pXinPic->info[idx].id,
+					    PictureType);
+
+	/* Not a match.... Next! */
+	if (!pPic || !pPic->pDrawable) return;
+	if (pPic->pDrawable->type != DRAWABLE_PIXMAP) return;
+	if (pPic->pDrawable != (DrawablePtr) pDst) return;
+
+	for (i = 0; i < PanoramiXNumScreens; i++) {
+	    dmxPixPrivPtr  pSrcPriv = NULL;
+
+	    if (i == idx) continue; /* Self replication is bad */
+
+	    pPic = (PicturePtr) LookupIDByType (pXinPic->info[i].id,
+						PictureType);
+
+	    pSrcPriv = DMX_GET_PIXMAP_PRIV ((PixmapPtr) pPic->pDrawable);
+	    if (pSrcPriv->pixmap)
+	    {
+		FoundPixImage = True;
+		return;
+	    }
+	}
+    }
+#endif
+
+    else if ((type & TypeMask) == (XRT_WINDOW & TypeMask))
+    {
+	PixmapPtr      pDst     = (PixmapPtr)p;
+	int            idx      = pDst->drawable.pScreen->myNum;
+	PanoramiXRes  *pXinWin  = (PanoramiXRes *) value;
+	Bool	      border;
+	WindowPtr     pWin;
+	int           i;
+
+	pWin = (WindowPtr) LookupIDByType (pXinWin->info[idx].id, RT_WINDOW);
+
+	if (!pWin) return;
+	if (!pWin->borderIsPixel && pWin->border.pixmap == pDst)
+	{
+	    border = TRUE;
+	}
+	else if (pWin->backgroundState == BackgroundPixmap &&
+		 pWin->background.pixmap == pDst)
+	{
+	    border = FALSE;
+	}
+	else
+	{
+	    return;
+	}
+
+	for (i = 0; i < PanoramiXNumScreens; i++) {
+	    dmxPixPrivPtr pSrcPriv = NULL;
+
+	    if (i == idx) continue; /* Self replication is bad */
+
+	    pWin = (WindowPtr) LookupIDByType (pXinWin->info[i].id, RT_WINDOW);
+
+	    if (border)
+		pSrcPriv = DMX_GET_PIXMAP_PRIV (pWin->border.pixmap);
+	    else
+		pSrcPriv = DMX_GET_PIXMAP_PRIV (pWin->background.pixmap);
+
+	    if (pSrcPriv->pixmap)
+	    {
+		FoundPixImage = True;
+		return;
+	    }
+	}
+    }
 }
 #endif
 
@@ -1426,6 +1856,7 @@ static void dmxBESavePixmap(PixmapPtr pPixmap)
 	    ScreenPtr      pScreen   = pPixmap->drawable.pScreen;
 	    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 
+	    XLIB_PROLOGUE (dmxScreen);
 	    pPixPriv->detachedImage = XGetImage(dmxScreen->beDisplay,
 						pPixPriv->pixmap,
 						0, 0,
@@ -1433,8 +1864,15 @@ static void dmxBESavePixmap(PixmapPtr pPixmap)
 						pPixmap->drawable.height,
 						-1,
 						ZPixmap);
+	    XLIB_EPILOGUE (dmxScreen);
+
 	    if (!pPixPriv->detachedImage)
-		dmxLog(dmxWarning, "Cannot save pixmap image\n");
+	    {
+		dmxLog(dmxWarning, "Cannot save pixmap image: %p - %dx%d %d\n",
+		       pPixmap, pPixmap->drawable.width,
+		       pPixmap->drawable.height,
+		       pPixmap->drawable.depth);
+	    }
 	}
     }
 #else
@@ -1476,22 +1914,31 @@ static void dmxBEDestroyResources(pointer value, XID id, RESTYPE type,
     } else if ((type & TypeMask) == (RT_FONT & TypeMask)) {
 	dmxBEFreeFont(pScreen, (FontPtr)value);
     } else if ((type & TypeMask) == (RT_CURSOR & TypeMask)) {
-	dmxBEFreeCursor(pScreen, (CursorPtr)value);
+	dmxBEFreeCursor (pScreen, (CursorPtr) value);
     } else if ((type & TypeMask) == (RT_COLORMAP & TypeMask)) {
 	ColormapPtr  pCmap = value;
 	if (pCmap->pScreen->myNum == scrnNum)
 	    dmxBEFreeColormap((ColormapPtr)value);
+    } else if ((type & TypeMask) == (DMX_SHMSEG & TypeMask)) {
+	dmxBEDetachShmSeg (&dmxScreens[scrnNum], (dmxShmSegInfoPtr) value);
 #ifdef RENDER
     } else if ((type & TypeMask) == (PictureType & TypeMask)) {
 	PicturePtr  pPict = value;
-	if (pPict->pDrawable->pScreen->myNum == scrnNum) {
-	    /* Free the pixmaps on the backend if needed */
-	    if (pPict->pDrawable->type == DRAWABLE_PIXMAP) {
-		PixmapPtr pPixmap = (PixmapPtr)(pPict->pDrawable);
-		dmxBESavePixmap(pPixmap);
-		dmxBEFreePixmap(pPixmap);
+	if (pPict->pDrawable) {
+	    if (pPict->pDrawable->pScreen->myNum == scrnNum) {
+		/* Free the pixmaps on the backend if needed */
+		if (pPict->pDrawable->type == DRAWABLE_PIXMAP) {
+		    PixmapPtr pPixmap = (PixmapPtr)(pPict->pDrawable);
+		    dmxBESavePixmap(pPixmap);
+		    dmxBEFreePixmap(pPixmap);
+		}
+
+		dmxBEFreePicture(pScreen, (PicturePtr)value);
 	    }
-	    dmxBEFreePicture((PicturePtr)value);
+	}
+	else
+	{
+	    dmxBEFreePicture(pScreen, (PicturePtr)value);
 	}
     } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
 	dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
@@ -1531,6 +1978,10 @@ static void dmxBEDestroyWindowTree(int idx)
 	/* Destroy the window */
 	dmxBEDestroyWindow(pChild);
 
+	if (wUseDefault(pChild, cursor, 0))
+	    dmxBEFreeCursor (screenInfo.screens[idx],
+			     pChild->optional->cursor);
+
 	/* Make sure we destroy the window's border and background
 	 * pixmaps if they exist */
 	if (!pChild->borderIsPixel) {
@@ -1545,6 +1996,9 @@ static void dmxBEDestroyWindowTree(int idx)
 	while (!pChild->nextSib && (pChild != pWin)) {
 	    pChild = pChild->parent;
 	    dmxBEDestroyWindow(pChild);
+	    if (wUseDefault(pChild, cursor, 0))
+		dmxBEFreeCursor (screenInfo.screens[idx],
+				 pChild->optional->cursor);
 	    if (!pChild->borderIsPixel) {
 		dmxBESavePixmap(pChild->border.pixmap);
 		dmxBEFreePixmap(pChild->border.pixmap);
@@ -1562,11 +2016,68 @@ static void dmxBEDestroyWindowTree(int idx)
     }
 }
 
+void
+dmxDisableScreen (int idx)
+{
+    ScreenPtr     pScreen;
+    DMXScreenInfo *dmxScreen;
+    int           i;
+
+    pScreen = screenInfo.screens[idx];
+    dmxScreen = &dmxScreens[idx];
+
+    dmxLogOutput(dmxScreen, "Disable screen #%d\n", idx);
+
+    dmxInputDisable (&dmxScreen->input);
+
+#ifdef XV
+    dmxBEXvScreenFini (pScreen);
+#endif
+
+#ifdef RANDR
+    dmxBERRScreenFini (pScreen);
+#endif
+
+    /* Save all relevant state (TODO) */
+
+    /* Free all non-window resources related to this screen */
+    for (i = currentMaxClients; --i >= 0; )
+	if (clients[i])
+	    FindAllClientResources(clients[i], dmxBEDestroyResources,
+				   (pointer)idx);
+
+    /* Free scratch GCs */
+    dmxBEDestroyScratchGCs(idx);
+
+    /* Free window resources related to this screen */
+    dmxBEDestroyWindowTree(idx);
+
+    /* Free default stipple */
+    dmxBESavePixmap(pScreen->PixmapPerDepth[0]);
+    dmxBEFreePixmap(pScreen->PixmapPerDepth[0]);
+
+    if (pScreen->pScratchPixmap)
+	dmxBEFreePixmap(pScreen->pScratchPixmap);
+
+    /* Free the remaining screen resources and close the screen */
+    dmxBECloseScreen(pScreen);
+
+    /* Screen is now disabled */
+    dmxScreen->beDisplay = NULL;
+
+    /* Make sure we don't have any pending sync replies */
+    dmxScreenSyncReply (pScreen, 0, NULL, NULL, 0);
+
+#ifdef RANDR
+    RRGetInfo (screenInfo.screens[0]);
+#endif
+
+}
+
 /** Detach back-end screen. */
 int dmxDetachScreen(int idx)
 {
-    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-    int            i;
+    DMXScreenInfo *dmxScreen;
 
     /* Return failure if dynamic addition/removal of screens is disabled */
     if (!dmxAddRemoveScreens) {
@@ -1584,8 +2095,17 @@ int dmxDetachScreen(int idx)
     /* Cannot remove a screen that does not exist */
     if (idx < 0 || idx >= dmxNumScreens) return 1;
 
+    dmxScreen = &dmxScreens[idx];
+
+    if (idx == 0) {
+	dmxLog(dmxWarning,
+	       "Attempting to remove screen #%d\n",
+	       idx);
+	return 1;
+    }
+
     /* Cannot detach from a screen that is not opened */
-    if (!dmxScreen->beDisplay) {
+    if (!dmxScreen->beAttachedDisplay && !dmxScreen->beDisplay) {
 	dmxLog(dmxWarning,
 	       "Attempting to remove screen #%d but it has not been opened\n",
 	       idx);
@@ -1594,32 +2114,60 @@ int dmxDetachScreen(int idx)
 
     dmxLogOutput(dmxScreen, "Detaching screen #%d\n", idx);
 
-    /* Detach input */
-    dmxInputDetachAll(dmxScreen);
+    if (dmxScreen->beDisplay)
+	dmxDisableScreen (idx);
 
-    /* Save all relevant state (TODO) */
+    /* Detach input */
+    dmxInputDetach (&dmxScreen->input);
+
+    dmxScreen->beDisplay = dmxScreen->beAttachedDisplay;
+    dmxCloseDisplay (dmxScreen);
+
+    dmxScreen->beAttachedDisplay = NULL;
+    dmxScreen->beDisplay = NULL;
+
+    dmxScreen->scrnWidth   = 1;
+    dmxScreen->scrnHeight  = 1;
+    dmxScreen->rootX       = 0;
+    dmxScreen->rootY       = 0;
+    dmxScreen->beWidth     = 1;
+    dmxScreen->beHeight    = 1;
+    dmxScreen->beXDPI      = 75;
+    dmxScreen->beYDPI      = 75;
+    dmxScreen->beDepth     = 24;
+    dmxScreen->beBPP       = 32;
+
+    if (dmxScreen->name)
+    {
+	free (dmxScreen->name);
+	dmxScreen->name = NULL;
+    }
 
-    /* Free all non-window resources related to this screen */
-    for (i = currentMaxClients; --i >= 0; )
-	if (clients[i])
-	    FindAllClientResources(clients[i], dmxBEDestroyResources,
-				   (pointer)idx);
+    if (dmxScreen->display)
+    {
+	free (dmxScreen->display);
+	dmxScreen->display = NULL;
+    }
 
-    /* Free scratch GCs */
-    dmxBEDestroyScratchGCs(idx);
+    if (dmxScreen->authType)
+    {
+	free (dmxScreen->authType);
+	dmxScreen->authType = NULL;
+    }
 
-    /* Free window resources related to this screen */
-    dmxBEDestroyWindowTree(idx);
+    dmxScreen->authTypeLen = 0;
 
-    /* Free default stipple */
-    dmxBESavePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
-    dmxBEFreePixmap(screenInfo.screens[idx]->PixmapPerDepth[0]);
+    if (dmxScreen->authData)
+    {
+	free (dmxScreen->authData);
+	dmxScreen->authData = NULL;
+    }
 
-    /* Free the remaining screen resources and close the screen */
-    dmxBECloseScreen(screenInfo.screens[idx]);
+    dmxScreen->authDataLen = 0;
 
-    /* Adjust the cursor boundaries (paints detached console window) */
-    dmxAdjustCursorBoundaries();
+#ifdef RANDR
+    RRGetInfo (screenInfo.screens[0]);
+#endif
 
     return 0; /* Success */
 }
diff --git a/hw/dmx/dmxextension.h b/hw/dmx/dmxextension.h
index 342d8c5..c1cbc39 100644
--- a/hw/dmx/dmxextension.h
+++ b/hw/dmx/dmxextension.h
@@ -42,6 +42,7 @@
 /** Screen attributes.  Used by #ProcDMXGetScreenAttributes and
  * #ProcDMXChangeScreenAttributes. */
 typedef struct {
+    const char   *name;
     const char   *displayName;
     int          logicalScreen;
 
@@ -95,6 +96,8 @@ extern Bool          dmxGetScreenAttributes(int physical,
                                             DMXScreenAttributesPtr attr);
 extern Bool          dmxGetWindowAttributes(WindowPtr pWindow,
                                             DMXWindowAttributesPtr attr);
+extern Bool          dmxGetDrawableAttributes(DrawablePtr pDraw,
+					      DMXWindowAttributesPtr attr);
 extern void          dmxGetDesktopAttributes(DMXDesktopAttributesPtr attr);
 extern int           dmxGetInputCount(void);
 extern int           dmxGetInputAttributes(int deviceId,
@@ -113,6 +116,24 @@ extern int           dmxConfigureDesktop(DMXDesktopAttributesPtr attribs);
 extern void          dmxUpdateScreenResources(ScreenPtr pScreen,
                                               int x, int y, int w, int h);
 
-extern int           dmxAttachScreen(int idx, DMXScreenAttributesPtr attr);
+
+typedef void (*dmxErrorSetProcPtr) (void       *error,
+				    const char *name,
+				    const char *format,
+				    ...);
+
+extern void          dmxEnableScreen(int idx);
+extern void          dmxDisableScreen(int idx);
+
+extern int           dmxAttachScreen (int                    idx,
+				      DMXScreenAttributesPtr attr,
+				      unsigned int	     window,
+				      const char             *authType,
+				      int                    authTypeLen,
+				      const char             *authData,
+				      int                    authDataLen,
+				      dmxErrorSetProcPtr     errorSet,
+				      void		     *error,
+				      const char             *errorName);
 extern int           dmxDetachScreen(int idx);
 #endif
diff --git a/hw/dmx/dmxfont.c b/hw/dmx/dmxfont.c
index b70f7d2..f7d7d77 100644
--- a/hw/dmx/dmxfont.c
+++ b/hw/dmx/dmxfont.c
@@ -38,8 +38,6 @@
 #include <dmx-config.h>
 #endif
 
-#define DMX_FONTPATH_DEBUG 0
-
 #include "dmx.h"
 #include "dmxsync.h"
 #include "dmxfont.h"
@@ -49,202 +47,6 @@
 #include "dixfont.h"
 #include "dixstruct.h"
 
-static int (*dmxSaveProcVector[256])(ClientPtr);
-static int   dmxFontLastError;
-
-static int dmxFontErrorHandler(Display *dpy, XErrorEvent *ev)
-{
-    dmxFontLastError = ev->error_code;
-
-    return 0;
-}
-
-static char **dmxGetFontPath(int *npaths)
-{
-    char          **fp;
-    unsigned char  *c, *paths;
-    char           *newfp;
-    int             len, l, i;
-
-    GetFontPath(serverClient, npaths, &len, &paths);
-
-    newfp = xalloc(*npaths + len);
-    c = (unsigned char *)newfp;
-    fp = xalloc(*npaths * sizeof(*fp));
-
-    memmove(newfp, paths+1, *npaths + len - 1);
-    l = *paths;
-    for (i = 0; i < *npaths; i++) {
-	fp[i] = (char *)c;
-	c += l;
-	l = *c;
-	*c++ = '\0';
-    }
-
-#if DMX_FONTPATH_DEBUG
-    for (i = 0; i < *npaths; i++)
-        dmxLog(dmxDebug, "FontPath[%d] = %s\n", i, fp[i]);
-#endif
-
-    return fp;
-}
-
-static void dmxFreeFontPath(char **fp)
-{
-    xfree(fp[0]);
-    xfree(fp);
-}
-
-static Bool dmxCheckFontPathElement(DMXScreenInfo *dmxScreen, char *fp)
-{
-    int  (*oldErrorHandler)(Display *, XErrorEvent *);
-
-    if (!dmxScreen->beDisplay)
-	return TRUE;
-
-    dmxFontLastError = 0;
-    oldErrorHandler = XSetErrorHandler(dmxFontErrorHandler);
-    XSetFontPath(dmxScreen->beDisplay, &fp, 1);
-    dmxSync(dmxScreen, TRUE);   /* Must complete before removing handler */
-    XSetErrorHandler(oldErrorHandler);
-
-    return (dmxFontLastError == 0);
-}
-
-static int dmxSetFontPath(DMXScreenInfo *dmxScreen)
-{
-    int  (*oldErrorHandler)(Display *, XErrorEvent *);
-    char **fp;
-    int    result = Success;
-    int    npaths;
-
-    if (!dmxScreen->beDisplay)
-	return result;
-
-    fp = dmxGetFontPath(&npaths);
-    if (!fp) return BadAlloc;
-
-    dmxFontLastError = 0;
-    oldErrorHandler = XSetErrorHandler(dmxFontErrorHandler);
-    XSetFontPath(dmxScreen->beDisplay, fp, npaths);
-    dmxSync(dmxScreen, TRUE);   /* Must complete before removing handler */
-    XSetErrorHandler(oldErrorHandler);
-
-    if (dmxFontLastError) {
-	result = dmxFontLastError;
-	/* We could set *error here to the offending path, but it is
-	 * ignored, so we don't bother figuring out which path is bad.
-	 * If we do add this support in the future, we'll need to add
-	 * error to the function's argument list.
-	 */
-    }
-
-    dmxFreeFontPath(fp);
-
-    return result;
-}
-
-static int dmxCheckFontPath(DMXScreenInfo *dmxScreen, int *error)
-{
-    char **oldFontPath;
-    int    nOldPaths;
-    int    result = Success;
-
-    if (!dmxScreen->beDisplay)
-	return result;
-
-    /* Save old font path */
-    oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths);
-
-    result = dmxSetFontPath(dmxScreen);
-
-    /* Restore old font path */
-    XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths);
-    XFreeFontPath(oldFontPath);
-    dmxSync(dmxScreen, FALSE);
-
-    return result;
-}
-
-static int dmxProcSetFontPath(ClientPtr client)
-{
-    unsigned char *ptr;
-    unsigned long  nbytes, total, n;
-    long           nfonts;
-    int            i, result;
-    int            error;
-    unsigned char *oldFontPath, *tmpFontPath;
-    int            nOldPaths;
-    int            lenOldPaths;
-    REQUEST(xSetFontPathReq);
-    
-    REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
-    
-    nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
-    total = nbytes;
-    ptr = (unsigned char *)&stuff[1];
-    nfonts = stuff->nFonts;
-
-    while (--nfonts >= 0) {
-	if ((total == 0) || (total < (n = (*ptr + 1))))
-	    return BadLength;
-	total -= n;
-	ptr += n;
-    }
-    if (total >= 4)
-        return BadLength;
-
-    GetFontPath(serverClient, &nOldPaths, &lenOldPaths, &tmpFontPath);
-    oldFontPath = xalloc(nOldPaths + lenOldPaths);
-    memmove(oldFontPath, tmpFontPath, nOldPaths + lenOldPaths);
-
-    result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1],
-			 &error);
-    if (!result) {
-	for (i = 0; i < dmxNumScreens; i++)
-	    if ((result = dmxCheckFontPath(&dmxScreens[i], &error)))
-		break;
-
-	if (result) {
-	    int  ignoreresult, ignoreerror;
-
-	    /* Restore old fontpath in the DMX server */
-	    ignoreresult = SetFontPath(client, nOldPaths, oldFontPath,
-				       &ignoreerror);
-	} else {
-	    result = client->noClientException;
-	    client->errorValue = error;
-	}
-    }
-
-    xfree(oldFontPath);
-    return result;
-}
-
-/** Initialize font support.  In addition to the screen function call
- *  pointers, DMX also hooks in at the ProcVector[] level.  Here the old
- *  ProcVector function pointers are saved and the new ProcVector
- *  function pointers are initialized. */
-void dmxInitFonts(void)
-{
-    int  i;
-
-    for (i = 0; i < 256; i++)
-	dmxSaveProcVector[i] = ProcVector[i];
-
-    ProcVector[X_SetFontPath] = dmxProcSetFontPath;
-}
-
-/** Reset font support by restoring the original ProcVector function
- *  pointers. */
-void dmxResetFonts(void)
-{
-    int  i;
-
-    for (i = 0; i < 256; i++)
-	ProcVector[i] = dmxSaveProcVector[i];
-}
-
 /** Load the font, \a pFont, on the back-end server associated with \a
  *  pScreen.  When a font is loaded, the font path on back-end server is
  *  first initialized to that specified on the command line with the
@@ -254,8 +56,6 @@ Bool dmxBELoadFont(ScreenPtr pScreen, FontPtr pFont)
     DMXScreenInfo  *dmxScreen = &dmxScreens[pScreen->myNum];
     dmxFontPrivPtr  pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex);
     char           *name;
-    char          **oldFontPath = NULL;
-    int             nOldPaths;
     Atom            name_atom, value_atom;
     int             i;
 
@@ -268,141 +68,6 @@ Bool dmxBELoadFont(ScreenPtr pScreen, FontPtr pFont)
 	return TRUE; /* Already loaded font */
     }
 
-    /* Save old font path */
-    oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths);
-
-    /* Set the font path for the font about to be loaded on the back-end */
-    if (dmxSetFontPath(dmxScreen)) {
-	char **fp;
-	int    npaths;
-	Bool  *goodfps;
-
-	/* This could fail only when first starting the X server and
-	 * loading the default font.  If it fails here, then the default
-	 * font path is invalid, no default font path will be set, the
-	 * DMX server will fail to load the default font, and it will
-	 * exit with an error unless we remove the offending font paths
-	 * with the -ignorebadfontpaths command line option.
-	 */
-
-	fp = dmxGetFontPath(&npaths);
-	if (!fp) {
-	    dmxLog(dmxError,
-		   "No default font path set.\n");
-	    dmxLog(dmxError,
-		   "Please see the Xdmx man page for information on how to\n");
-	    dmxLog(dmxError,
-		   "initialize the DMX server's default font path.\n");
-	    XFreeFontPath(oldFontPath);
-	    return FALSE;
-	}
-
-	if (!dmxFontPath)
-	    dmxLog(dmxWarning, "No default font path is set.\n");
-
-	goodfps = xalloc(npaths * sizeof(*goodfps));
-
-	dmxLog(dmxError,
-	       "The DMX server failed to set the following font paths on "
-	       "screen #%d:\n", pScreen->myNum);
-	
-	for (i = 0; i < npaths; i++)
-	    if (!(goodfps[i] = dmxCheckFontPathElement(dmxScreen, fp[i])))
-		dmxLog(dmxError, "    %s\n", fp[i]);
-
-	if (dmxIgnoreBadFontPaths) {
-	    char *newfp;
-	    int   newnpaths = 0;
-	    int   len = 0;
-	    int   j = 0;
-	    int   error;
-
-	    dmxLog(dmxError,
-		   "These font paths will not be used because the "
-		   "\"-ignorebadfontpaths\"\n");
-	    dmxLog(dmxError,
-		   "option is set.\n");
-
-	    for (i = 0; i < npaths; i++)
-		if (goodfps[i]) {
-		    len += strlen(fp[i]) + 1;
-		    newnpaths++;
-		}
-
-	    if (!newnpaths) {
-		/* No valid font paths were found */
-		dmxLog(dmxError,
-		       "After removing the font paths above, no valid font "
-		       "paths were\n");
-		dmxLog(dmxError,
-		       "available.  Please check that the font paths set on "
-		       "the command\n");
-		dmxLog(dmxError,
-		       "line or in the configuration file via the "
-		       "\"-fontpath\" option\n");
-		dmxLog(dmxError,
-		       "are valid on all back-end servers.  See the Xdmx man "
-		       "page for\n");
-		dmxLog(dmxError,
-		       "more information on font paths.\n");
-		dmxFreeFontPath(fp);
-		XFreeFontPath(oldFontPath);
-		xfree(goodfps);
-		return FALSE;
-	    }
-
-	    newfp = xalloc(len * sizeof(*newfp));
-	    for (i = 0; i < npaths; i++) {
-		if (goodfps[i]) {
-		    int n = strlen(fp[i]);
-		    newfp[j++] = n;
-		    strncpy(&newfp[j], fp[i], n);
-		    j += n;
-		}
-	    }
-
-	    if (SetFontPath(serverClient, newnpaths, (unsigned char *)newfp,
-			    &error)) {
-		/* Note that this should never happen since all of the
-		 * FPEs were previously valid. */
-		dmxLog(dmxError, "Cannot reset the default font path.\n");
-	    }
-	} else if (dmxFontPath) {
-	    dmxLog(dmxError,
-		   "Please remove these font paths from the command line "
-		   "or\n");
-	    dmxLog(dmxError,
-		   "configuration file, or set the \"-ignorebadfontpaths\" "
-		   "option to\n");
-	    dmxLog(dmxError,
-		   "ignore them.  For more information on these options, see "
-		   "the\n");
-	    dmxLog(dmxError,
-		   "Xdmx man page.\n");
-	} else {
-	    dmxLog(dmxError,
-		   "Please specify the font paths that are available on all "
-		   "back-end\n");
-	    dmxLog(dmxError,
-		   "servers with the \"-fontpath\" option, or use the "
-                   "\"-ignorebadfontpaths\"\n");
-            dmxLog(dmxError,
-                   "to ignore bad defaults.  For more information on "
-                   "these and other\n");
-	    dmxLog(dmxError,
-		   "font-path-related options, see the Xdmx man page.\n");
-	}
-
-	if (!dmxIgnoreBadFontPaths ||
-	    (dmxIgnoreBadFontPaths && dmxSetFontPath(dmxScreen))) {
-	    /* We still have errors so return with error */
-	    dmxFreeFontPath(fp);
-	    XFreeFontPath(oldFontPath);
-	    xfree(goodfps);
-	    return FALSE;
-	}
-    }
-
     /* Find requested font on back-end server */
     name_atom = MakeAtom("FONT", 4, TRUE);
     value_atom = 0L;
@@ -418,12 +83,13 @@ Bool dmxBELoadFont(ScreenPtr pScreen, FontPtr pFont)
     name = (char *)NameForAtom(value_atom);
     if (!name) return FALSE;
 
-    pFontPriv->font[pScreen->myNum] = 
+    pFontPriv->font[pScreen->myNum] = None;
+
+    XLIB_PROLOGUE (dmxScreen);
+    pFontPriv->font[pScreen->myNum] =
 	XLoadQueryFont(dmxScreen->beDisplay, name);
+    XLIB_EPILOGUE (dmxScreen);
 
-    /* Restore old font path */
-    XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths);
-    XFreeFontPath(oldFontPath);
     dmxSync(dmxScreen, FALSE);
 
     if (!pFontPriv->font[pScreen->myNum]) return FALSE;
@@ -472,7 +138,9 @@ Bool dmxBEFreeFont(ScreenPtr pScreen, FontPtr pFont)
     dmxFontPrivPtr  pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex);
 
     if (pFontPriv && pFontPriv->font[pScreen->myNum]) {
+	XLIB_PROLOGUE (dmxScreen);
 	XFreeFont(dmxScreen->beDisplay, pFontPriv->font[pScreen->myNum]);
+	XLIB_EPILOGUE (dmxScreen);
 	pFontPriv->font[pScreen->myNum] = NULL;
 	return TRUE;
     }
diff --git a/hw/dmx/dmxfont.h b/hw/dmx/dmxfont.h
index 086e71b..70195ec 100644
--- a/hw/dmx/dmxfont.h
+++ b/hw/dmx/dmxfont.h
@@ -45,9 +45,6 @@ typedef struct _dmxFontPriv {
     XFontStruct **font;
 } dmxFontPrivRec, *dmxFontPrivPtr;
 
-extern void dmxInitFonts(void);
-extern void dmxResetFonts(void);
-
 extern Bool dmxRealizeFont(ScreenPtr pScreen, FontPtr pFont);
 extern Bool dmxUnrealizeFont(ScreenPtr pScreen, FontPtr pFont);
 
diff --git a/hw/dmx/dmxgc.c b/hw/dmx/dmxgc.c
index eb21d3c..0d3524a 100644
--- a/hw/dmx/dmxgc.c
+++ b/hw/dmx/dmxgc.c
@@ -60,8 +60,8 @@ static GCFuncs dmxGCFuncs = {
 };
 
 static GCOps dmxGCOps = {
-    dmxFillSpans,
-    dmxSetSpans,
+    NULL, /* dmxFillSpans */
+    NULL, /* dmxSetSpans */
     dmxPutImage,
     dmxCopyArea,
     dmxCopyPlane,
@@ -77,8 +77,8 @@ static GCOps dmxGCOps = {
     dmxPolyText16,
     dmxImageText8,
     dmxImageText16,
-    dmxImageGlyphBlt,
-    dmxPolyGlyphBlt,
+    NULL, /* dmxImageGlyphBlt */
+    NULL, /* dmxPolyGlyphBlt */
     dmxPushPixels
 };
 
@@ -106,9 +106,13 @@ void dmxBECreateGC(ScreenPtr pScreen, GCPtr pGC)
 	    gcvals.graphics_exposures = FALSE;
 
 	    /* Create GC in the back-end servers */
+	    pGCPriv->gc = None;
+
+	    XLIB_PROLOGUE (dmxScreen);
 	    pGCPriv->gc = XCreateGC(dmxScreen->beDisplay,
 				    dmxScreen->scrnDefDrawables[i],
 				    mask, &gcvals);
+	    XLIB_EPILOGUE (dmxScreen);
 	    break;
 	}
     }
@@ -275,14 +279,20 @@ void dmxChangeGC(GCPtr pGC, unsigned long mask)
     if (mask & GCDashList) {
 	mask &= ~GCDashList;
 	if (dmxScreen->beDisplay)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
 	    XSetDashes(dmxScreen->beDisplay, pGCPriv->gc,
 		       pGC->dashOffset, (char *)pGC->dash,
 		       pGC->numInDashList);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
     }
     if (mask & GCArcMode)           v.arc_mode = pGC->arcMode;
 
     if (mask && dmxScreen->beDisplay) {
+	XLIB_PROLOGUE (dmxScreen);
 	XChangeGC(dmxScreen->beDisplay, pGCPriv->gc, mask, &v);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
@@ -303,7 +313,11 @@ void dmxCopyGC(GCPtr pGCSrc, unsigned long changes, GCPtr pGCDst)
 
     /* Copy the GC on the back-end server */
     if (dmxScreen->beDisplay)
+    {
+	XLIB_PROLOGUE (dmxScreen);
 	XCopyGC(dmxScreen->beDisplay, pGCSrcPriv->gc, changes, pGCDstPriv->gc);
+	XLIB_EPILOGUE (dmxScreen);
+    }
 
     DMX_GC_FUNC_EPILOGUE(pGCDst);
 }
@@ -316,7 +330,9 @@ Bool dmxBEFreeGC(GCPtr pGC)
     dmxGCPrivPtr   pGCPriv   = DMX_GET_GC_PRIV(pGC);
 
     if (pGCPriv->gc) {
+	XLIB_PROLOGUE (dmxScreen);
 	XFreeGC(dmxScreen->beDisplay, pGCPriv->gc);
+	XLIB_EPILOGUE (dmxScreen);
 	pGCPriv->gc = NULL;
 	return TRUE;
     }
@@ -358,7 +374,11 @@ void dmxChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
     switch (pGC->clientClipType) {
     case CT_NONE:
 	if (dmxScreen->beDisplay)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
 	    XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
 	break;
 
     case CT_REGION:
@@ -374,20 +394,18 @@ void dmxChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
 		pRects[i].height = pBox[i].y2 - pBox[i].y1;
 	    }
 
+	    XLIB_PROLOGUE (dmxScreen);
 	    XSetClipRectangles(dmxScreen->beDisplay, pGCPriv->gc,
 			       pGC->clipOrg.x, pGC->clipOrg.y,
 			       pRects, nRects, Unsorted);
+	    XLIB_EPILOGUE (dmxScreen);
 
 	    xfree(pRects);
 	}
 	break;
 
-    case CT_PIXMAP:
-    case CT_UNSORTED:
-    case CT_YSORTED:
-    case CT_YXSORTED:
-    case CT_YXBANDED:
-	/* These clip types are condensed down to either NONE or REGION
+    default:
+	/* Other clip types are condensed down to either NONE or REGION
            in the mi code */
 	break;
     }
@@ -407,7 +425,11 @@ void dmxDestroyClip(GCPtr pGC)
 
     /* Set the client clip on the back-end server to None */
     if (dmxScreen->beDisplay)
+    {
+	XLIB_PROLOGUE (dmxScreen);
 	XSetClipMask(dmxScreen->beDisplay, pGCPriv->gc, None);
+	XLIB_EPILOGUE (dmxScreen);
+    }
 
     DMX_GC_FUNC_EPILOGUE(pGC);
 }
diff --git a/hw/dmx/dmxgcops.c b/hw/dmx/dmxgcops.c
index eaabf16..3499c86 100644
--- a/hw/dmx/dmxgcops.c
+++ b/hw/dmx/dmxgcops.c
@@ -44,6 +44,7 @@
 #include "dmxgcops.h"
 #include "dmxwindow.h"
 #include "dmxpixmap.h"
+#include "dmxlog.h"
 
 #include "mi.h"
 #include "gcstruct.h"
@@ -52,6 +53,13 @@
 
 #include "panoramiXsrv.h"
 
+#include <xcb/xcb_image.h>
+
+/* hm, conflicting definition of xcb_popcount in xcbext.h and xcb_bitops.h */
+#define xcb_popcount xcb_popcount2
+#include <xcb/xcb_bitops.h>
+#undef xcb_popcount
+
 #define DMX_GCOPS_SET_DRAWABLE(_pDraw, _draw)				\
 do {									\
     if ((_pDraw)->type == DRAWABLE_WINDOW) {				\
@@ -67,26 +75,11 @@ do {									\
 
 #define DMX_GCOPS_OFFSCREEN(_pDraw)					\
     (!dmxScreens[(_pDraw)->pScreen->myNum].beDisplay ||			\
-     (dmxOffScreenOpt &&						\
-      (_pDraw)->type == DRAWABLE_WINDOW &&				\
-      (DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->offscreen ||		\
-       !DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->window)))
-
-/** Fill spans -- this function should never be called. */
-void dmxFillSpans(DrawablePtr pDrawable, GCPtr pGC,
-		  int nInit, DDXPointPtr pptInit, int *pwidthInit,
-		  int fSorted)
-{
-    /* Error -- this should never happen! */
-}
-
-/** Set spans -- this function should never be called. */
-void dmxSetSpans(DrawablePtr pDrawable, GCPtr pGC,
-		 char *psrc, DDXPointPtr ppt, int *pwidth, int nspans,
-		 int fSorted)
-{
-    /* Error -- this should never happen! */
-}
+     (((_pDraw)->type == DRAWABLE_WINDOW) ?				\
+      ((!DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->window ||		\
+	(dmxOffScreenOpt &&						\
+	 DMX_GET_WINDOW_PRIV((WindowPtr)(_pDraw))->offscreen))) :	\
+      (!(DMX_GET_PIXMAP_PRIV((PixmapPtr)(_pDraw)))->pixmap)))
 
 /** Transfer \a pBits image to back-end server associated with \a
  *  pDrawable's screen.  If primitive subdivision optimization is
@@ -98,16 +91,18 @@ void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC,
 {
     DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
     dmxGCPrivPtr   pGCPriv = DMX_GET_GC_PRIV(pGC);
-    XImage        *img;
+    XImage        *img = NULL;
 
     if (DMX_GCOPS_OFFSCREEN(pDrawable)) return;
 
+    XLIB_PROLOGUE (dmxScreen);
     img = XCreateImage(dmxScreen->beDisplay,
 		       dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
 		       depth, format, leftPad, pBits, w, h,
 		       BitmapPad(dmxScreen->beDisplay),
 		       (format == ZPixmap) ?
 		       PixmapBytePad(w, depth) : BitmapBytePad(w+leftPad));
+    XLIB_EPILOGUE (dmxScreen);
 
     if (img) {
 	Drawable draw;
@@ -136,6 +131,7 @@ void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC,
 	    nBox = REGION_NUM_RECTS(pSubImages);
 	    pBox = REGION_RECTS(pSubImages);
 
+	    XLIB_PROLOGUE (dmxScreen);
 	    while (nBox--) {
 		XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc, img,
 			  pBox->x1 - box.x1,
@@ -146,11 +142,14 @@ void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC,
 			  pBox->y2 - pBox->y1);
 		pBox++;
 	    }
+	    XLIB_EPILOGUE (dmxScreen);
             REGION_DESTROY(pGC->pScreen, pClip);
             REGION_DESTROY(pGC->pScreen, pSubImages);
 	} else {
+	    XLIB_PROLOGUE (dmxScreen);
 	    XPutImage(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		      img, 0, 0, x, y, w, h);
+	    XLIB_EPILOGUE (dmxScreen);
 	}
 	XFree(img);             /* Use XFree instead of XDestroyImage
                                  * because pBits is passed in from the
@@ -159,6 +158,7 @@ void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC,
 	dmxSync(dmxScreen, FALSE);
     } else {
 	/* Error -- this should not happen! */
+	FatalError ("XCreateImage failed\n");
     }
 }
 
@@ -180,8 +180,10 @@ RegionPtr dmxCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
     DMX_GCOPS_SET_DRAWABLE(pSrc, srcDraw);
     DMX_GCOPS_SET_DRAWABLE(pDst, dstDraw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XCopyArea(dmxScreen->beDisplay, srcDraw, dstDraw, pGCPriv->gc,
 	      srcx, srcy, w, h, dstx, dsty);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 
     return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, w, h,
@@ -207,8 +209,10 @@ RegionPtr dmxCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
     DMX_GCOPS_SET_DRAWABLE(pSrc, srcDraw);
     DMX_GCOPS_SET_DRAWABLE(pDst, dstDraw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XCopyPlane(dmxScreen->beDisplay, srcDraw, dstDraw, pGCPriv->gc,
 	       srcx, srcy, width, height, dstx, dsty, bitPlane);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 
     return miHandleExposures(pSrc, pDst, pGC, srcx, srcy, width, height,
@@ -230,8 +234,10 @@ void dmxPolyPoint(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XDrawPoints(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		(XPoint *)pptInit, npt, mode);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
@@ -250,8 +256,10 @@ void dmxPolylines(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XDrawLines(dmxScreen->beDisplay, draw, pGCPriv->gc,
 	       (XPoint *)pptInit, npt, mode);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
@@ -270,8 +278,10 @@ void dmxPolySegment(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XDrawSegments(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		  (XSegment *)pSegs, nseg);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
@@ -290,8 +300,10 @@ void dmxPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XDrawRectangles(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		    (XRectangle *)pRects, nrects);
+    XLIB_EPILOGUE (dmxScreen);
 
     dmxSync(dmxScreen, FALSE);
 }
@@ -311,8 +323,10 @@ void dmxPolyArc(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XDrawArcs(dmxScreen->beDisplay, draw, pGCPriv->gc,
 	      (XArc *)parcs, narcs);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
@@ -331,8 +345,10 @@ void dmxFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XFillPolygon(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		 (XPoint *)pPts, count, shape, mode);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
@@ -351,8 +367,10 @@ void dmxPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XFillRectangles(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		    (XRectangle *)prectInit, nrectFill);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
@@ -371,8 +389,10 @@ void dmxPolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XFillArcs(dmxScreen->beDisplay, draw, pGCPriv->gc,
 	      (XArc *)parcs, narcs);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
@@ -400,8 +420,10 @@ int dmxPolyText8(DrawablePtr pDrawable, GCPtr pGC,
     if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) {
 	DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+	XLIB_PROLOGUE (dmxScreen);
 	XDrawString(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		    x, y, chars, count);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
@@ -433,8 +455,10 @@ int dmxPolyText16(DrawablePtr pDrawable, GCPtr pGC,
     if (n != 0 && !DMX_GCOPS_OFFSCREEN(pDrawable)) {
 	DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+	XLIB_PROLOGUE (dmxScreen);
 	XDrawString16(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		      x, y, (XChar2b *)chars, count);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
@@ -456,8 +480,10 @@ void dmxImageText8(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XDrawImageString(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		     x, y, chars, count);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
@@ -476,71 +502,110 @@ void dmxImageText16(DrawablePtr pDrawable, GCPtr pGC,
 
     DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 
+    XLIB_PROLOGUE (dmxScreen);
     XDrawImageString16(dmxScreen->beDisplay, draw, pGCPriv->gc,
 		       x, y, (XChar2b *)chars, count);
+    XLIB_EPILOGUE (dmxScreen);
     dmxSync(dmxScreen, FALSE);
 }
 
-/** Image Glyph Blt -- this function should never be called. */
-void dmxImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
-		      int x, int y, unsigned int nglyph,
-		      CharInfoPtr *ppci, pointer pglyphBase)
-{
-    /* Error -- this should never happen! */
-}
-
-/** Poly Glyph Blt -- this function should never be called. */
-void dmxPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
-		     int x, int y, unsigned int nglyph,
-		     CharInfoPtr *ppci, pointer pglyphBase)
+void dmxPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDst,
+		   int width, int height, int x, int y)
 {
-    /* Error -- this should never happen! */
-}
-
-/** Push Pixels -- this function should never be called. */
-void dmxPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
-		   int w, int h, int x, int y)
-{
-    /* Error -- this should never happen! */
+    /* only works for solid bitmaps */
+    if (pGC->fillStyle == FillSolid)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[pDst->pScreen->myNum];
+	dmxGCPrivPtr  pGCPriv = DMX_GET_GC_PRIV(pGC);
+	dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV(pBitmap);
+	Drawable      draw;
+
+	if (DMX_GCOPS_OFFSCREEN(pDst)) return;
+
+	DMX_GCOPS_SET_DRAWABLE(pDst, draw);
+
+	XLIB_PROLOGUE (dmxScreen);
+	XSetStipple (dmxScreen->beDisplay, pGCPriv->gc, pPixPriv->pixmap);
+	XSetTSOrigin (dmxScreen->beDisplay, pGCPriv->gc, x, y);
+	XSetFillStyle (dmxScreen->beDisplay, pGCPriv->gc, FillStippled);
+	XFillRectangle (dmxScreen->beDisplay, draw,
+			pGCPriv->gc, x, y, width, height);
+	XSetFillStyle (dmxScreen->beDisplay, pGCPriv->gc, FillSolid);
+	XLIB_EPILOGUE (dmxScreen);
+	dmxSync(dmxScreen, FALSE);
+    }
+    else
+    {
+	dmxLog (dmxWarning, "function dmxPushPixels fillStyle != FillSolid "
+		"not implemented\n");
+    }
 }
 
 /**********************************************************************
  * Miscellaneous drawing commands
  */
 
-/** When Xinerama is active, the client pixmaps are always obtained from
- * screen 0.  When screen 0 is detached, the pixmaps must be obtained
- * from any other screen that is not detached.  Usually, this is screen
- * 1. */
-static DMXScreenInfo *dmxFindAlternatePixmap(DrawablePtr pDrawable, XID *draw)
+static DMXScreenInfo *
+dmxGetAlternateWindow (DrawablePtr pDrawable,
+		       int         i,
+		       XID         *draw)
 {
+
+#ifdef PANORAMIX
+    PanoramiXRes  *pXinWin;
+    DMXScreenInfo *dmxScreen = &dmxScreens[i];
+            
+    if (noPanoramiXExtension) return NULL;
+    if (!dmxScreen->beDisplay) return NULL;
+    
+    if ((pXinWin = (PanoramiXRes *) LookupIDByType (pDrawable->id,
+						    XRT_WINDOW)))
+    {
+	WindowPtr     pSrc;
+	dmxWinPrivPtr pSrcPriv;
+            
+	pSrc = (WindowPtr) LookupIDByType (pXinWin->info[i].id, RT_WINDOW);
+	pSrcPriv = DMX_GET_WINDOW_PRIV (pSrc);
+	if (pSrcPriv->window)
+	{
+	    *draw = pSrcPriv->window;
+	    return dmxScreen;
+	}
+    }
+#endif
+
+    return NULL;
+}
+
+static DMXScreenInfo *
+dmxGetAlternatePixmap (DrawablePtr pDrawable,
+		       int         i,
+		       XID         *draw)
+{
+
 #ifdef PANORAMIX
     PanoramiXRes  *pXinPix;
-    int           i;
-    DMXScreenInfo *dmxScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[i];
             
-    if (noPanoramiXExtension)               return NULL;
-    if (pDrawable->type != DRAWABLE_PIXMAP) return NULL;
+    if (noPanoramiXExtension) return NULL;
+    if (!dmxScreen->beDisplay) return NULL;
     
-    if (!(pXinPix = (PanoramiXRes *)LookupIDByType(pDrawable->id, XRT_PIXMAP)))
-        return NULL;
-
-    for (i = 1; i < PanoramiXNumScreens; i++) {
-        dmxScreen = &dmxScreens[i];
-        if (dmxScreen->beDisplay) {
-            PixmapPtr     pSrc;
-            dmxPixPrivPtr pSrcPriv;
+    if ((pXinPix = (PanoramiXRes *) LookupIDByType (pDrawable->id,
+						    XRT_PIXMAP)))
+    {
+	PixmapPtr     pSrc;
+	dmxPixPrivPtr pSrcPriv;
             
-            pSrc = (PixmapPtr)LookupIDByType(pXinPix->info[i].id,
-                                             RT_PIXMAP);
-            pSrcPriv = DMX_GET_PIXMAP_PRIV(pSrc);
-            if (pSrcPriv->pixmap) {
-                *draw = pSrcPriv->pixmap;
-                return dmxScreen;
-            }
-        }
+	pSrc = (PixmapPtr) LookupIDByType (pXinPix->info[i].id, RT_PIXMAP);
+	pSrcPriv = DMX_GET_PIXMAP_PRIV (pSrc);
+	if (pSrcPriv->pixmap)
+	{
+	    *draw = pSrcPriv->pixmap;
+	    return dmxScreen;
+	}
     }
 #endif
+
     return NULL;
 }
 
@@ -553,8 +618,8 @@ void dmxGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
 		 unsigned int format, unsigned long planeMask, char *pdstLine)
 {
     DMXScreenInfo *dmxScreen = &dmxScreens[pDrawable->pScreen->myNum];
-    XImage        *img;
-    Drawable       draw;
+    Drawable      draw;
+    int           i = 0;
 
     /* Cannot get image from unviewable window */
     if (pDrawable->type == DRAWABLE_WINDOW) {
@@ -569,33 +634,90 @@ void dmxGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
 		return;
 	    }
 	}
-	DMX_GCOPS_SET_DRAWABLE(&pWindow->drawable, draw);
+	DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
 	if (DMX_GCOPS_OFFSCREEN(&pWindow->drawable))
-	    return;
+	    draw = None;
     } else {
 	DMX_GCOPS_SET_DRAWABLE(pDrawable, draw);
-	if (DMX_GCOPS_OFFSCREEN(pDrawable)) {
-            /* Try to find the pixmap on a non-detached Xinerama screen */
-            dmxScreen = dmxFindAlternatePixmap(pDrawable, &draw);
-            if (!dmxScreen) return;
-        }
+	if (DMX_GCOPS_OFFSCREEN(pDrawable))
+	    draw = None;
     }
+    
+    while (i < dmxNumScreens)
+    {
+	xcb_get_image_reply_t *reply;
+
+	if (!draw)
+	{
+	    if (pDrawable->type == DRAWABLE_WINDOW)
+		dmxScreen = dmxGetAlternateWindow (pDrawable, i++, &draw);
+	    else
+		dmxScreen = dmxGetAlternatePixmap (pDrawable, i++, &draw);
+
+	    if (!dmxScreen) continue;
+	}
 
-    img = XGetImage(dmxScreen->beDisplay, draw,
-		    sx, sy, w, h, planeMask, format);
-    if (img) {
-	int len = img->bytes_per_line * img->height;
-	memmove(pdstLine, img->data, len);
-	XDestroyImage(img);
-    }
+	reply = xcb_get_image_reply (dmxScreen->connection,
+				     xcb_get_image (dmxScreen->connection,
+						    format,
+						    draw,
+						    sx, sy, w, h,
+						    planeMask),
+				     NULL);
+	if (reply)
+	{
+	    const xcb_setup_t *setup = xcb_get_setup (dmxScreen->connection);
+	    uint32_t          bytes = xcb_get_image_data_length (reply);
+	    uint8_t           *data = xcb_get_image_data (reply);
+
+	    /* based on code in xcb_image.c, Copyright (C) 2007 Bart Massey */
+	    switch (format) {
+	    case XCB_IMAGE_FORMAT_XY_PIXMAP:
+		planeMask &= xcb_mask (reply->depth);
+		if (planeMask != xcb_mask (reply->depth))
+		{
+		    uint32_t rpm = planeMask;
+		    uint8_t  *src_plane = data;
+		    uint8_t  *dst_plane = (uint8_t *) pdstLine;
+		    uint32_t scanline_pad = setup->bitmap_format_scanline_pad;
+		    uint32_t stride = xcb_roundup (w, scanline_pad) >> 3;
+		    uint32_t size = h * stride;
+		    int      i;
+
+		    if (setup->image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
+			rpm = xcb_bit_reverse (planeMask, reply->depth);
+
+		    for (i = 0; i < reply->depth; i++)
+		    {
+			if (rpm & 1)
+			{
+			    memcpy (dst_plane, src_plane, size);
+			    src_plane += size;
+			}
+			else
+			{
+			    memset (dst_plane, 0, size);
+			}
+
+			dst_plane += size;
+		    }
+		    break;
+		}
+
+		/* fall through */
+	    case XCB_IMAGE_FORMAT_Z_PIXMAP:
+		memmove (pdstLine, data, bytes);
+	    default:
+		break;
+	    }
 
-    dmxSync(dmxScreen, FALSE);
-}
+	    free (reply);
+	    break;
+	}
 
-/** Get Spans -- this function should never be called. */
-void dmxGetSpans(DrawablePtr pDrawable, int wMax,
-		 DDXPointPtr ppt, int *pwidth, int nspans,
-		 char *pdstStart)
-{
-    /* Error -- this should never happen! */
+	if (pDrawable->type != DRAWABLE_WINDOW)
+	    break;
+
+	draw = None;
+    }
 }
diff --git a/hw/dmx/dmxgcops.h b/hw/dmx/dmxgcops.h
index da14d4d..ceb1524 100644
--- a/hw/dmx/dmxgcops.h
+++ b/hw/dmx/dmxgcops.h
@@ -37,12 +37,6 @@
 #ifndef DMXGCOPS_H
 #define DMXGCOPS_H
 
-extern void dmxFillSpans(DrawablePtr pDrawable, GCPtr pGC,
-			 int nInit, DDXPointPtr pptInit, int *pwidthInit,
-			 int fSorted);
-extern void dmxSetSpans(DrawablePtr pDrawable, GCPtr pGC,
-			char *psrc, DDXPointPtr ppt, int *pwidth, int nspans,
-			int fSorted);
 extern void dmxPutImage(DrawablePtr pDrawable, GCPtr pGC,
 			int depth, int x, int y, int w, int h,
 			int leftPad, int format, char *pBits);
@@ -76,20 +70,11 @@ extern void dmxImageText8(DrawablePtr pDrawable, GCPtr pGC,
 			  int x, int y, int count, char *chars);
 extern void dmxImageText16(DrawablePtr pDrawable, GCPtr pGC,
 			   int x, int y, int count, unsigned short *chars);
-extern void dmxImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
-			     int x, int y, unsigned int nglyph,
-			     CharInfoPtr *ppci, pointer pglyphBase);
-extern void dmxPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
-			    int x, int y, unsigned int nglyph,
-			    CharInfoPtr *ppci, pointer pglyphBase);
-extern void dmxPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
-			  int w, int h, int x, int y);
+extern void dmxPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable,
+			  int width, int height, int x, int y);
 
 extern void dmxGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
 			unsigned int format, unsigned long planeMask,
 			char *pdstLine);
-extern void dmxGetSpans(DrawablePtr pDrawable, int wMax,
-			DDXPointPtr ppt, int *pwidth, int nspans,
-			char *pdstStart);
 
 #endif /* DMXGCOPS_H */
diff --git a/hw/dmx/dmxgrab.c b/hw/dmx/dmxgrab.c
new file mode 100644
index 0000000..297ea31
--- /dev/null
+++ b/hw/dmx/dmxgrab.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxinput.h"
+#include "dmxgrab.h"
+
+#include "windowstr.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+static int (*dmxSaveProcVector[256]) (ClientPtr);
+
+static void
+dmxGrabKeyboard (DeviceIntPtr pDev,
+		 GrabPtr      pGrab)
+{
+
+#ifdef PANORAMIX
+    PanoramiXRes *win = NULL;
+#endif
+
+    WindowPtr    pWin;
+    int          i;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	if (!(win = (PanoramiXRes *)SecurityLookupIDByType(
+		  serverClient, pGrab->window->drawable.id, XRT_WINDOW,
+		  DixGetAttrAccess)))
+	    return;
+    }
+#endif
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	if (!dmxScreen->beDisplay)
+	    continue;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    dixLookupWindow (&pWin,
+			     win->info[i].id,
+			     serverClient,
+			     DixGetAttrAccess);
+	}
+	else
+#endif
+
+	{
+	    pWin = pGrab->window;
+	    if (i != pWin->drawable.pScreen->myNum)
+		continue;
+	}
+
+	dmxInputGrabKeyboard (&dmxScreen->input, pDev, pWin);
+    }
+}
+
+static void
+dmxUngrabKeyboard (DeviceIntPtr pDev,
+		   GrabPtr      pGrab)
+{
+
+#ifdef PANORAMIX
+    PanoramiXRes *win = NULL;
+#endif
+
+    WindowPtr    pWin;
+    int          i;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	if (!(win = (PanoramiXRes *)SecurityLookupIDByType(
+		  serverClient, pGrab->window->drawable.id, XRT_WINDOW,
+		  DixGetAttrAccess)))
+	    return;
+    }
+#endif
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	if (!dmxScreen->beDisplay)
+	    continue;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    dixLookupWindow (&pWin,
+			     win->info[i].id,
+			     serverClient,
+			     DixGetAttrAccess);
+	}
+	else
+#endif
+
+	{
+	    pWin = pGrab->window;
+	    if (i != pWin->drawable.pScreen->myNum)
+		continue;
+	}
+
+	dmxInputUngrabKeyboard (&dmxScreen->input, pDev, pWin);
+    }
+}
+
+void
+dmxActivateKeyboardGrab (DeviceIntPtr pDev,
+			 GrabPtr      pGrab,
+			 TimeStamp    time,
+			 Bool         autoGrab)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+    dmxGrabKeyboard (pDev, pGrab);
+
+    DMX_UNWRAP (ActivateGrab, pDevPriv, &pDev->deviceGrab);
+    (*pDev->deviceGrab.ActivateGrab) (pDev, pGrab, time, autoGrab);
+    DMX_WRAP (ActivateGrab, dmxActivateKeyboardGrab, pDevPriv,
+	      &pDev->deviceGrab);
+}
+
+void
+dmxDeactivateKeyboardGrab (DeviceIntPtr pDev)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+    GrabPtr          pGrab = pDev->deviceGrab.grab;
+
+    /* DeactivateGrab might call ActivateGrab so make sure we ungrab here */
+    dmxUngrabKeyboard (pDev, pGrab);
+
+    DMX_UNWRAP (DeactivateGrab, pDevPriv, &pDev->deviceGrab);
+    (*pDev->deviceGrab.DeactivateGrab) (pDev);
+    DMX_WRAP (DeactivateGrab, dmxDeactivateKeyboardGrab, pDevPriv,
+	      &pDev->deviceGrab);
+}
+
+static void
+dmxGrabPointer (DeviceIntPtr pDev,
+		GrabPtr      pGrab)
+{
+
+#ifdef PANORAMIX
+    PanoramiXRes *win = NULL, *confineToWin = NULL;
+#endif
+
+    WindowPtr    pWin, pConfineTo = NULL;
+    int          i;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	if (!(win = (PanoramiXRes *)SecurityLookupIDByType(
+		  serverClient, pGrab->window->drawable.id, XRT_WINDOW,
+		  DixGetAttrAccess)))
+	    return;
+	if (pGrab->confineTo)
+	    if (!(confineToWin = (PanoramiXRes *)SecurityLookupIDByType(
+		      serverClient, pGrab->confineTo->drawable.id,
+		      XRT_WINDOW, DixGetAttrAccess)))
+		return;
+    }
+#endif
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	if (!dmxScreen->beDisplay)
+	    continue;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    dixLookupWindow (&pWin,
+			     win->info[i].id,
+			     serverClient,
+			     DixGetAttrAccess);
+	    if (confineToWin)
+		dixLookupWindow (&pConfineTo,
+				 confineToWin->info[i].id,
+				 serverClient,
+				 DixGetAttrAccess);
+	}
+	else
+#endif
+
+	{
+	    pWin = pGrab->window;
+	    if (i != pWin->drawable.pScreen->myNum)
+		continue;
+	}
+
+	dmxInputGrabPointer (&dmxScreen->input,
+			     pDev,
+			     pWin,
+			     pConfineTo,
+			     pGrab->cursor);
+    }
+}
+
+static void
+dmxUngrabPointer (DeviceIntPtr pDev,
+		  GrabPtr      pGrab)
+{
+
+#ifdef PANORAMIX
+    PanoramiXRes *win = NULL;
+#endif
+
+    WindowPtr    pWin;
+    int          i;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	if (!(win = (PanoramiXRes *)SecurityLookupIDByType(
+		  serverClient, pGrab->window->drawable.id, XRT_WINDOW,
+		  DixGetAttrAccess)))
+	    return;
+    }
+#endif
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	if (!dmxScreen->beDisplay)
+	    continue;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    dixLookupWindow (&pWin,
+			     win->info[i].id,
+			     serverClient,
+			     DixGetAttrAccess);
+	}
+	else
+#endif
+
+	{
+	    pWin = pGrab->window;
+	    if (i != pWin->drawable.pScreen->myNum)
+		continue;
+	}
+
+	dmxInputUngrabPointer (&dmxScreen->input, pDev, pWin);
+    }
+}
+
+void
+dmxActivatePointerGrab (DeviceIntPtr pDev,
+			GrabPtr      pGrab,
+			TimeStamp    time,
+			Bool         autoGrab)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+    dmxGrabPointer (pDev, pGrab);
+
+    DMX_UNWRAP (ActivateGrab, pDevPriv, &pDev->deviceGrab);
+    (*pDev->deviceGrab.ActivateGrab) (pDev, pGrab, time, autoGrab);
+    DMX_WRAP (ActivateGrab, dmxActivatePointerGrab, pDevPriv,
+	      &pDev->deviceGrab);
+}
+
+void
+dmxDeactivatePointerGrab (DeviceIntPtr pDev)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+    GrabPtr          pGrab = pDev->deviceGrab.grab;
+
+    /* DeactivateGrab might call ActivateGrab so make sure we ungrab here */
+    dmxUngrabPointer (pDev, pGrab);
+
+    DMX_UNWRAP (DeactivateGrab, pDevPriv, &pDev->deviceGrab);
+    (*pDev->deviceGrab.DeactivateGrab) (pDev);
+    DMX_WRAP (DeactivateGrab, dmxDeactivatePointerGrab, pDevPriv,
+	      &pDev->deviceGrab);
+}
+
+Bool
+dmxActivateFakeGrab (DeviceIntPtr pDev,
+		     GrabPtr      pGrab)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+    if (pDevPriv->fakeGrab)
+	return TRUE;
+
+    if (pDev->deviceGrab.grab)
+	return FALSE;
+
+    pDevPriv->fakeGrab = TRUE;
+
+    DMX_UNWRAP (ActivateGrab, pDevPriv, &pDev->deviceGrab);
+    (*pDev->deviceGrab.ActivateGrab) (pDev, pGrab, currentTime, FALSE);
+    DMX_WRAP (ActivateGrab, dmxActivatePointerGrab, pDevPriv,
+	      &pDev->deviceGrab);
+
+    return TRUE;
+}
+
+void
+dmxDeactivateFakeGrab (DeviceIntPtr pDev)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+    if (!pDevPriv->fakeGrab)
+	return;
+
+    pDevPriv->fakeGrab = FALSE;
+
+    DMX_UNWRAP (DeactivateGrab, pDevPriv, &pDev->deviceGrab);
+    (*pDev->deviceGrab.DeactivateGrab) (pDev);
+    DMX_WRAP (DeactivateGrab, dmxDeactivatePointerGrab, pDevPriv,
+	      &pDev->deviceGrab);
+}
+
+static int
+dmxProcChangeActivePointerGrab (ClientPtr client)
+{
+    DeviceIntPtr pDev;
+    GrabPtr      pGrab;
+    int          err;
+
+    err = (*dmxSaveProcVector[X_ChangeActivePointerGrab]) (client);
+    if (err != Success)
+	return err;
+
+    pDev = PickPointer (client);
+    pGrab = pDev->deviceGrab.grab;
+    if (pGrab)
+	dmxGrabPointer (pDev, pGrab);
+
+    return Success;
+}
+
+void dmxInitGrabs (void)
+{
+    int i;
+
+    for (i = 0; i < 256; i++)
+	dmxSaveProcVector[i] = ProcVector[i];
+
+    ProcVector[X_ChangeActivePointerGrab] = dmxProcChangeActivePointerGrab;
+}
+
+void dmxResetGrabs (void)
+{
+    int  i;
+
+    for (i = 0; i < 256; i++)
+	ProcVector[i] = dmxSaveProcVector[i];
+}
diff --git a/hw/dmx/dmxgrab.h b/hw/dmx/dmxgrab.h
new file mode 100644
index 0000000..fe0dc0b
--- /dev/null
+++ b/hw/dmx/dmxgrab.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXGRAB_H
+#define DMXGRAB_H
+
+#include "dmxinput.h"
+
+extern void dmxActivateKeyboardGrab (DeviceIntPtr pDev,
+				     GrabPtr      pGrab,
+				     TimeStamp    time,
+				     Bool         autoGrab);
+extern void dmxDeactivateKeyboardGrab (DeviceIntPtr pDev);
+
+extern void dmxActivatePointerGrab (DeviceIntPtr pDev,
+				    GrabPtr      pGrab,
+				    TimeStamp    time,
+				    Bool         autoGrab);
+extern void dmxDeactivatePointerGrab (DeviceIntPtr pDev);
+
+extern Bool dmxActivateFakeGrab (DeviceIntPtr pDev,
+				 GrabPtr      pGrab);
+extern void dmxDeactivateFakeGrab (DeviceIntPtr pDev);
+
+extern void dmxInitGrabs (void);
+extern void dmxResetGrabs (void);
+
+#endif /* DMXGRAB_H */
diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c
index 6a0c259..e96c2d2 100644
--- a/hw/dmx/dmxinit.c
+++ b/hw/dmx/dmxinit.c
@@ -49,19 +49,35 @@
 #include "dmxscrinit.h"
 #include "dmxcursor.h"
 #include "dmxfont.h"
-#include "config/dmxconfig.h"
 #include "dmxcb.h"
 #include "dmxprop.h"
 #include "dmxstat.h"
+#include "dmxlaunch.h"
+#include "dmxgrab.h"
+#include "dmxselection.h"
+#include "dmxshm.h"
 #ifdef RENDER
 #include "dmxpict.h"
 #endif
+#ifdef COMPOSITE
+#include "dmxcomp.h"
+#endif
+#include "dmxextension.h"
 
 #include <X11/Xos.h>                /* For gettimeofday */
 #include "dixstruct.h"
+#include "opaque.h"
 #include "panoramiXsrv.h"
 
+#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */
+# include <sha1.h>
+#else /* Use OpenSSL's libcrypto */
+# include <stddef.h>  /* buggy openssl/sha.h wants size_t */
+# include <openssl/sha.h>
+#endif
+
 #include <signal.h>             /* For SIGQUIT */
+#include <execinfo.h>
 
 #ifdef GLXEXT
 #include <GL/glx.h>
@@ -81,21 +97,16 @@ extern void GlxSetVisualConfigs(
 int             dmxNumScreens;
 DMXScreenInfo  *dmxScreens;
 
-int             dmxNumInputs;
-DMXInputInfo   *dmxInputs;
-
-int             dmxShadowFB = FALSE;
-
 XErrorEvent     dmxLastErrorEvent;
 Bool            dmxErrorOccurred = FALSE;
 
 char           *dmxFontPath = NULL;
 
-Bool            dmxOffScreenOpt = TRUE;
+Bool            dmxOffScreenOpt = FALSE;
 
 Bool            dmxSubdividePrimitives = TRUE;
 
-Bool            dmxLazyWindowCreation = TRUE;
+Bool            dmxLazyWindowCreation = FALSE;
 
 Bool            dmxUseXKB = TRUE;
 
@@ -104,7 +115,7 @@ int             dmxDepth = 0;
 #ifndef GLXEXT
 static Bool     dmxGLXProxy = FALSE;
 #else
-Bool            dmxGLXProxy = TRUE;
+Bool            dmxGLXProxy = FALSE;
 
 Bool            dmxGLXSwapGroupSupport = TRUE;
 
@@ -115,7 +126,52 @@ Bool            dmxGLXFinishSwap = FALSE;
 
 Bool            dmxIgnoreBadFontPaths = FALSE;
 
-Bool            dmxAddRemoveScreens = FALSE;
+Bool            dmxAddRemoveScreens = TRUE;
+
+int             dmxLaunchIndex = 0;
+char            *dmxLaunchVT = NULL;
+
+int             dmxNumDetached = 4;
+
+#ifdef RANDR
+int             xRROutputsPerScreen = 1;
+int             xRRCrtcsPerScreen = 1;
+#endif
+
+DMXPropTrans    *dmxPropTrans = NULL;
+int             dmxPropTransNum = 0;
+
+DMXSelectionMap *dmxSelectionMap = NULL;
+int             dmxSelectionMapNum = 0;
+
+#ifdef XV
+char            **dmxXvImageFormats = NULL;
+int             dmxXvImageFormatsNum = 0;
+#endif
+
+char            dmxDigest[64];
+
+#include <execinfo.h>
+
+static void
+dmxSigHandler (int signo)
+{
+    void   *array[64];
+    size_t size, i;
+    char   **strings;
+
+    ErrorF ("\nBacktrace:\n");
+
+    size    = backtrace (array, 64);
+    strings = backtrace_symbols (array, size);
+
+    for (i = 0; i < size; i++)
+	ErrorF ("%d: %s\n", i, strings[i]);
+
+    free (strings);
+
+    FatalError ("Caught signal %d.  Server aborting\n", signo);
+}
 
 /* dmxErrorHandler catches errors that occur when calling one of the
  * back-end servers.  Some of this code is based on _XPrintDefaultError
@@ -180,6 +236,30 @@ static int dmxErrorHandler(Display *dpy, XErrorEvent *ev)
            ev->serial);
     dmxLog(dmxWarning, "                 Current serial number: %d\n",
            dpy->request);
+
+//    abort ();
+
+    return 0;
+}
+
+int     _dmx_jumpbuf_set = 0;
+int     _dmx_io_error = 0;
+jmp_buf _dmx_jumpbuf;
+
+static int dmxIOErrorHandler (Display *dpy)
+{
+    _dmx_io_error++;
+
+    if (!_dmx_jumpbuf_set)
+    {
+	ErrorF ("_dmx_jumpbuf not set\n");
+	abort ();
+    }
+    else
+    {
+	longjmp (_dmx_jumpbuf, 1);
+    }
+
     return 0;
 }
 
@@ -190,18 +270,125 @@ static int dmxNOPErrorHandler(Display *dpy, XErrorEvent *ev)
 }
 #endif
 
-Bool dmxOpenDisplay(DMXScreenInfo *dmxScreen)
+char *
+dmxMemDup (const char *data,
+	   int        dataLen)
+{
+    char *d;
+
+    d = malloc (dataLen);
+    if (!d)
+	return NULL;
+
+    memcpy (d, data, dataLen);
+
+    return d;
+}
+
+DMXScreenInfo *
+dmxAddScreen(const char *name,
+	     const char *display,
+	     const char *authType,
+	     int        authTypeLen,
+	     const char *authData,
+	     int        authDataLen,
+	     int        virtualFb)
+{
+    DMXScreenInfo *dmxScreen;
+    
+    if (!(dmxScreens = realloc(dmxScreens,
+                               (dmxNumScreens+1) * sizeof(*dmxScreens))))
+        dmxLog(dmxFatal,
+               "dmxAddScreen: realloc failed for screen %d (%s)\n",
+               dmxNumScreens, name);
+
+    dmxScreen = &dmxScreens[dmxNumScreens];
+    memset(dmxScreen, 0, sizeof(*dmxScreen));
+    dmxScreen->name        = strdup (name);
+    dmxScreen->display     = strdup (display);
+    dmxScreen->index       = dmxNumScreens;
+    dmxScreen->scrnWidth   = 0;
+    dmxScreen->scrnHeight  = 0;
+    dmxScreen->rootX       = 0;
+    dmxScreen->rootY       = 0;
+    dmxScreen->stat        = dmxStatAlloc();
+    dmxScreen->authType    = dmxMemDup (authType, authTypeLen);
+    dmxScreen->authTypeLen = authTypeLen;
+    dmxScreen->authData    = dmxMemDup (authData, authDataLen);
+    dmxScreen->authDataLen = authDataLen;
+    dmxScreen->virtualFb   = virtualFb;
+    ++dmxNumScreens;
+
+    return dmxScreen;
+}
+
+Bool dmxOpenDisplay(DMXScreenInfo *dmxScreen,
+		    const char    *display,
+		    const char    *authType,
+		    int           authTypeLen,
+		    const char    *authData,
+		    int           authDataLen)
 {
-    if (!(dmxScreen->beDisplay = XOpenDisplay(dmxScreen->name)))
+    dmxScreen->beDisplay = NULL;
+
+    if (!display || !*display)
 	return FALSE;
 
-    dmxPropertyDisplay(dmxScreen);
+    if (authType && *authType)
+	XSetAuthorization ((char *) authType, authTypeLen,
+			   (char *) authData, authDataLen);
+
+    dmxScreen->alive = 1;
+
+    XLIB_PROLOGUE (dmxScreen);
+    dmxScreen->beDisplay = XOpenDisplay (display);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!dmxScreen->beDisplay)
+    {
+        dmxScreen->alive = 0;	
+	return FALSE;
+    }
+
+    dmxScreen->alive      = 1;
+    dmxScreen->broken     = 0;
+    dmxScreen->inDispatch = FALSE;
+    dmxScreen->fd         = XConnectionNumber (dmxScreen->beDisplay);
+    dmxScreen->connection = XGetXCBConnection (dmxScreen->beDisplay);
+
+    XSetEventQueueOwner (dmxScreen->beDisplay, XCBOwnsEventQueue);
+
+    dmxScreen->sync.sequence = 0;
+
+    AddEnabledDevice (dmxScreen->fd);
+
+    dmxScreen->atomTable     = NULL;
+    dmxScreen->atomTableSize = 0;
+
+    dmxScreen->beAtomTable     = NULL;
+    dmxScreen->beAtomTableSize = 0;
+
     return TRUE;
 }
 
+void dmxCloseDisplay(DMXScreenInfo *dmxScreen)
+{
+    RemoveEnabledDevice (dmxScreen->fd);
+
+    if (dmxScreen->atomTable)
+	xfree (dmxScreen->atomTable);
+    if (dmxScreen->beAtomTable)
+	xfree (dmxScreen->beAtomTable);
+
+    xcb_disconnect (dmxScreen->connection);
+
+    dmxScreen->alive = 0;
+}
+
 void dmxSetErrorHandler(DMXScreenInfo *dmxScreen)
 {
     XSetErrorHandler(dmxErrorHandler);
+    XSetIOErrorHandler(dmxIOErrorHandler);
 }
 
 static void dmxPrintScreenInfo(DMXScreenInfo *dmxScreen)
@@ -269,14 +456,6 @@ static void dmxPrintScreenInfo(DMXScreenInfo *dmxScreen)
                  (DoesBackingStore (s) == NotUseful) ? "no" :
                  ((DoesBackingStore (s) == Always) ? "yes" : "when mapped"),
                  DoesSaveUnders (s) ? "yes" : "no");
-    dmxLogOutput(dmxScreen, "Window Manager running: %s\n",
-		 (dmxScreen->WMRunningOnBE) ? "yes" : "no");
-
-    if (dmxScreen->WMRunningOnBE) {
-	dmxLogOutputWarning(dmxScreen,
-			    "Window manager running "
-			    "-- colormaps not supported\n");
-    }
     XFree(depths);
 }
 
@@ -292,41 +471,10 @@ void dmxGetScreenAttribs(DMXScreenInfo *dmxScreen)
 
     dmxScreen->beWidth  = attribs.width;
     dmxScreen->beHeight = attribs.height;
-    
-                                /* Fill in missing geometry information */
-    if (dmxScreen->scrnXSign < 0) {
-        if (dmxScreen->scrnWidth) {
-            dmxScreen->scrnX   = (attribs.width - dmxScreen->scrnWidth
-				  - dmxScreen->scrnX);
-        } else {
-            dmxScreen->scrnWidth  = attribs.width - dmxScreen->scrnX;
-            dmxScreen->scrnX   = 0;
-        }
-    }
-    if (dmxScreen->scrnYSign < 0) {
-        if (dmxScreen->scrnHeight) {
-            dmxScreen->scrnY   = (attribs.height - dmxScreen->scrnHeight
-				  - dmxScreen->scrnY);
-        } else {
-            dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY;
-            dmxScreen->scrnY   = 0;
-        }
-    }
-    if (!dmxScreen->scrnWidth)
-        dmxScreen->scrnWidth  = attribs.width  - dmxScreen->scrnX;
-    if (!dmxScreen->scrnHeight)
-        dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY;
-
-    if (!dmxScreen->rootWidth)  dmxScreen->rootWidth  = dmxScreen->scrnWidth;
-    if (!dmxScreen->rootHeight) dmxScreen->rootHeight = dmxScreen->scrnHeight;
-    if (dmxScreen->rootWidth + dmxScreen->rootX > dmxScreen->scrnWidth)
-        dmxScreen->rootWidth = dmxScreen->scrnWidth - dmxScreen->rootX;
-    if (dmxScreen->rootHeight + dmxScreen->rootY > dmxScreen->scrnHeight)
-        dmxScreen->rootHeight = dmxScreen->scrnHeight - dmxScreen->rootY;
 
     /* FIXME: Get these from the back-end server */
-    dmxScreen->beXDPI = 75;
-    dmxScreen->beYDPI = 75;
+    dmxScreen->beXDPI = 96;
+    dmxScreen->beYDPI = 96;
 
     dmxScreen->beDepth  = attribs.depth; /* FIXME: verify that this
 					  * works always.  In
@@ -340,6 +488,12 @@ void dmxGetScreenAttribs(DMXScreenInfo *dmxScreen)
     else if (dmxScreen->beDepth <= 16) dmxScreen->beBPP = 16;
     else                               dmxScreen->beBPP = 32;
 
+    if (dmxScreen->scrnWin != DefaultRootWindow(dpy))
+        XGetWindowAttributes(dpy, dmxScreen->scrnWin, &attribs);
+    
+    dmxScreen->scrnWidth  = attribs.width;
+    dmxScreen->scrnHeight = attribs.height;
+
 #ifdef GLXEXT
     /* get the majorOpcode for the back-end GLX extension */
     XQueryExtension(dpy, "GLX", &dmxScreen->glxMajorOpcode,
@@ -347,9 +501,8 @@ void dmxGetScreenAttribs(DMXScreenInfo *dmxScreen)
 #endif
 
     dmxPrintScreenInfo(dmxScreen);
-    dmxLogOutput(dmxScreen, "%dx%d+%d+%d on %dx%d at depth=%d, bpp=%d\n",
+    dmxLogOutput(dmxScreen, "%dx%d on %dx%d at depth=%d, bpp=%d\n",
                  dmxScreen->scrnWidth, dmxScreen->scrnHeight,
-                 dmxScreen->scrnX, dmxScreen->scrnY,
                  dmxScreen->beWidth, dmxScreen->beHeight,
                  dmxScreen->beDepth, dmxScreen->beBPP);
     if (dmxScreen->beDepth == 8)
@@ -471,38 +624,70 @@ static Bool dmxSetPixmapFormats(ScreenInfo *pScreenInfo,
     return TRUE;
 }
 
-void dmxCheckForWM(DMXScreenInfo *dmxScreen)
-{
-    Status status;
-    XWindowAttributes xwa;
-
-    status = XGetWindowAttributes(dmxScreen->beDisplay,
-				  DefaultRootWindow(dmxScreen->beDisplay),
-				  &xwa);
-    dmxScreen->WMRunningOnBE =
-	(status &&
-	 ((xwa.all_event_masks & SubstructureRedirectMask) ||
-	  (xwa.all_event_masks & SubstructureNotifyMask)));
-}
-
 /** Initialize the display and collect relevant information about the
  *  display properties */
-static void dmxDisplayInit(DMXScreenInfo *dmxScreen)
+static Bool dmxDisplayInit(DMXScreenInfo *dmxScreen)
 {
-    if (!dmxOpenDisplay(dmxScreen))
-	dmxLog(dmxFatal,
-               "dmxOpenDisplay: Unable to open display %s\n",
-               dmxScreen->name);
+    if (!dmxOpenDisplay(dmxScreen,
+			dmxScreen->display,
+			dmxScreen->authType,
+			dmxScreen->authTypeLen,
+			dmxScreen->authData,
+			dmxScreen->authDataLen))
+    {
+	if (dmxScreen->display && *dmxScreen->display)
+	    dmxLog(dmxWarning,
+		   "dmxOpenDisplay: Unable to open display %s\n",
+		   dmxScreen->display);
+
+	dmxScreen->scrnWidth  = 1;
+	dmxScreen->scrnHeight = 1;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    dmxScreen->scrnWidth  = dmxScreens[0].scrnWidth;
+	    dmxScreen->scrnHeight = dmxScreens[0].scrnHeight;
+	}
+#endif
 
-    dmxSetErrorHandler(dmxScreen);
-    dmxCheckForWM(dmxScreen);
-    dmxGetScreenAttribs(dmxScreen);
+	dmxScreen->beWidth    = 1;
+	dmxScreen->beHeight   = 1;
+	dmxScreen->beXDPI     = 96;
+	dmxScreen->beYDPI     = 96;
+	dmxScreen->beDepth    = 24;
+	dmxScreen->beBPP      = 32;
 
-    if (!dmxGetVisualInfo(dmxScreen))
-	dmxLog(dmxFatal, "dmxGetVisualInfo: No matching visuals found\n");
+	return FALSE;
+    }
+    else
+    {
+	if (!dmxScreen->scrnWin)
+	    dmxScreen->scrnWin = DefaultRootWindow (dmxScreen->beDisplay);
+	    
+	dmxSetErrorHandler(dmxScreen);
+	dmxGetScreenAttribs(dmxScreen);
+
+	if (!dmxGetVisualInfo(dmxScreen))
+	{
+	    dmxLog(dmxWarning,
+		   "dmxGetVisualInfo: No matching visuals found\n");
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    XCloseDisplay(dmxScreen->beDisplay);
+	    XLIB_EPILOGUE (dmxScreen);
+	    dmxScreen->beDisplay = NULL;
+
+	    return FALSE;
+	}
+	else
+	{
+	    dmxGetColormaps(dmxScreen);
+	    dmxGetPixmapFormats(dmxScreen);
+	}
+    }
 
-    dmxGetColormaps(dmxScreen);
-    dmxGetPixmapFormats(dmxScreen);
+    return TRUE;
 }
 
 /* If this doesn't compile, just add || defined(yoursystem) to the line
@@ -558,7 +743,7 @@ static const char *dmxExecHost(void)
 /** This routine is called in Xserver/dix/main.c from \a main(). */
 void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
 {
-    int                  i;
+    int                  i, nDetached;
     static unsigned long dmxGeneration = 0;
 #ifdef GLXEXT
     Bool                 glxSupported  = TRUE;
@@ -567,6 +752,37 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
     if (dmxGeneration != serverGeneration) {
 	int vendrel = VENDOR_RELEASE;
         int major, minor, year, month, day;
+	unsigned char sha1[20];
+	const char *host = dmxExecHost ();
+	time_t t = time (NULL);
+	pid_t pid = getpid ();
+
+#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */
+	SHA1_CTX ctx;
+
+	SHA1Init (&ctx);
+	SHA1Update (&ctx, display, strlen (display));
+	SHA1Update (&ctx, host, strlen (host));
+	SHA1Update (&ctx, &t, sizeof (time_t));
+	SHA1Update (&ctx, &pid, sizeof (pid_t));
+	SHA1Final (sha1, &ctx);
+#else /* Use OpenSSL's libcrypto */
+	SHA_CTX ctx;
+
+	if (!SHA1_Init (&ctx)                              ||
+	    !SHA1_Update (&ctx, display, strlen (display)) ||
+	    !SHA1_Update (&ctx, host, strlen (host))       ||
+	    !SHA1_Update (&ctx, &t, sizeof (time_t))       ||
+	    !SHA1_Update (&ctx, &pid, sizeof (pid_t))      ||
+	    !SHA1_Final (sha1, &ctx))
+	{
+	    dmxLog(dmxFatal, "SHA1_Init failed\n");
+	}
+#endif
+
+	for (i = 0; i < sizeof (sha1); i++)
+	    snprintf(dmxDigest + 2 * i, sizeof (dmxDigest) - 2 * i, "%02x",
+		     sha1[i]);
         
         dmxGeneration = serverGeneration;
 
@@ -584,6 +800,7 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
         if (major > 0 && minor > 0) year += 2000;
 
         dmxLog(dmxInfo, "Generation:         %d\n", dmxGeneration);
+	dmxLog(dmxInfo, "DMX digest:         %s\n", dmxDigest);
         dmxLog(dmxInfo, "DMX version:        %d.%d.%02d%02d%02d (%s)\n",
                major, minor, year, month, day, VENDOR_STRING);
 
@@ -601,17 +818,13 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
         for (i = 0; i < dmxNumScreens; i++) {
             if (dmxScreens[i].beDisplay)
                 dmxLog(dmxWarning, "Display \"%s\" still open\n",
-                       dmxScreens[i].name);
+                       dmxScreens[i].display);
             dmxStatFree(dmxScreens[i].stat);
             dmxScreens[i].stat = NULL;
         }
-        for (i = 0; i < dmxNumInputs; i++) dmxInputFree(&dmxInputs[i]);
         if (dmxScreens) free(dmxScreens);
-        if (dmxInputs)  free(dmxInputs);
         dmxScreens    = NULL;
-        dmxInputs     = NULL;
         dmxNumScreens = 0;
-        dmxNumInputs  = 0;
     }
 
     /* Make sure that the command-line arguments are sane. */
@@ -633,14 +846,49 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
 	       "Dynamic screen addition/removal error (see above).\n");
     }
 
-    /* ddxProcessArgument has been called at this point, but any data
-     * from the configuration file has not been applied.  Do so, and be
-     * sure we have at least one back-end display. */
-    dmxConfigConfigure();
+    for (i = 0; i < dmxPropTransNum; i++)
+	dmxPropTrans[i].type = MakeAtom ((char *) dmxPropTrans[i].name,
+					 strlen (dmxPropTrans[i].name),
+					 TRUE);
+
+    for (i = 0; i < dmxSelectionMapNum; i++)
+    {
+	char *beName;
+
+	dmxSelectionMap[i].atom = MakeAtom ((char *) dmxSelectionMap[i].name,
+					    strlen (dmxSelectionMap[i].name),
+					    TRUE);
+
+	beName = xalloc (strlen (dmxSelectionMap[i].name) +
+			 strlen (dmxDigest) + 2);
+	if (!beName)
+	    dmxLog (dmxFatal, "InitOutput: not enough memory\n");
+	
+	sprintf (beName, "%s_%s", dmxSelectionMap[i].name, dmxDigest);
+	dmxSelectionMap[i].beAtom = MakeAtom ((char *) beName,
+					      strlen (beName),
+					      TRUE);
+	xfree (beName);
+    }
+
     if (!dmxNumScreens)
-        dmxLog(dmxFatal, "InitOutput: no back-end displays found\n");
-    if (!dmxNumInputs)
-        dmxLog(dmxInfo, "InitOutput: no inputs found\n");
+    {
+	dmxLaunchDisplay (argc, argv, dmxLaunchIndex, dmxLaunchVT);
+	if (!dmxNumScreens)
+	    dmxLog(dmxFatal, "InitOutput: no back-end displays found\n");
+    }
+
+    nDetached = dmxNumDetached;
+    if (dmxNumScreens + nDetached > MAXSCREENS)
+	nDetached = MAXSCREENS - dmxNumScreens;
+    
+    if (nDetached > 0)
+    {
+	dmxLog (dmxInfo, "Adding %d detached displays\n", nDetached);
+
+	while (nDetached--)
+	    dmxAddScreen ("", "", NULL, 0, NULL, 0, 0);
+    }
     
     /* Disable lazy window creation optimization if offscreen
      * optimization is disabled */
@@ -656,7 +904,10 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
 
     /* Open each display and gather information about it. */
     for (i = 0; i < dmxNumScreens; i++)
-        dmxDisplayInit(&dmxScreens[i]);
+	if (!dmxDisplayInit(&dmxScreens[i]) && i == 0)
+	    dmxLog(dmxFatal,
+		   "dmxOpenDisplay: Unable to open display %s\n",
+		   dmxScreens[i].display);
 
 #if PANORAMIX
     /* Register a Xinerama callback which will run from within
@@ -682,7 +933,11 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
      * same as the behavior of SIGINT.  However, leaving the modifier
      * map of the input devices empty is even more unexpected.) --RF
      */
-    OsSignal(SIGQUIT, GiveUp);
+    OsSignal (SIGQUIT, GiveUp);
+    OsSignal (SIGSEGV, dmxSigHandler);
+    OsSignal (SIGILL,  dmxSigHandler);
+    OsSignal (SIGFPE,  dmxSigHandler);
+    OsSignal (SIGABRT, dmxSigHandler);
 
 #ifdef GLXEXT
     /* Check if GLX extension exists on all back-end servers */
@@ -779,19 +1034,16 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
 	AddScreen(dmxScreenInit, argc, argv);
     }
 
-    /* Compute origin information. */
-    dmxInitOrigins();
-
-    /* Compute overlap information. */
-    dmxInitOverlap();
-
     /* Make sure there is a global width/height available */
-    dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
+    dmxComputeWidthHeight ();
 
-    /* FIXME: The following is temporarily placed here.  When the DMX
-     * extension is available, it will be move there.
-     */
-    dmxInitFonts();
+    dmxInitProps();
+    dmxInitGrabs();
+    dmxInitSelections();
+
+#ifdef MITSHM
+    dmxInitShm();
+#endif
 
 #ifdef RENDER
     /* Initialize the render extension */
@@ -799,12 +1051,19 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
 	dmxInitRender();
 #endif
 
+#ifdef COMPOSITE
+    /* Initialize the composite extension */
+    if (!noCompositeExtension)
+	dmxInitComposite();
+#endif
+
     /* Initialized things that need timer hooks */
     dmxStatInit();
     dmxSyncInit();              /* Calls RegisterBlockAndWakeupHandlers */
 
-    dmxLog(dmxInfo, "Shadow framebuffer support %s\n",
-	   dmxShadowFB ? "enabled" : "disabled");
+    for (i = 0; i < dmxNumScreens; i++)
+	if (dmxScreens[i].beDisplay)
+	    dmxBEScreenInit (screenInfo.screens[i]);
 }
 
 /* RATS: Assuming the fp string (which comes from the command-line argv
@@ -842,6 +1101,8 @@ void AbortDDX(void)
         if (dmxScreen->beDisplay) XCloseDisplay(dmxScreen->beDisplay);
         dmxScreen->beDisplay = NULL;
     }
+
+    dmxAbortDisplay ();
 }
 
 /** This function is called in Xserver/dix/main.c from \a main() when
@@ -852,9 +1113,73 @@ void ddxGiveUp(void)
     AbortDDX();
 }
 
+#ifdef PANORAMIX
+static Bool dmxNoPanoramiXExtension = FALSE;
+#endif
+
 /** This function is called in Xserver/os/osinit.c from \a OsInit(). */
 void OsVendorInit(void)
 {
+    if (!dmxPropTrans)
+    {
+	dmxPropTrans = xalloc (sizeof (DMXPropTrans) * 2);
+	dmxPropTrans[0].name = "ATOM_PAIR";
+	dmxPropTrans[0].format = "aa..";
+	dmxPropTrans[0].type = 0;
+	dmxPropTrans[1].name = "_COMPIZ_WINDOW_DECOR";
+	dmxPropTrans[1].format = "xP";
+	dmxPropTrans[1].type = 0;
+	dmxPropTransNum = 2;
+    }
+
+    if (!dmxSelectionMap)
+    {
+	dmxSelectionMap = xalloc (sizeof (DMXSelectionMap) * 9);
+	dmxSelectionMap[0].name = "WM_S0";
+	dmxSelectionMap[0].atom = 0;
+	dmxSelectionMap[0].beAtom = 0;
+	dmxSelectionMap[1].name = "_NET_WM_CM_S0";
+	dmxSelectionMap[1].atom = 0;
+	dmxSelectionMap[1].beAtom = 0;
+	dmxSelectionMap[2].name = "_NET_SYSTEM_TRAY_S0";
+	dmxSelectionMap[2].atom = 0;
+	dmxSelectionMap[2].beAtom = 0;
+	dmxSelectionMap[3].name = "_NET_DESKTOP_LAYOUT_S0";
+	dmxSelectionMap[3].atom = 0;
+	dmxSelectionMap[3].beAtom = 0;
+	dmxSelectionMap[4].name = "_NET_DESKTOP_MANAGER_S0";
+	dmxSelectionMap[4].atom = 0;
+	dmxSelectionMap[4].beAtom = 0;
+	dmxSelectionMap[5].name = "_XSETTINGS_S0";
+	dmxSelectionMap[5].atom = 0;
+	dmxSelectionMap[5].beAtom = 0;
+	dmxSelectionMap[6].name = "CLIPBOARD_MANAGER";
+	dmxSelectionMap[6].atom = 0;
+	dmxSelectionMap[6].beAtom = 0;
+	dmxSelectionMap[7].name = "GVM_SELECTION";
+	dmxSelectionMap[7].atom = 0;
+	dmxSelectionMap[7].beAtom = 0;
+	dmxSelectionMap[8].name = "_COMPIZ_DM_S0";
+	dmxSelectionMap[8].atom = 0;
+	dmxSelectionMap[8].beAtom = 0;
+	dmxSelectionMapNum = 9;
+    }
+
+#ifdef PANORAMIX
+    noPanoramiXExtension = dmxNoPanoramiXExtension;
+    PanoramiXExtensionDisabledHack = TRUE;
+#endif
+
+#ifdef XV
+    if (!dmxXvImageFormats)
+    {
+	dmxXvImageFormats = xalloc (sizeof (char *) * 2);
+	dmxXvImageFormats[0] = "YV12";
+	dmxXvImageFormats[1] = "YUY2";
+	dmxXvImageFormatsNum = 2;
+    }
+#endif
+
 }
 
 /** This function is called in Xserver/os/utils.c from \a FatalError()
@@ -870,33 +1195,12 @@ void OsVendorFatalError(void)
 int ddxProcessArgument(int argc, char *argv[], int i)
 {
     int retval = 0;
-    
+
     if (!strcmp(argv[i], "-display")) {
-	if (++i < argc) dmxConfigStoreDisplay(argv[i]);
-        retval = 2;
-    } else if (!strcmp(argv[i], "-inputfrom") || !strcmp(argv[i], "-input")) {
-	if (++i < argc) dmxConfigStoreInput(argv[i]);
-        retval = 2;
-    } else if (!strcmp(argv[i], "-xinputfrom") || !strcmp(argv[i],"-xinput")) {
-        if (++i < argc) dmxConfigStoreXInput(argv[i]);
-        retval = 2;
-    } else if (!strcmp(argv[i], "-noshadowfb")) {
-        dmxLog(dmxWarning,
-               "-noshadowfb has been deprecated "
-	       "since it is now the default\n");
-	dmxShadowFB = FALSE;
-	retval = 1;
-    } else if (!strcmp(argv[i], "-nomulticursor")) {
-        dmxCursorNoMulti();
-	retval = 1;
-    } else if (!strcmp(argv[i], "-shadowfb")) {
-	dmxShadowFB = TRUE;
-	retval = 1;
-    } else if (!strcmp(argv[i], "-configfile")) {
-        if (++i < argc) dmxConfigStoreFile(argv[i]);
+	if (++i < argc) dmxAddScreen(argv[i], argv[i], NULL, 0, NULL, 0, 0);
         retval = 2;
-    } else if (!strcmp(argv[i], "-config")) {
-        if (++i < argc) dmxConfigStoreConfig(argv[i]);
+    } else if (!strcmp(argv[i], "-numDetached")) {
+	if (++i < argc) dmxNumDetached = atoi (argv[i]);
         retval = 2;
     } else if (!strcmp(argv[i], "-fontpath")) {
         if (++i < argc) dmxSetDefaultFontPath(argv[i]);
@@ -907,14 +1211,14 @@ int ddxProcessArgument(int argc, char *argv[], int i)
     } else if (!strcmp(argv[i], "-syncbatch")) {
         if (++i < argc) dmxSyncActivate(argv[i]);
         retval = 2;
-    } else if (!strcmp(argv[i], "-nooffscreenopt")) {
-	dmxOffScreenOpt = FALSE;
+    } else if (!strcmp(argv[i], "-offscreenopt")) {
+	dmxOffScreenOpt = TRUE;
         retval = 1;
     } else if (!strcmp(argv[i], "-nosubdivprims")) {
 	dmxSubdividePrimitives = FALSE;
         retval = 1;
-    } else if (!strcmp(argv[i], "-nowindowopt")) {
-	dmxLazyWindowCreation = FALSE;
+    } else if (!strcmp(argv[i], "-windowopt")) {
+	dmxLazyWindowCreation = TRUE;
         retval = 1;
     } else if (!strcmp(argv[i], "-noxkb")) {
 	dmxUseXKB = FALSE;
@@ -942,29 +1246,94 @@ int ddxProcessArgument(int argc, char *argv[], int i)
     } else if (!strcmp(argv[i], "-ignorebadfontpaths")) {
 	dmxIgnoreBadFontPaths = TRUE;
         retval = 1;
-    } else if (!strcmp(argv[i], "-addremovescreens")) {
-	dmxAddRemoveScreens = TRUE;
+    } else if (!strcmp(argv[i], "-noaddremovescreens")) {
+	dmxAddRemoveScreens = FALSE;
         retval = 1;
-    } else if (!strcmp(argv[i], "-param")) {
-        if ((i += 2) < argc) {
-            if (!strcasecmp(argv[i-1], "xkbrules"))
-                dmxConfigSetXkbRules(argv[i]);
-            else if (!strcasecmp(argv[i-1], "xkbmodel"))
-                dmxConfigSetXkbModel(argv[i]);
-            else if (!strcasecmp(argv[i-1], "xkblayout"))
-                dmxConfigSetXkbLayout(argv[i]);
-            else if (!strcasecmp(argv[i-1], "xkbvariant"))
-                dmxConfigSetXkbVariant(argv[i]);
-            else if (!strcasecmp(argv[i-1], "xkboptions"))
-                dmxConfigSetXkbOptions(argv[i]);
-            else
-                dmxLog(dmxWarning,
-                       "-param requires: XkbRules, XkbModel, XkbLayout,"
-                       " XkbVariant, or XkbOptions\n");
-        }
+#ifdef PANORAMIX
+    } else if (!strcmp (argv[i], "-xinerama")) {
+	dmxNoPanoramiXExtension = TRUE;
+	retval = 1;
+#endif
+#ifdef RANDR
+    } else if (!strcmp(argv[i], "-outputs")) {
+	if (++i < argc) xRROutputsPerScreen = atoi(argv[i]);
+        retval = 2;
+    } else if (!strcmp(argv[i], "-crtcs")) {
+	if (++i < argc) xRRCrtcsPerScreen = atoi(argv[i]);
+        retval = 2;
+    }
+#endif
+    else if (!strcmp (argv[i], "-prop"))
+    {
+	if ((i + 2) < argc)
+	{
+	    DMXPropTrans *prop;
+
+	    prop = xrealloc (dmxPropTrans, sizeof (DMXPropTrans) *
+			     (dmxPropTransNum + 1));
+	    if (prop)
+	    {
+		prop[dmxPropTransNum].name   = argv[i + 1];
+		prop[dmxPropTransNum].format = argv[i + 2];
+		prop[dmxPropTransNum].type   = 0;
+
+		dmxPropTransNum++;
+		dmxPropTrans = prop;
+	    }
+	}
         retval = 3;
     }
-    if (!serverGeneration) dmxConfigSetMaxScreens();
+    else if (!strcmp (argv[i], "-selection"))
+    {
+	if (++i < argc)
+	{
+	    DMXSelectionMap *selection;
+
+	    selection = xrealloc (dmxSelectionMap, sizeof (DMXSelectionMap) *
+				  (dmxSelectionMapNum + 1));
+	    if (selection)
+	    {
+		selection[dmxSelectionMapNum].name   = argv[i];
+		selection[dmxSelectionMapNum].atom   = 0;
+		selection[dmxSelectionMapNum].beAtom = 0;
+
+		dmxSelectionMapNum++;
+		dmxSelectionMap = selection;
+	    }
+	}
+        retval = 2;
+    }
+#ifdef XV
+    else if (!strcmp (argv[i], "-xvimage"))
+    {
+	if (++i < argc)
+	{
+	    char **formats;
+
+	    formats = xrealloc (dmxXvImageFormats,
+				sizeof (char *) *
+				(dmxXvImageFormatsNum + 1));
+	    if (formats)
+	    {
+		formats[dmxXvImageFormatsNum] = argv[i];
+
+		dmxXvImageFormatsNum++;
+		dmxXvImageFormats = formats;
+	    }
+	}
+        retval = 2;
+    }
+#endif
+    else if ((argv[i][0] == 'v') && (argv[i][1] == 't'))
+    {
+        dmxLaunchVT = argv[i];
+	retval = 1;
+    }
+    else if (!strcmp(argv[i], "--")) {
+        dmxLaunchIndex = i + 1;
+        retval = argc - i;
+    }
+
     return retval;
 }
 
@@ -973,61 +1342,36 @@ void ddxUseMsg(void)
 {
     ErrorF("\n\nDevice Dependent Usage:\n");
     ErrorF("-display string      Specify the back-end display(s)\n");
-    ErrorF("-input string        Specify input source for core device\n");
-    ErrorF("-xinput string       Specify input source for XInput device\n");
+    ErrorF("-numDetached num     Specify detached back-end display(s)\n");
     ErrorF("-shadowfb            Enable shadow frame buffer\n");
-    ErrorF("-configfile file     Read from a configuration file\n");
-    ErrorF("-config config       Select a specific configuration\n");
-    ErrorF("-nomulticursor       Turn of multiple cursor support\n");
     ErrorF("-fontpath            Sets the default font path\n");
     ErrorF("-stat inter scrns    Print out performance statistics\n");
     ErrorF("-syncbatch inter     Set interval for XSync batching\n");
-    ErrorF("-nooffscreenopt      Disable offscreen optimization\n");
+    ErrorF("-offscreenopt        Enable offscreen optimization\n");
     ErrorF("-nosubdivprims       Disable primitive subdivision\n");
     ErrorF("                     optimization\n");
-    ErrorF("-nowindowopt         Disable lazy window creation optimization\n");
+    ErrorF("-windowopt           Enable lazy window creation optimization\n");
     ErrorF("-noxkb               Disable use of the XKB extension with\n");
     ErrorF("                     backend displays (cf. -kb).\n");
     ErrorF("-depth               Specify the default root window depth\n");
     ErrorF("-norender            Disable RENDER extension support\n");
 #ifdef GLXEXT
-    ErrorF("-noglxproxy          Disable GLX Proxy\n");
+    ErrorF("-glxproxy            Enable GLX Proxy\n");
     ErrorF("-noglxswapgroup      Disable swap group and swap barrier\n");
     ErrorF("                     extensions in GLX proxy\n");
     ErrorF("-glxsyncswap         Force XSync after swap buffers\n");
     ErrorF("-glxfinishswap       Force glFinish after swap buffers\n");
 #endif
     ErrorF("-ignorebadfontpaths  Ignore bad font paths during initialization\n");
-    ErrorF("-addremovescreens    Enable dynamic screen addition/removal\n");
-    ErrorF("-param ...           Specify configuration parameters (e.g.,\n");
-    ErrorF("                     XkbRules, XkbModel, XkbLayout, etc.)\n");
-    ErrorF("\n");
-    ErrorF("    If the -input string matches a -display string, then input\n"
-           "    is taken from that backend display.  (XInput cannot be taken\n"
-           "    from a backend display.)  Placing \",console\" after the\n"
-           "    display name will force a console window to be opened on\n"
-           "    that display in addition to the backend input.  This is\n"
-           "    useful if the backend window does not cover the whole\n"
-           "    physical display.\n\n");
-    
-    ErrorF("    Otherwise, if the -input or -xinput string specifies another\n"
-           "    X display, then a console window will be created on that\n"
-           "    display.  Placing \",windows\" or \",nowindows\" after the\n"
-           "    display name will control the display of window outlines in\n"
-           "    the console.\n\n");
-    
-    ErrorF("    -input or -xinput dummy specifies no input.\n");
-    ErrorF("    -input or -xinput local specifies the use of a raw keyboard,\n"
-           "    mouse, or other (extension) device:\n"
-           "        -input local,kbd,ps2 will use a ps2 mouse\n"
-           "        -input local,kbd,ms  will use a serial mouse\n"
-           "        -input local,usb-kbd,usb-mou will use USB devices \n"
-           "        -xinput local,usb-oth will use a non-mouse and\n"
-           "                non-keyboard USB device with XInput\n\n");
-    
-    ErrorF("    Special Keys:\n");
-    ErrorF("        Ctrl-Alt-g    Server grab/ungrab (console only)\n");
-    ErrorF("        Ctrl-Alt-f    Fine (1-pixel) mouse mode (console only)\n");
-    ErrorF("        Ctrl-Alt-q    Quit (core devices only)\n");
-    ErrorF("        Ctrl-Alt-F*   Switch to VC (local only)\n");
+    ErrorF("-noaddremovescreens  Disable dynamic screen addition/removal\n");
+#ifdef RANDR
+    ErrorF("-outputs num         RANDR outputs for each back-end display\n");
+    ErrorF("-crtcs num           RANDR crtcs for each back-end display\n");
+#endif
+    ErrorF("-prop name format    Specify property translation\n");
+    ErrorF("-selection name      Specify selection that needs unique prefix\n");
+#ifdef XV
+    ErrorF("-xvimage fourcc      Enable XVideo image format\n");
+#endif
+    ErrorF("--  [ server ] [ display ] [ options ]\n");
 }
diff --git a/hw/dmx/dmxinit.h b/hw/dmx/dmxinit.h
index 7d166fd..43f5a91 100644
--- a/hw/dmx/dmxinit.h
+++ b/hw/dmx/dmxinit.h
@@ -38,10 +38,21 @@
 #define DMXINIT_H
 
 #include "scrnintstr.h"
-
-extern Bool dmxOpenDisplay(DMXScreenInfo *dmxScreen);
+extern DMXScreenInfo *dmxAddScreen(const char *name,
+				   const char *display,
+				   const char *authType,
+				   int        authTypeLen,
+				   const char *authData,
+				   int        authDataLen,
+				   int        virtualFb);
+extern Bool dmxOpenDisplay(DMXScreenInfo *dmxScreen,
+			   const char    *display,
+			   const char    *authType,
+			   int           authTypeLen,
+			   const char    *authData,
+			   int           authDataLen);
+extern void dmxCloseDisplay(DMXScreenInfo *dmxScreen);
 extern void dmxSetErrorHandler(DMXScreenInfo *dmxScreen);
-extern void dmxCheckForWM(DMXScreenInfo *dmxScreen);
 extern void dmxGetScreenAttribs(DMXScreenInfo *dmxScreen);
 extern Bool dmxGetVisualInfo(DMXScreenInfo *dmxScreen);
 extern void dmxGetColormaps(DMXScreenInfo *dmxScreen);
diff --git a/hw/dmx/dmxinput.c b/hw/dmx/dmxinput.c
index 83f8a4a..91a52b6 100644
--- a/hw/dmx/dmxinput.c
+++ b/hw/dmx/dmxinput.c
@@ -1,41 +1,26 @@
 /*
- * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina.
+ * Copyright © 2008 Novell, Inc.
  *
- * All Rights Reserved.
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
  *
- * 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 on 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
- * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- *   David H. Dawes <dawes@xfree86.org>
- *   Kevin E. Martin <kem@redhat.com>
- *   Rickard E. (Rik) Faith <faith@redhat.com>
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
  *
- */
-
-/** \file
- * Provide the main entry points for input initialization and processing
- * that arequired by the dix layer.
+ * Author: David Reveman <davidr@novell.com>
  */
 
 #ifdef HAVE_DMX_CONFIG_H
@@ -45,74 +30,2384 @@
 #include "dmx.h"
 #include "dmxlog.h"
 #include "dmxinput.h"
+#include "dmxgrab.h"
+#include "dmxdnd.h"
+#include "dmxwindow.h"
+#include "dmxcursor.h"
+#include "dmxscrinit.h"
+#include "dmxxlibio.h"
 
 #include "inputstr.h"
 #include "input.h"
 #include "mi.h"
+#include "exevents.h"
+#include "XIstubs.h"
+#include "xace.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#include <X11/keysym.h>
+#include <xcb/xinput.h>
+
+#define DMX_KEYBOARD_EVENT_MASK					        \
+    (KeyPressMask | KeyReleaseMask | KeymapStateMask | FocusChangeMask)
+
+#define DMX_POINTER_EVENT_MASK				       \
+    (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \
+     LeaveWindowMask)
+
+static EventListPtr dmxEvents = NULL;
+
+static void
+dmxUpdateKeycodeMap (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr  pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo     *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+    const xcb_setup_t *setup = xcb_get_setup (dmxScreen->connection);
+    KeySymsPtr        dst = &pDevice->key->curKeySyms;
+    KeySymsPtr        src = &pDevPriv->keySyms;
+    int               width = src->mapWidth;
+    int               i;
+
+    if (!pDevice->isMaster && pDevice->u.master)
+    {
+	if (IsKeyboardDevice (pDevice->u.master))
+	    dst = &pDevice->u.master->key->curKeySyms;
+    }
+
+    if (dst->mapWidth < width)
+	width = dst->mapWidth;
+
+    memset (pDevPriv->keycode, 0,
+	    sizeof (KeyCode) * (setup->max_keycode - setup->min_keycode));
+
+    for (i = src->minKeyCode - setup->min_keycode;
+	 i < (src->maxKeyCode - src->minKeyCode);
+	 i++)
+    {
+	int j;
 
-/** Returns TRUE if the key is a valid modifier.  For PC-class
- * keyboards, all keys can be used as modifiers, so return TRUE
- * always. */
-Bool LegalModifier(unsigned int key, DeviceIntPtr pDev)
+	for (j = 0; j < (dst->maxKeyCode - dst->minKeyCode); j++)
+	{
+	    int k;
+
+	    for (k = 0; k < i; k++)
+		if (pDevPriv->keycode[k] == (dst->minKeyCode + j))
+		    break;
+
+	    /* make sure the keycode is not already in use */
+	    if (k < i)
+		continue;
+
+	    for (k = 0; k < width; k++)
+		if (dst->map[j * dst->mapWidth + k] != NoSymbol &&
+		    src->map[i * src->mapWidth + k] != NoSymbol)
+		    if (dst->map[j * dst->mapWidth + k] !=
+			src->map[i * src->mapWidth + k])
+			break;
+
+	    if (k == width)
+		break;
+	}
+
+	if (j < (dst->maxKeyCode - dst->minKeyCode))
+	    pDevPriv->keycode[i] = dst->minKeyCode + j;
+    }
+}
+
+static void
+dmxUpdateKeyboardMapping (DeviceIntPtr pDevice,
+			  int          first,
+			  int          count)
 {
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+    KeySymsRec       keysyms;
+    xcb_keysym_t     *syms;
+    int              n;
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	xcb_input_get_device_key_mapping_reply_t *reply;
+
+	reply = xcb_input_get_device_key_mapping_reply
+	    (dmxScreen->connection,
+	     xcb_input_get_device_key_mapping (dmxScreen->connection,
+					       pDevPriv->deviceId,
+					       first,
+					       count),
+	     NULL);
+
+	if (reply)
+	{
+	    syms = xcb_input_get_device_key_mapping_keysyms (reply);
+	    n    = xcb_input_get_device_key_mapping_keysyms_length (reply);
+
+	    keysyms.minKeyCode = first;
+	    keysyms.maxKeyCode = first + n - 1;
+	    keysyms.mapWidth   = reply->keysyms_per_keycode;
+	    keysyms.map        = (KeySym *) syms;
+    
+	    SetKeySymsMap (&pDevPriv->keySyms, &keysyms);
+
+	    free (reply);
+	}
+    }
+    else
+    {
+	xcb_get_keyboard_mapping_reply_t *reply;
+
+	reply = xcb_get_keyboard_mapping_reply
+	    (dmxScreen->connection,
+	     xcb_get_keyboard_mapping (dmxScreen->connection,
+				       first,
+				       count),
+	     NULL);
+
+	if (reply)
+	{
+	    syms = xcb_get_keyboard_mapping_keysyms (reply);
+	    n    = xcb_get_keyboard_mapping_keysyms_length (reply);
+
+	    keysyms.minKeyCode = first;
+	    keysyms.maxKeyCode = first + n - 1;
+	    keysyms.mapWidth   = reply->keysyms_per_keycode;
+	    keysyms.map        = (KeySym *) syms;
+    
+	    SetKeySymsMap (&pDevPriv->keySyms, &keysyms);
+
+	    free (reply);
+	}
+    }
+
+    dmxUpdateKeycodeMap (pDevice);
+}
+
+static DeviceIntPtr
+dmxGetButtonDevice (DMXInputInfo *dmxInput,
+		    XID          deviceId)
+{
+    int i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (dmxInput->devs[i]);
+
+	if (!IsPointerDevice (dmxInput->devs[i]))
+	    continue;
+	
+	if (deviceId >= 0)
+	{
+	    if (pDevPriv->deviceId != deviceId)
+		continue;
+	}
+
+	return dmxInput->devs[i];
+    }
+
+    return NULL;
+}
+
+static DeviceIntPtr
+dmxGetPairedButtonDevice (DeviceIntPtr pDev)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+    return dmxGetButtonDevice (pDevPriv->dmxInput, pDevPriv->masterId);
+}
+
+static int
+dmxButtonEvent (DeviceIntPtr pDevice,
+		int          button,
+		int          x,
+		int          y,
+		int          type)
+{
+    int v[2] = { x, y };
+    int nEvents, i;
+
+    GetEventList (&dmxEvents);
+    nEvents = GetPointerEvents (dmxEvents,
+				pDevice,
+				type,
+				button,
+				POINTER_ABSOLUTE,
+				0, 2,
+				v);
+
+    for (i = 0; i < nEvents; i++)
+	mieqEnqueue (pDevice, dmxEvents[i].event);
+
+    if (button > 0 && button <= 255)
+    {
+	dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+
+	switch (type) {
+	case XCB_BUTTON_PRESS:
+	    pDevPriv->state[button >> 3] |= 1 << (button & 7);
+	    break;
+	case XCB_BUTTON_RELEASE:
+	    pDevPriv->state[button >> 3] &= ~(1 << (button & 7));
+	default:
+	    break;
+	}
+    }
+	
+    return nEvents;
+}
+
+static int
+dmxKeyEvent (DeviceIntPtr pDevice,
+	     int          key,
+	     int          type)
+{
+    dmxDevicePrivPtr  pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo     *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+    const xcb_setup_t *setup = xcb_get_setup (dmxScreen->connection);
+    int               nEvents = 0;
+
+    if (key >= setup->min_keycode && key <= setup->max_keycode)
+    {
+	int keycode = pDevPriv->keycode[key - setup->min_keycode];
+
+	if (keycode)
+	{
+	    int i;
+
+	    GetEventList (&dmxEvents);
+	    nEvents = GetKeyboardEvents (dmxEvents, pDevice, type, keycode);
+	    for (i = 0; i < nEvents; i++)
+		mieqEnqueue (pDevice, dmxEvents[i].event);
+	}
+    }
+
+    if (key > 0 && key <= 255)
+    {
+	switch (type) {
+	case XCB_KEY_PRESS:
+	    pDevPriv->state[key >> 3] |= 1 << (key & 7);
+	    break;
+	case XCB_KEY_RELEASE:
+	    pDevPriv->state[key >> 3] &= ~(1 << (key & 7));
+	default:
+	    break;
+	}
+    }
+
+    return nEvents;
+}
+
+static int
+dmxUpdateButtonState (DeviceIntPtr pDevice,
+		      const char   *buttons)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    int              i, j, nEvents = 0;
+
+    for (i = 0; i < 32; i++)
+    {
+	if (!(pDevPriv->state[i] ^ buttons[i]))
+	    continue;
+	
+	for (j = 0; j < 8; j++)
+	{
+	    /* button is down, but shouldn't be */
+	    if ((pDevPriv->state[i] & (1 << j)) && !(buttons[i] & (1 << j)))
+		nEvents += dmxButtonEvent (pDevice,
+					   (i << 3) + j,
+					   pDevice->last.valuators[0],
+					   pDevice->last.valuators[1],
+					   XCB_BUTTON_RELEASE);
+
+	    /* button should be down, but isn't */
+	    if (!(pDevPriv->state[i] & (1 << j)) && (buttons[i] & (1 << j)))
+		nEvents += dmxButtonEvent (pDevice,
+					   (i << 3) + j,
+					   pDevice->last.valuators[0],
+					   pDevice->last.valuators[1],
+					   XCB_BUTTON_PRESS);
+	}
+    }
+
+    return nEvents;
+}
+
+static int
+dmxUpdateKeyState (DeviceIntPtr pDevice,
+		   const char   *keys)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    int              i, j, nEvents = 0;
+
+    for (i = 0; i < 32; i++)
+    {
+	if (!(pDevPriv->state[i] ^ keys[i]))
+	    continue;
+
+	for (j = 0; j < 8; j++)
+	{
+	    /* key is down, but shouldn't be */
+	    if ((pDevPriv->state[i] & (1 << j)) && !(keys[i] & (1 << j)))
+		nEvents += dmxKeyEvent (pDevice,
+					(i << 3) + j,
+					XCB_KEY_RELEASE);
+
+	    /* key should be down, but isn't */
+	    if (!(pDevPriv->state[i] & (1 << j)) && (keys[i] & (1 << j)))
+		nEvents += dmxKeyEvent (pDevice,
+					(i << 3) + j,
+					XCB_KEY_PRESS);
+	}
+    }
+
+    return nEvents;
+}
+
+static int
+dmxChangeButtonState (DeviceIntPtr pDevice,
+		      int          button,
+		      int          how)
+{
+    int nEvents = 0;
+
+    if (button > 0 && button <= 255)
+    {
+	dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+	char             buttons[32];
+
+	memcpy (buttons, pDevPriv->state, sizeof (buttons));
+
+	switch (how) {
+	case XCB_BUTTON_PRESS:
+	    buttons[button >> 3] |= 1 << (button & 7);
+	    break;
+	case XCB_BUTTON_RELEASE:
+	    buttons[button >> 3] &= ~(1 << (button & 7));
+	default:
+	    break;
+	}
+
+	dmxUpdateButtonState (pDevice, buttons);
+    }
+
+    return nEvents;
+}
+
+static int
+dmxChangeKeyState (DeviceIntPtr pDevice,
+		   int          key,
+		   int          how)
+{
+    int nEvents = 0;
+
+    if (key > 0 && key <= 255)
+    {
+	dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+	char             keys[32];
+
+	memcpy (keys, pDevPriv->state, sizeof (keys));
+
+	switch (how) {
+	case XCB_KEY_PRESS:
+	    keys[key >> 3] |= 1 << (key & 7);
+	    break;
+	case XCB_KEY_RELEASE:
+	    keys[key >> 3] &= ~(1 << (key & 7));
+	default:
+	    break;
+	}
+
+	dmxUpdateKeyState (pDevice, keys);
+    }
+
+    return nEvents;
+}
+
+static int
+dmxUpdateSpritePosition (DeviceIntPtr pDevice,
+			 int          x,
+			 int          y)
+{
+    ScreenPtr pScreen = miPointerGetScreen (pDevice);
+
+    if (x >= pScreen->width)
+	x = pScreen->width - 1;
+    else if (x < 0)
+	x = 0;
+
+    if (y >= pScreen->height)
+	y = pScreen->height - 1;
+    else if (y < 0)
+	y = 0;
+	
+    if (x == pDevice->last.valuators[0] && y == pDevice->last.valuators[1])
+	return 0;
+
+    return dmxButtonEvent (pDevice, 0, x, y, XCB_MOTION_NOTIFY);
+}
+
+static Bool
+dmxFakePointerGrab (DMXInputInfo *dmxInput)
+{
+    DMXScreenInfo *dmxScreen = (DMXScreenInfo *) dmxInput;
+    WindowPtr     pWin = WindowTable[dmxScreen->index];
+    GrabRec       newGrab;
+    int           i;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+	pWin = WindowTable[0];
+#endif
+
+    memset (&newGrab, 0, sizeof (GrabRec));	    
+
+    newGrab.window       = pWin;
+    newGrab.resource     = 0;
+    newGrab.ownerEvents  = xFalse;
+    newGrab.cursor       = NULL;
+    newGrab.confineTo    = NullWindow;
+    newGrab.eventMask    = NoEventMask;
+    newGrab.genericMasks = NULL;
+    newGrab.next         = NULL;
+    newGrab.keyboardMode = GrabModeAsync;
+    newGrab.pointerMode  = GrabModeAsync;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pDevice = dmxInput->devs[i];
+
+	if (!pDevice->isMaster && pDevice->u.master)
+	    pDevice = pDevice->u.master;
+
+	if (!IsPointerDevice (pDevice))
+	    continue;
+
+	newGrab.device = pDevice;
+
+	if (!dmxActivateFakeGrab (pDevice, &newGrab))
+	    return FALSE;
+    }
+
     return TRUE;
 }
 
-/** Called from dix/main.c on each server generation to initialize
- * inputs.  All the work is done in dmxInputInit.  \see
- * dmxInputInit() */
-void InitInput(int argc, char **argv)
+static void
+dmxReleaseFakePointerGrab (DMXInputInfo *dmxInput)
+{
+    int i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pDevice = dmxInput->devs[i];
+
+	if (!pDevice->isMaster && pDevice->u.master)
+	    pDevice = pDevice->u.master;
+
+	if (!IsPointerDevice (pDevice))
+	    continue;
+
+	dmxDeactivateFakeGrab (pDevice);
+    }
+}
+
+static Bool
+dmxFakeKeyboardGrab (DMXInputInfo *dmxInput)
 {
+    DMXScreenInfo *dmxScreen = (DMXScreenInfo *) dmxInput;
+    WindowPtr     pWin = WindowTable[dmxScreen->index];
+    GrabRec       newGrab;
+    int           i;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+	pWin = WindowTable[0];
+#endif
+
+    memset (&newGrab, 0, sizeof (GrabRec));	    
+
+    newGrab.window       = pWin;
+    newGrab.resource     = 0;
+    newGrab.ownerEvents  = xFalse;
+    newGrab.cursor       = NULL;
+    newGrab.confineTo    = NullWindow;
+    newGrab.eventMask    = NoEventMask;
+    newGrab.genericMasks = NULL;
+    newGrab.next         = NULL;
+    newGrab.keyboardMode = GrabModeAsync;
+    newGrab.pointerMode  = GrabModeAsync;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pDevice = dmxInput->devs[i];
+
+	if (!pDevice->isMaster && pDevice->u.master)
+	    pDevice = pDevice->u.master;
+
+	if (!IsKeyboardDevice (pDevice))
+	    continue;
+
+	newGrab.device = pDevice;
+
+	if (!dmxActivateFakeGrab (pDevice, &newGrab))
+	    return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+dmxReleaseFakeKeyboardGrab (DMXInputInfo *dmxInput)
+{
+    int i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pDevice = dmxInput->devs[i];
+
+	if (!pDevice->isMaster && pDevice->u.master)
+	    pDevice = pDevice->u.master;
+
+	if (!IsKeyboardDevice (pDevice))
+	    continue;
+
+	dmxDeactivateFakeGrab (pDevice);
+    }
+}
+
+Bool
+dmxFakeMotion (DMXInputInfo *dmxInput,
+	       int          x,
+	       int          y)
+{
+    int i;
+
+    if (!dmxFakePointerGrab (dmxInput))
+	return FALSE;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pDevice = dmxInput->devs[i];
+
+	if (!IsPointerDevice (pDevice))
+	    continue;
+
+	dmxUpdateSpritePosition (pDevice, x, y);
+    }
+
+    return TRUE;
+}
+
+void
+dmxEndFakeMotion (DMXInputInfo *dmxInput)
+{
+    dmxReleaseFakePointerGrab (dmxInput);
+}
+
+static void
+dmxInputGrabDeviceReply (ScreenPtr           pScreen,
+			 unsigned int        sequence,
+			 xcb_generic_reply_t *reply,
+			 xcb_generic_error_t *error,
+			 void                *data)
+{
+    DMXInputInfo *dmxInput = &dmxScreens[pScreen->myNum].input;
     int          i;
-    DMXInputInfo *dmxInput;
 
-    if (!dmxNumInputs)
-        dmxLog(dmxFatal, "InitInput: no inputs specified\n");
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr     pDevice = dmxInput->devs[i];
+	dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+
+	if ((*pDevPriv->ReplyCheck) (pDevice, sequence, reply))
+	    break;
+    }
+}
+
+/* not in xcb-xinput yet */
+
+#define DMX_XCB_WARP_DEVICE_POINTER 41
+
+typedef struct dmx_xcb_warp_device_pointer_request_t {
+    uint8_t      major_opcode;
+    uint8_t      minor_opcode;
+    uint16_t     length;
+    xcb_window_t src_win;
+    xcb_window_t dst_win;
+    int16_t      src_x;
+    int16_t      src_y;
+    uint16_t     src_width;
+    uint16_t     src_height;
+    int16_t      dst_x;
+    int16_t      dst_y;
+    uint8_t      deviceid;
+    uint8_t      pad0;
+    uint16_t     pad1;
+} dmx_xcb_warp_device_pointer_request_t;
+
+#define DMX_XCB_INPUT_EXTENDED_GRAB_DEVICE 45
+
+typedef struct dmx_xcb_input_extended_grab_device_request_t {
+    uint8_t         major_opcode;
+    uint8_t         minor_opcode;
+    uint16_t        length;
+    xcb_window_t    grab_window;
+    xcb_timestamp_t time;
+    uint8_t         deviceid;
+    uint8_t         device_mode;
+    uint8_t         owner_events;
+    uint8_t         pad0;
+    xcb_window_t    confine_to;
+    xcb_cursor_t    cursor;
+    uint16_t        event_count;
+    uint16_t        generic_event_count;
+} dmx_xcb_input_extended_grab_device_request_t;
+
+#define DMX_XCB_INPUT_DEVICE_LEAVE_NOTIFY 17
+
+typedef struct dmx_xcb_input_device_state_notify_event_t {
+    uint8_t         response_type;
+    uint8_t         detail;
+    uint16_t        sequence;
+    xcb_timestamp_t time;
+    xcb_window_t    root;
+    xcb_window_t    event;
+    xcb_window_t    child;
+    int16_t         root_x;
+    int16_t         root_y;
+    int16_t         event_x;
+    int16_t         event_y;
+    uint16_t        state;
+    uint8_t         mode;
+    uint8_t         device_id;
+} dmx_xcb_input_device_state_notify_event_t;
+
+typedef xcb_input_focus_in_event_t dmx_xcb_input_focus_out_event_t;
+
+static void
+dmxDeviceGrabKeyboard (DeviceIntPtr pDevice,
+		       WindowPtr    pWindow)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+    Window           window = (DMX_GET_WINDOW_PRIV (pWindow))->window;
+
+    if (pDevPriv->grabStatus != XCB_GRAB_STATUS_SUCCESS && !pDevPriv->active)
+	return;
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	dmx_xcb_input_extended_grab_device_request_t grab = {
+	    .grab_window  = window,
+	    .deviceid     = pDevPriv->deviceId,
+	    .device_mode  = XCB_GRAB_MODE_ASYNC,
+	    .owner_events = TRUE,
+	    .event_count  = 2
+	};
+	xcb_protocol_request_t request = {
+	    2,
+	    &xcb_input_id,
+	    DMX_XCB_INPUT_EXTENDED_GRAB_DEVICE,
+	    FALSE
+	};
+	XEventClass  cls[3];
+	int          type;
+	struct iovec vector[] =  {
+	    { &grab, sizeof (grab) },
+	    { cls,   sizeof (cls)  }
+	};
+
+	DeviceKeyPress (pDevPriv->device, type, cls[1]);
+	DeviceKeyRelease (pDevPriv->device, type, cls[2]);
+
+	pDevPriv->grab.sequence =
+	    xcb_send_request (dmxScreen->connection,
+			      0,
+			      vector,
+			      &request);
+    }
+    else
+    {
+	pDevPriv->grab.sequence =
+	    xcb_grab_keyboard (dmxScreen->connection,
+			       TRUE,
+			       window,
+			       0,
+			       XCB_GRAB_MODE_ASYNC,
+			       XCB_GRAB_MODE_ASYNC).sequence;
+    }
+
+    dmxAddRequest (&dmxScreen->request,
+		   dmxInputGrabDeviceReply,
+		   pDevPriv->grab.sequence,
+		   0);
+}
+
+static void
+dmxDeviceUngrabKeyboard (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	xcb_input_ungrab_device (dmxScreen->connection,
+				 0,
+				 pDevPriv->deviceId);
+    }
+    else
+    {
+	xcb_ungrab_keyboard (dmxScreen->connection, 0);
+    }
+
+    pDevPriv->grabStatus = !XCB_GRAB_STATUS_SUCCESS;
+}
+
+static Bool
+dmxDeviceKeyboardReplyCheck (DeviceIntPtr        pDevice,
+			     unsigned int        request,
+			     xcb_generic_reply_t *reply)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+
+    if (request == pDevPriv->grab.sequence)
+    {
+	if (reply)
+	{
+	    if (pDevPriv->deviceId >= 0)
+	    {
+		xcb_input_grab_device_reply_t *xgrab =
+		    (xcb_input_grab_device_reply_t *) reply;
+
+		pDevPriv->grabStatus = xgrab->status;
+	    }
+	    else
+	    {
+		xcb_grab_keyboard_reply_t *xgrab =
+		    (xcb_grab_keyboard_reply_t *) reply;
+
+		pDevPriv->grabStatus = xgrab->status;
+	    }
+	}
+
+	pDevPriv->grab.sequence = 0;
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+static void
+dmxDeviceGrabPointer (DeviceIntPtr pDevice,
+		      WindowPtr    pWindow,
+		      WindowPtr    pConfineTo,
+		      CursorPtr    pCursor)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+    ScreenPtr        pScreen = screenInfo.screens[dmxScreen->index];
+    Window           window = (DMX_GET_WINDOW_PRIV (pWindow))->window;
+    Window           confineTo = None;
+    Cursor           cursor = None;
+
+    if (pDevPriv->grabStatus != XCB_GRAB_STATUS_SUCCESS && !pDevPriv->active)
+	return;
+
+    if (pConfineTo)
+	confineTo = (DMX_GET_WINDOW_PRIV (pConfineTo))->window;
+
+    if (pCursor)
+	cursor = (DMX_GET_CURSOR_PRIV (pCursor, pScreen))->cursor;
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	dmx_xcb_input_extended_grab_device_request_t grab = {
+	    .grab_window  = window,
+	    .deviceid     = pDevPriv->deviceId,
+	    .device_mode  = XCB_GRAB_MODE_ASYNC,
+	    .owner_events = TRUE,
+	    .confine_to   = confineTo,
+	    .cursor       = cursor,
+	    .event_count  = 3
+	};
+	xcb_protocol_request_t request = {
+	    2,
+	    &xcb_input_id,
+	    DMX_XCB_INPUT_EXTENDED_GRAB_DEVICE,
+	    FALSE
+	};
+	XEventClass  cls[3];
+	int          type;
+	struct iovec vector[] =  {
+	    { &grab, sizeof (grab) },
+	    { cls,   sizeof (cls)  }
+	};
+
+	DeviceMotionNotify (pDevPriv->device, type, cls[0]);
+	DeviceButtonPress (pDevPriv->device, type, cls[1]);
+	DeviceButtonRelease (pDevPriv->device, type, cls[2]);
+
+	pDevPriv->grab.sequence =
+	    xcb_send_request (dmxScreen->connection,
+			      0,
+			      vector,
+			      &request);
+    }
+    else
+    {
+	pDevPriv->grab.sequence =
+	    xcb_grab_pointer (dmxScreen->connection,
+			      TRUE,
+			      window,
+			      DMX_POINTER_EVENT_MASK,
+			      XCB_GRAB_MODE_ASYNC,
+			      XCB_GRAB_MODE_ASYNC,
+			      confineTo,
+			      cursor,
+			      0).sequence;
+    }
+
+    dmxAddRequest (&dmxScreen->request,
+		   dmxInputGrabDeviceReply,
+		   pDevPriv->grab.sequence,
+		   0);
+}
+
+static void
+dmxDeviceUngrabPointer (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	xcb_input_ungrab_device (dmxScreen->connection,
+				 0,
+				 pDevPriv->deviceId);
+    }
+    else
+    {
+	xcb_ungrab_pointer (dmxScreen->connection, 0);
+    }
+
+    pDevPriv->grabStatus = !XCB_GRAB_STATUS_SUCCESS;
+}
+
+static Bool
+dmxDevicePointerReplyCheck (DeviceIntPtr        pDevice,
+			    unsigned int        request,
+			    xcb_generic_reply_t *reply)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+
+    if (request == pDevPriv->grab.sequence)
+    {
+	if (reply)
+	{
+	    if (pDevPriv->deviceId >= 0)
+	    {
+		xcb_input_grab_device_reply_t *xgrab =
+		    (xcb_input_grab_device_reply_t *) reply;
+
+		pDevPriv->grabStatus = xgrab->status;
+	    }
+	    else
+	    {
+		xcb_grab_pointer_reply_t *xgrab =
+		    (xcb_grab_pointer_reply_t *) reply;
+
+		pDevPriv->grabStatus = xgrab->status;
+	    }
+	}
+
+	pDevPriv->grab.sequence = 0;
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+static void
+dmxDevicePointerActivate (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+
+    if (pDevPriv->active)
+	return;
+
+    pDevPriv->active = TRUE;
+
+    dmxReleaseFakePointerGrab (pDevPriv->dmxInput);
+
+    if (pDevPriv->grabStatus != XCB_GRAB_STATUS_SUCCESS &&
+	pDevPriv->grab.sequence == 0)
+    {
+	DeviceIntPtr pMaster = pDevice;
+
+	if (!pDevice->isMaster && pDevice->u.master)
+	    pMaster = pDevice->u.master;
+
+	if (pMaster->deviceGrab.grab)
+	{
+	    GrabPtr   pGrab = pMaster->deviceGrab.grab;
+	    WindowPtr pWin, pConfineTo = NULL;
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		PanoramiXRes *win, *confineToWin = NULL;
+		int          i = dmxScreen->index;
+
+		if (!(win = (PanoramiXRes *)
+		      SecurityLookupIDByType(
+			  serverClient, pGrab->window->drawable.id, XRT_WINDOW,
+			  DixGetAttrAccess)))
+		    return;
+		if (pGrab->confineTo)
+		    if (!(confineToWin = (PanoramiXRes *)
+			  SecurityLookupIDByType(
+			      serverClient, pGrab->confineTo->drawable.id,
+			      XRT_WINDOW, DixGetAttrAccess)))
+			return;
+
+		if (dixLookupWindow (&pWin,
+				     win->info[i].id,
+				     serverClient,
+				     DixGetAttrAccess) != Success)
+		    return;
+
+		if (confineToWin)
+		    if (dixLookupWindow (&pConfineTo,
+					 confineToWin->info[i].id,
+					 serverClient,
+					 DixGetAttrAccess) != Success)
+			return;
+	    }
+	    else
+#endif
+	    {
+		pWin       = pGrab->window;
+		pConfineTo = pGrab->confineTo;
+	    }
+
+	    dmxDeviceGrabPointer (pDevice,
+				  pWin,
+				  pConfineTo,
+				  pGrab->cursor);
+	}
+    }
+}
+
+static void
+dmxDevicePointerDeactivate (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+
+    if (!pDevPriv->active)
+	return;
+
+    pDevPriv->active = FALSE;
+
+    dmxFakePointerGrab (pDevPriv->dmxInput);
+}
+
+static void
+dmxUpdateSpriteFromEvent (DeviceIntPtr pDevice,
+			  xcb_window_t event,
+			  int          x,
+			  int          y,
+			  int          rootX,
+			  int          rootY)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+    ScreenPtr        pScreen = screenInfo.screens[dmxScreen->index];
+
+    if (event != dmxScreen->rootWin)
+    {
+	DeviceIntPtr pMaster = pDevice;
+	WindowPtr    pWin;
+
+	if (!pDevice->isMaster && pDevice->u.master)
+	    pMaster = pDevice->u.master;
+
+	if (!pMaster->deviceGrab.grab)
+	{
+	    dmxDeviceUngrabPointer (pDevice);
+	    dmxLog (dmxWarning, "non-root window event without active grab\n");
+	    return;
+	}
+
+	pWin = WindowTable[dmxScreen->index];
+	for (;;)
+	{
+	    dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pWin);
+
+	    if (pWinPriv->window == event)
+		break;
+
+	    if (pWin->firstChild)
+	    {
+		pWin = pWin->firstChild;
+		continue;
+	    }
+
+	    while (!pWin->nextSib && (pWin != WindowTable[dmxScreen->index]))
+		pWin = pWin->parent;
+
+	    if (pWin == WindowTable[dmxScreen->index])
+		break;
+
+	    pWin = pWin->nextSib;
+	}
+
+	if (!pWin)
+	    return;
+
+	x += pWin->drawable.x;
+	y += pWin->drawable.y;
+    }
+
+    dmxEndFakeMotion (&dmxScreen->input);
+    dmxBEDnDSpriteUpdate (pScreen, event, rootX, rootY);
+    dmxUpdateSpritePosition (pDevice, x, y);
+    dmxDevicePointerActivate (pDevice);
+}
+
+static Bool
+dmxDevicePointerEventCheck (DeviceIntPtr        pDevice,
+			    xcb_generic_event_t *event)
+{
+    DeviceIntPtr     pButtonDev = pDevice;
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pButtonDev);
+    DMXInputInfo     *dmxInput = pDevPriv->dmxInput;
+    int              reltype, type = event->response_type & 0x7f;
+    int              id = pDevPriv->deviceId;
+
+    switch (type) {
+    case XCB_MOTION_NOTIFY: {
+	xcb_motion_notify_event_t *xmotion =
+	    (xcb_motion_notify_event_t *) event;
+
+	dmxUpdateSpriteFromEvent (pButtonDev,
+				  xmotion->event,
+				  xmotion->event_x,
+				  xmotion->event_y,
+				  xmotion->root_x,
+				  xmotion->root_y);
+    } break;
+    case XCB_BUTTON_PRESS:
+    case XCB_BUTTON_RELEASE: {
+	xcb_button_press_event_t *xbutton =
+	    (xcb_button_press_event_t *) event;
+
+	dmxUpdateSpriteFromEvent (pButtonDev,
+				  xbutton->event,
+				  xbutton->event_x,
+				  xbutton->event_y,
+				  xbutton->root_x,
+				  xbutton->root_y);
+	dmxChangeButtonState (pButtonDev,
+			      xbutton->detail,
+			      type);
+    } break;
+    case XCB_LEAVE_NOTIFY: {
+	xcb_leave_notify_event_t *xcrossing =
+	    (xcb_leave_notify_event_t *) event;
+
+	if (xcrossing->detail != XCB_NOTIFY_DETAIL_INFERIOR)
+	    dmxDevicePointerDeactivate (pButtonDev);
+    } break;
+    default:
+	if (id < 0)
+	    return FALSE;
+
+	reltype = type - dmxInput->eventBase;
+
+	switch (reltype) {
+	case XCB_INPUT_DEVICE_VALUATOR: {
+	    xcb_input_device_valuator_event_t *xvaluator =
+		(xcb_input_device_valuator_event_t *) event;
+
+	    if (id != (xvaluator->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    /* eat valuator events */
+	} break;
+	case XCB_INPUT_DEVICE_MOTION_NOTIFY: {
+	    xcb_input_device_motion_notify_event_t *xmotion =
+		(xcb_input_device_motion_notify_event_t *) event;
+
+	    if (id != (xmotion->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    dmxUpdateSpriteFromEvent (pButtonDev,
+				      xmotion->event,
+				      xmotion->event_x,
+				      xmotion->event_y,
+				      xmotion->root_x,
+				      xmotion->root_y);
+	} break;
+	case XCB_INPUT_DEVICE_BUTTON_PRESS:
+	case XCB_INPUT_DEVICE_BUTTON_RELEASE: {
+	    xcb_input_device_button_press_event_t *xbutton =
+		(xcb_input_device_button_press_event_t *) event;
+
+	    if (id != (xbutton->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    dmxUpdateSpriteFromEvent (pButtonDev,
+				      xbutton->event,
+				      xbutton->event_x,
+				      xbutton->event_y,
+				      xbutton->root_x,
+				      xbutton->root_y);
+	    dmxChangeButtonState (pButtonDev,
+				  xbutton->detail, XCB_BUTTON_RELEASE +
+				  (reltype -
+				   XCB_INPUT_DEVICE_BUTTON_RELEASE));
+	} break;
+	case XCB_INPUT_DEVICE_STATE_NOTIFY: {
+	    xcb_input_device_state_notify_event_t *xstate =
+		(xcb_input_device_state_notify_event_t *) event;
+
+	    if (id != (xstate->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    if (!(xstate->classes_reported & (1 << ButtonClass)))
+		return FALSE;
+
+	    memset (pDevPriv->keysbuttons, 0, 32);
+
+	    if (xstate->response_type & MORE_EVENTS)
+	    {
+		memcpy (pDevPriv->keysbuttons, xstate->buttons, 4);
+	    }
+	    else
+	    {
+		memcpy (pDevPriv->keysbuttons, xstate->buttons, 4);
+		dmxUpdateButtonState (pButtonDev,
+				      pDevPriv->keysbuttons);
+	    }
+	} break;
+	case XCB_INPUT_DEVICE_BUTTON_STATE_NOTIFY: {
+	    xcb_input_device_button_state_notify_event_t *xstate =
+		(xcb_input_device_button_state_notify_event_t *) event;
+
+	    if (id != (xstate->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    memcpy (&pDevPriv->keysbuttons[4], xstate->buttons, 28);
+	    dmxUpdateButtonState (pButtonDev, pDevPriv->keysbuttons);
+	} break;
+	case DMX_XCB_INPUT_DEVICE_LEAVE_NOTIFY: {
+	    dmx_xcb_input_device_state_notify_event_t *xcrossing =
+		(dmx_xcb_input_device_state_notify_event_t *) event;
+
+	    if (id != (xcrossing->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    if (xcrossing->detail != XCB_NOTIFY_DETAIL_INFERIOR)
+		dmxDevicePointerDeactivate (pButtonDev);
+	} break;
+	default:
+	    return FALSE;
+	}
+    }
+
+    return TRUE;
+}
+
+static void
+dmxDeviceKeyboardActivate (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+
+    if (pDevPriv->active)
+	return;
+
+    dmxReleaseFakeKeyboardGrab (pDevPriv->dmxInput);
+
+    pDevPriv->active = TRUE;
+
+    if (pDevPriv->grabStatus != XCB_GRAB_STATUS_SUCCESS &&
+	pDevPriv->grab.sequence == 0)
+    {
+	DeviceIntPtr pMaster = pDevice;
+
+	if (!pDevice->isMaster && pDevice->u.master)
+	    pMaster = pDevice->u.master;
+
+	if (pMaster->deviceGrab.grab)
+	{
+	    GrabPtr   pGrab = pMaster->deviceGrab.grab;
+	    WindowPtr pWin;
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		PanoramiXRes *win;
+		int          i = dmxScreen->index;
+
+		if (!(win = (PanoramiXRes *)
+		      SecurityLookupIDByType(
+			  serverClient, pGrab->window->drawable.id, XRT_WINDOW,
+			  DixGetAttrAccess)))
+		    return;
+
+		if (dixLookupWindow (&pWin,
+				     win->info[i].id,
+				     serverClient,
+				     DixGetAttrAccess) != Success)
+		    return;
+	    }
+	    else
+#endif
+	    {
+		pWin = pGrab->window;
+	    }
+
+	    dmxDeviceGrabKeyboard (pDevice, pWin);
+	}
+    }
+}
+
+static void
+dmxDeviceKeyboardDeactivate (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+
+    if (!pDevPriv->active)
+	return;
+
+    pDevPriv->active = FALSE;
+
+    dmxFakeKeyboardGrab (pDevPriv->dmxInput);
+}
+
+static void
+dmxUpdateKeyStateFromEvent (DeviceIntPtr pDevice,
+			    xcb_window_t event,
+			    int          detail,
+			    int          x,
+			    int          y,
+			    int          rootX,
+			    int          rootY,
+			    int          type)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+    ScreenPtr        pScreen = screenInfo.screens[dmxScreen->index];
+    DeviceIntPtr     pButtonDev;
+
+    if (event != dmxScreen->rootWin)
+    {
+	DeviceIntPtr pMaster = pDevice;
+	WindowPtr    pWin;
+
+	if (!pDevice->isMaster && pDevice->u.master)
+	    pMaster = pDevice->u.master;
+
+	if (!pMaster->deviceGrab.grab)
+	{
+	    dmxDeviceUngrabKeyboard (pDevice);
+	    dmxLog (dmxWarning, "non-root window event without active grab\n");
+	    return;
+	}
+
+	pWin = WindowTable[dmxScreen->index];
+	for (;;)
+	{
+	    dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pWin);
+
+	    if (pWinPriv->window == event)
+		break;
+
+	    if (pWin->firstChild)
+	    {
+		pWin = pWin->firstChild;
+		continue;
+	    }
+
+	    while (!pWin->nextSib && (pWin != WindowTable[dmxScreen->index]))
+		pWin = pWin->parent;
+
+	    if (pWin == WindowTable[dmxScreen->index])
+		break;
+
+	    pWin = pWin->nextSib;
+	}
+
+	if (!pWin)
+	    return;
+
+	x += pWin->drawable.x;
+	y += pWin->drawable.y;
+    }
+
+    pButtonDev = dmxGetPairedButtonDevice (pDevice);
+    if (pButtonDev && DMX_GET_DEVICE_PRIV (pButtonDev)->active)
+    {
+	dmxEndFakeMotion (&dmxScreen->input);
+	dmxBEDnDSpriteUpdate (pScreen, event, rootX, rootY);
+	dmxUpdateSpritePosition (pButtonDev, x, y);
+    }
+
+    dmxChangeKeyState (pDevice, detail, type);
+}
+
+static Bool
+dmxDeviceKeyboardEventCheck (DeviceIntPtr        pDevice,
+			     xcb_generic_event_t *event)
+{
+    DeviceIntPtr     pKeyDev = pDevice;
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pKeyDev);
+    DMXInputInfo     *dmxInput = pDevPriv->dmxInput;
+    int              reltype, type = event->response_type & 0x7f;
+    int              id = pDevPriv->deviceId;
+
+    switch (type) {
+    case XCB_KEY_PRESS:
+    case XCB_KEY_RELEASE: {
+	xcb_key_press_event_t *xkey = (xcb_key_press_event_t *) event;
+
+	dmxUpdateKeyStateFromEvent (pKeyDev,
+				    xkey->event,
+				    xkey->detail,
+				    xkey->event_x,
+				    xkey->event_y,
+				    xkey->root_x,
+				    xkey->root_y,
+				    type);
+    } break;
+    case XCB_KEYMAP_NOTIFY: {
+	xcb_keymap_notify_event_t *xkeymap =
+	    (xcb_keymap_notify_event_t *) event;
+	char state[32];
+
+	state[0] = 0;
+	memcpy (&state[1], xkeymap->keys, 31);
     
-    for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
-        dmxInputInit(dmxInput);
-    if (!dmxeqInitialized()) {
-        dmxLog(dmxWarning, "Use keyboard/mouse pair with the first -input\n");
-        dmxLog(dmxFatal,   "At least one core keyboard/mouse pair required\n");
+	dmxUpdateKeyState (pKeyDev, state);
+    } break;
+    case XCB_MAPPING_NOTIFY: {
+	xcb_mapping_notify_event_t *xmapping =
+	    (xcb_mapping_notify_event_t *) event;
+
+	if (xmapping->request == XCB_MAPPING_KEYBOARD)
+	    dmxUpdateKeyboardMapping (pKeyDev,
+				      xmapping->first_keycode,
+				      xmapping->count);
+    } break;
+    case XCB_FOCUS_IN: {
+	xcb_focus_in_event_t *xfocus = (xcb_focus_in_event_t *) event;
+
+	if (xfocus->detail != XCB_NOTIFY_DETAIL_INFERIOR)
+	    dmxDeviceKeyboardActivate (pKeyDev);
+    } break;
+    case XCB_FOCUS_OUT: {
+	xcb_focus_out_event_t *xfocus = (xcb_focus_out_event_t *) event;
+
+	if (xfocus->detail != XCB_NOTIFY_DETAIL_INFERIOR)
+	    dmxDeviceKeyboardDeactivate (pKeyDev);
+    } break;
+    default:
+	if (id < 0)
+	    return FALSE;
+
+	reltype = type - dmxInput->eventBase;
+
+	switch (reltype) {
+	case XCB_INPUT_DEVICE_VALUATOR: {
+	    xcb_input_device_valuator_event_t *xvaluator =
+		(xcb_input_device_valuator_event_t *) event;
+
+	    if (id != (xvaluator->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    /* eat valuator events */
+	} break;
+	case XCB_INPUT_DEVICE_KEY_PRESS:
+	case XCB_INPUT_DEVICE_KEY_RELEASE: {
+	    xcb_input_device_key_press_event_t *xkey =
+		(xcb_input_device_key_press_event_t *) event;
+
+	    if (id != (xkey->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    dmxUpdateKeyStateFromEvent (pKeyDev,
+					xkey->event,
+					xkey->detail,
+					xkey->event_x,
+					xkey->event_y,
+					xkey->root_x,
+					xkey->root_y,
+					XCB_KEY_PRESS +
+					(reltype - XCB_INPUT_DEVICE_KEY_PRESS));
+	} break;
+	case XCB_INPUT_DEVICE_STATE_NOTIFY: {
+	    xcb_input_device_state_notify_event_t *xstate =
+		(xcb_input_device_state_notify_event_t *) event;
+
+	    if (id != (xstate->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    if (!(xstate->classes_reported & (1 << KeyClass)))
+		return FALSE;
+
+	    memset (pDevPriv->keysbuttons, 0, 32);
+
+	    if (xstate->response_type & MORE_EVENTS)
+	    {
+		memcpy (pDevPriv->keysbuttons, xstate->keys, 4);
+	    }
+	    else
+	    {
+		memcpy (pDevPriv->keysbuttons, xstate->keys, 4);
+		dmxUpdateKeyState (pKeyDev, pDevPriv->keysbuttons);
+	    }
+	} break;
+	case XCB_INPUT_DEVICE_KEY_STATE_NOTIFY: {
+	    xcb_input_device_key_state_notify_event_t *xstate =
+		(xcb_input_device_key_state_notify_event_t *) event;
+
+	    if (id != (xstate->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    memcpy (&pDevPriv->keysbuttons[4], xstate->keys, 28);
+	    dmxUpdateKeyState (pKeyDev, pDevPriv->keysbuttons);
+	} break;
+	case XCB_INPUT_DEVICE_MAPPING_NOTIFY: {
+	    xcb_input_device_mapping_notify_event_t *xmapping =
+		(xcb_input_device_mapping_notify_event_t *) event;
+
+	    if (id != (xmapping->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    if (xmapping->request == XCB_MAPPING_KEYBOARD)
+		dmxUpdateKeyboardMapping (pKeyDev,
+					  xmapping->first_keycode,
+					  xmapping->count);
+	} break;
+	case XCB_INPUT_FOCUS_IN: {
+	    xcb_input_focus_in_event_t *xfocus =
+		(xcb_input_focus_in_event_t *) event;
+
+	    if (id != (xfocus->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    if (xfocus->detail != XCB_NOTIFY_DETAIL_INFERIOR)
+		dmxDeviceKeyboardActivate (pKeyDev);
+	} break;
+	case XCB_INPUT_FOCUS_OUT: {
+	    dmx_xcb_input_focus_out_event_t *xfocus =
+		(dmx_xcb_input_focus_out_event_t *) event;
+
+	    if (id != (xfocus->device_id & DEVICE_BITS))
+		return FALSE;
+
+	    if (xfocus->detail != XCB_NOTIFY_DETAIL_INFERIOR)
+		dmxDeviceKeyboardDeactivate (pKeyDev);
+	} break;
+	default:
+	    return FALSE;
+	}
     }
 
-    mieqInit();
+    return TRUE;
 }
 
-/** Called from dix/dispatch.c in Dispatch() whenever input events
- * require processing.  All the work is done in the lower level
- * routines. */
-void ProcessInputEvents(void)
+Bool
+dmxInputEventCheck (DMXInputInfo        *dmxInput,
+		    xcb_generic_event_t *event)
 {
-    int          i;
-    DMXInputInfo *dmxInput;
+    int i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr     pDevice = dmxInput->devs[i];
+	dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+
+        if ((*pDevPriv->EventCheck) (pDevice, event))
+	    return TRUE;
+    }
 
-    for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
-        if (!dmxInput->detached && dmxInput->processInputEvents)
-            dmxInput->processInputEvents(dmxInput);
+    return FALSE;
 }
 
-/** This routine is called from #dmxwindow.c whenever the layout of
- * windows on the display might have changed.  This information is used
- * by input drivers (currently only the console driver) that provide
- * information about window layout to the user. */
-void dmxUpdateWindowInfo(DMXUpdateType type, WindowPtr pWindow)
+void
+dmxInputGrabKeyboard (DMXInputInfo *dmxInput,
+		      DeviceIntPtr pDevice,
+		      WindowPtr    pWindow)
 {
-    int          i;
-    DMXInputInfo *dmxInput;
+    int i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pExtDevice = dmxInput->devs[i];
+
+	if (pExtDevice->u.master != pDevice)
+	    continue;
 
-    for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++)
-        if (!dmxInput->detached && dmxInput->updateWindowInfo)
-            dmxInput->updateWindowInfo(dmxInput, type, pWindow);
+	if (!IsKeyboardDevice (pExtDevice))
+	    continue;
+
+	dmxDeviceGrabKeyboard (pExtDevice, pWindow);
+    }
+}
+
+void
+dmxInputUngrabKeyboard (DMXInputInfo *dmxInput,
+			DeviceIntPtr pDevice,
+			WindowPtr    pWindow)
+{
+    int i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pExtDevice = dmxInput->devs[i];
+
+	if (pExtDevice->u.master != pDevice)
+	    continue;
+
+	if (!IsKeyboardDevice (pExtDevice))
+	    continue;
+
+	dmxDeviceUngrabKeyboard (pExtDevice);
+    }
+}
+
+void
+dmxInputGrabPointer (DMXInputInfo *dmxInput,
+		     DeviceIntPtr pDevice,
+		     WindowPtr    pWindow,
+		     WindowPtr    pConfineTo,
+		     CursorPtr    pCursor)
+{
+    int i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pExtDevice = dmxInput->devs[i];
+
+	if (pExtDevice->u.master != pDevice)
+	    continue;
+
+	if (!IsPointerDevice (pExtDevice))
+	    continue;
+
+	dmxDeviceGrabPointer (pExtDevice,
+			      pWindow,
+			      pConfineTo,
+			      pCursor);
+    }
+}
+
+void
+dmxInputUngrabPointer (DMXInputInfo *dmxInput,
+		       DeviceIntPtr pDevice,
+		       WindowPtr    pWindow)
+{
+    int i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr pExtDevice = dmxInput->devs[i];
+
+	if (pExtDevice->u.master != pDevice)
+	    continue;
+
+	if (!IsPointerDevice (pExtDevice))
+	    continue;
+
+	dmxDeviceUngrabPointer (pExtDevice);
+    }
+}
+
+void
+dmxInputWarpPointer (DMXInputInfo *dmxInput,
+		     DeviceIntPtr pDevice,
+		     int          x,
+		     int          y)
+{
+    DMXScreenInfo *dmxScreen = (DMXScreenInfo *) dmxInput;
+    int           i;
+
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	DeviceIntPtr     pExtDevice = dmxInput->devs[i];
+	dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pExtDevice);
+
+	if (pExtDevice->u.master != pDevice)
+	    continue;
+
+	if (!IsPointerDevice (pExtDevice))
+	    continue;
+
+	if (!pDevPriv->active)
+	    continue;
+
+	if (pDevPriv->deviceId >= 0)
+	{
+	    dmx_xcb_warp_device_pointer_request_t warp = {
+		.src_win  = dmxScreen->rootWin,
+		.dst_win  = dmxScreen->rootWin,
+		.dst_x    = x,
+		.dst_y    = y,
+		.deviceid = pDevPriv->deviceId
+	    };
+	    xcb_protocol_request_t request = {
+		1,
+		&xcb_input_id,
+		DMX_XCB_WARP_DEVICE_POINTER,
+		FALSE
+	    };
+	    struct iovec vector[] =  {
+		{ &warp, sizeof (warp) }
+	    };
+
+	    xcb_send_request (dmxScreen->connection,
+			      0,
+			      vector,
+			      &request);
+	}
+	else
+	{
+	    xcb_warp_pointer (dmxScreen->connection,
+			      dmxScreen->rootWin, dmxScreen->rootWin,
+			      0, 0,
+			      0, 0,
+			      x, y);
+	}
+    }
+}
+
+static void
+dmxKeyboardBell (int          volume,
+		 DeviceIntPtr pDevice,
+		 pointer      arg,
+		 int          something)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+
+    if (dmxScreen)
+	xcb_bell (dmxScreen->connection, volume);
+}
+
+static int
+dmxKeyboardOn (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr  pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo     *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+    const xcb_setup_t *setup = xcb_get_setup (dmxScreen->connection);
+    int               nKeycode = setup->max_keycode - setup->min_keycode;
+
+    pDevPriv->keycode = xalloc (nKeycode * sizeof (KeyCode));
+    if (!pDevPriv->keycode)
+	return -1;
+
+    pDevPriv->keySyms.map        = (KeySym *) NULL;
+    pDevPriv->keySyms.mapWidth   = 0;
+    pDevPriv->keySyms.minKeyCode = setup->min_keycode;
+    pDevPriv->keySyms.maxKeyCode = setup->max_keycode;
+
+    dmxUpdateKeyboardMapping (pDevice, setup->min_keycode, nKeycode);
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	XEventClass cls[5];
+	int         type;
+
+	pDevPriv->device = XOpenDevice (dmxScreen->beDisplay,
+					pDevPriv->deviceId);
+	if (!pDevPriv->device)
+	{
+	    dmxLog (dmxWarning, "Cannot open %s device (id=%d) on %s\n",
+		    pDevice->name, pDevPriv->deviceId, dmxScreen->name);
+	    xfree (pDevPriv->keycode);
+	    return -1;
+	}
+
+	DeviceKeyPress (pDevPriv->device, type, cls[0]);
+	DeviceKeyRelease (pDevPriv->device, type, cls[1]);
+	DeviceStateNotify (pDevPriv->device, type, cls[2]);
+	DeviceFocusIn (pDevPriv->device, type, cls[3]);
+	DeviceFocusOut (pDevPriv->device, type, cls[4]);
+
+	XLIB_PROLOGUE (dmxScreen);
+	XSelectExtensionEvent (dmxScreen->beDisplay, dmxScreen->rootWin,
+			       cls, 5);
+	XLIB_EPILOGUE (dmxScreen);
+    }
+    else
+    {
+	dmxScreen->rootEventMask |= DMX_KEYBOARD_EVENT_MASK;
+
+	XLIB_PROLOGUE (dmxScreen);
+	XSelectInput (dmxScreen->beDisplay, dmxScreen->rootWin,
+		      dmxScreen->rootEventMask);
+	XLIB_EPILOGUE (dmxScreen);
+    }
+
+    return Success;
+}
+
+static void
+dmxKeyboardOff (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	if (pDevPriv->device)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    XCloseDevice (dmxScreen->beDisplay, pDevPriv->device);
+	    XLIB_EPILOGUE (dmxScreen);
+
+	    pDevPriv->device = NULL;
+	}
+    }
+    else
+    {
+	dmxScreen->rootEventMask &= ~DMX_KEYBOARD_EVENT_MASK;
+
+	if (dmxScreen->scrnWin)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    XSelectInput (dmxScreen->beDisplay, dmxScreen->rootWin,
+			  dmxScreen->rootEventMask);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+    }
+
+    if (pDevPriv->keySyms.map)
+	xfree (pDevPriv->keySyms.map);
+
+    xfree (pDevPriv->keycode);
+}
+
+static int
+dmxKeyboardProc (DeviceIntPtr pDevice,
+		 int          what)
+{
+    DevicePtr            pDev = (DevicePtr) pDevice;
+    CARD8                modMap[MAP_LENGTH];
+    KeySymsRec           keySyms;
+
+#ifdef XKB
+    XkbComponentNamesRec names;
+#endif
+
+    switch (what) {
+    case DEVICE_INIT:
+        keySyms.minKeyCode = 8;
+        keySyms.maxKeyCode = 255;
+        keySyms.mapWidth = 4;
+        keySyms.map = (KeySym *) Xcalloc (sizeof (KeySym),
+					  (keySyms.maxKeyCode -
+					   keySyms.minKeyCode + 1) *
+					  keySyms.mapWidth);
+        if (!keySyms.map)
+	{
+            ErrorF ("[dmx] Couldn't allocate keymap\n");
+            return BadAlloc;
+        }
+
+        bzero ((char *) modMap, MAP_LENGTH);
+
+#ifdef XKB
+        if (!noXkbExtension)
+	{
+            bzero (&names, sizeof (names));
+
+            XkbSetRulesDflts ("base", "pc105", "us", NULL, NULL);
+            XkbInitKeyboardDeviceStruct (pDevice,
+					 &names,
+					 &keySyms,
+					 modMap,
+					 dmxKeyboardBell,
+					 (KbdCtrlProcPtr) NoopDDA);
+        }
+        else
+#endif
+        {
+            /* FIXME Our keymap here isn't exactly useful. */
+            InitKeyboardDeviceStruct (pDev,
+				      &keySyms,
+				      modMap,
+                                      dmxKeyboardBell,
+				      (KbdCtrlProcPtr) NoopDDA);
+        }
+
+        xfree (keySyms.map);
+	break;
+    case DEVICE_ON:
+	pDev->on = 1;
+	dmxKeyboardOn (pDevice);
+	break;
+    case DEVICE_OFF:
+	pDev->on = 0;
+	dmxKeyboardOff (pDevice);
+	break;
+    case DEVICE_CLOSE:
+	if (pDev->on)
+	{
+	    pDev->on = 0;
+	    dmxKeyboardOff (pDevice);
+	}
+	break;
+    }
+
+    return Success;
+}
+
+static int
+dmxPointerOn (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXInputInfo     *dmxInput = pDevPriv->dmxInput;
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) dmxInput;
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	XEventClass cls[6];
+	int         type;
+
+	pDevPriv->device = XOpenDevice (dmxScreen->beDisplay,
+					pDevPriv->deviceId);
+	if (!pDevPriv->device)
+	{
+	    dmxLog (dmxWarning, "Cannot open %s device (id=%d) on %s\n",
+		    pDevice->name, pDevPriv->deviceId, dmxScreen->name);
+	    return -1;
+	}
+
+	DeviceMotionNotify (pDevPriv->device, type, cls[0]);
+	DeviceButtonPress (pDevPriv->device, type, cls[1]);
+	DeviceButtonRelease (pDevPriv->device, type, cls[2]);
+	DeviceButtonPressGrab (pDevPriv->device, type, cls[3]);
+	DeviceStateNotify (pDevPriv->device, type, cls[4]);
+
+	cls[5] = (pDevPriv->device->device_id << 8) |
+	    (dmxInput->eventBase + DMX_XCB_INPUT_DEVICE_LEAVE_NOTIFY);
+
+	XLIB_PROLOGUE (dmxScreen);
+	XSelectExtensionEvent (dmxScreen->beDisplay, dmxScreen->rootWin,
+			       cls, 6);
+	XLIB_EPILOGUE (dmxScreen);
+    }
+    else
+    {
+	dmxScreen->rootEventMask |= DMX_POINTER_EVENT_MASK;
+
+	XLIB_PROLOGUE (dmxScreen);
+	XSelectInput (dmxScreen->beDisplay, dmxScreen->rootWin,
+		      dmxScreen->rootEventMask);
+	XLIB_EPILOGUE (dmxScreen);
+    }
+    
+    return -1;
+}
+
+static void
+dmxPointerOff (DeviceIntPtr pDevice)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+    DMXScreenInfo    *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+
+    if (pDevPriv->deviceId >= 0)
+    {
+	if (pDevPriv->device)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    XCloseDevice (dmxScreen->beDisplay, pDevPriv->device);
+	    XLIB_EPILOGUE (dmxScreen);
+
+	    pDevPriv->device = NULL;
+	}
+    }
+    else
+    {
+	dmxScreen->rootEventMask &= ~DMX_POINTER_EVENT_MASK;
+	
+	if (dmxScreen->scrnWin)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    XSelectInput (dmxScreen->beDisplay, dmxScreen->rootWin,
+			  dmxScreen->rootEventMask);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+    }
+}
+
+static int
+dmxPointerProc (DeviceIntPtr pDevice,
+		int          what)
+{
+    DevicePtr pDev = (DevicePtr) pDevice;
+    BYTE      map[33];
+    int       i;
+
+    switch (what) {
+    case DEVICE_INIT:
+	for (i = 1; i <= 32; i++)
+            map[i] = i;
+
+        InitPointerDeviceStruct (pDev,
+				 map, 32,
+				 (PtrCtrlProcPtr) NoopDDA,
+				 GetMotionHistorySize (), 2);
+
+	pDevice->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
+        pDevice->last.valuators[0] = pDevice->valuator->axisVal[0];
+        pDevice->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
+        pDevice->last.valuators[1] = pDevice->valuator->axisVal[1];
+	break;
+    case DEVICE_ON:
+	pDev->on = 1;
+	dmxPointerOn (pDevice);
+	break;
+    case DEVICE_OFF:
+	pDev->on = 0;
+	dmxPointerOff (pDevice);
+	break;
+    case DEVICE_CLOSE:
+	if (pDev->on)
+	{
+	    pDev->on = 0;
+	    dmxPointerOff (pDevice);
+	}
+	break;
+    }
+
+    return Success;
+}
+
+static char *
+dmxMakeUniqueDeviceName (DMXInputInfo *dmxInput,
+			 const char   *deviceName)
+{
+    DMXScreenInfo *dmxScreen = (DMXScreenInfo *) dmxInput;
+    char          *name;
+    int           i, n = 2;
+
+#define LEN 32
+
+    name = xalloc (strlen (dmxScreen->name) + strlen (deviceName) + LEN);
+    if (!name)
+	return NULL;
+	
+    sprintf (name, "%s's %s", dmxScreen->name, deviceName);
+
+    do {
+	for (i = 0; i < dmxInput->numDevs; i++)
+	{
+	    if (strcmp (dmxInput->devs[i]->name, name) == 0)
+	    {
+		sprintf (name, "%s's %s%d", dmxScreen->name, deviceName, n++);
+		break;
+	    }
+	}
+    } while (i < dmxInput->numDevs);
+
+    return name;
+}
+
+static DeviceIntPtr
+dmxAddInputDevice (DMXInputInfo *dmxInput,
+		   DeviceProc   deviceProc,
+		   const char   *deviceName,
+		   int          deviceId,
+		   int          masterId,
+		   Bool         (*EventCheck) (DeviceIntPtr,
+					       xcb_generic_event_t *),
+		   Bool         (*ReplyCheck) (DeviceIntPtr,
+					       unsigned int,
+					       xcb_generic_reply_t *))
+{
+    DeviceIntPtr pDevice, *devs;
+    char         *name;
+
+    devs = xrealloc (dmxInput->devs, sizeof (DeviceIntPtr) *
+		     (dmxInput->numDevs + 1));
+    if (!devs)
+	return NULL;
+
+    dmxInput->devs = devs;
+
+    name = dmxMakeUniqueDeviceName (dmxInput, deviceName);
+    if (!name)
+	return NULL;
+
+    pDevice = AddInputDevice (serverClient, deviceProc, TRUE);
+    if (pDevice)
+    {
+	dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+	
+	pDevice->name = name;
+
+	pDevPriv->dmxInput   = dmxInput;
+	pDevPriv->deviceId   = deviceId;
+	pDevPriv->masterId   = masterId;
+	pDevPriv->device     = NULL;
+	pDevPriv->fakeGrab   = xFalse;
+	pDevPriv->grabStatus = !XCB_GRAB_STATUS_SUCCESS;
+	pDevPriv->active     = xFalse;
+	pDevPriv->EventCheck = EventCheck;
+	pDevPriv->ReplyCheck = ReplyCheck;
+
+	memset (pDevPriv->state, 0, sizeof (pDevPriv->state));
+	memset (pDevPriv->keysbuttons, 0, sizeof (pDevPriv->keysbuttons));
+
+	pDevPriv->grab.sequence = 0;
+
+	RegisterOtherDevice (pDevice);
+
+	dmxInput->devs[dmxInput->numDevs] = pDevice;
+	dmxInput->numDevs++;
+
+	dmxLogInput (dmxInput, "Added extension device called %s\n", name);
+    }
+    else
+    {
+	xfree (name);
+    }
+
+    return pDevice;
+}
+
+static XID
+dmxGetMasterDevice (XDeviceInfo *device)
+{
+    XAttachInfoPtr ai;
+    int            i;
+
+    for (i = 0, ai = (XAttachInfoPtr) device->inputclassinfo;
+	 i < device->num_classes;
+	 ai = (XAttachInfoPtr) ((char *) ai + ai->length), i++)
+	if (ai->class == AttachClass)
+	    return ai->attached;
+
+    return -1;
+}
+
+static Bool
+dmxInputAddExtensionDevices (DMXInputInfo *dmxInput)
+{
+    DMXScreenInfo     *dmxScreen = (DMXScreenInfo *) dmxInput;
+    XExtensionVersion *ext;
+    XDeviceInfo       *devices;
+    int               num;
+    int               i;
+
+    ext = XQueryInputVersion (dmxScreen->beDisplay, XI_2_Major, XI_2_Minor);
+    if (!ext || ext == (XExtensionVersion *) NoSuchExtension)
+    {
+        dmxLogInput (dmxInput, "%s is not available\n", INAME);
+	return FALSE;
+    }
+
+    /* Only use XInput Extension if 2.0 or greater */
+    if (ext->major_version < 2)
+    {
+        dmxLogInput (dmxInput, "%s version %d.%d is too old\n",
+		     INAME, ext->major_version, ext->minor_version);
+	XFree (ext);
+	return FALSE;
+    }
+
+    XQueryExtension (dmxScreen->beDisplay,
+		     INAME,
+		     &i,
+		     &dmxInput->eventBase,
+		     &i);
+    
+    dmxLogInput (dmxInput, "Locating devices on %s (%s version %d.%d)\n",
+		 dmxScreen->name, INAME,
+		 ext->major_version, ext->minor_version);
+
+    XFree (ext);
+
+    devices = XListInputDevices (dmxScreen->beDisplay, &num);
+    if (devices)
+    {
+	for (i = 0; i < num; i++)
+	{
+	    switch (devices[i].use) {
+	    case IsXKeyboard:
+		dmxAddInputDevice (dmxInput,
+				   dmxKeyboardProc,
+				   devices[i].name,
+				   devices[i].id,
+				   dmxGetMasterDevice (&devices[i]),
+				   dmxDeviceKeyboardEventCheck,
+				   dmxDeviceKeyboardReplyCheck);
+		break;
+	    case IsXPointer:
+		dmxAddInputDevice (dmxInput,
+				   dmxPointerProc,
+				   devices[i].name,
+				   devices[i].id,
+				   dmxGetMasterDevice (&devices[i]),
+				   dmxDevicePointerEventCheck,
+				   dmxDevicePointerReplyCheck);
+		break;
+	    }
+	}
+
+	XFreeDeviceList (devices);
+    }
+
+    return TRUE;
+}
+
+static void
+dmxInputAddDevices (DMXInputInfo *dmxInput)
+{
+    if (!dmxInputAddExtensionDevices (dmxInput))
+    {
+	dmxLogInput (dmxInput, "Using core devices from %s\n",
+		     ((DMXScreenInfo *) dmxInput)->name);
+
+	dmxAddInputDevice (dmxInput,
+			   dmxKeyboardProc, "core keyboard",
+			   -1, -1,
+			   dmxDeviceKeyboardEventCheck,
+			   dmxDeviceKeyboardReplyCheck);
+	dmxAddInputDevice (dmxInput,
+			   dmxPointerProc, "core pointer",
+			   -1, -1,
+			   dmxDevicePointerEventCheck,
+			   dmxDevicePointerReplyCheck);
+    }
+}
+
+static void
+dmxInputRemoveDevices (DMXInputInfo *dmxInput)
+{
+    dmxLogInput (dmxInput, "Removing devices from %s\n",
+		 ((DMXScreenInfo *) dmxInput)->name);
+
+    while (dmxInput->numDevs)
+	DeleteInputDeviceRequest (*dmxInput->devs);
+}
+
+int
+dmxInputEnable (DMXInputInfo *dmxInput)
+{
+    int i;
+    
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+	dmxLogInput (dmxInput, "Activate device id %d: %s\n",
+		     dmxInput->devs[i]->id, dmxInput->devs[i]->name);
+
+        if (ActivateDevice (dmxInput->devs[i]) != Success)
+	    return BadImplementation;
+	
+	if (!EnableDevice (dmxInput->devs[i]))
+	    return BadImplementation;
+    }
+
+    return 0;
+}
+
+int
+dmxInputDisable (DMXInputInfo *dmxInput)
+{
+    char state[32];
+    int  i;
+
+    memset (state, 0, sizeof (state));
+    
+    for (i = 0; i < dmxInput->numDevs; i++)
+    {
+        dmxLogInput (dmxInput, "Disable device id %d: %s\n",
+		     dmxInput->devs[i]->id, dmxInput->devs[i]->name);
+
+	if (IsKeyboardDevice (dmxInput->devs[i]))
+	    dmxUpdateKeyState (dmxInput->devs[i], state);
+	else if (IsPointerDevice (dmxInput->devs[i]))
+	    dmxUpdateButtonState (dmxInput->devs[i], state);
+
+        DisableDevice (dmxInput->devs[i]);
+    }
+
+    return 0;
+}
+
+int
+dmxInputAttach (DMXInputInfo *dmxInput)
+{
+    dmxInputAddDevices (dmxInput);
+
+    return 0;
+}
+
+int
+dmxInputDetach (DMXInputInfo *dmxInput)
+{
+    ProcessInputEvents ();
+
+    dmxInputRemoveDevices (dmxInput);
+
+    return 0;
+}
+
+void
+dmxInputInit (DMXInputInfo *dmxInput)
+{
+    dmxInput->devs      = NULL;
+    dmxInput->numDevs   = 0;
+    dmxInput->eventBase = 0;
+}
+
+void
+dmxInputFini (DMXInputInfo *dmxInput)
+{
+    if (dmxInput->devs)
+	xfree (dmxInput->devs);
+}
+
+Bool
+LegalModifier (unsigned int key,
+	       DeviceIntPtr pDev)
+{
+    return TRUE;
+}
+
+static void
+dmxInitMasterKeyboard (DeviceIntPtr pDev)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+    DMX_WRAP (ActivateGrab, dmxActivateKeyboardGrab, pDevPriv,
+	      &pDev->deviceGrab);
+    DMX_WRAP (DeactivateGrab, dmxDeactivateKeyboardGrab, pDevPriv,
+	      &pDev->deviceGrab);
+}
+
+static void
+dmxInitMasterPointer (DeviceIntPtr pDev)
+{
+    dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+    DMX_WRAP (ActivateGrab, dmxActivatePointerGrab, pDevPriv,
+	      &pDev->deviceGrab);
+    DMX_WRAP (DeactivateGrab, dmxDeactivatePointerGrab, pDevPriv,
+	      &pDev->deviceGrab);
+}
+
+void
+InitInput (int argc, char **argv)
+{
+    int i;
+
+    GetEventList (&dmxEvents);
+
+    for (i = 0; i < dmxNumScreens; i++)
+	if (dmxScreens[i].beDisplay && !dmxScreens[i].virtualFb)
+	    dmxInputAddDevices (&dmxScreens[i].input);
+
+    /* XXX: init devices created using XChangeDeviceHierarchy */
+    dmxInitMasterKeyboard (inputInfo.keyboard);
+    dmxInitMasterPointer (inputInfo.pointer);
+
+    mieqInit ();
+}
+
+void
+ProcessInputEvents (void)
+{
+    mieqProcessInputEvents ();
+}
+
+void
+CloseInputDevice (DeviceIntPtr pDevice,
+		  ClientPtr    client)
+{
+}
+
+void
+AddOtherInputDevices (void)
+{
+}
+
+void
+OpenInputDevice (DeviceIntPtr pDevice,
+		 ClientPtr    client,
+		 int          *status)
+{
+    *status = XaceHook (XACE_DEVICE_ACCESS, client, pDevice, DixReadAccess);
 }
 
 int
-NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
+SetDeviceMode (ClientPtr    client,
+	       DeviceIntPtr pDevice,
+	       int          mode)
+{
+    return BadMatch;
+}
+
+int
+SetDeviceValuators (ClientPtr    client,
+		    DeviceIntPtr pDevice,
+		    int          *valuators,
+		    int          first_valuator,
+		    int          num_valuators)
+{
+    return BadMatch;
+}
+
+int
+ChangeDeviceControl (ClientPtr    client,
+		     DeviceIntPtr pDevice,
+		     xDeviceCtl   *control)
+{
+    return BadMatch;
+}
+
+int
+NewInputDeviceRequest (InputOption  *options,
+		       DeviceIntPtr *ppDevice)
 {
     return BadRequest;
 }
 
 void
-DeleteInputDeviceRequest(DeviceIntPtr pDev)
+DeleteInputDeviceRequest (DeviceIntPtr pDevice)
+{
+    int i, j;
+
+    RemoveDevice (pDevice);
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	for (j = 0; j < dmxScreens[i].input.numDevs; j++)
+	{
+	    if (dmxScreens[i].input.devs[j] == pDevice)
+	    {
+		for (; j < dmxScreens[i].input.numDevs - 1; j++)
+		    dmxScreens[i].input.devs[j] =
+			dmxScreens[i].input.devs[j + 1];
+
+		dmxScreens[i].input.numDevs--;
+		return;
+	    }
+	}
+    }
+}
+
+void
+DDXRingBell (int volume,
+	     int pitch,
+	     int duration)
 {
 }
diff --git a/hw/dmx/dmxinput.h b/hw/dmx/dmxinput.h
index 7af7b18..caacab0 100644
--- a/hw/dmx/dmxinput.h
+++ b/hw/dmx/dmxinput.h
@@ -1,162 +1,121 @@
 /*
- * Copyright 2001,2002 Red Hat Inc., Durham, North Carolina.
+ * Copyright © 2008 Novell, Inc.
  *
- * All Rights Reserved.
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
  *
- * 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 on 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
- * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- *   David H. Dawes <dawes@xfree86.org>
- *   Kevin E. Martin <kem@redhat.com>
- *   Rickard E. (Rik) Faith <faith@redhat.com>
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
  *
+ * Author: David Reveman <davidr@novell.com>
  */
 
-/** \file
- * This file provides access to:
- * - global variables available to all hw/dmx routines, and
- * - enumerations and typedefs needed by input routines in hw/dmx (and
- *   hw/dmx/input).
- *
- * The goal is that no files in hw/dmx should include header files from
- * hw/dmx/input -- the interface defined here should be the only
- * interface exported to the hw/dmx layer.  \see input/dmxinputinit.c.
- */
- 
 #ifndef DMXINPUT_H
 #define DMXINPUT_H
 
-/** Maximum number of file descriptors for SIGIO handling */
-#define DMX_MAX_SIGIO_FDS 4
-
-struct _DMXInputInfo;
-
-/** Reason why window layout was updated. */
-typedef enum {
-    DMX_UPDATE_REALIZE,         /**< Window realized        */
-    DMX_UPDATE_UNREALIZE,       /**< Window unrealized      */
-    DMX_UPDATE_RESTACK,         /**< Stacking order changed */
-    DMX_UPDATE_COPY,            /**< Window copied          */
-    DMX_UPDATE_RESIZE,          /**< Window resized         */
-    DMX_UPDATE_REPARENT         /**< Window reparented      */
-} DMXUpdateType;
-
-typedef void (*ProcessInputEventsProc)(struct _DMXInputInfo *);
-typedef void (*UpdateWindowInfoProc)(struct _DMXInputInfo *,
-                                     DMXUpdateType, WindowPtr);
-
-/** An opaque structure that is only exposed in the dmx/input layer. */
-typedef struct _DMXLocalInputInfo *DMXLocalInputInfoPtr;
-
-/** State of the SIGIO engine */
-typedef enum {
-    DMX_NOSIGIO = 0,            /**< Device does not use SIGIO at all. */
-    DMX_USESIGIO,               /**< Device can use SIGIO, but is not
-                                 * (e.g., because the VT is switch
-                                 * away). */
-    DMX_ACTIVESIGIO             /**< Device is currently using SIGIO. */
-} dmxSigioState;
-
-/** DMXInputInfo is typedef'd in #dmx.h so that all routines can have
- * access to the global pointers.  However, the elements are only
- * available to input-related routines. */
-struct _DMXInputInfo {
-    const char              *name; /**< Name of input display or device
-                                    * (from command line or config
-                                    * file)  */
-    Bool                    freename; /**< If true, free name on destroy */
-    Bool                    detached; /**< If true, input screen is detached */
-    int                     inputIdx; /**< Index into #dmxInputs global */
-    int                     scrnIdx;  /**< Index into #dmxScreens global */
-    Bool                    core;  /**< If True, initialize these
-                                    * devices as devices that send core
-                                    * events */
-    Bool                    console; /**< True if console and backend
-                                      * input share the same backend
-                                      * display  */
-
-    Bool                    windows; /**< True if window outlines are
-                                      * draw in console */
-
-    ProcessInputEventsProc  processInputEvents;
-    UpdateWindowInfoProc    updateWindowInfo;
-
-                                /* Local input information */
-    dmxSigioState           sigioState;    /**< Current stat */
-    int                     sigioFdCount;  /**< Number of fds in use */
-    int                     sigioFd[DMX_MAX_SIGIO_FDS];    /**< List of fds */
-    Bool                    sigioAdded[DMX_MAX_SIGIO_FDS]; /**< Active fds */
-
-    
-    /** True if a VT switch is pending, but has not yet happened. */
-    int                     vt_switch_pending;
-
-    /** True if a VT switch has happened. */
-    int                     vt_switched;
-
-    /** Number of devices handled in this _DMXInputInfo structure. */
-    int                     numDevs;
-
-    /** List of actual input devices.  Each _DMXInputInfo structure can
-     * refer to more than one device.  For example, the keyboard and the
-     * pointer of a backend display; or all of the XInput extension
-     * devices on a backend display. */
-    DMXLocalInputInfoPtr    *devs;
-
-    char                    *keycodes; /**< XKB keycodes from command line */
-    char                    *symbols;  /**< XKB symbols from command line */
-    char                    *geometry; /**< XKB geometry from command line */
-};
-
-extern int                  dmxNumInputs; /**< Number of #dmxInputs */
-extern DMXInputInfo         *dmxInputs;   /**< List of inputs */
-
-extern void dmxInputInit(DMXInputInfo *dmxInput);
-extern void dmxInputReInit(DMXInputInfo *dmxInput);
-extern void dmxInputLateReInit(DMXInputInfo *dmxInput);
-extern void dmxInputFree(DMXInputInfo *dmxInput);
-extern void dmxInputLogDevices(void);
-extern void dmxUpdateWindowInfo(DMXUpdateType type, WindowPtr pWindow);
-
-/* These functions are defined in input/dmxeq.c */
-extern Bool dmxeqInitialized(void);
-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 */
-typedef enum {
-    DMX_NO_BLOCK = 0,
-    DMX_BLOCK    = 1
-} DMXBlockType;
-
-extern void          dmxGetGlobalPosition(int *x, int *y);
-extern DMXScreenInfo *dmxFindFirstScreen(int x, int y);
-extern void          dmxCoreMotion(DevicePtr pDev, int x, int y, int delta,
-                                   DMXBlockType block);
-
-/* Support for dynamic addition of inputs.  This functions is defined in
- * config/dmxconfig.c */
-extern DMXInputInfo *dmxConfigAddInput(const char *name, int core);
+extern DevPrivateKey dmxDevicePrivateKey;
+
+/** Device private area. */
+typedef struct _dmxDevicePriv {
+    DMXInputInfo             *dmxInput;
+    long                     deviceId;
+    long                     masterId;
+    XDevice                  *device;
+    char		     state[32];
+    char		     keysbuttons[32];
+    KeySymsRec               keySyms;
+    KeyCode                  *keycode;
+    xcb_void_cookie_t        grab;
+    int                      grabStatus;
+    Bool                     fakeGrab;
+    Bool                     active;
+
+    Bool (*EventCheck) (DeviceIntPtr, xcb_generic_event_t *);
+    Bool (*ReplyCheck) (DeviceIntPtr, unsigned int, xcb_generic_reply_t *);
+
+    void (*ActivateGrab)   (DeviceIntPtr, GrabPtr, TimeStamp, Bool);
+    void (*DeactivateGrab) (DeviceIntPtr);
+} dmxDevicePrivRec, *dmxDevicePrivPtr;
+
+#define DMX_GET_DEVICE_PRIV(_pDev)				\
+    ((dmxDevicePrivPtr)dixLookupPrivate(&(_pDev)->devPrivates,	\
+					dmxDevicePrivateKey))
+
+void
+dmxInputInit (DMXInputInfo *dmxInput);
+
+void
+dmxInputLogDevices (void);
+
+Bool
+dmxInputEventCheck (DMXInputInfo        *dmxInput,
+		    xcb_generic_event_t *event);
+
+Bool
+dmxFakeMotion (DMXInputInfo *dmxInput,
+	       int          x,
+	       int          y);
+
+void
+dmxEndFakeMotion (DMXInputInfo *dmxInput);
+
+void
+dmxInputGrabKeyboard (DMXInputInfo *dmxInput,
+		      DeviceIntPtr pDevice,
+		      WindowPtr    pWindow);
+
+void
+dmxInputUngrabKeyboard (DMXInputInfo *dmxInput,
+			DeviceIntPtr pDevice,
+			WindowPtr    pWindow);
+
+void
+dmxInputGrabPointer (DMXInputInfo *dmxInput,
+		     DeviceIntPtr pDevice,
+		     WindowPtr    pWindow,
+		     WindowPtr    pConfineTo,
+		     CursorPtr    pCursor);
+
+void
+dmxInputUngrabPointer (DMXInputInfo *dmxInput,
+		       DeviceIntPtr pDevice,
+		       WindowPtr    pWindow);
+
+void
+dmxInputWarpPointer (DMXInputInfo *dmxInput,
+		     DeviceIntPtr pDevice,
+		     int          x,
+		     int          y);
+
+int
+dmxInputEnable (DMXInputInfo *dmxInput);
+
+int
+dmxInputDisable (DMXInputInfo *dmxInput);
+
+int
+dmxInputAttach (DMXInputInfo *dmxInput);
+
+int
+dmxInputDetach (DMXInputInfo *dmxInput);
+
+void
+dmxInputInit (DMXInputInfo *dmxInput);
+
+void
+dmxInputFini (DMXInputInfo *dmxInput);
+
 #endif /* DMXINPUT_H */
diff --git a/hw/dmx/dmxlaunch.c b/hw/dmx/dmxlaunch.c
new file mode 100644
index 0000000..4cab118
--- /dev/null
+++ b/hw/dmx/dmxlaunch.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright © 2005 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: David Reveman <davidr@novell.com>
+ *          Matthias Hopf <mhopf@suse.de>
+ */
+
+#include "dmx.h"
+#include "dmxlaunch.h"
+#include "dmxinit.h"
+#include "opaque.h"
+
+#include <X11/Xauth.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <libgen.h>
+#include <fcntl.h>
+
+typedef void (*sighandler_t) (int);
+
+#define XBE_DIE_TIMEOUT 3
+#define XBE_DEV_RANDOM  "/dev/urandom"
+
+static char xbeAuthBuf[256];
+static char *xbeAuthTempl = "/tmp/.Xdmx-auth-XXXXXX";
+static char *xbeAuth      = NULL;
+
+static char *xbeProgs[] = { "/var/X11R6/bin/Xbackend", "/usr/bin/X" };
+static char *xbeProg    = NULL;
+
+static char xbeDisplayBuf[256];
+static char *xbeDisplay      = NULL;
+static int  xbeDisplayOffset = 53;
+
+static pid_t   xbePid = 0;
+static int     receivedUsr1 = 0;
+static jmp_buf jumpbuf;
+
+static char **xbeArgv = 0;
+static int  nXbeArgv  = 0;
+
+static int
+dmxAddXbeArguments (char **argv,
+		    int  n)
+{
+    char **newArgv;
+    int  i;
+
+    newArgv = xrealloc (xbeArgv, sizeof (char *) * (nXbeArgv + n));
+    if (!newArgv)
+	return 0;
+
+    for (i = 0; i < n; i++)
+	newArgv[nXbeArgv + i] = argv[i];
+
+    xbeArgv   = newArgv;
+    nXbeArgv += n;
+
+    return n;
+}
+
+static void
+sigAlarm (int sig)
+{
+    ErrorF ("%s won't die, killing it\n", basename (xbeProg));
+
+    kill (xbePid, SIGKILL);
+    if (xbePid)
+	while (waitpid (xbePid, NULL, 0) == -1 && errno == EINTR);
+}
+
+void
+dmxAbortDisplay (void)
+{
+    sighandler_t oldSigAlarm;
+    unsigned int oldAlarm;
+    int          status = 0;
+    char	 *name;
+
+    if (!xbePid)
+	return;
+
+    name = basename (xbeProg);
+
+    oldAlarm    = alarm (0);
+    oldSigAlarm = signal (SIGALRM, sigAlarm);
+
+    kill (xbePid, SIGTERM);
+
+    alarm (XBE_DIE_TIMEOUT);
+    while (waitpid (xbePid, &status, 0) == -1 && errno == EINTR);
+    alarm (0);
+
+    signal (SIGALRM, oldSigAlarm);
+    alarm (oldAlarm);
+
+    if (WIFEXITED (status))
+    {
+	if (WEXITSTATUS (status))
+	    ErrorF ("%s died, exit status %d\n", name, WEXITSTATUS (status));
+    }
+    else if (WIFSIGNALED (status))
+	ErrorF ("%s died, signal %d\n", name, WTERMSIG (status));
+    else
+	ErrorF ("%s died, dubious exit\n", name);
+
+    if (xbeAuth)
+	unlink (xbeAuth);
+
+    xbePid = 0;
+}
+
+static void
+sigUsr1Waiting (int sig)
+{
+    signal (sig, sigUsr1Waiting);
+    receivedUsr1++;
+}
+
+static void
+sigUsr1Jump (int sig)
+{
+
+#ifdef SIG_BLOCK
+    sigset_t set;
+#endif
+
+    signal (sig, sigUsr1Waiting);
+
+#ifdef SIG_BLOCK
+    sigemptyset (&set);
+    sigaddset (&set, SIGUSR1);
+    sigprocmask (SIG_UNBLOCK, &set, NULL);
+#endif
+
+    longjmp (jumpbuf, 1);
+}
+
+#define AUTH_DATA_LEN 16 /* bytes of authorization data */
+
+static Bool
+dmxSetupAuth (char *name, int authFd)
+{
+    Xauth   auth;
+    int	    randomFd, i;
+    ssize_t bytes, size;
+    char    authHost[256];
+    char    authData[AUTH_DATA_LEN];
+    char    realProg[PATH_MAX], buf[PATH_MAX];
+    FILE    *file;
+    int     virtualFb = FALSE;
+
+    auth.family = FamilyLocal;
+
+    gethostname (authHost, sizeof (authHost));
+
+    auth.address	= authHost;
+    auth.address_length = strlen (authHost);
+
+    auth.number	= strrchr (xbeDisplay, ':');
+    if (!auth.number)
+    {
+	ErrorF ("Bad back-end X display name: %s\n", xbeDisplay);
+	return FALSE;
+    }
+
+    auth.number++;
+
+    auth.number_length = strlen (auth.number);
+    if (!auth.number_length)
+    {
+	ErrorF ("Bad back-end X display name: %s\n", xbeDisplay);
+	return FALSE;
+    }
+
+    auth.name	     = "MIT-MAGIC-COOKIE-1";
+    auth.name_length = strlen (auth.name);
+
+    randomFd = open (XBE_DEV_RANDOM, O_RDONLY);
+    if (randomFd == -1)
+    {
+	ErrorF ("Failed to open " XBE_DEV_RANDOM "\n");
+	return FALSE;
+    }
+
+    bytes = 0;
+    do {
+	size = read (randomFd, authData + bytes, AUTH_DATA_LEN - bytes);
+	if (size <= 0)
+	    break;
+
+	bytes += size;
+    } while (bytes != AUTH_DATA_LEN);
+
+    close (randomFd);
+
+    if (bytes != AUTH_DATA_LEN)
+    {
+	ErrorF ("Failed to read %d random bytes from " XBE_DEV_RANDOM "\n",
+		AUTH_DATA_LEN);
+	return FALSE;
+    }
+
+    auth.data	     = authData;
+    auth.data_length = AUTH_DATA_LEN;
+
+    file = fdopen (authFd, "w");
+    if (!file)
+    {
+	ErrorF ("Failed to open authorization file: %s\n", name);
+	close (authFd);
+	return FALSE;
+    }
+
+    XauWriteAuth (file, &auth);
+    fclose (file);
+
+    strcpy (realProg, xbeProg);
+
+#define MAX_SYMLINKS 32
+
+    for (i = 0; i < MAX_SYMLINKS; i++)
+    {
+	size = readlink (realProg, buf, sizeof (buf) - 1);
+	if (size == -1)
+	    break;
+	
+	memcpy (realProg, buf, size);
+	realProg[size] = '\0';
+    }
+
+    /* a bit hackish but very useful */
+    if (strcmp (basename (realProg), "Xvfb")  == 0 ||
+	strcmp (basename (realProg), "Xfake") == 0)
+	virtualFb = TRUE;
+    
+    dmxAddScreen (basename (realProg),
+		  xbeDisplay,
+		  auth.name,
+		  auth.name_length,
+		  auth.data,
+		  auth.data_length,
+		  virtualFb);
+
+    return TRUE;
+}
+
+Bool
+dmxLaunchDisplay (int argc, char *argv[], int index, char *vt)
+{
+    sighandler_t oldSigUsr1;
+    pid_t	 pid;
+    char	 *name;
+    char	 *auth[] = { "-auth", xbeAuthBuf };
+    char	 *defs[] = { "-terminate", "-nolisten", "tcp" };
+    char	 *endArg = NULL;
+    int		 authFd;
+    int		 mask;
+
+    if (xbePid)
+	return FALSE;
+
+    if (xbeArgv)
+    {
+	free (xbeArgv);
+	xbeArgv = NULL;
+	nXbeArgv = 0;
+    }
+
+    receivedUsr1 = 0;
+
+    strcpy (xbeAuthBuf, xbeAuthTempl);
+    mask = umask (0077);
+    authFd = mkstemp (xbeAuthBuf);
+    umask (mask);
+    if (authFd == -1)
+	FatalError ("Failed to generate unique authorization file\n");
+
+    xbeAuth = xbeAuthBuf;
+
+    if (index && index < argc)
+    {
+        xbeProg = argv[index];
+    }
+    else
+    {
+        struct stat buf;
+	int         i;
+
+	for (i = 0; i < sizeof (xbeProgs) / sizeof (char *); i++)
+	{
+	    if (stat (xbeProgs[i], &buf) == 0)
+	    {
+		xbeProg = xbeProgs[i];
+		break;
+	    }
+	}
+
+	if (!xbeProg)
+            FatalError ("Can't find X server executable\n");
+    }
+
+    if (!dmxAddXbeArguments (&xbeProg, 1))
+	return FALSE;
+
+    if (!dmxAddXbeArguments (auth, sizeof (auth) / sizeof (char *)))
+	return FALSE;
+
+    xbeDisplay = xbeDisplayBuf;
+    sprintf (xbeDisplay, ":%d", xbeDisplayOffset + atoi (display));
+    
+    if (index)
+    {
+	int i;
+
+	for (i = index + 1; i < argc; i++)
+	{
+	    if (*argv[i] == ':')
+	    {
+		xbeDisplay = argv[i];
+		break;
+	    }
+	}
+
+	if (i >= argc)
+	    if (!dmxAddXbeArguments (&xbeDisplay, 1))
+		return FALSE;
+
+        if (argc > index)
+            if (!dmxAddXbeArguments (&argv[index + 1], argc - index))
+                return FALSE;
+    }
+    else
+    {
+	if (!dmxAddXbeArguments (&xbeDisplay, 1))
+	    return FALSE;
+
+        if (!dmxAddXbeArguments (defs, sizeof (defs) / sizeof (char *)))
+            return FALSE;
+    }
+
+    if (vt)
+	if (!dmxAddXbeArguments (&vt, 1))
+	    return FALSE;
+
+    if (!dmxAddXbeArguments (&endArg, 1))
+	return FALSE;
+
+    name = basename (xbeProg);
+
+    if (!dmxSetupAuth (xbeAuth, authFd))
+	FatalError ("Failed to set up authorization: %s\n", xbeAuth);
+
+    oldSigUsr1 = signal (SIGUSR1, sigUsr1Waiting);
+
+    pid = fork ();
+
+    switch (pid) {
+    case -1:
+	perror ("fork");
+	FatalError ("fork");
+	break;
+    case 0:
+	signal (SIGUSR1, SIG_IGN);
+	execv (xbeArgv[0], xbeArgv);
+	perror (xbeArgv[0]);
+	exit (2);
+	break;
+    default:
+	xbePid = pid;
+	break;
+    }
+
+    for (;;)
+    {
+	int status;
+
+	signal (SIGUSR1, sigUsr1Waiting);
+	if (setjmp (jumpbuf))
+	    break;
+
+	signal (SIGUSR1, sigUsr1Jump);
+	if (receivedUsr1)
+	    break;
+
+	if (waitpid (xbePid, &status, 0) != -1)
+	{
+	    if (WIFEXITED (status))
+	    {
+                FatalError ("%s died, exit status %d\n", name,
+                            WEXITSTATUS (status));
+	    }
+	    else if (WIFSIGNALED (status))
+		FatalError ("%s died, signal %d\n", name, WTERMSIG (status));
+	    else
+		FatalError ("%s died, dubious exit\n", name);
+	}
+    }
+
+    signal (SIGUSR1, oldSigUsr1);
+
+    return TRUE;
+}
diff --git a/hw/dmx/dmxlaunch.h b/hw/dmx/dmxlaunch.h
new file mode 100644
index 0000000..beef622
--- /dev/null
+++ b/hw/dmx/dmxlaunch.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXLAUNCH_H
+#define DMXLAUNCH_H
+
+extern Bool dmxLaunchDisplay (int argc, char *argv[], int index, char *vt);
+extern void dmxAbortDisplay (void);
+
+#endif /* DMXLAUNCH_H */
diff --git a/hw/dmx/dmxlog.c b/hw/dmx/dmxlog.c
index 94b8035..69bee7a 100644
--- a/hw/dmx/dmxlog.c
+++ b/hw/dmx/dmxlog.c
@@ -124,21 +124,12 @@ static void dmxHeader(dmxLogLevel logLevel, DMXInputInfo *dmxInput,
     case dmxFatal:   type = "Fatal Error"; break;
     }
 
-    if (dmxInput && dmxScreen) {
-        ErrorF("(%s) dmx[i%d/%s;o%d/%s]: ", type,
-               dmxInput->inputIdx, dmxInput->name,
-               dmxScreen->index, dmxScreen->name);
-    } else if (dmxScreen) {
-        ErrorF("(%s) dmx[o%d/%s]: ", type,
-               dmxScreen->index, dmxScreen->name);
-    } else if (dmxInput) {
-        const char *pt = strchr(dmxInput->name, ',');
-        int        len = (pt
-                          ? (size_t)(pt-dmxInput->name)
-                          : strlen(dmxInput->name));
-
-        ErrorF("(%s) dmx[i%d/%*.*s]: ", type,
-               dmxInput->inputIdx, len, len, dmxInput->name);
+    if (dmxInput)
+	dmxScreen = (DMXScreenInfo *) dmxInput;
+
+    if (dmxScreen) {
+        ErrorF("(%s) dmx[o%d/%s/%s]: ", type,
+               dmxScreen->index, dmxScreen->display, dmxScreen->name);
     } else {
         ErrorF("(%s) dmx: ", type);
     }
diff --git a/hw/dmx/dmxpict.c b/hw/dmx/dmxpict.c
index 37dfa10..460cdff 100644
--- a/hw/dmx/dmxpict.c
+++ b/hw/dmx/dmxpict.c
@@ -64,27 +64,113 @@ static int (*dmxSaveRenderVector[RenderNumberRequests])(ClientPtr);
 
 
 static int dmxProcRenderCreateGlyphSet(ClientPtr client);
-static int dmxProcRenderFreeGlyphSet(ClientPtr client);
+static int dmxProcRenderReferenceGlyphSet(ClientPtr client);
 static int dmxProcRenderAddGlyphs(ClientPtr client);
 static int dmxProcRenderFreeGlyphs(ClientPtr client);
 static int dmxProcRenderCompositeGlyphs(ClientPtr client);
 static int dmxProcRenderSetPictureTransform(ClientPtr client);
 static int dmxProcRenderSetPictureFilter(ClientPtr client);
+static int dmxProcRenderChangePicture (ClientPtr client);
 #if 0
 /* FIXME: Not (yet) supported */
 static int dmxProcRenderCreateCursor(ClientPtr client);
 static int dmxProcRenderCreateAnimCursor(ClientPtr client);
 #endif
+static int dmxProcRenderCreateSolidFill (ClientPtr pClient);
+static int dmxProcRenderCreateLinearGradient (ClientPtr pClient);
+static int dmxProcRenderCreateRadialGradient (ClientPtr pClient);
+static int dmxProcRenderCreateConicalGradient (ClientPtr pClient);
 
-/** Catch errors that might occur when allocating Glyph Sets.  Errors
- *  are saved in dmxGlyphLastError for later handling. */
-static int dmxGlyphLastError;
-static int dmxGlyphErrorHandler(Display *dpy, XErrorEvent *ev)
+unsigned long DMX_GLYPHSET;
+unsigned long DMX_SOURCEPICT;
+
+static int
+dmxFreeGlyphSet (pointer value,
+		 XID     gid)
 {
-    dmxGlyphLastError = ev->error_code;
-    return 0;
+    GlyphSetPtr	glyphSet = (GlyphSetPtr) value;
+
+    if (glyphSet->refcnt <= 2) {
+	dmxGlyphPrivPtr  glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+	int              i;
+
+	for (i = 0; i < dmxNumScreens; i++) {
+	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	    if (dmxScreen->beDisplay) {
+		if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
+		    dmxSync(dmxScreen, FALSE);
+	    }
+	}
+
+        MAXSCREENSFREE(glyphPriv->glyphSets);
+    }
+
+    return FreeGlyphSet (value, gid);
 }
 
+static int
+dmxFreeSourcePict (pointer value,
+		   XID     gid)
+{
+    PicturePtr pPicture = (PicturePtr) value;
+
+    if (pPicture->refcnt <= 2) {
+	dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+	int            i;
+
+	for (i = 0; i < dmxNumScreens; i++) {
+	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	    if (dmxScreen->beDisplay)
+		dmxBEFreePicture (screenInfo.screens[i], pPicture);
+	}
+
+        MAXSCREENSFREE(pPictPriv->sourcePict);
+    }
+
+    return FreePicture (value, gid);
+}
+
+static Bool
+dmxRealizeGlyph (ScreenPtr pScreen,
+		 GlyphPtr  glyph)
+{
+    PictureScreenPtr ps  = GetPictureScreen (pScreen);
+    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
+    int              ret;
+
+    if (pScreen->myNum == 0)
+	*((PrivateRec **) dixLookupPrivateAddr (&(glyph)->devPrivates,
+						dmxGlyphPrivateKey)) = NULL;
+
+    DMX_UNWRAP (RealizeGlyph, dmxScreen, ps);
+    ret = (*ps->RealizeGlyph) (pScreen, glyph);
+    DMX_WRAP (RealizeGlyph, dmxRealizeGlyph, dmxScreen, ps);
+
+    return ret;
+}
+
+static void
+dmxUnrealizeGlyph (ScreenPtr pScreen,
+		   GlyphPtr  glyph)
+{
+    PictureScreenPtr ps = GetPictureScreen (pScreen);
+    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (pScreen->myNum == 0)
+    {
+	char *data;
+
+	data = dixLookupPrivate (&(glyph)->devPrivates, dmxGlyphPrivateKey);
+	if (data)
+	    xfree (data);
+    }
+
+    DMX_UNWRAP (UnrealizeGlyph, dmxScreen, ps);
+    (*ps->UnrealizeGlyph) (pScreen, glyph);
+    DMX_WRAP (UnrealizeGlyph, dmxUnrealizeGlyph, dmxScreen, ps);
+}
 
 /** Initialize the Proc Vector for the RENDER extension.  The functions
  *  here cannot be handled by the mi layer RENDER hooks either because
@@ -96,13 +182,16 @@ void dmxInitRender(void)
 {
     int i;
 
+    DMX_GLYPHSET = CreateNewResourceType (dmxFreeGlyphSet);
+    DMX_SOURCEPICT = CreateNewResourceType (dmxFreeSourcePict);
+
     for (i = 0; i < RenderNumberRequests; i++)
         dmxSaveRenderVector[i] = ProcRenderVector[i];
 
     ProcRenderVector[X_RenderCreateGlyphSet]
 	= dmxProcRenderCreateGlyphSet;
-    ProcRenderVector[X_RenderFreeGlyphSet]
-	= dmxProcRenderFreeGlyphSet;
+    ProcRenderVector[X_RenderReferenceGlyphSet]
+	= dmxProcRenderReferenceGlyphSet;
     ProcRenderVector[X_RenderAddGlyphs]
 	= dmxProcRenderAddGlyphs;
     ProcRenderVector[X_RenderFreeGlyphs]
@@ -117,6 +206,16 @@ void dmxInitRender(void)
 	= dmxProcRenderSetPictureTransform;
     ProcRenderVector[X_RenderSetPictureFilter]
 	= dmxProcRenderSetPictureFilter;
+    ProcRenderVector[X_RenderChangePicture]
+	= dmxProcRenderChangePicture;
+    ProcRenderVector[X_RenderCreateSolidFill] =
+	dmxProcRenderCreateSolidFill;
+    ProcRenderVector[X_RenderCreateLinearGradient] =
+	dmxProcRenderCreateLinearGradient;
+    ProcRenderVector[X_RenderCreateRadialGradient] =
+	dmxProcRenderCreateRadialGradient;
+    ProcRenderVector[X_RenderCreateConicalGradient] =
+	dmxProcRenderCreateConicalGradient;
 }
 
 /** Reset the Proc Vector for the RENDER extension back to the original
@@ -130,6 +229,245 @@ void dmxResetRender(void)
         ProcRenderVector[i] = dmxSaveRenderVector[i];
 }
 
+static int
+dmxVisualDepth (ScreenPtr pScreen, VisualPtr pVisual)
+{
+    DepthPtr pDepth;
+    int	     d, v;
+
+    for (d = 0; d < pScreen->numDepths; d++)
+    {
+	pDepth = &pScreen->allowedDepths[d];
+	for (v = 0; v < pDepth->numVids; v++)
+	    if (pDepth->vids[v] == pVisual->vid)
+		return pDepth->depth;
+    }
+
+    return 0;
+}
+
+typedef struct _dmxformatInit {
+    CARD32 format;
+    CARD8  depth;
+} dmxFormatInitRec, *dmxFormatInitPtr;
+
+static int
+dmxAddFormat (dmxFormatInitPtr formats,
+	      int	       nformat,
+	      CARD32	       format,
+	      CARD8	       depth)
+{
+    int	n;
+
+    for (n = 0; n < nformat; n++)
+	if (formats[n].format == format && formats[n].depth == depth)
+	    return nformat;
+
+    formats[nformat].format = format;
+    formats[nformat].depth = depth;
+
+    return ++nformat;
+}
+
+#define Mask(n)	((n) == 32 ? 0xffffffff : ((1 << (n)) - 1))
+
+static PictFormatPtr
+dmxCreateDefaultFormats (ScreenPtr pScreen, int *nformatp)
+{
+    int		     f, nformats = 0;
+    PictFormatPtr    pFormats;
+    dmxFormatInitRec formats[64];
+    CARD32	     format;
+    CARD8	     depth;
+    VisualPtr	     pVisual;
+    int		     v;
+    int		     bpp;
+    int		     r, g, b;
+    int		     d;
+    DepthPtr	     pDepth;
+
+    /* formats required by protocol */
+    formats[nformats].format = PICT_a1;
+    formats[nformats].depth = 1;
+    nformats++;
+    formats[nformats].format = PICT_a4;
+    formats[nformats].depth = 4;
+    nformats++;
+    formats[nformats].format = PICT_a8;
+    formats[nformats].depth = 8;
+    nformats++;
+    formats[nformats].format = PICT_a8r8g8b8;
+    formats[nformats].depth = 32;
+    nformats++;
+
+    /* now look through the depths and visuals adding other formats */
+    for (v = 0; v < pScreen->numVisuals; v++)
+    {
+	pVisual = &pScreen->visuals[v];
+	depth = dmxVisualDepth (pScreen, pVisual);
+	if (!depth || depth == 32)
+	    continue;
+
+	bpp = BitsPerPixel (depth);
+	switch (pVisual->class) {
+	case DirectColor:
+	case TrueColor:
+	    r = Ones (pVisual->redMask);
+	    g = Ones (pVisual->greenMask);
+	    b = Ones (pVisual->blueMask);
+	    if (pVisual->offsetBlue == 0 &&
+		pVisual->offsetGreen == b &&
+		pVisual->offsetRed == b + g)
+	    {
+		format = PICT_FORMAT (bpp, PICT_TYPE_ARGB, 0, r, g, b);
+		nformats = dmxAddFormat (formats, nformats, format, depth);
+	    }
+	    break;
+	case StaticColor:
+	case PseudoColor:
+	case StaticGray:
+	case GrayScale:
+	    break;
+	}
+    }
+
+    /*
+     * Walk supported depths and add useful Direct formats
+     */
+    for (d = 0; d < 0; d++)
+    {
+	pDepth = &pScreen->allowedDepths[d];
+	bpp = BitsPerPixel (pDepth->depth);
+	format = 0;
+	switch (bpp) {
+	case 16:
+	    /* depth 12 formats */
+	    if (pDepth->depth >= 12)
+	    {
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_x4r4g4b4, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_x4b4g4r4, pDepth->depth);
+	    }
+	    /* depth 15 formats */
+	    if (pDepth->depth >= 15)
+	    {
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_x1r5g5b5, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_x1b5g5r5, pDepth->depth);
+	    }
+	    /* depth 16 formats */
+	    if (pDepth->depth >= 16)
+	    {
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_a1r5g5b5, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_a1b5g5r5, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_r5g6b5, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_b5g6r5, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_a4r4g4b4, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_a4b4g4r4, pDepth->depth);
+	    }
+	    break;
+	case 24:
+	    if (pDepth->depth >= 24)
+	    {
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_r8g8b8, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_b8g8r8, pDepth->depth);
+	    }
+	    break;
+	case 32:
+	    if (pDepth->depth >= 24)
+	    {
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_x8r8g8b8, pDepth->depth);
+		nformats = dmxAddFormat (formats, nformats,
+					 PICT_x8b8g8r8, pDepth->depth);
+	    }
+	    break;
+	}
+    }
+
+
+    pFormats = (PictFormatPtr) xalloc (nformats * sizeof (PictFormatRec));
+    if (!pFormats)
+	return 0;
+    memset (pFormats, '\0', nformats * sizeof (PictFormatRec));
+    for (f = 0; f < nformats; f++)
+    {
+        pFormats[f].id = FakeClientID (0);
+	pFormats[f].depth = formats[f].depth;
+	format = formats[f].format;
+	pFormats[f].format = format;
+	switch (PICT_FORMAT_TYPE(format)) {
+	case PICT_TYPE_ARGB:
+	    pFormats[f].type = PictTypeDirect;
+
+	    pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+	    if (pFormats[f].direct.alphaMask)
+		pFormats[f].direct.alpha = (PICT_FORMAT_R(format) +
+					    PICT_FORMAT_G(format) +
+					    PICT_FORMAT_B(format));
+
+	    pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
+	    pFormats[f].direct.red = (PICT_FORMAT_G(format) +
+				      PICT_FORMAT_B(format));
+
+	    pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
+	    pFormats[f].direct.green = PICT_FORMAT_B(format);
+
+	    pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
+	    pFormats[f].direct.blue = 0;
+	    break;
+
+	case PICT_TYPE_ABGR:
+	    pFormats[f].type = PictTypeDirect;
+
+	    pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+	    if (pFormats[f].direct.alphaMask)
+		pFormats[f].direct.alpha = (PICT_FORMAT_B(format) +
+					    PICT_FORMAT_G(format) +
+					    PICT_FORMAT_R(format));
+
+	    pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
+	    pFormats[f].direct.blue = (PICT_FORMAT_G(format) +
+				       PICT_FORMAT_R(format));
+
+	    pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
+	    pFormats[f].direct.green = PICT_FORMAT_R(format);
+
+	    pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
+	    pFormats[f].direct.red = 0;
+	    break;
+
+	case PICT_TYPE_A:
+	    pFormats[f].type = PictTypeDirect;
+
+	    pFormats[f].direct.alpha = 0;
+	    pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+
+	    /* remaining fields already set to zero */
+	    break;
+
+	case PICT_TYPE_COLOR:
+	case PICT_TYPE_GRAY:
+	    pFormats[f].type = PictTypeIndexed;
+	    pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
+	    break;
+	}
+    }
+
+    *nformatp = nformats;
+    return pFormats;
+}
+
 /** Initialize the RENDER extension, allocate the picture privates and
  *  wrap mi function hooks.  If the shadow frame buffer is used, then
  *  call the appropriate fb initialization function. */
@@ -138,8 +476,12 @@ Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
     PictureScreenPtr  ps;
 
-    /* The shadow framebuffer only relies on FB to be initialized */
-    if (dmxShadowFB) return fbPictureInit(pScreen, formats, nformats);
+    if (!formats)
+    {
+	formats = dmxCreateDefaultFormats (pScreen, &nformats);
+	if (!formats)
+	    return FALSE;
+    }
 
     if (!miPictureInit(pScreen, formats, nformats))
 	return FALSE;
@@ -147,6 +489,12 @@ Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
     if (!dixRequestPrivate(dmxPictPrivateKey, sizeof(dmxPictPrivRec)))
 	return FALSE;
 
+    if (!dixRequestPrivate(dmxGlyphSetPrivateKey, sizeof(dmxGlyphPrivRec)))
+	return FALSE;
+
+    if (!dixRequestPrivate(dmxGlyphPrivateKey, 0))
+	return FALSE;
+
     ps = GetPictureScreen(pScreen);
 
     DMX_WRAP(CreatePicture,      dmxCreatePicture,      dmxScreen, ps);
@@ -167,6 +515,9 @@ Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
     DMX_WRAP(TriStrip,           dmxTriStrip,           dmxScreen, ps);
     DMX_WRAP(TriFan,             dmxTriFan,             dmxScreen, ps);
 
+    DMX_WRAP(RealizeGlyph,       dmxRealizeGlyph,       dmxScreen, ps);
+    DMX_WRAP(UnrealizeGlyph,     dmxUnrealizeGlyph,     dmxScreen, ps);
+
     return TRUE;
 }
 
@@ -184,7 +535,10 @@ static XRenderPictFormat *dmxFindFormat(DMXScreenInfo *dmxScreen,
     if (!pFmt || !dmxScreen->beDisplay) return pFormat;
 
     while (1) {
+	pFormat = NULL;
+	XLIB_PROLOGUE (dmxScreen);
 	pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
+	XLIB_EPILOGUE (dmxScreen);
 	if (!pFormat) break;
 
 	if (pFormat->type             != pFmt->type)             continue;
@@ -213,7 +567,9 @@ Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
     DMXScreenInfo   *dmxScreen = &dmxScreens[idx];
 
     if (glyphPriv->glyphSets[idx]) {
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
+	XLIB_EPILOGUE (dmxScreen);
 	glyphPriv->glyphSets[idx] = (GlyphSet)0;
 	return TRUE;
     }
@@ -228,25 +584,19 @@ int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet)
     DMXScreenInfo     *dmxScreen = &dmxScreens[idx];
     dmxGlyphPrivPtr    glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
     PictFormatPtr      pFmt      = glyphSet->format;
-    int              (*oldErrorHandler)(Display *, XErrorEvent *);
 
     pFormat = dmxFindFormat(dmxScreen, pFmt);
     if (!pFormat) {
 	return BadMatch;
     }
 
-    dmxGlyphLastError = 0;
-    oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
+    glyphPriv->glyphSets[idx] = None;
 
     /* Catch when this fails */
+    XLIB_PROLOGUE (dmxScreen);
     glyphPriv->glyphSets[idx]
 	= XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat);
-
-    XSetErrorHandler(oldErrorHandler);
-
-    if (dmxGlyphLastError) {
-	return dmxGlyphLastError;
-    }
+    XLIB_EPILOGUE (dmxScreen);
 
     return Success;
 }
@@ -273,68 +623,46 @@ static int dmxProcRenderCreateGlyphSet(ClientPtr client)
 	
 	glyphSet = SecurityLookupIDByType(client, stuff->gsid, GlyphSetType,
 					  DixDestroyAccess);
-	glyphPriv = xalloc(sizeof(dmxGlyphPrivRec));
-	if (!glyphPriv) return BadAlloc;
+	glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
         glyphPriv->glyphSets = NULL;
         MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
-	DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
+	memset (glyphPriv->glyphSets, 0,
+		sizeof (*glyphPriv->glyphSets) * MAXSCREENS);
+	glyphSet->refcnt++;
+	AddResource (stuff->gsid, DMX_GLYPHSET, glyphSet);
 
 	for (i = 0; i < dmxNumScreens; i++) {
 	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
-	    int beret;
 
-	    if (!dmxScreen->beDisplay) {
-		glyphPriv->glyphSets[i] = 0;
+	    if (!dmxScreen->beDisplay)
 		continue;
-	    }
-
-	    if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
-		int  j;
-
-		/* Free the glyph sets we've allocated thus far */
-		for (j = 0; j < i; j++)
-		    dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet);
-
-		/* Free the resource created by render */
-		FreeResource(stuff->gsid, RT_NONE);
 
-		return beret;
-	    }
+	    dmxBECreateGlyphSet (i, glyphSet);
+	    dmxSync (dmxScreen, FALSE);
 	}
     }
 
     return ret;
 }
 
-/** Free the previously allocated Glyph Sets for each screen. */
-static int dmxProcRenderFreeGlyphSet(ClientPtr client)
+static int dmxProcRenderReferenceGlyphSet (ClientPtr client)
 {
-    GlyphSetPtr  glyphSet;
-    REQUEST(xRenderFreeGlyphSetReq);
+    int ret;
+    REQUEST(xRenderReferenceGlyphSetReq);
 
-    REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
-    glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType,
-				      DixDestroyAccess);
-
-    if (glyphSet && glyphSet->refcnt == 1) {
-	dmxGlyphPrivPtr  glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
-	int              i;
+    ret = dmxSaveRenderVector[stuff->renderReqType](client);
 
-	for (i = 0; i < dmxNumScreens; i++) {
-	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
-	    
-	    if (dmxScreen->beDisplay) {
-		if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
-		    dmxSync(dmxScreen, FALSE);
-	    }
-	}
+    if (ret == Success)
+    {
+	GlyphSetPtr glyphSet;
 
-        MAXSCREENSFREE(glyphPriv->glyphSets);
-	xfree(glyphPriv);
-	DMX_SET_GLYPH_PRIV(glyphSet, NULL);
+	glyphSet = SecurityLookupIDByType (client, stuff->gsid, GlyphSetType,
+					   DixDestroyAccess);
+	glyphSet->refcnt++;
+	AddResource (stuff->gsid, DMX_GLYPHSET, glyphSet);
     }
 
-    return dmxSaveRenderVector[stuff->renderReqType](client);
+    return ret;
 }
 
 /** Add glyphs to the Glyph Set on each screen. */
@@ -354,7 +682,8 @@ static int dmxProcRenderAddGlyphs(ClientPtr client)
 	Glyph           *gidsCopy;
 	xGlyphInfo      *gi;
 	CARD8           *bits;
-	int              nbytes;
+	int              nbytes, size;
+	void		*data;
 
 	glyphSet = SecurityLookupIDByType(client, stuff->glyphset,
 					  GlyphSetType, DixReadAccess);
@@ -369,13 +698,42 @@ static int dmxProcRenderAddGlyphs(ClientPtr client)
 		  (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
 
         gidsCopy = xalloc(sizeof(*gidsCopy) * nglyphs);
-        for (i = 0; i < nglyphs; i++) gidsCopy[i] = gids[i];
+        for (i = 0; i < nglyphs; i++)
+	{
+	    GlyphPtr glyph;
+
+	    gidsCopy[i] = gids[i];
+
+	    size = gi[i].height * PixmapBytePad (gi[i].width,
+						 glyphSet->format->depth);
+	    if (size & 3)
+		size += 4 - (size & 3);
+
+	    glyph = FindGlyph (glyphSet, gids[i]);
+	    if (glyph)
+	    {
+		data = xalloc (size);
+		if (data)
+		{
+		    memcpy (data, bits, size);
+		    *((PrivateRec **)
+		      dixLookupPrivateAddr (&(glyph)->devPrivates,
+					    dmxGlyphPrivateKey)) = data;
+		}
+	    }
+
+	    bits += size;
+	}
+
+	bits = (CARD8 *)(gi + nglyphs);
 
 	/* FIXME: Will this ever fail? */
 	for (i = 0; i < dmxNumScreens; i++) {
 	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
 
 	    if (dmxScreen->beDisplay) {
+
+		XLIB_PROLOGUE (dmxScreen);
 		XRenderAddGlyphs(dmxScreen->beDisplay,
 				 glyphPriv->glyphSets[i],
 				 gidsCopy,
@@ -383,6 +741,7 @@ static int dmxProcRenderAddGlyphs(ClientPtr client)
 				 nglyphs,
 				 (char *)bits,
 				 nbytes);
+		XLIB_EPILOGUE (dmxScreen);
 		dmxSync(dmxScreen, FALSE);
 	    }
 	}
@@ -418,8 +777,10 @@ static int dmxProcRenderFreeGlyphs(ClientPtr client)
 		DMXScreenInfo *dmxScreen = &dmxScreens[i];
 
 		if (dmxScreen->beDisplay) {
+		    XLIB_PROLOGUE (dmxScreen);
 		    XRenderFreeGlyphs(dmxScreen->beDisplay,
 				      glyphPriv->glyphSets[i], gids, nglyphs);
+		    XLIB_EPILOGUE (dmxScreen);
 		    dmxSync(dmxScreen, FALSE);
 		}
 	    }
@@ -471,11 +832,7 @@ static int dmxProcRenderCompositeGlyphs(ClientPtr client)
 	GlyphSetPtr        glyphSet;
 	dmxGlyphPrivPtr    glyphPriv;
 
-	pSrc = SecurityLookupIDByType(client, stuff->src, PictureType,
-				      DixReadAccess);
-	pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
-	if (!pSrcPriv->pict)
-	    return ret;
+	Picture	           src = None;
 
 	pDst = SecurityLookupIDByType(client, stuff->dst, PictureType,
 				      DixWriteAccess);
@@ -486,6 +843,18 @@ static int dmxProcRenderCompositeGlyphs(ClientPtr client)
 	scrnNum = pDst->pDrawable->pScreen->myNum;
 	dmxScreen = &dmxScreens[scrnNum];
 
+	pSrc = SecurityLookupIDByType(client, stuff->src, PictureType,
+				      DixReadAccess);
+	pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+
+	if (pSrc->pDrawable)
+	    src = pSrcPriv->pict;
+	else
+	    src = pSrcPriv->sourcePict[scrnNum];
+
+	if (!src)
+	    return ret;
+
 	/* Note: If the back-end display has been detached, then it
 	 * should not be possible to reach here since the pSrcPriv->pict
 	 * and pDstPriv->pict will have already been set to 0.
@@ -578,30 +947,34 @@ static int dmxProcRenderCompositeGlyphs(ClientPtr client)
 	    }
 	}
 
+	XLIB_PROLOGUE (dmxScreen);
+
 	switch (stuff->renderReqType) {
 	case X_RenderCompositeGlyphs8:
 	    XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
-				  pSrcPriv->pict, pDstPriv->pict,
+				  src, pDstPriv->pict,
 				  pFormat,
 				  stuff->xSrc, stuff->ySrc,
 				  0, 0, elts, nelt);
 	    break;
 	case X_RenderCompositeGlyphs16:
 	    XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
-				   pSrcPriv->pict, pDstPriv->pict,
+				   src, pDstPriv->pict,
 				   pFormat,
 				   stuff->xSrc, stuff->ySrc,
 				   0, 0, (XGlyphElt16 *)elts, nelt);
 	    break;
 	case X_RenderCompositeGlyphs32:
 	    XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
-				   pSrcPriv->pict, pDstPriv->pict,
+				   src, pDstPriv->pict,
 				   pFormat,
 				   stuff->xSrc, stuff->ySrc,
 				   0, 0, (XGlyphElt32 *)elts, nelt);
 	    break;
 	}
 
+	XLIB_EPILOGUE (dmxScreen);
+
 	dmxSync(dmxScreen, FALSE);
 
 	xfree(elts);
@@ -624,27 +997,49 @@ static int dmxProcRenderSetPictureTransform(ClientPtr client)
     VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess,
 		   RenderErrBase + BadPicture);
 
+    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+    xform.matrix[0][0] = stuff->transform.matrix11;
+    xform.matrix[0][1] = stuff->transform.matrix12;
+    xform.matrix[0][2] = stuff->transform.matrix13;
+    xform.matrix[1][0] = stuff->transform.matrix21;
+    xform.matrix[1][1] = stuff->transform.matrix22;
+    xform.matrix[1][2] = stuff->transform.matrix23;
+    xform.matrix[2][0] = stuff->transform.matrix31;
+    xform.matrix[2][1] = stuff->transform.matrix32;
+    xform.matrix[2][2] = stuff->transform.matrix33;
+
     /* For the following to work with PanoramiX, it assumes that Render
      * wraps the ProcRenderVector after dmxRenderInit has been called.
      */
-    dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
-    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+    if (pPicture->pDrawable)
+    {
+	dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
+
+	if (pPictPriv->pict) {
+	    XLIB_PROLOGUE (dmxScreen);
+	    XRenderSetPictureTransform(dmxScreen->beDisplay,
+				       pPictPriv->pict,
+				       &xform);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+    }
+    else if (pPictPriv->sourcePict)
+    {
+	int i;
 
-    if (pPictPriv->pict) {
-	xform.matrix[0][0] = stuff->transform.matrix11;
-	xform.matrix[0][1] = stuff->transform.matrix12;
-	xform.matrix[0][2] = stuff->transform.matrix13;
-	xform.matrix[1][0] = stuff->transform.matrix21;
-	xform.matrix[1][1] = stuff->transform.matrix22;
-	xform.matrix[1][2] = stuff->transform.matrix23;
-	xform.matrix[2][0] = stuff->transform.matrix31;
-	xform.matrix[2][1] = stuff->transform.matrix32;
-	xform.matrix[2][2] = stuff->transform.matrix33;
-
-	XRenderSetPictureTransform(dmxScreen->beDisplay,
-				   pPictPriv->pict,
-				   &xform);
-	dmxSync(dmxScreen, FALSE);
+	for (i = 0; i < dmxNumScreens; i++) {
+	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	    if (pPictPriv->sourcePict[i])
+	    {
+		XLIB_PROLOGUE (dmxScreen);
+		XRenderSetPictureTransform(dmxScreen->beDisplay,
+					   pPictPriv->sourcePict[i],
+					   &xform);
+		XLIB_EPILOGUE (dmxScreen);
+	    }
+	}
     }
 
     return dmxSaveRenderVector[stuff->renderReqType](client);
@@ -668,25 +1063,267 @@ static int dmxProcRenderSetPictureFilter(ClientPtr client)
     /* For the following to work with PanoramiX, it assumes that Render
      * wraps the ProcRenderVector after dmxRenderInit has been called.
      */
-    dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
+    if (pPicture->pDrawable)
+    {
+	dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
+	pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+	if (pPictPriv->pict)
+	{
+	    char name[256];
+
+	    filter  = (char *)(stuff + 1);
+	    params  = (XFixed *)(filter + ((stuff->nbytes + 3) & ~3));
+	    nparams = ((XFixed *)stuff + client->req_len) - params;
+
+	    strncpy (name, filter, stuff->nbytes);
+	    name[stuff->nbytes] = '\0';
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    XRenderSetPictureFilter(dmxScreen->beDisplay,
+				    pPictPriv->pict,
+				    name,
+				    params,
+				    nparams);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+    }
+
+    return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+static int dmxProcRenderChangePicture(ClientPtr client)
+{
+    int ret;
+    REQUEST(xRenderChangePictureReq);
+
+    ret = dmxSaveRenderVector[stuff->renderReqType](client);
+
+    if (ret == Success && (stuff->mask & CPRepeat)) {
+	PicturePtr     pPicture;
+	dmxPictPrivPtr pPictPriv;
+	int            i;
+
+	pPicture = SecurityLookupIDByType(client, stuff->picture, PictureType,
+					  DixDestroyAccess);
+	pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+	if (pPictPriv->sourcePict)
+	{
+	    XRenderPictureAttributes attribs;
+
+	    attribs.repeat = pPicture->repeatType;
+
+	    for (i = 0; i < dmxNumScreens; i++) {
+		DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+		if (pPictPriv->sourcePict[i])
+		{
+		    XLIB_PROLOGUE (dmxScreen);
+		    XRenderChangePicture(dmxScreen->beDisplay,
+					 pPictPriv->sourcePict[i],
+					 CPRepeat, &attribs);
+		    XLIB_EPILOGUE (dmxScreen);
+		}
+	    }
+	}
+    }
+
+    return ret;
+}
+
+static int
+dmxGetSourceStops (SourcePictPtr pSourcePict,
+		   XFixed **stops,
+		   XRenderColor **colors)
+{
+    if (pSourcePict->gradient.nstops)
+    {
+	int i;
+
+	*stops = xalloc (pSourcePict->gradient.nstops * sizeof (XFixed));
+	*colors = xalloc (pSourcePict->gradient.nstops *
+			  sizeof (XRenderColor));
+
+	for (i = 0; i < pSourcePict->gradient.nstops; i++)
+	{
+	    (*stops)[i]  = pSourcePict->gradient.stops[i].x;
+	    (*colors)[i].red = pSourcePict->gradient.stops[i].color.red;
+	    (*colors)[i].green = pSourcePict->gradient.stops[i].color.green;
+	    (*colors)[i].blue = pSourcePict->gradient.stops[i].color.blue;
+	    (*colors)[i].alpha = pSourcePict->gradient.stops[i].color.alpha;
+	}
+    }
+    else
+    {
+	*stops = NULL;
+	*colors = NULL;
+    }
+
+    return pSourcePict->gradient.nstops;
+}
+
+static Picture
+dmxDoCreateSourcePicture (int idx, PicturePtr pPicture)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+    Picture       pict = None;
+
+    if (pPicture->pSourcePict)
+    {
+	SourcePictPtr pSourcePict = pPicture->pSourcePict;
+	XFixed *stops = NULL;
+	XRenderColor *colors = NULL;
+	int nstops = 0;
+
+	if (!dmxScreen->beDisplay)
+	    return 0;
+
+	switch (pSourcePict->type) {
+	case SourcePictTypeSolidFill: {
+	    XRenderColor c;
+
+	    c.alpha = (pSourcePict->solidFill.color & 0xff000000) >> 16;
+	    c.red   = (pSourcePict->solidFill.color & 0x00ff0000) >> 8;
+	    c.green = (pSourcePict->solidFill.color & 0x0000ff00) >> 0;
+	    c.blue  = (pSourcePict->solidFill.color & 0x000000ff) << 8;
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    pict = XRenderCreateSolidFill (dmxScreen->beDisplay, &c);
+	    XLIB_EPILOGUE (dmxScreen);
+	} break;
+	case SourcePictTypeLinear: {
+	    XLinearGradient l;
+
+	    l.p1.x = pSourcePict->linear.p1.x;
+	    l.p1.y = pSourcePict->linear.p1.y;
+	    l.p2.x = pSourcePict->linear.p2.x;
+	    l.p2.y = pSourcePict->linear.p2.y;
+
+	    nstops = dmxGetSourceStops (pSourcePict, &stops, &colors);
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    pict = XRenderCreateLinearGradient (dmxScreen->beDisplay, &l,
+						stops, colors, nstops);
+	    XLIB_EPILOGUE (dmxScreen);
+	} break;
+	case SourcePictTypeRadial: {
+	    XRadialGradient r;
+
+	    r.inner.x = pSourcePict->radial.c1.x;
+	    r.inner.y = pSourcePict->radial.c1.y;
+	    r.inner.radius = pSourcePict->radial.c1.radius;
+	    r.outer.x = pSourcePict->radial.c2.x;
+	    r.outer.y = pSourcePict->radial.c2.y;
+	    r.outer.radius = pSourcePict->radial.c2.radius;
+
+	    nstops = dmxGetSourceStops (pSourcePict, &stops, &colors);
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    pict = XRenderCreateRadialGradient (dmxScreen->beDisplay, &r,
+						stops, colors, nstops);
+	    XLIB_EPILOGUE (dmxScreen);
+	} break;
+	case SourcePictTypeConical: {
+	    XConicalGradient c;
+
+	    c.center.x = pSourcePict->conical.center.x;
+	    c.center.y = pSourcePict->conical.center.y;
+	    c.angle = pSourcePict->conical.angle;
+
+	    nstops = dmxGetSourceStops (pSourcePict, &stops, &colors);
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    pict = XRenderCreateConicalGradient (dmxScreen->beDisplay, &c,
+						 stops, colors, nstops);
+	    XLIB_EPILOGUE (dmxScreen);
+	} break;
+	}
+
+	if (nstops)
+	{
+	    xfree (stops);
+	    xfree (colors);
+	}
+    }
+
+    return pict;
+}
+
+static int dmxCreateSourcePicture(ClientPtr client, XID pid)
+{
+    PicturePtr     pPicture;
+    dmxPictPrivPtr pPictPriv;
+    int            i;
+
+    pPicture = SecurityLookupIDByType(client, pid, PictureType,
+				      DixDestroyAccess);
     pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+    MAXSCREENSALLOC_RETURN(pPictPriv->sourcePict, BadAlloc);
+    memset (pPictPriv->sourcePict, 0,
+	    sizeof (*pPictPriv->sourcePict) * MAXSCREENS);
+    pPictPriv->pict = (Picture) 0;
+    AddResource (pid, DMX_SOURCEPICT, pPicture);
+    pPicture->refcnt++;
 
-    if (pPictPriv->pict) {
-	filter  = (char *)(stuff + 1);
-	params  = (XFixed *)(filter + ((stuff->nbytes + 3) & ~3));
-	nparams = ((XFixed *)stuff + client->req_len) - params;
-
-	XRenderSetPictureFilter(dmxScreen->beDisplay,
-				pPictPriv->pict,
-				filter,
-				params,
-				nparams);
-	dmxSync(dmxScreen, FALSE);
+    for (i = 0; i < dmxNumScreens; i++) {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	if (!dmxScreen->beDisplay)
+	    continue;
+
+	pPictPriv->sourcePict[i] = dmxDoCreateSourcePicture (i, pPicture);
     }
 
-    return dmxSaveRenderVector[stuff->renderReqType](client);
+    return Success;
+}
+
+static int dmxProcRenderCreateSolidFill (ClientPtr client)
+{
+    int ret;
+    REQUEST(xRenderCreateSolidFillReq);
+
+    ret = dmxSaveRenderVector[stuff->renderReqType](client);
+    if (ret != Success)
+	return ret;
+
+    return dmxCreateSourcePicture (client, stuff->pid);
+}
+
+static int dmxProcRenderCreateLinearGradient (ClientPtr client)
+{
+    int ret;
+    REQUEST(xRenderCreateLinearGradientReq);
+
+    ret = dmxSaveRenderVector[stuff->renderReqType](client);
+    if (ret != Success)
+	return ret;
+
+    return dmxCreateSourcePicture (client, stuff->pid);
 }
 
+static int dmxProcRenderCreateRadialGradient (ClientPtr client)
+{
+    int ret;
+    REQUEST(xRenderCreateRadialGradientReq);
+
+    ret = dmxSaveRenderVector[stuff->renderReqType](client);
+    if (ret != Success)
+	return ret;
+
+    return dmxCreateSourcePicture (client, stuff->pid);
+}
+
+static int dmxProcRenderCreateConicalGradient (ClientPtr client)
+{
+    int ret;
+    REQUEST(xRenderCreateConicalGradientReq);
+
+    ret = dmxSaveRenderVector[stuff->renderReqType](client);
+    if (ret != Success)
+	return ret;
+
+    return dmxCreateSourcePicture (client, stuff->pid);
+}
 
 /** Create a picture on the appropriate screen.  This is the actual
  *  function that creates the picture.  However, if the associated
@@ -698,9 +1335,10 @@ static Picture dmxDoCreatePicture(PicturePtr pPicture)
     ScreenPtr                 pScreen   = pDraw->pScreen;
     DMXScreenInfo            *dmxScreen = &dmxScreens[pScreen->myNum];
     XRenderPictFormat        *pFormat;
-    Drawable                  draw;
+    Drawable                 draw;
+    Picture pict = 0;
 
-    if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
+    if (pDraw->type == DRAWABLE_WINDOW) {
 	dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw));
 
 	if (!(draw = pWinPriv->window)) {
@@ -729,7 +1367,11 @@ static Picture dmxDoCreatePicture(PicturePtr pPicture)
 
     pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
 
-    return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
+    XLIB_PROLOGUE (dmxScreen);
+    pict = XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
+    XLIB_EPILOGUE (dmxScreen);
+
+    return pict;
 }
 
 /** Create a list of pictures.  This function is called by
@@ -753,15 +1395,47 @@ void dmxCreatePictureList(WindowPtr pWindow)
 }
 
 /** Create \a pPicture on the backend. */
-int dmxBECreatePicture(PicturePtr pPicture)
+int dmxBECreatePicture(int idx, PicturePtr pPicture)
 {
     dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 
-    /* Create picutre on BE */
-    pPictPriv->pict = dmxDoCreatePicture(pPicture);
+    /* Create picture on BE */
+    if (pPicture->pDrawable)
+    {
+	pPictPriv->pict = dmxDoCreatePicture(pPicture);
 
-    /* Flush changes to the backend server */
-    dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1);
+	/* Flush changes to the backend server */
+	dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1);
+    }
+    else
+    {
+	pPictPriv->sourcePict[idx] = dmxDoCreateSourcePicture(idx, pPicture);
+	if (pPictPriv->sourcePict[idx])
+	{
+	    DMXScreenInfo            *dmxScreen = &dmxScreens[idx];
+	    XRenderPictureAttributes attribs;
+	    XTransform		     xform;
+	    int                      i, j;
+
+	    attribs.repeat = pPicture->repeatType;
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    XRenderChangePicture(dmxScreen->beDisplay,
+				 pPictPriv->sourcePict[idx],
+				 CPRepeat, &attribs);
+	    XLIB_EPILOGUE (dmxScreen);
+
+	    for (i = 0; i < 3; i++)
+		for (j = 0; j < 3; j++)
+		    xform.matrix[i][j] = pPicture->transform->matrix[i][j];
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    XRenderSetPictureTransform(dmxScreen->beDisplay,
+				       pPictPriv->sourcePict[idx],
+				       &xform);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+    }
 
     return Success;
 }
@@ -784,7 +1458,8 @@ int dmxCreatePicture(PicturePtr pPicture)
 #endif
 
     /* Create picture on back-end server */
-    pPictPriv->pict      = dmxDoCreatePicture(pPicture);
+    pPictPriv->pict = dmxDoCreatePicture(pPicture);
+    pPictPriv->sourcePict = NULL;
     pPictPriv->savedMask = 0;
 
     DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
@@ -793,17 +1468,27 @@ int dmxCreatePicture(PicturePtr pPicture)
 }
 
 /** Destroy \a pPicture on the back-end server. */
-Bool dmxBEFreePicture(PicturePtr pPicture)
+Bool dmxBEFreePicture(ScreenPtr pScreen, PicturePtr pPicture)
 {
-    ScreenPtr      pScreen   = pPicture->pDrawable->pScreen;
     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
 
     if (pPictPriv->pict) {
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
+	XLIB_EPILOGUE (dmxScreen);
 	pPictPriv->pict = (Picture)0;
 	return TRUE;
     }
+    if (pPictPriv->sourcePict) {
+	if (pPictPriv->sourcePict[pScreen->myNum]) {
+	    XLIB_PROLOGUE (dmxScreen);
+	    XRenderFreePicture(dmxScreen->beDisplay,
+			       pPictPriv->sourcePict[pScreen->myNum]);
+	    XLIB_EPILOGUE (dmxScreen);
+	    pPictPriv->sourcePict[pScreen->myNum] = (Picture) 0;
+	}
+    }
 
     return FALSE;
 }
@@ -817,7 +1502,7 @@ Bool dmxDestroyPictureList(WindowPtr pWindow)
     Bool        ret      = FALSE;
 
     while (pPicture) {
-	ret |= dmxBEFreePicture(pPicture);
+	ret |= dmxBEFreePicture(pWindow->drawable.pScreen, pPicture);
 	pPicture = pPicture->pNext;
     }
 
@@ -836,7 +1521,7 @@ void dmxDestroyPicture(PicturePtr pPicture)
     DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
 
     /* Destroy picture on back-end server */
-    if (dmxBEFreePicture(pPicture))
+    if (dmxBEFreePicture(pScreen, pPicture))
 	dmxSync(dmxScreen, FALSE);
 
 #if 1
@@ -868,8 +1553,10 @@ int dmxChangePictureClip(PicturePtr pPicture, int clipType,
 	 */
 	if (clipType == CT_NONE) {
 	    /* Disable clipping, show all */
+	    XLIB_PROLOGUE (dmxScreen);
 	    XFixesSetPictureClipRegion(dmxScreen->beDisplay,
 				       pPictPriv->pict, 0, 0, None);
+	    XLIB_EPILOGUE (dmxScreen);
 	} else if (pPicture->clientClip) {
 	    RegionPtr   pClip = pPicture->clientClip;
 	    BoxPtr      pBox  = REGION_RECTS(pClip);
@@ -890,16 +1577,20 @@ int dmxChangePictureClip(PicturePtr pPicture, int clipType,
 		pRect++;
 	    }
 
+	    XLIB_PROLOGUE (dmxScreen);
 	    XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
 					    pPictPriv->pict,
 					    0, 0,
 					    pRects,
 					    nRects);
+	    XLIB_EPILOGUE (dmxScreen);
 	    xfree(pRects);
 	} else {
+	    XLIB_PROLOGUE (dmxScreen);
 	    XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
 					    pPictPriv->pict,
 					    0, 0, NULL, 0);
+	    XLIB_EPILOGUE (dmxScreen);
 	}
 	dmxSync(dmxScreen, FALSE);
     } else {
@@ -927,9 +1618,11 @@ void dmxDestroyPictureClip(PicturePtr pPicture)
 
     /* Destroy picture clip rects on back-end server */
     if (pPictPriv->pict) {
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
 					pPictPriv->pict,
 					0, 0, NULL, 0);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     } else {
 	/* FIXME: Handle destroying clip region when offscreen */
@@ -1017,9 +1710,10 @@ void dmxValidatePicture(PicturePtr pPicture, Mask mask)
 	if (mask & CPComponentAlpha)
 	    attribs.component_alpha = pPicture->componentAlpha;
 
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
 			     mask, &attribs);
-	dmxSync(dmxScreen, FALSE);
+	XLIB_EPILOGUE (dmxScreen);
     } else {
 	pPictPriv->savedMask |= mask;
     }
@@ -1047,11 +1741,22 @@ void dmxComposite(CARD8 op,
     ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
     PictureScreenPtr  ps        = GetPictureScreen(pScreen);
-    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
-    dmxPictPrivPtr    pMaskPriv = NULL;
     dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
-
-    if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask);
+    Picture	      src = None;
+    Picture	      mask = None;
+
+    if (pSrc->pDrawable)
+	src = (DMX_GET_PICT_PRIV (pSrc))->pict;
+    else
+	src = (DMX_GET_PICT_PRIV (pSrc))->sourcePict[pScreen->myNum];
+
+    if (pMask)
+    {
+	if (pMask->pDrawable)
+	    mask = (DMX_GET_PICT_PRIV (pMask))->pict;
+	else
+	    mask = (DMX_GET_PICT_PRIV (pMask))->sourcePict[pScreen->myNum];
+    }
 
     DMX_UNWRAP(Composite, dmxScreen, ps);
 #if 0
@@ -1062,21 +1767,22 @@ void dmxComposite(CARD8 op,
 #endif
 
     /* Composite on back-end server */
-    if (pSrcPriv->pict && pDstPriv->pict &&
-	((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
+    if (src && pDstPriv->pict)
+    {
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderComposite(dmxScreen->beDisplay,
 			 op,
-			 pSrcPriv->pict,
-			 pMaskPriv ? pMaskPriv->pict : None,
+			 src,
+			 mask,
 			 pDstPriv->pict,
 			 xSrc, ySrc,
 			 xMask, yMask,
 			 xDst, yDst,
 			 width, height);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
-
     DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
 }
 
@@ -1114,12 +1820,14 @@ void dmxCompositeRects(CARD8 op,
 
     /* CompositeRects on back-end server */
     if (pPictPriv->pict) {
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderFillRectangles(dmxScreen->beDisplay,
 			      op,
 			      pPictPriv->pict,
 			      (XRenderColor *)color,
 			      (XRectangle *)rects,
 			      nRect);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
@@ -1154,8 +1862,8 @@ void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
     ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
     PictureScreenPtr  ps        = GetPictureScreen(pScreen);
-    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
     dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
+    Picture	      src = None;
 
     DMX_UNWRAP(Trapezoids, dmxScreen, ps);
 #if 0
@@ -1163,6 +1871,11 @@ void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
 #endif
 
+    if (pSrc->pDrawable)
+	src = (DMX_GET_PICT_PRIV (pSrc))->pict;
+    else
+	src = (DMX_GET_PICT_PRIV (pSrc))->sourcePict[pScreen->myNum];
+
     /* Draw trapezoids on back-end server */
     if (pDstPriv->pict) {
 	XRenderPictFormat *pFormat;
@@ -1172,14 +1885,16 @@ void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	    /* FIXME: Error! */
 	}
 
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderCompositeTrapezoids(dmxScreen->beDisplay,
 				   op,
-				   pSrcPriv->pict,
+				   src,
 				   pDstPriv->pict,
 				   pFormat,
 				   xSrc, ySrc,
 				   (XTrapezoid *)traps,
 				   ntrap);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
@@ -1197,8 +1912,8 @@ void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
     ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
     PictureScreenPtr  ps        = GetPictureScreen(pScreen);
-    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
     dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
+    Picture	      src = None;
 
     DMX_UNWRAP(Triangles, dmxScreen, ps);
 #if 0
@@ -1206,6 +1921,11 @@ void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
 #endif
 
+    if (pSrc->pDrawable)
+	src = (DMX_GET_PICT_PRIV (pSrc))->pict;
+    else
+	src = (DMX_GET_PICT_PRIV (pSrc))->sourcePict[pScreen->myNum];
+
     /* Draw trapezoids on back-end server */
     if (pDstPriv->pict) {
 	XRenderPictFormat *pFormat;
@@ -1215,14 +1935,16 @@ void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	    /* FIXME: Error! */
 	}
 
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderCompositeTriangles(dmxScreen->beDisplay,
 				  op,
-				  pSrcPriv->pict,
+				  src,
 				  pDstPriv->pict,
 				  pFormat,
 				  xSrc, ySrc,
 				  (XTriangle *)tris,
 				  ntri);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
@@ -1240,8 +1962,8 @@ void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
     ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
     PictureScreenPtr  ps        = GetPictureScreen(pScreen);
-    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
     dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
+    Picture	      src = None;
 
     DMX_UNWRAP(TriStrip, dmxScreen, ps);
 #if 0
@@ -1249,6 +1971,11 @@ void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
 #endif
 
+    if (pSrc->pDrawable)
+	src = (DMX_GET_PICT_PRIV (pSrc))->pict;
+    else
+	src = (DMX_GET_PICT_PRIV (pSrc))->sourcePict[pScreen->myNum];
+
     /* Draw trapezoids on back-end server */
     if (pDstPriv->pict) {
 	XRenderPictFormat *pFormat;
@@ -1258,14 +1985,16 @@ void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	    /* FIXME: Error! */
 	}
 
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderCompositeTriStrip(dmxScreen->beDisplay,
 				 op,
-				 pSrcPriv->pict,
+				 src,
 				 pDstPriv->pict,
 				 pFormat,
 				 xSrc, ySrc,
 				 (XPointFixed *)points,
 				 npoint);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
@@ -1282,8 +2011,8 @@ void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
     ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
     DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
     PictureScreenPtr  ps        = GetPictureScreen(pScreen);
-    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
     dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
+    Picture	      src = None;
 
     DMX_UNWRAP(TriFan, dmxScreen, ps);
 #if 0
@@ -1291,6 +2020,11 @@ void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
 #endif
 
+    if (pSrc->pDrawable)
+	src = (DMX_GET_PICT_PRIV (pSrc))->pict;
+    else
+	src = (DMX_GET_PICT_PRIV (pSrc))->sourcePict[pScreen->myNum];
+
     /* Draw trapezoids on back-end server */
     if (pDstPriv->pict) {
 	XRenderPictFormat *pFormat;
@@ -1300,14 +2034,16 @@ void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 	    /* FIXME: Error! */
 	}
 
+	XLIB_PROLOGUE (dmxScreen);
 	XRenderCompositeTriFan(dmxScreen->beDisplay,
 			       op,
-			       pSrcPriv->pict,
+			       src,
 			       pDstPriv->pict,
 			       pFormat,
 			       xSrc, ySrc,
 			       (XPointFixed *)points,
 			       npoint);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 
diff --git a/hw/dmx/dmxpict.h b/hw/dmx/dmxpict.h
index a81eb7d..7c968d6 100644
--- a/hw/dmx/dmxpict.h
+++ b/hw/dmx/dmxpict.h
@@ -46,6 +46,7 @@ typedef struct _dmxPictPriv {
     Picture  pict;		/**< Picture ID from back-end server */
     Mask     savedMask;         /**< Mask of picture attributes saved for
 				 *   lazy window creation. */
+    Picture  *sourcePict;
 } dmxPictPrivRec, *dmxPictPrivPtr;
 
 
@@ -113,20 +114,17 @@ extern void dmxTriFan(CARD8 op,
 
 extern int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet);
 extern Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet);
-extern int dmxBECreatePicture(PicturePtr pPicture);
-extern Bool dmxBEFreePicture(PicturePtr pPicture);
+extern int dmxBECreatePicture(int idx, PicturePtr pPicture);
+extern Bool dmxBEFreePicture(ScreenPtr pScreen, PicturePtr pPicture);
 
 extern DevPrivateKey dmxPictPrivateKey;	/**< Index for picture private data */
 extern DevPrivateKey dmxGlyphSetPrivateKey; /**< Index for glyphset private data */
-
+extern DevPrivateKey dmxGlyphPrivateKey; /**< Index for glyph private data */
 
 /** Get the picture private data given a picture pointer */
 #define DMX_GET_PICT_PRIV(_pPict)					\
     (dmxPictPrivPtr)dixLookupPrivate(&(_pPict)->devPrivates, dmxPictPrivateKey)
 
-/** Set the glyphset private data given a glyphset pointer */
-#define DMX_SET_GLYPH_PRIV(_pGlyph, _pPriv)				\
-    GlyphSetSetPrivate((_pGlyph), dmxGlyphSetPrivateKey, (_pPriv))
 /** Get the glyphset private data given a glyphset pointer */
 #define DMX_GET_GLYPH_PRIV(_pGlyph)					\
     (dmxGlyphPrivPtr)GlyphSetGetPrivate((_pGlyph), dmxGlyphSetPrivateKey)
diff --git a/hw/dmx/dmxpixmap.c b/hw/dmx/dmxpixmap.c
index 6622403..40b4834 100644
--- a/hw/dmx/dmxpixmap.c
+++ b/hw/dmx/dmxpixmap.c
@@ -70,11 +70,13 @@ void dmxBECreatePixmap(PixmapPtr pPixmap)
 	return;
 
     if (pPixmap->drawable.width && pPixmap->drawable.height) {
+	XLIB_PROLOGUE (dmxScreen);
 	pPixPriv->pixmap = XCreatePixmap(dmxScreen->beDisplay,
 					 dmxScreen->scrnWin,
 					 pPixmap->drawable.width,
 					 pPixmap->drawable.height,
 					 pPixmap->drawable.depth);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, FALSE);
     }
 }
@@ -122,9 +124,13 @@ PixmapPtr dmxCreatePixmap(ScreenPtr pScreen, int width, int height, int depth,
     pPixPriv->pixmap = (Pixmap)0;
     pPixPriv->detachedImage = NULL;
 
-    /* Create the pixmap on the back-end server */
-    if (dmxScreen->beDisplay) {
-	dmxBECreatePixmap(pPixmap);
+    if (usage_hint != CREATE_PIXMAP_USAGE_GLYPH_PICTURE &&
+	usage_hint != CREATE_PIXMAP_USAGE_BACKING_PIXMAP)
+    {
+	/* Create the pixmap on the back-end server */
+	if (dmxScreen->beDisplay) {
+	    dmxBECreatePixmap(pPixmap);
+	}
     }
 
 #if 0
@@ -142,7 +148,9 @@ Bool dmxBEFreePixmap(PixmapPtr pPixmap)
     dmxPixPrivPtr  pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
 
     if (pPixPriv->pixmap) {
+	XLIB_PROLOGUE (dmxScreen);
 	XFreePixmap(dmxScreen->beDisplay, pPixPriv->pixmap);
+	XLIB_EPILOGUE (dmxScreen);
 	pPixPriv->pixmap = (Pixmap)0;
 	return TRUE;
     }
@@ -150,6 +158,15 @@ Bool dmxBEFreePixmap(PixmapPtr pPixmap)
     return FALSE;
 }
 
+static Bool FoundPix = False;
+
+static void findPixmap (pointer value, XID id, RESTYPE type, pointer p)
+{
+    if ((type & TypeMask) == (RT_PIXMAP & TypeMask))
+	if ((PixmapPtr) p == (PixmapPtr) value)
+	    FoundPix = True;
+}
+
 /** Destroy the pixmap pointed to by \a pPixmap. */
 Bool dmxDestroyPixmap(PixmapPtr pPixmap)
 {
@@ -162,8 +179,45 @@ Bool dmxDestroyPixmap(PixmapPtr pPixmap)
 #endif
 
     if (--pPixmap->refcnt)
+    {
+	int i;
+
 	return TRUE;
 
+	FoundPix = False;
+	for (i = currentMaxClients; --i >= 0; )
+	    if (clients[i])
+		FindAllClientResources (clients[i], findPixmap,
+					(pointer) pPixmap);
+
+	if (!FoundPix)
+	{
+	    dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV (pPixmap);
+
+	    if (!pPixPriv->detachedImage)
+	    {
+		ScreenPtr      pScreen   = pPixmap->drawable.pScreen;
+		DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+		pPixPriv->detachedImage = NULL;
+
+		XLIB_PROLOGUE (dmxScreen);
+		pPixPriv->detachedImage = XGetImage(dmxScreen->beDisplay,
+						    pPixPriv->pixmap,
+						    0, 0,
+						    pPixmap->drawable.width,
+						    pPixmap->drawable.height,
+						    -1,
+						    ZPixmap);
+		XLIB_EPILOGUE (dmxScreen);
+		if (!pPixPriv->detachedImage)
+		    ErrorF ("Cannot save pixmap image\n");
+	    }
+	}
+
+	return TRUE;
+    }
+
     /* Destroy pixmap on back-end server */
     if (dmxScreen->beDisplay) {
 	if (dmxBEFreePixmap(pPixmap)) {
@@ -193,7 +247,7 @@ RegionPtr dmxBitmapToRegion(PixmapPtr pPixmap)
     ScreenPtr      pScreen = pPixmap->drawable.pScreen;
     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
     dmxPixPrivPtr  pPixPriv = DMX_GET_PIXMAP_PRIV(pPixmap);
-    XImage        *ximage;
+    XImage        *ximage = NULL;
     RegionPtr      pReg, pTmpReg;
     int            x, y;
     unsigned long  previousPixel, currentPixel;
@@ -205,9 +259,13 @@ RegionPtr dmxBitmapToRegion(PixmapPtr pPixmap)
 	return pReg;
     }
 
+    XLIB_PROLOGUE (dmxScreen);
     ximage = XGetImage(dmxScreen->beDisplay, pPixPriv->pixmap, 0, 0,
 		       pPixmap->drawable.width, pPixmap->drawable.height,
 		       1, XYPixmap);
+    XLIB_EPILOGUE (dmxScreen);
+    if (!ximage)
+	return NullRegion;
 
     pReg = REGION_CREATE(pScreen, NullBox, 1);
     pTmpReg = REGION_CREATE(pScreen, NullBox, 1);
@@ -219,6 +277,7 @@ RegionPtr dmxBitmapToRegion(PixmapPtr pPixmap)
     for (y = 0; y < pPixmap->drawable.height; y++) {
 	Box.y1 = y;
 	Box.y2 = y + 1;
+	Box.x1 = 0;
 	previousPixel = 0L;
 	for (x = 0; x < pPixmap->drawable.width; x++) {
 	    currentPixel = XGetPixel(ximage, x, y);
@@ -251,3 +310,94 @@ RegionPtr dmxBitmapToRegion(PixmapPtr pPixmap)
     dmxSync(dmxScreen, FALSE);
     return(pReg);
 }
+
+Bool
+dmxModifyPixmapHeader (PixmapPtr pPixmap,
+		       int	 width,
+		       int	 height,
+		       int	 depth,
+		       int	 bitsPerPixel,
+		       int	 devKind,
+		       pointer	 pPixData)
+{
+    ScreenPtr     pScreen = pPixmap->drawable.pScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    int           oldWidth, oldHeight, oldDepth;
+    Bool          status;
+
+    oldWidth  = pPixmap->drawable.width;
+    oldHeight = pPixmap->drawable.height;
+    oldDepth  = pPixmap->drawable.depth;
+
+    DMX_UNWRAP (ModifyPixmapHeader, dmxScreen, pScreen);
+    status = (*pScreen->ModifyPixmapHeader) (pPixmap,
+					     width,
+					     height,
+					     depth,
+					     bitsPerPixel,
+					     devKind,
+					     pPixData);
+    DMX_WRAP (ModifyPixmapHeader, dmxModifyPixmapHeader, dmxScreen, pScreen);
+
+    if (!status)
+	return FALSE;
+
+    if (pPixmap->drawable.width  != oldWidth  ||
+	pPixmap->drawable.height != oldHeight ||
+	pPixmap->drawable.depth  != oldDepth)
+    {
+	dmxBEFreePixmap (pPixmap);
+    }
+
+    if (pPixData && dmxScreen->beDisplay)
+    {
+	dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV (pPixmap);
+	XlibGC        gc = NULL;
+	unsigned long m;
+	XGCValues     v;
+	XImage        ximage;
+
+	ximage.width = pPixmap->drawable.width;
+	ximage.height = pPixmap->drawable.height;
+	ximage.format = ZPixmap;
+	ximage.byte_order = IMAGE_BYTE_ORDER;
+	ximage.bitmap_unit = 32;
+	ximage.bitmap_bit_order = BITMAP_BIT_ORDER;
+	ximage.bitmap_pad = 32;
+	ximage.depth = pPixmap->drawable.depth;
+	ximage.red_mask = 0;
+	ximage.green_mask = 0;
+	ximage.blue_mask = 0;
+	ximage.xoffset = 0;
+	ximage.bits_per_pixel = pPixmap->drawable.bitsPerPixel;
+	ximage.bytes_per_line = pPixmap->devKind;
+	ximage.data = (char *) pPixData;
+
+	XInitImage (&ximage);
+
+	dmxBECreatePixmap (pPixmap);
+
+	m = GCFunction | GCPlaneMask | GCClipMask;
+
+	v.function   = GXcopy;
+	v.plane_mask = AllPlanes;
+	v.clip_mask  = None;
+
+	XLIB_PROLOGUE (dmxScreen);
+	gc = XCreateGC (dmxScreen->beDisplay, pPixPriv->pixmap, m, &v);
+	XLIB_EPILOGUE (dmxScreen);
+
+	if (gc)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    XPutImage (dmxScreen->beDisplay,
+		       pPixPriv->pixmap,
+		       gc, &ximage, 0, 0, 0, 0,
+		       pPixmap->drawable.width, pPixmap->drawable.height);
+	    XFreeGC (dmxScreen->beDisplay, gc);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+    }
+
+    return TRUE;
+}
diff --git a/hw/dmx/dmxpixmap.h b/hw/dmx/dmxpixmap.h
index 6441834..4fcb710 100644
--- a/hw/dmx/dmxpixmap.h
+++ b/hw/dmx/dmxpixmap.h
@@ -53,6 +53,13 @@ extern PixmapPtr dmxCreatePixmap(ScreenPtr pScreen,
 				 unsigned usage_hint);
 extern Bool      dmxDestroyPixmap(PixmapPtr pPixmap);
 extern RegionPtr dmxBitmapToRegion(PixmapPtr pPixmap);
+extern Bool      dmxModifyPixmapHeader (PixmapPtr pPixmap,
+					int	 width,
+					int	 height,
+					int	 depth,
+					int	 bitsPerPixel,
+					int	 devKind,
+					pointer	 pPixData);
 
 extern void      dmxBECreatePixmap(PixmapPtr pPixmap);
 extern Bool      dmxBEFreePixmap(PixmapPtr pPixmap);
diff --git a/hw/dmx/dmxprop.c b/hw/dmx/dmxprop.c
index 376313d..2dc5bf4 100644
--- a/hw/dmx/dmxprop.c
+++ b/hw/dmx/dmxprop.c
@@ -61,287 +61,327 @@
 
 #include "dmx.h"
 #include "dmxprop.h"
+#include "dmxwindow.h"
 #include "dmxlog.h"
+#include "dmxatom.h"
+#include "dmxselection.h"
 
-/** Holds the window id of all DMX windows on the backend X server. */
-#define DMX_ATOMNAME "DMX_NAME"
-
-/** The identification string of this DMX server */
-#define DMX_IDENT    "Xdmx"
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
 
-extern char *display;
+static int (*dmxSaveProcVector[256]) (ClientPtr);
 
-static int dmxPropertyErrorHandler(Display *dpy, XErrorEvent *ev)
+static int
+dmxProcChangeProperty (ClientPtr client)
 {
-    return 0;
+    WindowPtr   pWin;
+    PropertyPtr pProp;
+    int         err;
+    REQUEST(xChangePropertyReq);
+
+    err = (*dmxSaveProcVector[X_ChangeProperty]) (client);
+    if (err != Success)
+	return err;
+
+    if (dixLookupWindow (&pWin,
+			 stuff->window,
+			 serverClient,
+			 DixReadAccess) != Success ||
+	dixLookupProperty (&pProp,
+			   pWin,
+			   stuff->property,
+			   serverClient,
+			   DixReadAccess) != Success)
+	return Success;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	PanoramiXRes *win;
+	int          j;
+
+	if ((win = (PanoramiXRes *) SecurityLookupIDByType (serverClient,
+							    stuff->window,
+							    XRT_WINDOW,
+							    DixReadAccess)))
+	{
+	    FOR_NSCREENS_BACKWARD(j) {
+		WindowPtr pScrWin;
+
+		if (dixLookupWindow (&pScrWin,
+				     win->info[j].id,
+				     serverClient,
+				     DixReadAccess) == Success)
+		    dmxBESetWindowProperty (pScrWin, pProp);
+	    }
+	}
+	
+	dmxSelectionPropertyChangeCheck (pWin,
+					 stuff->property,
+					 stuff->nUnits);
+
+	return Success;
+    }
+#endif
+
+    dmxBESetWindowProperty (pWin, pProp);
+
+    dmxSelectionPropertyChangeCheck (pWin,
+				     stuff->property,
+				     stuff->nUnits);
+
+    return Success;
 }
 
-static const unsigned char *dmxPropertyIdentifier(void)
+static void
+dmxDeleteProperty (WindowPtr pWin,
+		   Atom      property)
 {
-                                /* RATS: These buffers are only used in
-                                 * length-limited calls. */
-    char          hostname[256];
-    static char   buf[128];
-    static int    initialized = 0;
-
-    if (initialized++) return (unsigned char *)buf;
-    
-    XmuGetHostname(hostname, sizeof(hostname));
-    XmuSnprintf(buf, sizeof(buf), "%s:%s:%s", DMX_IDENT, hostname, display);
-    return (unsigned char *)buf;
+    ScreenPtr     pScreen = pWin->drawable.pScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    Window        window;
+
+    window = dmxBEGetSelectionAdjustedPropertyWindow (pWin);
+    if (!window)
+	return;
+
+    XLIB_PROLOGUE (dmxScreen);
+    XDeleteProperty (dmxScreen->beDisplay,
+		     window,
+		     dmxBEAtom (dmxScreen, property));
+    XLIB_EPILOGUE (dmxScreen);
 }
 
-/** Starting with the \a start screen, iterate over all of the screens
- * on the same physical X server as \a start, calling \a f with the
- * screen and the \a closure.  (The common case is that \a start is the
- * only DMX window on the backend X server.) */
-void *dmxPropertyIterate(DMXScreenInfo *start,
-                         void *(*f)(DMXScreenInfo *dmxScreen, void *),
-                         void *closure)
+static int
+dmxProcDeleteProperty (ClientPtr client)
 {
-    DMXScreenInfo *pt;
-
-    if (!start->next) {
-        if (!start->beDisplay) return NULL;
-        return f(start, closure);
+    WindowPtr pWin;
+    int       err;
+    REQUEST(xDeletePropertyReq);
+
+    err = (*dmxSaveProcVector[X_DeleteProperty]) (client);
+    if (err != Success)
+	return err;
+
+    if (dixLookupWindow (&pWin,
+			 stuff->window,
+			 serverClient,
+			 DixReadAccess) != Success)
+	return err;
+
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	PanoramiXRes *win;
+	int          j;
+
+	if ((win = (PanoramiXRes *) SecurityLookupIDByType (serverClient,
+							    stuff->window,
+							    XRT_WINDOW,
+							    DixReadAccess)))
+	{
+	    FOR_NSCREENS_BACKWARD(j) {
+		WindowPtr pScrWin;
+
+		if (dixLookupWindow (&pScrWin,
+				     win->info[j].id,
+				     serverClient,
+				     DixReadAccess) == Success)
+		    dmxDeleteProperty (pScrWin, stuff->property);
+	    }
+	}
+
+	dmxSelectionPropertyChangeCheck (pWin,
+					 stuff->property,
+					 -1);
+
+	return Success;
     }
+#endif
 
-    for (pt = start->next; /* condition at end of loop */; pt = pt->next) {
-        void *retval;
-        /* beDisplay ban be NULL if a screen was detached */
-        dmxLog(dmxDebug, "pt = %p\n", pt);
-        dmxLog(dmxDebug, "pt->beDisplay = %p\n", pt->beDisplay);
-        if (pt->beDisplay && (retval = f(pt, closure))) return retval;
-        if (pt == start) break;
-    }
-    return NULL;
+    dmxDeleteProperty (pWin, stuff->property);
+
+    dmxSelectionPropertyChangeCheck (pWin,
+				     stuff->property,
+				     -1);
+
+    return Success;
 }
 
-/** Returns 0 if this is the only Xdmx session on the display; 1
- * otherwise. */
-static int dmxPropertyCheckOtherServers(DMXScreenInfo *dmxScreen, Atom atom)
+static int
+dmxProcGetProperty (ClientPtr client)
 {
-    Display       *dpy    = dmxScreen->beDisplay;
-    XTextProperty tp;
-    XTextProperty tproot;
-    const char    *pt;
-    int           retcode = 0;
-    char          **list  = NULL;
-    int           count   = 0;
-    int           i;
-    int           (*dmxOldHandler)(Display *, XErrorEvent *);
-
-    if (!dpy)
-	return 0;
-
-    if (!XGetTextProperty(dpy, RootWindow(dpy,0), &tproot, atom)
-        || !tproot.nitems) return 0;
-    
-                                /* Ignore BadWindow errors for this
-                                 * routine because the window id stored
-                                 * in the property might be old */
-    dmxOldHandler = XSetErrorHandler(dmxPropertyErrorHandler);
-    for (pt = (const char *)tproot.value; pt && *pt; pt = pt ? pt + 1 : NULL) {
-        if ((pt = strchr(pt, ','))) {
-            Window win = strtol(pt+1, NULL, 10);
-            if (XGetTextProperty(dpy, win, &tp, atom) && tp.nitems) {
-                if (!strncmp((char *)tp.value, DMX_IDENT, strlen(DMX_IDENT))) {
-                    int flag = 0;
-                    for (i = 0; i < count; i++)
-                        if (!strcmp(list[i], (char *)tp.value)) {
-                            ++flag;
-                            break;
-                        }
-                    if (flag) continue;
-                    ++retcode;
-                    dmxLogOutputWarning(dmxScreen,
-                                        "%s also running on %s\n",
-                                        tp.value, dmxScreen->name);
-                    list = xrealloc(list, ++count * sizeof(*list));
-                    list[count-1] = xalloc(tp.nitems + 2);
-                    strncpy(list[count-1], (char *)tp.value, tp.nitems + 1);
-                }
-                XFree(tp.value);
-            }
-        }
+    WindowPtr   pWin;
+    PropertyPtr pProp;
+    int         err;
+    REQUEST(xGetPropertyReq);
+
+    err = (*dmxSaveProcVector[X_GetProperty]) (client);
+    if (err != Success || !stuff->delete)
+	return err;
+
+    if (dixLookupWindow (&pWin,
+			 stuff->window,
+			 serverClient,
+			 DixReadAccess) != Success ||
+	dixLookupProperty (&pProp,
+			   pWin,
+			   stuff->property,
+			   serverClient,
+			   DixReadAccess) != BadMatch)
+	return Success;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	PanoramiXRes *win;
+	int          j;
+
+	if ((win = (PanoramiXRes *) SecurityLookupIDByType (serverClient,
+							    stuff->window,
+							    XRT_WINDOW,
+							    DixReadAccess)))
+	{
+	    FOR_NSCREENS_BACKWARD(j) {
+		WindowPtr pScrWin;
+
+		if (dixLookupWindow (&pScrWin,
+				     win->info[j].id,
+				     serverClient,
+				     DixReadAccess) == Success)
+		{
+		    dmxDeleteProperty (pScrWin, stuff->property);
+		}
+	    }
+	}
+
+	dmxSelectionPropertyChangeCheck (pWin,
+					 stuff->property,
+					 -1);
+
+	return Success;
     }
-    XSetErrorHandler(dmxOldHandler);
-
-    for (i = 0; i < count; i++) xfree(list[i]);
-    xfree(list);
-    XFree(tproot.value);
-    if (!retcode)
-        dmxLogOutput(dmxScreen, "No Xdmx server running on backend\n");
-    return retcode;
+#endif
+
+    dmxDeleteProperty (pWin, stuff->property);
+
+    dmxSelectionPropertyChangeCheck (pWin,
+				     stuff->property,
+				     -1);
+
+    return Success;
 }
 
-/** Returns NULL if this is the only Xdmx window on the display.
- * Otherwise, returns a pointer to the dmxScreen of the other windows on
- * the display. */
-static DMXScreenInfo *dmxPropertyCheckOtherWindows(DMXScreenInfo *dmxScreen,
-                                                   Atom atom)
+static void
+dmxRotateProperties (WindowPtr pWin,
+		     Atom      *atoms,
+		     Atom      *buf,
+		     int       nAtoms,
+		     int       nPositions)
 {
-    Display             *dpy = dmxScreen->beDisplay;
-    const unsigned char *id  = dmxPropertyIdentifier();
-    XTextProperty       tproot;
-    XTextProperty       tp;
-    const char          *pt;
-    int                 (*dmxOldHandler)(Display *, XErrorEvent *);
-
-    if (!dpy)
-	return NULL;
-
-    if (!XGetTextProperty(dpy, RootWindow(dpy,0), &tproot, atom)
-        || !tproot.nitems) return 0;
-
-                                /* Ignore BadWindow errors for this
-                                 * routine because the window id stored
-                                 * in the property might be old */
-    dmxOldHandler = XSetErrorHandler(dmxPropertyErrorHandler);
-    for (pt = (const char *)tproot.value; pt && *pt; pt = pt ? pt + 1 : NULL) {
-        if ((pt = strchr(pt, ','))) {
-            Window win = strtol(pt+1, NULL, 10);
-            if (XGetTextProperty(dpy, win, &tp, atom) && tp.nitems) {
-                dmxLog(dmxDebug,"On %s/%lu: %s\n",
-                       dmxScreen->name, win, tp.value);
-                if (!strncmp((char *)tp.value, (char *)id,
-                             strlen((char *)id))) {
-                    int idx;
-                    
-                    if (!(pt = strchr((char *)tp.value, ','))) continue;
-                    idx = strtol(pt+1, NULL, 10);
-                    if (idx < 0 || idx >= dmxNumScreens) continue;
-                    if (dmxScreens[idx].scrnWin != win) continue;
-                    XSetErrorHandler(dmxOldHandler);
-                    return &dmxScreens[idx];
-                }
-                XFree(tp.value);
-            }
-        }
-    }
-    XSetErrorHandler(dmxOldHandler);
-    XFree(tproot.value);
-    return 0;
+    ScreenPtr     pScreen = pWin->drawable.pScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    Window        window;
+    int		  i;
+
+    window = dmxBEGetSelectionAdjustedPropertyWindow (pWin);
+    if (!window)
+	return;
+
+    for (i = 0; i < nAtoms; i++)
+	buf[i] = dmxBEAtom (dmxScreen, atoms[i]);
+
+    XLIB_PROLOGUE (dmxScreen);
+    XRotateWindowProperties (dmxScreen->beDisplay,
+			     window,
+			     buf,
+			     nAtoms,
+			     nPositions);
+    XLIB_EPILOGUE (dmxScreen);
 }
 
-/** Returns 0 if this is the only Xdmx session on the display; 1
- * otherwise. */
-int dmxPropertyDisplay(DMXScreenInfo *dmxScreen)
+static int
+dmxProcRotateProperties (ClientPtr client)
 {
-    Atom                atom;
-    const unsigned char *id  = dmxPropertyIdentifier();
-    Display             *dpy = dmxScreen->beDisplay;
+    WindowPtr pWin;
+    int       err;
+    Atom      *buf, *atoms;
+    REQUEST(xRotatePropertiesReq);
+
+    err = (*dmxSaveProcVector[X_RotateProperties]) (client);
+    if (err != Success)
+	return err;
+
+    atoms = (Atom *) & stuff[1];
+    buf   = (Atom *) xalloc (stuff->nAtoms * sizeof (Atom));
+    if (!buf)
+	return Success;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	PanoramiXRes *win;
+	int          j;
+
+	if ((win = (PanoramiXRes *) SecurityLookupIDByType (serverClient,
+							    stuff->window,
+							    XRT_WINDOW,
+							    DixReadAccess)))
+	{
+	    FOR_NSCREENS_FORWARD(j) {
+		if (dixLookupWindow (&pWin,
+				     win->info[j].id,
+				     serverClient,
+				     DixReadAccess) == Success)
+		    dmxRotateProperties (pWin, atoms, buf, stuff->nAtoms,
+					 stuff->nPositions);
+	    }
+	}
+
+	xfree (buf);
+
+	return Success;
+    }
+#endif
 
-    if (!dpy)
-	return 0;
+    if (dixLookupWindow (&pWin,
+			 stuff->window,
+			 serverClient,
+			 DixReadAccess) == Success)
+	dmxRotateProperties (pWin, atoms, buf, stuff->nAtoms,
+			     stuff->nPositions);
 
-    atom = XInternAtom(dpy, DMX_ATOMNAME, False);
-    if (dmxPropertyCheckOtherServers(dmxScreen, atom)) {
-        dmxScreen->shared = 1;
-        return 1;
-    }
-    XChangeProperty(dpy, RootWindow(dpy,0), atom, XA_STRING, 8,
-                    PropModeReplace, id, strlen((char *)id));
-    return 0;
+    xfree (buf);
+
+    return Success;
 }
 
-/** Returns 1 if the dmxScreen and the display in \a name are on the
- * same display, or 0 otherwise.  We can't just compare the display
- * names because there can be multiple synonyms for the same display,
- * some of which cannot be determined without accessing the display
- * itself (e.g., domain aliases or machines with multiple NICs). */
-int dmxPropertySameDisplay(DMXScreenInfo *dmxScreen, const char *name)
+/** Initialize property support.  In addition to the screen function call
+ *  pointers, DMX also hooks in at the ProcVector[] level.  Here the old
+ *  ProcVector function pointers are saved and the new ProcVector
+ *  function pointers are initialized. */
+void dmxInitProps (void)
 {
-    Display             *dpy0  = dmxScreen->beDisplay;
-    Atom                atom0;
-    XTextProperty       tp0;
-    Display             *dpy1  = NULL;
-    Atom                atom1;
-    XTextProperty       tp1;
-    int                 retval = 0;
-
-    if (!dpy0)
-	return 0;
-
-    tp0.nitems = 0;
-    tp1.nitems = 0;
-
-    if ((atom0 = XInternAtom(dpy0, DMX_ATOMNAME, True)) == None) {
-        dmxLog(dmxWarning, "No atom on %s\n", dmxScreen->name);
-        return 0;
-    }
-    if (!XGetTextProperty(dpy0, RootWindow(dpy0,0), &tp0, atom0)
-        || !tp0.nitems) {
-        dmxLog(dmxWarning, "No text property on %s\n", dmxScreen->name);
-        return 0;
-    }
+    int  i;
 
-    if (!(dpy1 = XOpenDisplay(name))) {
-        dmxLog(dmxWarning, "Cannot open %s\n", name);
-        goto cleanup;
-    }
-    atom1 = XInternAtom(dpy1, DMX_ATOMNAME, True);
-    if (atom1 == None) {
-        dmxLog(dmxDebug, "No atom on %s\n", name);
-        goto cleanup;
-    }
-    if (!XGetTextProperty(dpy1, RootWindow(dpy1,0), &tp1, atom1)
-        || !tp1.nitems) {
-        dmxLog(dmxDebug, "No text property on %s\n", name);
-        goto cleanup;
-    }
-    if (!strcmp((char *)tp0.value, (char *)tp1.value)) retval = 1;
+    for (i = 0; i < 256; i++)
+	dmxSaveProcVector[i] = ProcVector[i];
 
-  cleanup:
-    if (tp0.nitems) XFree(tp0.value);
-    if (tp1.nitems) XFree(tp1.value);
-    if (dpy1)       XCloseDisplay(dpy1);
-    return retval;
+    ProcVector[X_ChangeProperty]   = dmxProcChangeProperty;
+    ProcVector[X_DeleteProperty]   = dmxProcDeleteProperty;
+    ProcVector[X_GetProperty]      = dmxProcGetProperty;
+    ProcVector[X_RotateProperties] = dmxProcRotateProperties;
 }
 
-/** Prints a log message if \a dmxScreen is on the same backend X server
- * as some other DMX backend (output) screen.  Modifies the property
- * (#DMX_ATOMNAME) on the backend X server to reflect the creation of \a
- * dmxScreen.
- *
- * The root window of the backend X server holds a list of window ids
- * for all DMX windows (on this DMX server or some other DMX server).
- *
- * This list can then be iterated, and the property for each window can
- * be examined.  This property contains the following tuple (no quotes):
- *
- * "#DMX_IDENT:<hostname running DMX>:<display name of DMX>,<screen number>"
- */
-void dmxPropertyWindow(DMXScreenInfo *dmxScreen)
+/** Reset property support by restoring the original ProcVector function
+ *  pointers. */
+void dmxResetProps (void)
 {
-    Atom                atom;
-    const unsigned char *id  = dmxPropertyIdentifier();
-    Display             *dpy = dmxScreen->beDisplay;
-    Window              win  = dmxScreen->scrnWin;
-    DMXScreenInfo       *other;
-    char                buf[128]; /* RATS: only used with XmuSnprintf */
-
-    if (!dpy)
-	return; /* FIXME: What should be done here if Xdmx is started
-		 * with this screen initially detached?
-		 */
-
-    atom = XInternAtom(dpy, DMX_ATOMNAME, False);
-    if ((other = dmxPropertyCheckOtherWindows(dmxScreen, atom))) {
-        DMXScreenInfo *tmp = dmxScreen->next;
-        dmxScreen->next    = (other->next ? other->next : other);
-        other->next        = (tmp         ? tmp         : dmxScreen);
-        dmxLog(dmxDebug, "%d/%s/%lu and %d/%s/%lu are on the same backend\n",
-               dmxScreen->index, dmxScreen->name, dmxScreen->scrnWin,
-               other->index, other->name, other->scrnWin);
-    }
-
-    XmuSnprintf(buf, sizeof(buf), ".%d,%lu", dmxScreen->index,
-                (long unsigned)win);
-    XChangeProperty(dpy, RootWindow(dpy,0), atom, XA_STRING, 8,
-                    PropModeAppend, (unsigned char *)buf, strlen(buf));
+    int  i;
 
-    XmuSnprintf(buf, sizeof(buf), "%s,%d", id, dmxScreen->index);
-    XChangeProperty(dpy, win, atom, XA_STRING, 8,
-                    PropModeAppend, (unsigned char *)buf, strlen(buf));
+    for (i = 0; i < 256; i++)
+	ProcVector[i] = dmxSaveProcVector[i];
 }
diff --git a/hw/dmx/dmxprop.h b/hw/dmx/dmxprop.h
index 50135cd..5f800f4 100644
--- a/hw/dmx/dmxprop.h
+++ b/hw/dmx/dmxprop.h
@@ -36,11 +36,6 @@
 
 #ifndef _DMXPROP_H_
 #define _DMXPROP_H_
-extern int  dmxPropertyDisplay(DMXScreenInfo *dmxScreen);
-extern void dmxPropertyWindow(DMXScreenInfo *dmxScreen);
-extern void *dmxPropertyIterate(DMXScreenInfo *start,
-                                void *(*f)(DMXScreenInfo *dmxScreen,
-                                           void *closure),
-                                void *closure);
-extern int dmxPropertySameDisplay(DMXScreenInfo *dmxScreen, const char *name);
+extern void dmxInitProps (void);
+extern void dmxResetProps (void);
 #endif
diff --git a/hw/dmx/dmxrandr.c b/hw/dmx/dmxrandr.c
new file mode 100644
index 0000000..18ba733
--- /dev/null
+++ b/hw/dmx/dmxrandr.c
@@ -0,0 +1,1353 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#ifdef RANDR
+#include "dmx.h"
+#include "dmxlog.h"
+#include "dmxextension.h"
+#include "dmxcb.h"
+#include "dmxrandr.h"
+#include "dmxclient.h"
+#include "dmxatom.h"
+#include "dmxwindow.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#include <xcb/randr.h>
+
+static int xRROutputsForFirstScreen = 1;
+static int xRRCrtcsForFirstScreen = 1;
+
+static DMXScreenInfo *
+dmxRRGetScreenForCrtc (ScreenPtr pScreen,
+		       RRCrtcPtr crtc)
+{
+    int i;
+
+    rrScrPriv (pScreen);
+
+    for (i = 0; i < pScrPriv->numCrtcs; i++)
+	if (pScrPriv->crtcs[i] == crtc)
+	    break;
+
+    if (i == pScrPriv->numCrtcs)
+	return NULL;
+
+    if (i < xRRCrtcsForFirstScreen)
+	return dmxScreens;
+
+    return &dmxScreens[((i - xRRCrtcsForFirstScreen) / xRRCrtcsPerScreen) + 1];
+}
+
+static DMXScreenInfo *
+dmxRRGetScreenForOutput (ScreenPtr   pScreen,
+			 RROutputPtr output)
+{
+    int i;
+
+    rrScrPriv (pScreen);
+
+    for (i = 0; i < pScrPriv->numOutputs; i++)
+	if (pScrPriv->outputs[i] == output)
+	    break;
+
+    if (i == pScrPriv->numOutputs)
+	return NULL;
+
+    if (i < xRROutputsForFirstScreen)
+	return dmxScreens;
+
+    return &dmxScreens[((i - xRROutputsForFirstScreen) / xRROutputsPerScreen) +
+		       1];
+}
+
+static RRModePtr
+dmxRRGetMode (XRRScreenResources *r,
+	      unsigned long	 mode)
+{
+    xRRModeInfo modeInfo;
+    int		i;
+
+    for (i = 0; i < r->nmode; i++)
+    {
+	if (r->modes[i].id == mode)
+	{
+	    memset (&modeInfo, '\0', sizeof (modeInfo));
+
+	    modeInfo.width      = r->modes[i].width;
+	    modeInfo.height     = r->modes[i].height;
+	    modeInfo.dotClock   = r->modes[i].dotClock;
+	    modeInfo.hSyncStart = r->modes[i].hSyncStart;
+	    modeInfo.hSyncEnd   = r->modes[i].hSyncEnd;
+	    modeInfo.hTotal     = r->modes[i].hTotal;
+	    modeInfo.hSkew      = r->modes[i].hSkew;
+	    modeInfo.vSyncStart = r->modes[i].vSyncStart;
+	    modeInfo.vSyncEnd   = r->modes[i].vSyncEnd;
+	    modeInfo.vTotal     = r->modes[i].vTotal;
+	    modeInfo.nameLength = strlen (r->modes[i].name);
+	    modeInfo.modeFlags  = r->modes[i].modeFlags;
+
+	    return RRModeGet (&modeInfo, r->modes[i].name);
+	}
+    }
+
+    return NULL;
+}
+
+static RRCrtcPtr
+dmxRRGetCrtc (ScreenPtr     pScreen,
+	      DMXScreenInfo *dmxScreen,
+	      unsigned long crtc)
+{
+    int baseCrtc = 0;
+    int numCrtc = xRRCrtcsForFirstScreen;
+    int i;
+
+    rrScrPriv (pScreen);
+
+    if (!crtc)
+	return NULL;
+
+    if (dmxScreen != dmxScreens)
+    {
+	baseCrtc = xRRCrtcsForFirstScreen +
+	    ((dmxScreen - dmxScreens) - 1) * xRRCrtcsPerScreen;
+	numCrtc  = xRRCrtcsPerScreen;
+    }
+
+    for (i = 0; i < numCrtc; i++)
+	if (pScrPriv->crtcs[baseCrtc + i]->devPrivate == (void *) crtc)
+	    return pScrPriv->crtcs[baseCrtc + i];
+
+    return NULL;
+}
+
+static RROutputPtr
+dmxRRGetOutput (ScreenPtr     pScreen,
+		DMXScreenInfo *dmxScreen,
+		unsigned long output)
+{
+    int baseOutput = 0;
+    int numOutput = xRROutputsForFirstScreen;
+    int i;
+
+    rrScrPriv (pScreen);
+
+    if (!output)
+	return NULL;
+
+    if (dmxScreen != dmxScreens)
+    {
+	baseOutput = xRROutputsForFirstScreen +
+	    ((dmxScreen - dmxScreens) - 1) * xRROutputsPerScreen;
+	numOutput  = xRROutputsPerScreen;
+    }
+
+    for (i = 0; i < numOutput; i++)
+	if (pScrPriv->outputs[baseOutput + i]->devPrivate == (void *) output)
+	    return pScrPriv->outputs[baseOutput + i];
+
+    return NULL;
+}
+
+static Bool
+dmxRRUpdateCrtc (ScreenPtr	    pScreen,
+		 DMXScreenInfo      *dmxScreen,
+		 XRRScreenResources *r,
+		 unsigned long	    xcrtc)
+{
+    XRRCrtcInfo   *c = NULL;
+    RRCrtcPtr	  crtc;
+    RRModePtr	  mode = NULL;
+    RROutputPtr	  *outputs = NULL;
+    XRRCrtcGamma  *gamma = NULL;
+    int		  i, noutput = 0;
+
+    crtc = dmxRRGetCrtc (pScreen, dmxScreen, xcrtc);
+    if (!crtc)
+	return TRUE; /* do nothing if the crtc doesn't exist */
+
+    XLIB_PROLOGUE (dmxScreen);
+    c = XRRGetCrtcInfo (dmxScreen->beDisplay, r, xcrtc);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!c)
+	return FALSE;
+
+    if (c->noutput)
+    {
+	outputs = xalloc (sizeof (RROutputPtr) * c->noutput);
+	if (!outputs)
+	    return FALSE;
+    }
+
+    if (c->mode)
+	mode = dmxRRGetMode (r, c->mode);
+
+    for (i = 0; i < c->noutput; i++)
+    {
+	outputs[noutput] = dmxRRGetOutput (pScreen, dmxScreen, c->outputs[i]);
+	if (outputs[noutput])
+	    noutput++;
+    }
+
+    XLIB_PROLOGUE (dmxScreen);
+    gamma = XRRGetCrtcGamma (dmxScreen->beDisplay, xcrtc);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!gamma)
+    {
+	if (mode)
+	    RRModeDestroy (mode);
+	
+	return FALSE;
+    }
+
+    RRCrtcGammaSet (crtc, gamma->red, gamma->green, gamma->blue);
+
+    XRRFreeGamma (gamma);
+
+    RRCrtcNotify (crtc, mode, c->x, c->y, c->rotation, noutput, outputs);
+
+    if (outputs)
+	xfree (outputs);
+
+    if (mode)
+	RRModeDestroy (mode);
+
+    XRRFreeCrtcInfo (c);
+
+    return TRUE;
+}
+
+static Bool
+dmxRRUpdateOutput (ScreenPtr	      pScreen,
+		   DMXScreenInfo      *dmxScreen,
+		   XRRScreenResources *r,
+		   unsigned long      xoutput)
+{
+    XRROutputInfo *o = NULL;
+    RROutputPtr	  output, *clones = NULL;
+    RRModePtr	  *modes = NULL;
+    RRCrtcPtr	  *crtcs = NULL;
+    int		  i, nclone = 0, ncrtc = 0;
+
+    output = dmxRRGetOutput (pScreen, dmxScreen, xoutput);
+    if (!output)
+	return TRUE; /* do nothing if the output doesn't exist */
+
+    XLIB_PROLOGUE (dmxScreen);
+    o = XRRGetOutputInfo (dmxScreen->beDisplay, r, xoutput);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!o)
+	return FALSE;
+
+    if (o->nclone)
+    {
+	clones = xalloc (sizeof (RROutputPtr) * o->nclone);
+	if (!clones)
+	    return FALSE;
+    }
+
+    if (o->nmode)
+    {
+	modes = xalloc (sizeof (RRModePtr) * o->nmode);
+	if (!modes)
+	    return FALSE;
+    }
+
+    if (o->ncrtc)
+    {
+	crtcs = xalloc (sizeof (RRCrtcPtr) * o->ncrtc);
+	if (!crtcs)
+	    return FALSE;
+    }
+
+    for (i = 0; i < o->nclone; i++)
+    {
+	clones[nclone] = dmxRRGetOutput (pScreen, dmxScreen, o->clones[i]);
+	if (clones[nclone])
+	    nclone++;
+    }
+
+    for (i = 0; i < o->ncrtc; i++)
+    {
+	crtcs[ncrtc] = dmxRRGetCrtc (pScreen, dmxScreen, o->crtcs[i]);
+	if (crtcs[ncrtc])
+	    ncrtc++;
+    }
+
+    for (i = 0; i < o->nmode; i++)
+    {
+	modes[i] = dmxRRGetMode (r, o->modes[i]);
+	if (!modes[i])
+	    return FALSE;
+    }
+
+    if (!RROutputSetClones (output, clones, nclone))
+	return FALSE;
+
+    if (!RROutputSetModes (output, modes, o->nmode, o->npreferred))
+	return FALSE;
+
+    if (!RROutputSetCrtcs (output, crtcs, ncrtc))
+	return FALSE;
+
+    if (!RROutputSetConnection (output, o->connection))
+	return FALSE;
+
+    if (!RROutputSetSubpixelOrder (output, o->subpixel_order))
+	return FALSE;
+
+    if (!RROutputSetPhysicalSize (output, o->mm_width, o->mm_height))
+	return FALSE;
+
+    if (clones)
+	xfree (clones);
+
+    if (modes)
+	xfree (modes);
+
+    if (crtcs)
+	xfree (crtcs);
+
+    XRRFreeOutputInfo (o);
+
+    return TRUE;
+}
+
+static Bool
+dmxRRUpdateOutputProperty (ScreenPtr	      pScreen,
+			   DMXScreenInfo      *dmxScreen,
+			   XRRScreenResources *r,
+			   unsigned long      xoutput,
+			   unsigned long      xproperty)
+{
+    RROutputPtr     output;
+    XRRPropertyInfo *info = NULL;
+    unsigned char   *prop;
+    int		    format, status = !Success;
+    unsigned long   nElements, bytesAfter;
+    Atom	    type, atom;
+    INT32           *values = NULL;
+
+    output = dmxRRGetOutput (pScreen, dmxScreen, xoutput);
+    if (!output)
+	return TRUE; /* do nothing if the output doesn't exist */
+
+    atom = dmxAtom (dmxScreen, xproperty);
+
+    XLIB_PROLOGUE (dmxScreen);
+    status = XRRGetOutputProperty (dmxScreen->beDisplay, xoutput, xproperty,
+				   0, 8192, FALSE, FALSE,
+				   AnyPropertyType, &type, &format,
+				   &nElements, &bytesAfter, &prop);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (status != Success)
+	return FALSE;
+
+    XLIB_PROLOGUE (dmxScreen);
+    info = XRRQueryOutputProperty (dmxScreen->beDisplay, xoutput, xproperty);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!info)
+	return FALSE;
+
+    if (info->num_values)
+    {
+	int i;
+
+	values = xalloc (info->num_values * sizeof (INT32));
+	if (!values)
+	    return FALSE;
+
+	for (i = 0; i < info->num_values; i++)
+	    values[i] = info->values[i];
+    }
+
+    if (type == XA_ATOM && format == 32)
+    {
+	INT32 *atoms = (INT32 *) prop;
+	int   i;
+
+	for (i = 0; i < nElements; i++)
+	    atoms[i] = dmxAtom (dmxScreen, atoms[i]);
+
+	if (!info->range && info->num_values > 0)
+	{
+	    for (i = 0; i < info->num_values; i++)
+		values[i] = dmxAtom (dmxScreen, values[i]);
+	}
+    }
+
+    RRConfigureOutputProperty (output, atom, FALSE,
+			       info->range, info->immutable, info->num_values,
+			       values);
+
+    RRChangeOutputProperty (output, atom, type, format, PropModeReplace,
+			    nElements, prop, FALSE, TRUE);
+
+    if (values)
+	xfree (values);
+
+    XFree (info);
+    XFree (prop);
+
+    return TRUE;
+}
+
+static Bool
+dmxRRGetInfo (ScreenPtr pScreen,
+	      Rotation  *rotations)
+{
+    int	i;
+
+    rrScrPriv (pScreen);
+
+    if (pScreen->myNum)
+    {
+	*rotations = RR_Rotate_0;
+	return TRUE;
+    }
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo      *dmxScreen = &dmxScreens[i];
+	XRRScreenResources *r = NULL;
+	int		   outputsPerScreen = xRROutputsForFirstScreen;
+	int		   baseOutput = 0;
+	int		   crtcsPerScreen = xRRCrtcsForFirstScreen;
+	int		   baseCrtc = 0;
+	int		   j;
+
+	if (i)
+	{
+	    outputsPerScreen = xRROutputsPerScreen;
+	    baseOutput       = xRROutputsForFirstScreen +
+		(i - 1) * xRROutputsPerScreen;
+	    crtcsPerScreen   = xRRCrtcsPerScreen;
+	    baseCrtc         = xRRCrtcsForFirstScreen +
+		(i - 1) * xRRCrtcsPerScreen;
+	}
+
+	assert (baseOutput + outputsPerScreen <= pScrPriv->numOutputs);
+	assert (baseCrtc + crtcsPerScreen <= pScrPriv->numCrtcs);
+
+	dmxScreen->beRandrPending = TRUE;
+
+	if (dmxScreen->beRandr && dmxScreen->beDisplay)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    r = XRRGetScreenResources (dmxScreen->beDisplay,
+				       dmxScreen->scrnWin);
+	    XLIB_EPILOGUE (dmxScreen);
+
+	    if (r)
+	    {
+		if (r->noutput > outputsPerScreen)
+		    dmxLog (dmxWarning,
+			    "dmxRRGetInfo: ignoring %d BE server outputs\n",
+			    r->noutput - outputsPerScreen);
+
+		if (r->ncrtc > crtcsPerScreen)
+		    dmxLog (dmxWarning,
+			    "dmxRRGetInfo: ignoring %d BE server crtcs\n",
+			    r->ncrtc - crtcsPerScreen);
+	    }
+	}
+
+	for (j = 0; j < outputsPerScreen; j++)
+	{
+	    RROutputPtr output = pScrPriv->outputs[baseOutput + j];
+
+	    if (r && j < r->noutput)
+		output->devPrivate = (void *) r->outputs[j];
+	    else
+		output->devPrivate = NULL;
+	}
+
+	for (j = 0; j < crtcsPerScreen; j++)
+	{
+	    RRCrtcPtr crtc = pScrPriv->crtcs[baseCrtc + j];
+
+	    crtc->devPrivate = NULL;
+
+	    if (r && j < r->ncrtc)
+		crtc->devPrivate = (void *) r->crtcs[j];
+	    else
+		crtc->devPrivate = NULL;
+	}
+
+	for (j = 0; j < outputsPerScreen; j++)
+	{
+	    RROutputPtr output = pScrPriv->outputs[baseOutput + j];
+
+	    if (r)
+	    {
+		if (j < r->noutput)
+		{
+#ifdef _XSERVER64
+		    Atom64 *props = NULL;
+#else
+		    Atom   *props = NULL;
+#endif
+
+		    int    nProp = 0, k;
+
+		    if (!dmxRRUpdateOutput (pScreen,
+					    dmxScreen,
+					    r,
+					    r->outputs[j]))
+			return (dmxScreen->beRandrPending = FALSE);
+
+		    XLIB_PROLOGUE (dmxScreen);
+		    props = XRRListOutputProperties (dmxScreen->beDisplay,
+						     r->outputs[j],
+						     &nProp);
+		    XLIB_EPILOGUE (dmxScreen);
+
+		    if (nProp)
+		    {
+			for (k = 0; k < nProp; k++)
+			    if (!dmxRRUpdateOutputProperty (pScreen,
+							    dmxScreen,
+							    r,
+							    r->outputs[j],
+							    props[k]))
+				return (dmxScreen->beRandrPending = FALSE);
+
+			XFree (props);
+		    }
+		}
+		else
+		{
+		    if (!RROutputSetModes (output, NULL, 0, 0))
+			return (dmxScreen->beRandrPending = FALSE);
+		    if (!RROutputSetClones (output, NULL, 0))
+			return (dmxScreen->beRandrPending = FALSE);
+		    if (!RROutputSetCrtcs (output, NULL, 0))
+			return (dmxScreen->beRandrPending = FALSE);
+		    if (!RROutputSetConnection (output, RR_Disconnected))
+			return (dmxScreen->beRandrPending = FALSE);
+		}
+	    }
+	    else if (dmxScreen->beDisplay && j == 0)
+	    {
+		RRModePtr   mode;
+		xRRModeInfo modeInfo;
+		char	    name[64];
+
+		sprintf (name,
+			 "%dx%d",
+			 dmxScreen->scrnWidth, dmxScreen->scrnHeight);
+
+		memset (&modeInfo, '\0', sizeof (modeInfo));
+		modeInfo.width = dmxScreen->scrnWidth;
+		modeInfo.height = dmxScreen->scrnHeight;
+		modeInfo.nameLength = strlen (name);
+
+		mode = RRModeGet (&modeInfo, name);
+		if (!mode)
+		    return (dmxScreen->beRandrPending = FALSE);
+
+		if (!RROutputSetModes (output, &mode, 1, 0))
+		    return (dmxScreen->beRandrPending = FALSE);
+		if (!RROutputSetClones (output, NULL, 0))
+		    return (dmxScreen->beRandrPending = FALSE);
+		if (!RROutputSetCrtcs (output, &pScrPriv->crtcs[baseCrtc], 1))
+		    return (dmxScreen->beRandrPending = FALSE);
+		if (!RROutputSetConnection (output, RR_Connected))
+		    return (dmxScreen->beRandrPending = FALSE);
+	    }
+	    else
+	    {
+		if (!RROutputSetModes (output, NULL, 0, 0))
+		    return (dmxScreen->beRandrPending = FALSE);
+		if (!RROutputSetClones (output, NULL, 0))
+		    return (dmxScreen->beRandrPending = FALSE);
+		if (!RROutputSetCrtcs (output, NULL, 0))
+		    return (dmxScreen->beRandrPending = FALSE);
+		if (!RROutputSetConnection (output, RR_Disconnected))
+		    return FALSE;
+	    }
+	}
+
+	for (j = 0; j < crtcsPerScreen; j++)
+	{
+	    RRCrtcPtr crtc = pScrPriv->crtcs[baseCrtc + j];
+
+	    if (r)
+	    {
+		if (j < r->ncrtc)
+		{
+		    if (!dmxRRUpdateCrtc (pScreen, dmxScreen, r, r->crtcs[j]))
+			return (dmxScreen->beRandrPending = FALSE);
+		}
+		else
+		{
+		    RRCrtcNotify (crtc, NULL, 0, 0, RR_Rotate_0, 0, NULL);
+		}
+	    }
+	    else if (dmxScreen->beDisplay && j == 0)
+	    {
+		RRModePtr   mode;
+		xRRModeInfo modeInfo;
+		char	    name[64];
+
+		sprintf (name,
+			 "%dx%d",
+			 dmxScreen->scrnWidth, dmxScreen->scrnHeight);
+
+		memset (&modeInfo, '\0', sizeof (modeInfo));
+		modeInfo.width = dmxScreen->scrnWidth;
+		modeInfo.height = dmxScreen->scrnHeight;
+		modeInfo.nameLength = strlen (name);
+
+		mode = RRModeGet (&modeInfo, name);
+		if (!mode)
+		    return (dmxScreen->beRandrPending = FALSE);
+
+		RRCrtcNotify (crtc, mode,
+			      dmxScreen->rootX, dmxScreen->rootY,
+			      RR_Rotate_0, 1,
+			      &pScrPriv->outputs[baseOutput]);
+
+		if (mode)
+		    RRModeDestroy (mode);
+	    }
+	    else
+	    {
+		RRCrtcNotify (crtc, NULL, 0, 0, RR_Rotate_0, 0, NULL);
+	    }
+	}
+
+	if (r)
+	    XRRFreeScreenResources (r);
+
+	dmxScreen->beRandrPending = FALSE;
+    }
+
+    *rotations = RR_Rotate_0;
+
+    for (i = 0; i < pScrPriv->numCrtcs; i++)
+	*rotations |= pScrPriv->crtcs[i]->rotations;
+
+    return TRUE;
+}
+
+static unsigned long
+dmxRRGetXMode (XRRScreenResources *r,
+	       RRModePtr	  mode)
+{
+    xRRModeInfo modeInfo = mode->mode;
+    int		i;
+
+    for (i = 0; i < r->nmode; i++)
+    {
+	if (modeInfo.width      == r->modes[i].width	  &&
+	    modeInfo.height     == r->modes[i].height	  &&
+	    modeInfo.dotClock   == r->modes[i].dotClock	  &&
+	    modeInfo.hSyncStart == r->modes[i].hSyncStart &&
+	    modeInfo.hSyncEnd   == r->modes[i].hSyncEnd	  &&
+	    modeInfo.hTotal     == r->modes[i].hTotal	  &&
+	    modeInfo.hSkew      == r->modes[i].hSkew	  &&
+	    modeInfo.vSyncStart == r->modes[i].vSyncStart &&
+	    modeInfo.vSyncEnd   == r->modes[i].vSyncEnd	  &&
+	    modeInfo.vTotal     == r->modes[i].vTotal	  &&
+	    modeInfo.nameLength == r->modes[i].nameLength &&
+	    modeInfo.modeFlags  == r->modes[i].modeFlags)
+	{
+	    if (!memcmp (r->modes[i].name, mode->name, modeInfo.nameLength))
+		return r->modes[i].id;
+	}
+    }
+
+    return None;
+}
+
+static Bool
+dmxRRScreenSetSize (ScreenPtr pScreen,
+		    CARD16    width,
+		    CARD16    height,
+		    CARD32    mmWidth,
+		    CARD32    mmHeight)
+{
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	int i;
+
+	for (i = 0; i < dmxNumScreens; i++)
+	    dmxResizeRootWindow (WindowTable[i], 0, 0, width, height);
+
+	for (i = 0; i < dmxNumScreens; i++)
+	    dmxUpdateScreenResources (screenInfo.screens[i],
+				      0, 0, width, height);
+
+	dmxSetWidthHeight (width, height);
+	XineramaReinitData (pScreen);
+        dmxConnectionBlockCallback ();
+    }
+    else
+#endif
+    {
+	dmxResizeRootWindow (WindowTable[pScreen->myNum], 0, 0, width, height);
+	dmxUpdateScreenResources (pScreen, 0, 0, width, height);
+    }
+
+    pScreen->mmWidth  = mmWidth;
+    pScreen->mmHeight = mmHeight;
+
+    RRScreenSizeNotify (pScreen);
+
+    return TRUE;
+}
+
+static Bool
+dmxRRCrtcSet (ScreenPtr   pScreen,
+	      RRCrtcPtr   crtc,
+	      RRModePtr   mode,
+	      int	  x,
+	      int	  y,
+	      Rotation    rotation,
+	      int	  numOutputs,
+	      RROutputPtr *outputs)
+{
+    XRRScreenResources *r = NULL;
+
+#ifdef _XSERVER64
+    RROutput64	       *o = NULL;
+#else
+    RROutput	       *o = NULL;
+#endif
+
+    RRMode	       m = None;
+    Status	       status = !RRSetConfigSuccess;
+    int		       i;
+    DMXScreenInfo      *dmxScreen;
+
+    dmxScreen = dmxRRGetScreenForCrtc (pScreen, crtc);
+    if (!dmxScreen)
+	return FALSE;
+
+    if (dmxScreen->beRandrPending)
+	return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
+
+    for (i = 0; i < numOutputs; i++)
+	if (!dmxRRGetOutput (pScreen,
+			     dmxScreen,
+			     (unsigned long) outputs[i]->devPrivate))
+	    return FALSE;
+
+    if (numOutputs)
+    {
+	o = xalloc (sizeof (*o) * numOutputs);
+	if (!o)
+	    return FALSE;
+    }
+
+    XLIB_PROLOGUE (dmxScreen);
+    r = XRRGetScreenResources (dmxScreen->beDisplay,
+			       DefaultRootWindow (dmxScreen->beDisplay));
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!r)
+	return FALSE;
+
+    if (mode)
+    {
+	m = dmxRRGetXMode (r, mode);
+	if (!m)
+	{
+	    XRRFreeScreenResources (r);
+	    if (o)
+		xfree (o);
+
+	    return FALSE;
+	}
+    }
+
+    for (i = 0; i < numOutputs; i++)
+	o[i] = (unsigned long) outputs[i]->devPrivate;
+
+    XLIB_PROLOGUE (dmxScreen);
+    status = XRRSetCrtcConfig (dmxScreen->beDisplay, r,
+			       (unsigned long) crtc->devPrivate,
+			       CurrentTime,
+			       x, y,
+			       m,
+			       rotation,
+			       o, numOutputs);
+    XLIB_EPILOGUE (dmxScreen);
+
+    XRRFreeScreenResources (r);
+
+    if (o)
+	xfree (o);
+
+    if (status != RRSetConfigSuccess)
+	return FALSE;
+
+    return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
+}
+
+static Bool
+dmxRRCrtcSetGamma (ScreenPtr pScreen,
+		   RRCrtcPtr crtc)
+{
+    XRRCrtcGamma  *gamma;
+    DMXScreenInfo *dmxScreen;
+
+    dmxScreen = dmxRRGetScreenForCrtc (pScreen, crtc);
+    if (!dmxScreen)
+	return FALSE;
+
+    if (dmxScreen->beRandrPending)
+	return TRUE;
+
+    gamma = XRRAllocGamma (crtc->gammaSize);
+    if (!gamma)
+	return FALSE;
+
+    memcpy (gamma->red,   crtc->gammaRed,   gamma->size * sizeof (CARD16));
+    memcpy (gamma->green, crtc->gammaGreen, gamma->size * sizeof (CARD16));
+    memcpy (gamma->blue,  crtc->gammaBlue,  gamma->size * sizeof (CARD16));
+
+    XLIB_PROLOGUE (dmxScreen);
+    XRRSetCrtcGamma (dmxScreen->beDisplay, (unsigned long) crtc->devPrivate,
+		     gamma);
+    XLIB_EPILOGUE (dmxScreen);
+
+    XRRFreeGamma (gamma);
+
+    return TRUE;
+}
+
+static Bool
+dmxRROutputSetProperty (ScreenPtr	   pScreen,
+			RROutputPtr	   output,
+			Atom	           property,
+			RRPropertyValuePtr value)
+{
+    RRPropertyPtr p;
+
+#ifdef _XSERVER64
+    Atom64	  atom = 0, type = 0;
+#else
+    Atom	  atom = 0, type = 0;
+#endif
+
+    long	  *values = value->data;
+    long	  *validValues;
+    int		  i;
+    DMXScreenInfo *dmxScreen;
+
+    dmxScreen = dmxRRGetScreenForOutput (pScreen, output);
+    if (!dmxScreen)
+	return FALSE;
+
+    if (dmxScreen->beRandrPending)
+	return TRUE;
+
+    p = RRQueryOutputProperty (output, property);
+    if (!p)
+	return FALSE;
+
+    validValues = p->valid_values;
+
+    atom = dmxBEAtom (dmxScreen, property);
+    type = dmxBEAtom (dmxScreen, value->type);
+
+    if (type == XA_ATOM && value->format == 32)
+    {
+	INT32 *atoms = (INT32 *) value->data;
+
+	for (i = 0; i < value->size; i++)
+	    if (!ValidAtom (atoms[i]))
+		return FALSE;
+
+	if (p->num_valid > 0)
+	{
+	    for (i = 0; i < p->num_valid; i++)
+		if (!ValidAtom (p->valid_values[i]))
+		    return FALSE;
+
+	    for (i = 0; i < value->size; i++)
+	    {
+		int j;
+
+		for (j = 0; j < p->num_valid; j++)
+		    if (p->valid_values[j] == atoms[i])
+			break;
+
+		if (j == p->num_valid)
+		    return FALSE;
+	    }
+
+	    validValues = xalloc (p->num_valid * sizeof (long));
+	    if (!validValues)
+		return FALSE;
+
+	    for (i = 0; i < p->num_valid; i++)
+		validValues[i] = dmxBEAtom (dmxScreen, p->valid_values[i]);
+	}
+
+	if (value->size)
+	{
+	    int size = value->size * (value->format / 8);
+
+	    values = xalloc (size);
+	    if (!values)
+		return FALSE;
+
+	    for (i = 0; i < value->size; i++)
+		values[i] = dmxBEAtom (dmxScreen, atoms[i]);
+	}
+    }
+    else
+    {
+	if (p->num_valid > 0)
+	{
+	    validValues = xalloc (p->num_valid * sizeof (long));
+	    if (!validValues)
+		return FALSE;
+
+	    for (i = 0; i < p->num_valid; i++)
+		validValues[i] = p->valid_values[i];
+	}
+    }
+
+    XLIB_PROLOGUE (dmxScreen);
+    XRRConfigureOutputProperty (dmxScreen->beDisplay,
+				(unsigned long) output->devPrivate,
+				atom, p->is_pending, p->range, p->num_valid,
+				validValues);
+    XRRChangeOutputProperty (dmxScreen->beDisplay,
+			     (unsigned long) output->devPrivate,
+			     atom, type, value->format, PropModeReplace,
+			     (unsigned char *) values, value->size);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (validValues != p->valid_values)
+	xfree (validValues);
+
+    if (values != value->data)
+	xfree (values);
+
+    return TRUE;
+}
+
+static Bool
+dmxRROutputValidateMode (ScreenPtr   pScreen,
+			 RROutputPtr output,
+			 RRModePtr   mode)
+{
+    XRRModeInfo   *modeInfo;
+
+#ifdef _XSERVER64
+    RRMode64      m = 0;
+#else
+    RRMode        m = 0;
+#endif
+
+    DMXScreenInfo *dmxScreen;
+
+    dmxScreen = dmxRRGetScreenForOutput (pScreen, output);
+    if (!dmxScreen)
+	return FALSE;
+
+    if (dmxScreen->beRandrPending)
+	return TRUE;
+
+    modeInfo = XRRAllocModeInfo (mode->name, mode->mode.nameLength);
+    if (!modeInfo)
+	return FALSE;
+
+    modeInfo->width      = mode->mode.width;
+    modeInfo->height     = mode->mode.height;
+    modeInfo->dotClock   = mode->mode.dotClock;
+    modeInfo->hSyncStart = mode->mode.hSyncStart;
+    modeInfo->hSyncEnd   = mode->mode.hSyncEnd;
+    modeInfo->hTotal     = mode->mode.hTotal;
+    modeInfo->hSkew      = mode->mode.hSkew;
+    modeInfo->vSyncStart = mode->mode.vSyncStart;
+    modeInfo->vSyncEnd   = mode->mode.vSyncEnd;
+    modeInfo->vTotal     = mode->mode.vTotal;
+    modeInfo->modeFlags  = mode->mode.modeFlags;
+
+    XLIB_PROLOGUE (dmxScreen);
+    m = XRRCreateMode (dmxScreen->beDisplay,
+		       DefaultRootWindow (dmxScreen->beDisplay),
+		       modeInfo);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (!m)
+	return FALSE;
+
+    XRRFreeModeInfo (modeInfo);
+
+    XLIB_PROLOGUE (dmxScreen);
+    XRRAddOutputMode (dmxScreen->beDisplay,
+		      (unsigned long) output->devPrivate, m);
+    XLIB_EPILOGUE (dmxScreen);
+
+    return TRUE;
+}
+
+static void
+dmxRRModeDestroy (ScreenPtr pScreen,
+		  RRModePtr mode)
+{
+    XRRScreenResources *r;
+    int		       i;
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	if (!dmxScreen->beRandr)
+	    continue;
+
+	if (dmxScreen->beRandrPending)
+	    continue;
+
+	r = NULL;
+
+	XLIB_PROLOGUE (dmxScreen);
+	r = XRRGetScreenResources (dmxScreen->beDisplay, dmxScreen->scrnWin);
+	XLIB_EPILOGUE (dmxScreen);
+
+	if (r)
+	{
+
+#ifdef _XSERVER64
+	    RRMode64 m;
+#else
+	    RRMode   m;
+#endif
+
+	    m = dmxRRGetXMode (r, mode);
+	    if (m)
+	    {
+		XLIB_PROLOGUE (dmxScreen);
+		XRRDestroyMode (dmxScreen->beDisplay, m);
+		XLIB_EPILOGUE (dmxScreen);
+	    }
+
+	    XRRFreeScreenResources (r);
+	}
+    }
+}
+
+Bool
+dmxScreenEventCheckRR (ScreenPtr           pScreen,
+		       xcb_generic_event_t *event)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    switch (event->response_type & ~0x80) {
+    case XCB_MAP_NOTIFY:
+	if (((xcb_map_notify_event_t *) event)->window == dmxScreen->rootWin)
+	    return TRUE;
+
+	return FALSE;
+    case XCB_CONFIGURE_NOTIFY: {
+	xcb_configure_notify_event_t *xconfigure =
+	    (xcb_configure_notify_event_t *) event;
+	XEvent                       X;
+
+	if (xconfigure->window == dmxScreen->scrnWin)
+	{
+	    if (dmxScreen->scrnWidth  == xconfigure->width &&
+		dmxScreen->scrnHeight == xconfigure->height)
+		return TRUE;
+
+	    dmxScreen->scrnWidth  = xconfigure->width;
+	    dmxScreen->scrnHeight = xconfigure->height;
+	}
+	else if (xconfigure->window == dmxScreen->rootWin)
+	{
+	    if (dmxScreen->rootX == xconfigure->x &&
+		dmxScreen->rootY == xconfigure->y)
+		return TRUE;
+
+	    dmxScreen->rootX = xconfigure->x;
+	    dmxScreen->rootY = xconfigure->y;
+	}
+	else
+	{
+	    return FALSE;
+	}
+
+	X.xconfigure.type    = XCB_CONFIGURE_NOTIFY;
+	X.xconfigure.display = dmxScreen->beDisplay;
+	X.xconfigure.window  = xconfigure->window;
+	X.xconfigure.width   = xconfigure->width;
+	X.xconfigure.height  = xconfigure->height;
+
+	XRRUpdateConfiguration (&X);
+    } break;
+    default:
+	if (!dmxScreen->beRandr)
+	    return FALSE;
+
+	switch ((event->response_type & ~0x80) - dmxScreen->beRandrEventBase) {
+	case XCB_RANDR_SCREEN_CHANGE_NOTIFY: {
+	    xcb_randr_screen_change_notify_event_t *scevent =
+		(xcb_randr_screen_change_notify_event_t *) event;
+	    XRRScreenChangeNotifyEvent             X;
+
+	    X.type           = event->response_type;
+	    X.display        = dmxScreen->beDisplay;
+	    X.root           = scevent->root;
+	    X.width          = scevent->width;
+	    X.mwidth         = scevent->mwidth;
+	    X.height         = scevent->height;
+	    X.mheight        = scevent->mheight;
+	    X.rotation       = scevent->rotation;
+	    X.subpixel_order = scevent->subpixel_order;
+	    
+	    XRRUpdateConfiguration ((XEvent *) &X);
+	} break;
+	case XCB_RANDR_NOTIFY:
+	    break;
+	default:
+	    return FALSE;
+	}
+    }
+
+    dmxScreen->beWidth =
+	DisplayWidth (dmxScreen->beDisplay,
+		      DefaultScreen (dmxScreen->beDisplay));
+    dmxScreen->beHeight =
+	DisplayHeight (dmxScreen->beDisplay,
+		       DefaultScreen (dmxScreen->beDisplay));
+
+    /* only call RRGetInfo when server is fully initialized */
+    if (dmxScreens[0].inputOverlayWid)
+	RRGetInfo (screenInfo.screens[0]);
+
+    return TRUE;
+}
+
+Bool
+dmxRRScreenInit (ScreenPtr pScreen)
+{
+    rrScrPrivPtr pScrPriv;
+
+    if (!RRScreenInit (pScreen))
+	return FALSE;
+
+    pScrPriv = rrGetScrPriv (pScreen);
+    pScrPriv->rrGetInfo            = dmxRRGetInfo;
+    pScrPriv->rrScreenSetSize      = dmxRRScreenSetSize;
+    pScrPriv->rrCrtcSet	           = dmxRRCrtcSet;
+    pScrPriv->rrCrtcSetGamma       = dmxRRCrtcSetGamma;
+    pScrPriv->rrOutputSetProperty  = dmxRROutputSetProperty;
+    pScrPriv->rrOutputValidateMode = dmxRROutputValidateMode;
+    pScrPriv->rrModeDestroy	   = dmxRRModeDestroy;
+
+    RRScreenSetSizeRange (pScreen, 1, 1, SHRT_MAX, SHRT_MAX);
+
+    if (pScreen->myNum)
+    {
+	char name[64];
+	int  i;
+
+	for (i = 0; i < xRROutputsPerScreen; i++)
+	{
+	    sprintf (name,
+		     "dmx%d",
+		     (pScreen->myNum - 1) * xRROutputsPerScreen + i);
+
+	    if (!RROutputCreate (screenInfo.screens[0],
+				 name,
+				 strlen (name),
+				 NULL))
+		return FALSE;
+	}
+
+	for (i = 0; i < xRRCrtcsPerScreen; i++)
+	    if (!RRCrtcCreate (screenInfo.screens[0], NULL))
+		return FALSE;
+    }
+    else
+    {
+	XRRScreenResources *r = NULL;
+	DMXScreenInfo      *dmxScreen = dmxScreens;
+	Display            *display = dmxScreen->beDisplay;
+	Bool               beRandr = FALSE;
+
+	if (display && dmxScreen->scrnWin == DefaultRootWindow (display))
+	{
+	    int major, minor, status = 0;
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    status = XRRQueryVersion (display, &major, &minor);
+	    XLIB_EPILOGUE (dmxScreen);
+
+	    if (status)
+	    {
+		if (major > 1 || (major == 1 && minor >= 2))
+		{
+		    int ignore;
+
+		    XLIB_PROLOGUE (dmxScreen);
+		    beRandr = XRRQueryExtension (display, &ignore, &ignore);
+		    XLIB_EPILOGUE (dmxScreen);
+		}
+	    }
+	}
+
+	if (display && beRandr)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    r = XRRGetScreenResources (display, DefaultRootWindow (display));
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+
+	if (r)
+	{
+	    int i;
+
+	    xRROutputsForFirstScreen = r->noutput;
+	    xRRCrtcsForFirstScreen   = r->ncrtc;
+
+	    for (i = 0; i < r->noutput; i++)
+	    {
+		XRROutputInfo *o;
+
+		o = XRRGetOutputInfo (display, r, r->outputs[i]);
+		if (!o)
+		    return FALSE;
+
+		if (!RROutputCreate (screenInfo.screens[0],
+				     o->name, strlen (o->name),
+				     NULL))
+		    return FALSE;
+	    }
+
+	    for (i = 0; i < r->ncrtc; i++)
+		if (!RRCrtcCreate (screenInfo.screens[0], NULL))
+		    return FALSE;
+
+	    XRRFreeScreenResources (r);
+	}
+	else
+	{
+	    if (!RROutputCreate (screenInfo.screens[0], "default", 7, NULL))
+		return FALSE;
+
+	    if (!RRCrtcCreate (screenInfo.screens[0], NULL))
+		return FALSE;
+	}
+    }
+
+    return TRUE;
+}
+
+Bool
+dmxBERRScreenInit (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    dmxScreen->beRandr = FALSE;
+
+    if (dmxScreen->scrnWin == DefaultRootWindow (dmxScreen->beDisplay))
+    {
+	int major, minor, status = 0;
+
+	XLIB_PROLOGUE (dmxScreen);
+	status = XRRQueryVersion (dmxScreen->beDisplay, &major, &minor);
+	XLIB_EPILOGUE (dmxScreen);
+
+	if (status)
+	{
+	    if (major > 1 || (major == 1 && minor >= 2))
+	    {
+		int ignore;
+
+		XLIB_PROLOGUE (dmxScreen);
+		dmxScreen->beRandr =
+		    XRRQueryExtension (dmxScreen->beDisplay,
+				       &dmxScreen->beRandrEventBase,
+				       &ignore);
+		XLIB_EPILOGUE (dmxScreen);
+
+		dmxLog (dmxInfo, "RandR 1.2 is present\n");
+	    }
+	    else
+	    {
+		dmxLog (dmxInfo, "RandR 1.2 is not present\n");
+	    }
+	}
+	else
+	{
+	    dmxLog (dmxInfo, "RandR extension missing\n");
+	}
+    }
+	
+    if (!dmxScreen->beRandr)
+	return FALSE;
+
+    XLIB_PROLOGUE (dmxScreen);
+    XRRSelectInput (dmxScreen->beDisplay,
+		    DefaultRootWindow (dmxScreen->beDisplay),
+		    RRScreenChangeNotifyMask |
+		    RRCrtcChangeNotifyMask   |
+		    RROutputChangeNotifyMask |
+		    RROutputPropertyNotifyMask);
+    XLIB_EPILOGUE (dmxScreen);
+
+    return TRUE;
+}
+
+void
+dmxBERRScreenFini (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (dmxScreen->beRandr)
+    {
+	XLIB_PROLOGUE (dmxScreen);
+	XRRSelectInput (dmxScreen->beDisplay,
+			DefaultRootWindow (dmxScreen->beDisplay),
+			0);
+	XLIB_EPILOGUE (dmxScreen);
+    }
+}
+
+
+#endif
diff --git a/hw/dmx/dmxrandr.h b/hw/dmx/dmxrandr.h
new file mode 100644
index 0000000..0f6822b
--- /dev/null
+++ b/hw/dmx/dmxrandr.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXRANDR_H
+#define DMXRANDR_H
+
+#include "dmxscrinit.h"
+#include "randrstr.h"
+
+extern Bool dmxRRScreenInit (ScreenPtr pScreen);
+extern Bool dmxScreenEventCheckRR (ScreenPtr           pScreen,
+				   xcb_generic_event_t *event);
+extern Bool dmxBERRScreenInit (ScreenPtr pScreen);
+extern void dmxBERRScreenFini (ScreenPtr pScreen);
+
+#endif /* DMXRANDR_H */
diff --git a/hw/dmx/dmxscrinit.c b/hw/dmx/dmxscrinit.c
index 0e49e96..53ae6ab 100644
--- a/hw/dmx/dmxscrinit.c
+++ b/hw/dmx/dmxscrinit.c
@@ -40,8 +40,8 @@
 #endif
 
 #include "dmx.h"
+#include "dmxextension.h"
 #include "dmxsync.h"
-#include "dmxshadow.h"
 #include "dmxscrinit.h"
 #include "dmxcursor.h"
 #include "dmxgc.h"
@@ -52,14 +52,41 @@
 #include "dmxcmap.h"
 #include "dmxprop.h"
 #include "dmxdpms.h"
+#include "dmxlog.h"
+#include "dmxcb.h"
+#include "dmxinit.h"
+#include "dmxgrab.h"
+#include "dmxselection.h"
+#include "dmxatom.h"
+#include "dmxshm.h"
+#include "dmxdnd.h"
+#include "dmxlaunch.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
 
 #ifdef RENDER
 #include "dmxpict.h"
 #endif
 
+#ifdef COMPOSITE
+#include "dmxcomp.h"
+#endif
+
+#ifdef RANDR
+#include "dmxrandr.h"
+#endif
+
+#ifdef XV
+#include "dmxxv.h"
+#endif
+
 #include "fb.h"
 #include "mipointer.h"
 #include "micmap.h"
+#include "mivalidate.h"
 
 extern Bool dmxCloseScreen(int idx, ScreenPtr pScreen);
 static Bool dmxSaveScreen(ScreenPtr pScreen, int what);
@@ -73,20 +100,20 @@ DevPrivateKey dmxPixPrivateKey = &dmxPixPrivateKey; /**< Private index for Pixma
 int dmxFontPrivateIndex;        /**< Private index for Fonts     */
 DevPrivateKey dmxScreenPrivateKey = &dmxScreenPrivateKey; /**< Private index for Screens   */
 DevPrivateKey dmxColormapPrivateKey = &dmxColormapPrivateKey; /**< Private index for Colormaps */
+DevPrivateKey dmxDevicePrivateKey = &dmxDevicePrivateKey; /**< Private index for Devices */
 #ifdef RENDER
 DevPrivateKey dmxPictPrivateKey = &dmxPictPrivateKey; /**< Private index for Picts     */
 DevPrivateKey dmxGlyphSetPrivateKey = &dmxGlyphSetPrivateKey; /**< Private index for GlyphSets */
+DevPrivateKey dmxGlyphPrivateKey = &dmxGlyphPrivateKey; /**< Private index for Glyphs */
 #endif
 
 /** Initialize the parts of screen \a idx that require access to the
  *  back-end server. */
-void dmxBEScreenInit(int idx, ScreenPtr pScreen)
+void dmxBEScreenInit(ScreenPtr pScreen)
 {
-    DMXScreenInfo        *dmxScreen = &dmxScreens[idx];
-    XSetWindowAttributes  attribs;
-    XGCValues             gcvals;
-    unsigned long         mask;
-    int                   i, j;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    char          buf[256];
+    int           i, j;
 
     /* FIXME: The dmxScreenInit() code currently assumes that it will
      * not be called if the Xdmx server is started with this screen
@@ -105,99 +132,873 @@ void dmxBEScreenInit(int idx, ScreenPtr pScreen)
     pScreen->whitePixel = dmxScreen->beWhitePixel;
     pScreen->blackPixel = dmxScreen->beBlackPixel;
 
-    /* Handle screen savers and DPMS on the backend */
-    dmxDPMSInit(dmxScreen);
-
-    /* Create root window for screen */
-    mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
-    attribs.background_pixel = dmxScreen->beBlackPixel;
-    attribs.event_mask = (KeyPressMask
-                          | KeyReleaseMask
-                          | ButtonPressMask
-                          | ButtonReleaseMask
-                          | EnterWindowMask
-                          | LeaveWindowMask
-                          | PointerMotionMask
-                          | KeymapStateMask
-                          | FocusChangeMask);
-    attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex];
-    attribs.override_redirect = True;
+    dmxScreen->selectionOwner = None;
+
+    sprintf(buf, "DMX_%s", dmxDigest);
+
+    /* prefetch all valid atoms */
+    for (i = 1; ValidAtom ((Atom) i); i++);
+    while (--i)
+	dmxBEPrefetchAtom (dmxScreen, (Atom) i);
     
-    dmxScreen->scrnWin =
-	XCreateWindow(dmxScreen->beDisplay, 
-		      DefaultRootWindow(dmxScreen->beDisplay),
-		      dmxScreen->scrnX,
-		      dmxScreen->scrnY,
-		      dmxScreen->scrnWidth,
-		      dmxScreen->scrnHeight,
-		      0,
-		      pScreen->rootDepth,
-		      InputOutput,
-		      dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
-		      mask,
-		      &attribs);
-    dmxPropertyWindow(dmxScreen);
+    XLIB_PROLOGUE (dmxScreen);
+    dmxScreen->beSelectionAtom = XInternAtom (dmxScreen->beDisplay, buf, 0);
+    XLIB_EPILOGUE (dmxScreen);
 
-    /*
-     * This turns off the cursor by defining a cursor with no visible
-     * components.
-     */
+    /* Handle screen savers and DPMS on the backend */
+    dmxBEDPMSScreenInit (pScreen);
+
+#ifdef MITSHM
+    dmxBEShmScreenInit (pScreen);
+#endif
+
+#ifdef RANDR
+    dmxBERRScreenInit (pScreen);
+#endif
+
+#ifdef XV
+    dmxBEXvScreenInit (pScreen);
+#endif
+
+    /* Create default drawables (used during GC creation) */
+    for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) 
+	for (j = 0; j < dmxScreen->beNumDepths; j++)
+	    if ((dmxScreen->bePixmapFormats[i].depth == 1) ||
+		(dmxScreen->bePixmapFormats[i].depth ==
+		 dmxScreen->beDepths[j])) {
+		XLIB_PROLOGUE (dmxScreen);
+		dmxScreen->scrnDefDrawables[i] = (Drawable)
+		    XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
+				  1, 1, dmxScreen->bePixmapFormats[i].depth);
+		XLIB_EPILOGUE (dmxScreen);
+		break;
+	    }
+}
+
+static void
+dmxSetWindowPixmap (WindowPtr pWin, PixmapPtr pPixmap)
+{
+    ScreenPtr       pScreen = pWin->drawable.pScreen;
+    DMXScreenInfo  *dmxScreen = &dmxScreens[pScreen->myNum];
+    PixmapPtr       pOld = (*pScreen->GetWindowPixmap) (pWin);
+
+    if (pPixmap != pOld)
     {
-	char noCursorData[] = {0, 0, 0, 0,
-			       0, 0, 0, 0};
-	Pixmap pixmap;
-	XColor color, tmp;
-
-	pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin,
-				       noCursorData, 8, 8);
-	XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0],
-			 "black", &color, &tmp);
-	dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay,
-						  pixmap, pixmap,
-						  &color, &color, 0, 0);
-	XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
-		      dmxScreen->noCursor);
-
-	XFreePixmap(dmxScreen->beDisplay, pixmap);
+	dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pWin);
+
+	if (pPixmap && (*pScreen->GetWindowPixmap) (pWin->parent) != pPixmap)
+	    pWinPriv->redirected = TRUE;
+	else
+	    pWinPriv->redirected = FALSE;
     }
 
-    XMapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
-
-    if (dmxShadowFB) {
-	mask = (GCFunction
-		| GCPlaneMask
-		| GCClipMask);
-	gcvals.function = GXcopy;
-	gcvals.plane_mask = AllPlanes;
-	gcvals.clip_mask = None;
-
-	dmxScreen->shadowGC = XCreateGC(dmxScreen->beDisplay,
-					dmxScreen->scrnWin,
-					mask, &gcvals);
-
-	dmxScreen->shadowFBImage =
-	    XCreateImage(dmxScreen->beDisplay,
-			 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
-			 dmxScreen->beDepth,
-			 ZPixmap,
-			 0,
-			 (char *)dmxScreen->shadow,
-			 dmxScreen->scrnWidth, dmxScreen->scrnHeight,
-			 dmxScreen->beBPP,
-			 PixmapBytePad(dmxScreen->scrnWidth,
-				       dmxScreen->beBPP));
-    } else {
-	/* Create default drawables (used during GC creation) */
-	for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) 
-	    for (j = 0; j < dmxScreen->beNumDepths; j++)
-		if ((dmxScreen->bePixmapFormats[i].depth == 1) ||
-		    (dmxScreen->bePixmapFormats[i].depth ==
-		     dmxScreen->beDepths[j])) {
-		    dmxScreen->scrnDefDrawables[i] = (Drawable)
-			XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
-				      1, 1, dmxScreen->bePixmapFormats[i].depth);
-		    break;
+    DMX_UNWRAP(SetWindowPixmap, dmxScreen, pScreen);
+    if (pScreen->SetWindowPixmap)
+	(*pScreen->SetWindowPixmap) (pWin, pPixmap);
+    DMX_WRAP(SetWindowPixmap, dmxSetWindowPixmap, dmxScreen, pScreen);
+}
+
+static Bool
+dmxScreenEventCheckInput (ScreenPtr           pScreen,
+			  xcb_generic_event_t *event)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    return dmxInputEventCheck (&dmxScreen->input, event);
+}
+
+static void
+dmxScreenGetSelectionOwner (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    dmxScreen->selectionOwner = None;
+    while (dmxScreen->selectionOwner == None)
+    {
+	xcb_connection_t                *c = dmxScreen->connection;
+	xcb_atom_t                      a = dmxScreen->beSelectionAtom;
+	xcb_get_selection_owner_reply_t *reply;
+
+	reply = xcb_get_selection_owner_reply (c,
+					       xcb_get_selection_owner (c, a),
+					       NULL);
+	if (!reply)
+	    break;
+
+	if (reply->owner)
+	{
+	    if (reply->owner != dmxScreen->rootWin)
+	    {
+		const uint32_t      value = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
+		xcb_void_cookie_t   r;
+		xcb_generic_error_t *error;
+		
+		r = xcb_change_window_attributes_checked (c,
+							  reply->owner,
+							  XCB_CW_EVENT_MASK,
+							  &value);
+		error = xcb_request_check (c, r);
+		if (error)
+		{
+		    if (error->error_code != BadWindow)
+			dmxScreen->selectionOwner = reply->owner;
+
+		    free (error);
+		}
+		else
+		{
+		    dmxScreen->selectionOwner = reply->owner;
 		}
+	    }
+	    else
+	    {
+		dmxScreen->selectionOwner = dmxScreen->rootWin;
+	    }
+	}
+	else
+	{
+	    xcb_set_selection_owner (dmxScreen->connection,
+				     dmxScreen->rootWin,
+				     dmxScreen->beSelectionAtom,
+				     0);
+	}
+
+	free (reply);
+    }
+}
+
+static Bool
+dmxScreenEventCheckSelection (ScreenPtr           pScreen,
+			      xcb_generic_event_t *event)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    switch (event->response_type & ~0x80) {
+    case XCB_DESTROY_NOTIFY: {
+	xcb_destroy_notify_event_t *xdestroy =
+	    (xcb_destroy_notify_event_t *) event;
+
+	if (dmxSelectionDestroyNotify (pScreen, xdestroy->window))
+	    return TRUE;
+
+	if (xdestroy->window != dmxScreen->selectionOwner)
+	    return FALSE;
+
+	if (dmxScreen->selectionOwner == dmxScreen->rootWin)
+	    return FALSE;
+
+	dmxScreenGetSelectionOwner (pScreen);
+    } break;
+    case XCB_PROPERTY_NOTIFY: {
+	xcb_property_notify_event_t *xproperty =
+	    (xcb_property_notify_event_t *) event;
+
+	if (!dmxSelectionPropertyNotify (pScreen,
+					 xproperty->window,
+					 xproperty->state,
+					 xproperty->atom,
+					 xproperty->time))
+	    return FALSE;
+    } break;
+    case XCB_SELECTION_CLEAR: {
+	xcb_selection_clear_event_t *xclear =
+	    (xcb_selection_clear_event_t *) event;
+
+	if (xclear->selection == dmxScreen->beSelectionAtom)
+	{
+	    dmxScreenGetSelectionOwner (pScreen);
+	}
+	else
+	{
+	    dmxSelectionClear (pScreen,
+			       xclear->owner,
+			       xclear->selection);
+	}
+    } break;
+    case XCB_SELECTION_NOTIFY: {
+	xcb_selection_notify_event_t *xnotify =
+	    (xcb_selection_notify_event_t *) event;
+
+	dmxSelectionNotify (pScreen,
+			    xnotify->requestor,
+			    xnotify->selection,
+			    xnotify->target,
+			    xnotify->property,
+			    xnotify->time);
+    } break;
+    case XCB_SELECTION_REQUEST: {
+	xcb_selection_request_event_t *xrequest =
+	    (xcb_selection_request_event_t *) event;
+
+	dmxSelectionRequest (pScreen,
+			     xrequest->owner,
+			     xrequest->requestor,
+			     xrequest->selection,
+			     xrequest->target,
+			     xrequest->property,
+			     xrequest->time);
+    } break;
+    default:
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+static void
+dmxDiscardIgnore (DMXScreenInfo *dmxScreen,
+		  unsigned long sequence)
+{
+    while (dmxScreen->ignore.head)
+    {
+	if ((long) (sequence - dmxScreen->ignore.head->sequence) > 0)
+	{
+	    DMXSequence *next = dmxScreen->ignore.head->next;
+
+	    free (dmxScreen->ignore.head);
+
+	    dmxScreen->ignore.head = next;
+	    if (!dmxScreen->ignore.head)
+		dmxScreen->ignore.tail = &dmxScreen->ignore.head;
+	}
+	else
+	    break;
+    }
+}
+
+static Bool
+dmxShouldIgnore (DMXScreenInfo *dmxScreen,
+		 unsigned long sequence)
+{
+    dmxDiscardIgnore (dmxScreen, sequence);
+
+    if (!dmxScreen->ignore.head)
+	return FALSE;
+
+    return dmxScreen->ignore.head->sequence == sequence;
+}
+
+static Bool
+dmxScreenEventCheckExpose (ScreenPtr           pScreen,
+			   xcb_generic_event_t *event)
+{
+    DMXScreenInfo      *dmxScreen = &dmxScreens[pScreen->myNum];
+    xcb_expose_event_t *xexpose = (xcb_expose_event_t *) event;
+    WindowPtr          pChild0, pChildN;
+
+    if ((event->response_type & ~0x80) != XCB_EXPOSE)
+	return FALSE;
+
+    if (dmxShouldIgnore (dmxScreen, xexpose->sequence))
+	return TRUE;
+
+    pChild0 = WindowTable[0];
+    pChildN = WindowTable[pScreen->myNum];
+
+    for (;;)
+    {
+	dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pChildN);
+
+	if (pWinPriv->window == xexpose->window)
+	    break;
+
+	if (pChild0->firstChild)
+	{
+	    assert (pChildN->firstChild);
+	    pChild0 = pChild0->firstChild;
+	    pChildN = pChildN->firstChild;
+	    continue;
+	}
+
+	while (!pChild0->nextSib && (pChild0 != WindowTable[0]))
+	{
+	    assert (!pChildN->nextSib &&
+		    (pChildN != WindowTable[pScreen->myNum]));
+	    pChild0 = pChild0->parent;
+	    pChildN = pChildN->parent;
+	}
+
+	if (pChild0 == WindowTable[0])
+	{
+	    assert (pChildN == WindowTable[pScreen->myNum]);
+	    break;
+	}
+
+	pChild0 = pChild0->nextSib;
+	pChildN = pChildN->nextSib;
+    }
+
+    if (pChild0)
+    {
+	RegionRec region;
+	BoxRec    box;
+
+	box.x1 = pChild0->drawable.x + xexpose->x;
+	box.y1 = pChild0->drawable.y + xexpose->y;
+	box.x2 = box.x1 + xexpose->width;
+	box.y2 = box.y1 + xexpose->height;
+
+	REGION_INIT (screenInfo.screens[0], &region, &box, 1);
+	(*pScreen->WindowExposures) (pChild0, &region, NullRegion);
+	REGION_UNINIT (screenInfo.screens[0], &region);
+    }
+
+    return TRUE;
+}
+
+static Bool
+dmxScreenEventCheckOutputWindow (ScreenPtr	     pScreen,
+				 xcb_generic_event_t *event)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    switch (event->response_type & ~0x80) {
+    case XCB_DESTROY_NOTIFY: {
+	xcb_destroy_notify_event_t *xdestroy =
+	    (xcb_destroy_notify_event_t *) event;
+	
+	if (xdestroy->window != dmxScreen->scrnWin)
+	    return FALSE;
+
+	/* output window has been destroyed, detach screen when we reach
+	   the block handler */
+	dmxScreen->scrnWin = None;
+	return TRUE;
+    } break;
+    case XCB_MAP_NOTIFY: {
+	xcb_map_notify_event_t *xmap = (xcb_map_notify_event_t *) event;
+
+	if (xmap->window == dmxScreen->scrnWin)
+	    return TRUE;
+    } break;
+    default:
+	break;
+    }
+
+    return FALSE;
+}
+
+static Bool
+dmxScreenEventCheckManageRoot (ScreenPtr	   pScreen,
+			       xcb_generic_event_t *event)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    WindowPtr     pChild = WindowTable[pScreen->myNum];
+    Window        xWindow;
+
+#ifdef PANORAMIX
+    PanoramiXRes  *win = NULL;
+    WindowPtr     pWin;
+#endif
+
+    xcb_circulate_request_event_t *xcirculaterequest =
+	(xcb_circulate_request_event_t *) event;
+    xcb_configure_request_event_t *xconfigurerequest =
+	(xcb_configure_request_event_t *) event;
+    xcb_map_request_event_t *xmaprequest =
+	(xcb_map_request_event_t *) event;
+    xcb_client_message_event_t *xclient =
+	(xcb_client_message_event_t *) event;
+    xcb_map_notify_event_t *xmap =
+	(xcb_map_notify_event_t *) event;
+
+    switch (event->response_type & ~0x80) {
+    case XCB_CIRCULATE_REQUEST:
+	xWindow = xcirculaterequest->window;
+	break;
+    case XCB_CONFIGURE_REQUEST:
+	xWindow = xconfigurerequest->window;
+	break;
+    case XCB_MAP_REQUEST:
+	xWindow = xmaprequest->window;
+	break;
+    case XCB_CLIENT_MESSAGE:
+	xWindow = xclient->window;
+	break;
+    case XCB_MAP_NOTIFY:
+	if (xmap->window == dmxScreen->rootWin)
+	{
+	    dmxScreenGetSelectionOwner (pScreen);
+	    return TRUE;
+	}
+
+	/* fall-through */
+    default:
+	return FALSE;
+    }
+
+    for (;;)
+    {
+	dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pChild);
+
+	if (pWinPriv->window == xWindow)
+	{
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+		win = PanoramiXFindIDByScrnum (XRT_WINDOW,
+					       pChild->drawable.id,
+					       pScreen->myNum);
+#endif
+
+	    break;
+	}
+
+	if (pChild->firstChild)
+	{
+	    pChild = pChild->firstChild;
+	    continue;
+	}
+
+	while (!pChild->nextSib &&
+	       (pChild != WindowTable[pScreen->myNum]))
+	    pChild = pChild->parent;
+
+	if (pChild == WindowTable[pScreen->myNum])
+	    break;
+
+	pChild = pChild->nextSib;
+    }
+
+    if (pChild
+
+#ifdef PANORAMIX
+	&& win
+#endif
+
+	)
+    {
+	XID    vlist[8];
+	Atom   type;
+	int    mask, i = 0;
+	int    status = Success;
+	xEvent x;
+
+	switch (event->response_type & ~0x80) {
+	case XCB_CIRCULATE_REQUEST:
+	    vlist[0] = None;
+
+	    if (xcirculaterequest->place == XCB_PLACE_ON_TOP)
+		vlist[1] = Above;
+	    else
+		vlist[1] = Below;
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		int j;
+
+		FOR_NSCREENS_FORWARD(j) {
+		    if (dixLookupWindow (&pWin,
+					 win->info[j].id,
+					 serverClient,
+					 DixReadAccess) == Success)
+			status |= ConfigureWindow (pWin,
+						   CWSibling |
+						   CWStackMode,
+						   vlist,
+						   serverClient);
+		}
+	    }
+	    else
+#endif
+		status = ConfigureWindow (pChild,
+					  CWSibling | CWStackMode,
+					  vlist,
+					  serverClient);
+	    break;
+	case XCB_CONFIGURE_REQUEST:
+	    mask = xconfigurerequest->value_mask;
+
+	    if (mask & (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y))
+	    {
+		vlist[i++] = xconfigurerequest->x;
+		vlist[i++] = xconfigurerequest->y;
+	    }
+
+	    if (mask & (XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT))
+	    {
+		vlist[i++] = xconfigurerequest->width;
+		vlist[i++] = xconfigurerequest->height;
+	    }
+
+	    if (mask & XCB_CONFIG_WINDOW_BORDER_WIDTH)
+		vlist[i++] = xconfigurerequest->border_width;
+
+	    if (mask & XCB_CONFIG_WINDOW_SIBLING)
+	    {
+		/* ignore stacking requests with sibling */
+		if (xconfigurerequest->sibling == None)
+		    vlist[i++] = None;
+		else
+		    mask &= ~(XCB_CONFIG_WINDOW_SIBLING |
+			      XCB_CONFIG_WINDOW_STACK_MODE);
+	    }
+
+	    if (mask & XCB_CONFIG_WINDOW_STACK_MODE)
+		vlist[i++] = xconfigurerequest->stack_mode;
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		int j;
+
+		FOR_NSCREENS_FORWARD(j) {
+		    if (dixLookupWindow (&pWin,
+					 win->info[j].id,
+					 serverClient,
+					 DixReadAccess) == Success)
+			status |= ConfigureWindow (pWin,
+						   mask,
+						   vlist,
+						   serverClient);
+		}
+	    }
+	    else
+#endif
+
+		status = ConfigureWindow (pChild,
+					  mask,
+					  vlist,
+					  serverClient);
+	    break;
+	case XCB_MAP_REQUEST:
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		int j;
+
+		FOR_NSCREENS_FORWARD(j) {
+		    if (dixLookupWindow (&pWin,
+					 win->info[j].id,
+					 serverClient,
+					 DixReadAccess) == Success)
+			status |= MapWindow (pWin, serverClient);
+		}
+	    }
+	    else
+#endif
+
+		status = MapWindow (pChild, serverClient);
+	    break;
+	case XCB_CLIENT_MESSAGE:
+	    x.u.u.type               = ClientMessage | 0x80;
+	    x.u.u.detail             = xclient->format;
+	    x.u.clientMessage.window = pChild->drawable.id;
+
+	    type = dmxAtom (dmxScreen, xclient->type);
+
+	    switch (xclient->format) {
+	    case 8:
+		x.u.clientMessage.u.b.type = type;
+
+		for (i = 0; i < 20; i++)
+		    x.u.clientMessage.u.b.bytes[i] = xclient->data.data8[i];
+		break;
+	    case 16:
+		x.u.clientMessage.u.s.type = type;
+
+		x.u.clientMessage.u.s.shorts0 = xclient->data.data16[0];
+		x.u.clientMessage.u.s.shorts1 = xclient->data.data16[1];
+		x.u.clientMessage.u.s.shorts2 = xclient->data.data16[2];
+		x.u.clientMessage.u.s.shorts3 = xclient->data.data16[3];
+		x.u.clientMessage.u.s.shorts4 = xclient->data.data16[4];
+		x.u.clientMessage.u.s.shorts5 = xclient->data.data16[5];
+		x.u.clientMessage.u.s.shorts6 = xclient->data.data16[6];
+		x.u.clientMessage.u.s.shorts7 = xclient->data.data16[7];
+		x.u.clientMessage.u.s.shorts8 = xclient->data.data16[8];
+		x.u.clientMessage.u.s.shorts9 = xclient->data.data16[9];
+		break;
+	    case 32:
+		x.u.clientMessage.u.l.type = type;
+
+		x.u.clientMessage.u.l.longs0 = xclient->data.data32[0];
+		x.u.clientMessage.u.l.longs1 = xclient->data.data32[1];
+		x.u.clientMessage.u.l.longs2 = xclient->data.data32[2];
+		x.u.clientMessage.u.l.longs3 = xclient->data.data32[3];
+		x.u.clientMessage.u.l.longs4 = xclient->data.data32[4];
+		break;
+	    }
+
+	    /* client messages are always forwarded to the root
+	       window as there's no way for us to know which
+	       windows they were originally intended for */
+	    pWin = WindowTable[pScreen->myNum];
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		x.u.clientMessage.window = win->info[0].id;
+		pWin = WindowTable[0];
+	    }
+#endif
+
+	    DeliverEventsToWindow (PickPointer (serverClient),
+				   pWin,
+				   &x,
+				   1,
+				   SubstructureRedirectMask |
+				   SubstructureNotifyMask,
+				   NullGrab, 0);
+	    break;
+	}
+
+	if (status != Success)
+	    dmxLog (dmxWarning,
+		    "dmxScreenManage: failed to handle "
+		    "request type %d\n",
+		    event->response_type & ~0x80);
+    }
+    else
+    {
+	XWindowChanges xwc;
+
+	switch (event->response_type & ~0x80) {
+	case XCB_CIRCULATE_REQUEST:
+	    XLIB_PROLOGUE (dmxScreen);
+	    if (xcirculaterequest->place == XCB_PLACE_ON_TOP)
+		XRaiseWindow (dmxScreen->beDisplay,
+			      xcirculaterequest->window);
+	    else
+		XLowerWindow (dmxScreen->beDisplay,
+			      xcirculaterequest->window);
+	    XLIB_EPILOGUE (dmxScreen);
+	    break;
+	case XCB_CONFIGURE_REQUEST:
+	    xwc.x	     = xconfigurerequest->x;
+	    xwc.y	     = xconfigurerequest->y;
+	    xwc.width	     = xconfigurerequest->width;
+	    xwc.height	     = xconfigurerequest->height;
+	    xwc.border_width = xconfigurerequest->border_width;
+	    xwc.sibling      = xconfigurerequest->sibling;
+	    xwc.stack_mode   = xconfigurerequest->stack_mode;
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    XConfigureWindow (dmxScreen->beDisplay,
+			      xconfigurerequest->window,
+			      xconfigurerequest->value_mask,
+			      &xwc);
+	    XLIB_EPILOGUE (dmxScreen);
+	    break;
+	case XCB_MAP_REQUEST:
+	    XLIB_PROLOGUE (dmxScreen);
+	    XMapWindow (dmxScreen->beDisplay, xmaprequest->window);
+	    XLIB_EPILOGUE (dmxScreen);
+	    break;
+	case XCB_CLIENT_MESSAGE:
+	    break;
+	}
+    }
+
+    return TRUE;
+}
+
+static Bool
+dmxScreenEventCheckIgnore (ScreenPtr	       pScreen,
+			   xcb_generic_event_t *event)
+{
+    switch (event->response_type & ~0x80) {
+    case XCB_MAPPING_NOTIFY:
+	return TRUE;
+    default:
+	break;
+    }
+
+    return FALSE;
+}
+
+void
+dmxBEDispatch (ScreenPtr pScreen)
+{
+    DMXScreenInfo       *dmxScreen = &dmxScreens[pScreen->myNum];
+    xcb_generic_event_t *event;
+    xcb_generic_error_t *error;
+    void                *reply;
+
+    assert (dmxScreen->inDispatch == FALSE);
+    dmxScreen->inDispatch = TRUE;
+
+    while ((event = xcb_poll_for_event (dmxScreen->connection)))
+    {
+	if (!dmxScreenEventCheckInput (pScreen, event)        &&
+	    !dmxScreenEventCheckSelection (pScreen, event)    &&
+	    !dmxScreenEventCheckDnD (pScreen, event)          &&
+	    !dmxScreenEventCheckOutputWindow (pScreen, event) &&
+	    !dmxScreenEventCheckManageRoot (pScreen, event)   &&
+	    !dmxScreenEventCheckExpose (pScreen, event)       &&
+
+#ifdef MITSHM
+	    !dmxScreenEventCheckShm (pScreen, event)          &&
+#endif
+
+#ifdef RANDR
+	    !dmxScreenEventCheckRR (pScreen, event)           &&
+#endif
+
+	    !dmxScreenEventCheckIgnore (pScreen, event))
+	{
+	    if (event->response_type == 0)
+	    {
+		xcb_generic_error_t *error = (xcb_generic_error_t *) event;
+
+		dmxLogOutput (dmxScreen, "unhandled error type %d\n",
+			      error->error_code);
+	    }
+	    else
+	    {
+		dmxLogOutput (dmxScreen, "unhandled event type %d\n",
+			      event->response_type);
+	    }
+	}
+
+	free (event);
+    }
+
+    while (dmxScreen->request.head &&
+	   xcb_poll_for_reply (dmxScreen->connection,
+			       dmxScreen->request.head->sequence,
+			       (void **) &reply,
+			       &error))
+    {
+	DMXRequest *head = (DMXRequest *) dmxScreen->request.head;
+
+	dmxScreen->request.head = head->base.next;
+	if (!dmxScreen->request.head)
+	    dmxScreen->request.tail = &dmxScreen->request.head;
+
+	(*head->reply) (pScreen,
+			head->base.sequence,
+			reply,
+			error,
+			head->data);
+
+        if (reply)
+	    free (reply);
+        if (error)
+            free (error);
+
+	free (head);
+    }
+
+    if (!dmxScreen->scrnWin ||
+	xcb_connection_has_error (dmxScreen->connection))
+    {
+	static xcb_generic_error_t detached_error = { 0, DMX_DETACHED };
+
+	while (dmxScreen->request.head)
+	{
+	    DMXRequest *head = (DMXRequest *) dmxScreen->request.head;
+
+	    dmxScreen->request.head = head->base.next;
+	    if (!dmxScreen->request.head)
+		dmxScreen->request.tail = &dmxScreen->request.head;
+
+	    (*head->reply) (pScreen,
+			    head->base.sequence,
+			    NULL,
+			    &detached_error,
+			    head->data);
+
+	    free (head);
+	}
+
+	dmxScreen->broken = TRUE;
+    }
+
+    dmxScreen->inDispatch = FALSE;
+}
+
+static void
+dmxScreenCheckForIOError (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (!dmxScreen->scrnWin ||
+	xcb_connection_has_error (dmxScreen->connection))
+    {
+	int i;
+
+	if (dmxScreen->scrnWin)
+	{
+	    dmxLogOutput (dmxScreen, "Detected broken connection\n");
+	    dmxScreen->alive = FALSE;
+	}
+
+	if (!dmxScreen->broken)
+	    dmxBEDispatch (pScreen);
+
+	dmxDetachScreen (pScreen->myNum);
+
+	for (i = 0; i < dmxNumScreens; i++)
+	    if (i != pScreen->myNum && dmxScreens[i].beDisplay)
+		break;
+
+	if (i == dmxNumScreens)
+	    dmxLog (dmxFatal, "No back-end server connection, "
+		    "giving up\n");
+    }
+}
+
+static void
+dmxScreenBlockHandler (pointer   blockData,
+		       OSTimePtr pTimeout,
+		       pointer   pReadMask)
+{
+    ScreenPtr     pScreen = (ScreenPtr) blockData;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (dmxScreen->alive)
+    {
+	xcb_flush (dmxScreen->connection);
+	dmxScreenCheckForIOError (pScreen);
+    }
+}
+
+static void
+dmxScreenWakeupHandler (pointer blockData,
+			int     result,
+			pointer pReadMask)
+{
+    ScreenPtr     pScreen = (ScreenPtr) blockData;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (dmxScreen->alive)
+	dmxBEDispatch (pScreen);
+}
+
+static void
+dmxHandleExposures (WindowPtr pWin)
+{
+    WindowPtr pChild;
+    ValidatePtr val;
+    ScreenPtr pScreen;
+    WindowExposuresProcPtr WindowExposures;
+
+    pScreen = pWin->drawable.pScreen;
+
+    pChild = pWin;
+    WindowExposures = pChild->drawable.pScreen->WindowExposures;
+    while (1)
+    {
+	if ( (val = pChild->valdata) )
+	{
+	    REGION_UNINIT(pScreen, &val->after.borderExposed);
+	    (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
+	    REGION_UNINIT(pScreen, &val->after.exposed);
+	    xfree(val);
+	    pChild->valdata = (ValidatePtr)NULL;
+	    if (pChild->firstChild)
+	    {
+		pChild = pChild->firstChild;
+		continue;
+	    }
+	}
+	while (!pChild->nextSib && (pChild != pWin))
+	    pChild = pChild->parent;
+	if (pChild == pWin)
+	    break;
+	pChild = pChild->nextSib;
     }
 }
 
@@ -216,15 +1017,27 @@ Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[])
 	dmxGeneration = serverGeneration;
     }
 
-    if (dmxShadowFB) {
-	dmxScreen->shadow = shadowAlloc(dmxScreen->scrnWidth,
-					dmxScreen->scrnHeight,
-					dmxScreen->beBPP);
-    } else {
-	if (!dmxInitGC(pScreen)) return FALSE;
-	if (!dmxInitWindow(pScreen)) return FALSE;
-	if (!dmxInitPixmap(pScreen)) return FALSE;
-    }
+    dmxInputInit (&dmxScreen->input);
+
+    dmxScreen->ignore.head = NULL;
+    dmxScreen->ignore.tail = &dmxScreen->ignore.head;
+
+    dmxScreen->request.head = NULL;
+    dmxScreen->request.tail = &dmxScreen->request.head;
+
+    dmxScreen->scrnEventMask = 0;
+
+    dmxScreen->rootEventMask = ExposureMask | StructureNotifyMask |
+	SubstructureRedirectMask;
+
+    dmxScreen->multipleAtom = MakeAtom ("MULTIPLE", strlen ("MULTIPLE"), TRUE);
+    dmxScreen->atomPairAtom = MakeAtom ("ATOM_PAIR", strlen ("ATOM_PAIR"), TRUE);
+    dmxScreen->incrAtom = MakeAtom ("INCR", strlen ("INCR"), TRUE);
+
+    if (!dmxInitGC(pScreen)) return FALSE;
+    if (!dmxInitWindow(pScreen)) return FALSE;
+    if (!dmxInitPixmap(pScreen)) return FALSE;
+    if (!dmxInitCursor(pScreen)) return FALSE;
 
     /*
      * Initalise the visual types.  miSetVisualTypesAndMasks() requires
@@ -233,120 +1046,213 @@ Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[])
      * Maybe a miAddVisualTypeAndMask() function will be added to make
      * things easier here.
      */
-    for (i = 0; i < dmxScreen->beNumDepths; i++) {
-	int    depth;
-	int    visuals        = 0;
-	int    bitsPerRgb     = 0;
-	int    preferredClass = -1;
-	Pixel  redMask        = 0;
-	Pixel  greenMask      = 0;
-	Pixel  blueMask       = 0;
-
-	depth = dmxScreen->beDepths[i];
-	for (j = 0; j < dmxScreen->beNumVisuals; j++) {
-	    XVisualInfo *vi;
-
-	    vi = &dmxScreen->beVisuals[j];
-	    if (vi->depth == depth) {
-		/* Assume the masks are all the same. */
-		visuals |= (1 << vi->class);
-		bitsPerRgb = vi->bits_per_rgb;
-		redMask = vi->red_mask;
-		greenMask = vi->green_mask;
-		blueMask = vi->blue_mask;
-		if (j == dmxScreen->beDefVisualIndex) {
-		    preferredClass = vi->class;
+    if (dmxScreen->beAttachedDisplay)
+    {
+	for (i = 0; i < dmxScreen->beNumDepths; i++) {
+	    int    depth;
+	    int    visuals        = 0;
+	    int    bitsPerRgb     = 0;
+	    int    preferredClass = -1;
+	    Pixel  redMask        = 0;
+	    Pixel  greenMask      = 0;
+	    Pixel  blueMask       = 0;
+
+	    depth = dmxScreen->beDepths[i];
+	    for (j = 0; j < dmxScreen->beNumVisuals; j++) {
+		XVisualInfo *vi;
+
+		vi = &dmxScreen->beVisuals[j];
+		if (vi->depth == depth) {
+		    /* Assume the masks are all the same. */
+		    visuals |= (1 << vi->class);
+		    bitsPerRgb = vi->bits_per_rgb;
+		    redMask = vi->red_mask;
+		    greenMask = vi->green_mask;
+		    blueMask = vi->blue_mask;
+		    if (j == dmxScreen->beDefVisualIndex) {
+			preferredClass = vi->class;
+		    }
 		}
 	    }
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		/* avoid additional DirectColor visuals for better
+		   back-end server support */
+		if (preferredClass != DirectColor)
+		    visuals &= ~(1 << DirectColor);
+	    }
+#endif
+
+	    miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb,
+				     preferredClass,
+				     redMask, greenMask, blueMask);
+	}
+    }
+    else
+    {
+	for (i = 0; i < dmxScreens[0].beNumDepths; i++) {
+	    int    depth;
+	    int    visuals        = 0;
+	    int    bitsPerRgb     = 0;
+	    int    preferredClass = -1;
+	    Pixel  redMask        = 0;
+	    Pixel  greenMask      = 0;
+	    Pixel  blueMask       = 0;
+
+	    depth = dmxScreens[0].beDepths[i];
+	    for (j = 0; j < dmxScreens[0].beNumVisuals; j++) {
+		XVisualInfo *vi;
+
+		vi = &dmxScreens[0].beVisuals[j];
+		if (vi->depth == depth) {
+		    /* Assume the masks are all the same. */
+		    visuals |= (1 << vi->class);
+		    bitsPerRgb = vi->bits_per_rgb;
+		    redMask = vi->red_mask;
+		    greenMask = vi->green_mask;
+		    blueMask = vi->blue_mask;
+		    if (j == dmxScreens[0].beDefVisualIndex) {
+			preferredClass = vi->class;
+		    }
+		}
+	    }
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		/* avoid additional DirectColor visuals for better
+		   back-end server support */
+		if (preferredClass != DirectColor)
+		    visuals &= ~(1 << DirectColor);
+	    }
+#endif
+
+	    miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb,
+				     preferredClass,
+				     redMask, greenMask, blueMask);
 	}
-	miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb, preferredClass,
-				 redMask, greenMask, blueMask);
     }
 
     fbScreenInit(pScreen,
-		 dmxShadowFB ? dmxScreen->shadow : NULL,
+		 NULL,
 		 dmxScreen->scrnWidth,
 		 dmxScreen->scrnHeight,
 		 dmxScreen->beXDPI,
-		 dmxScreen->beXDPI,
+		 dmxScreen->beYDPI,
 		 dmxScreen->scrnWidth,
 		 dmxScreen->beBPP);
+
+    if (!dmxScreen->scrnWin && dmxScreen->beDisplay)
+    {
+	dmxScreen->scrnWin = DefaultRootWindow (dmxScreen->beDisplay);
+	dmxScreen->scrnEventMask |= StructureNotifyMask;
+	XSelectInput (dmxScreen->beDisplay,
+		      dmxScreen->scrnWin,
+		      dmxScreen->scrnEventMask);
+    }
+
+#ifdef MITSHM
+    ShmRegisterDmxFuncs (pScreen);
+#endif
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	for (i = 0; i < pScreen->numVisuals; i++)
+	    if (pScreen->visuals[i].ColormapEntries > 256)
+		pScreen->visuals[i].ColormapEntries = 256;
+    }
+#endif
+
 #ifdef RENDER
-    (void)dmxPictureInit(pScreen, 0, 0);
+    if (!dmxPictureInit (pScreen, 0, 0))
+	return FALSE;
 #endif
 
-    if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL))
+#ifdef RANDR
+    if (!dmxRRScreenInit (pScreen))
+	return FALSE;
+#endif
+
+#ifdef XV
+    if (!dmxXvScreenInit (pScreen))
+	return FALSE;
+#endif
+
+    if (!dmxDnDScreenInit (pScreen))
 	return FALSE;
 
     miInitializeBackingStore(pScreen);
 
-    if (dmxShadowFB) {
-	miDCInitialize(pScreen, &dmxPointerCursorFuncs);
-    } else {
-        MAXSCREENSALLOC(dmxCursorGeneration);
-	if (dmxCursorGeneration[idx] != serverGeneration) {
-	    if (!(miPointerInitialize(pScreen,
-				      &dmxPointerSpriteFuncs,
-				      &dmxPointerCursorFuncs,
-				      FALSE)))
-		return FALSE;
-
-	    dmxCursorGeneration[idx] = serverGeneration;
-	}
+    MAXSCREENSALLOC(dmxCursorGeneration);
+    if (dmxCursorGeneration[idx] != serverGeneration) {
+	if (!(miPointerInitialize(pScreen,
+				  &dmxPointerSpriteFuncs,
+				  &dmxPointerCursorFuncs,
+				  FALSE)))
+	    return FALSE;
+
+	dmxCursorGeneration[idx] = serverGeneration;
     }
 
     DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen);
     DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen);
 
-    dmxBEScreenInit(idx, pScreen);
-
-    if (!dmxShadowFB) {
-	/* Wrap GC functions */
-	DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
-
-	/* Wrap Window functions */
-	DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
-	DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
-	DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
-	DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
-		 pScreen);
-	DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
-	DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
-	DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
-	DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
-	DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
-
-	DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
-	DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
-
-	DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
-
-	/* Wrap Image functions */
-	DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen);
-	DMX_WRAP(GetSpans, dmxGetSpans, dmxScreen, pScreen);
-
-	/* Wrap Pixmap functions */
-	DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
-	DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
-	DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen);
-
-	/* Wrap Font functions */
-	DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen);
-	DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen);
-
-	/* Wrap Colormap functions */
-	DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen);
-	DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen);
-	DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
-	DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen);
-
-	/* Wrap Shape functions */
-	DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
-    }
+    /* Wrap GC functions */
+    DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
+
+    /* Wrap Window functions */
+    DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
+    DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
+    DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
+    DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
+	     pScreen);
+    DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
+    DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
+    DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
+    DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
+
+    DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
+    DMX_WRAP(HandleExposures, dmxHandleExposures, dmxScreen, pScreen);
+    DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
+
+    DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
+
+    DMX_WRAP(ModifyPixmapHeader, dmxModifyPixmapHeader, dmxScreen, pScreen);
+
+    DMX_WRAP(SetWindowPixmap, dmxSetWindowPixmap, dmxScreen, pScreen);
+
+    /* Wrap Image functions */
+    DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen);
+    DMX_WRAP(GetSpans, NULL, dmxScreen, pScreen);
+
+    /* Wrap Pixmap functions */
+    DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
+    DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
+    DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen);
+
+    /* Wrap Font functions */
+    DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen);
+    DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen);
+
+    /* Wrap Colormap functions */
+    DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen);
+    DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen);
+    DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
+    DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen);
+
+    /* Wrap Shape functions */
+    DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
 
     if (!dmxCreateDefColormap(pScreen))
 	return FALSE;
 
+    RegisterBlockAndWakeupHandlers (dmxScreenBlockHandler,
+				    dmxScreenWakeupHandler,
+				    pScreen);
+
     return TRUE;
 }
 
@@ -356,51 +1262,38 @@ void dmxBECloseScreen(ScreenPtr pScreen)
     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
     int            i;
 
-    /* Restore the back-end screen-saver and DPMS state. */
-    dmxDPMSTerm(dmxScreen);
+#ifdef XV
+    dmxBEXvScreenFini (pScreen);
+#endif
 
-    /* Free the screen resources */
+#ifdef RANDR
+    dmxBERRScreenFini (pScreen);
+#endif
 
-    XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor);
-    dmxScreen->noCursor = (Cursor)0;
+    /* Restore the back-end screen-saver and DPMS state. */
+    dmxBEDPMSScreenFini (pScreen);
 
-    XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
-    XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
+    /* Free the screen resources */
     dmxScreen->scrnWin = (Window)0;
 
-    if (dmxShadowFB) {
-	/* Free the shadow GC and image assocated with the back-end server */
-	XFreeGC(dmxScreen->beDisplay, dmxScreen->shadowGC);
-	dmxScreen->shadowGC = NULL;
-	XFree(dmxScreen->shadowFBImage);
-	dmxScreen->shadowFBImage = NULL;
-    } else {
-	/* Free the default drawables */
-	for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
-	    XFreePixmap(dmxScreen->beDisplay, dmxScreen->scrnDefDrawables[i]);
-	    dmxScreen->scrnDefDrawables[i] = (Drawable)0;
-	}
+    /* Free the default drawables */
+    for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
+	XLIB_PROLOGUE (dmxScreen);
+	XFreePixmap(dmxScreen->beDisplay, dmxScreen->scrnDefDrawables[i]);
+	XLIB_EPILOGUE (dmxScreen);
+	dmxScreen->scrnDefDrawables[i] = (Drawable)0;
     }
 
     /* Free resources allocated during initialization (in dmxinit.c) */
     for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
+    {
+	XLIB_PROLOGUE (dmxScreen);
 	XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]);
+	XLIB_EPILOGUE (dmxScreen);
+    }
     xfree(dmxScreen->beDefColormaps);
     dmxScreen->beDefColormaps = NULL;
 
-#if 0
-    /* Do not free visuals, depths and pixmap formats here.  Free them
-     * in dmxCloseScreen() instead -- see comment below. */
-    XFree(dmxScreen->beVisuals);
-    dmxScreen->beVisuals = NULL;
-
-    XFree(dmxScreen->beDepths);
-    dmxScreen->beDepths = NULL;
-
-    XFree(dmxScreen->bePixmapFormats);
-    dmxScreen->bePixmapFormats = NULL;
-#endif
-
 #ifdef GLXEXT
     if (dmxScreen->glxVisuals) {
 	XFree(dmxScreen->glxVisuals);
@@ -409,9 +1302,8 @@ void dmxBECloseScreen(ScreenPtr pScreen)
     }
 #endif
 
-    /* Close display */
-    XCloseDisplay(dmxScreen->beDisplay);
-    dmxScreen->beDisplay = NULL;
+    dmxClearQueue (&dmxScreen->request);
+    dmxClearQueue (&dmxScreen->ignore);
 }
 
 /** Close screen number \a idx. */
@@ -419,62 +1311,77 @@ Bool dmxCloseScreen(int idx, ScreenPtr pScreen)
 {
     DMXScreenInfo *dmxScreen = &dmxScreens[idx];
 
+        /* Free input overlay window tree */
+    if (dmxScreen->inputOverlayWid)
+	FreeResource (dmxScreen->inputOverlayWid, RT_NONE);
+
     /* Reset the proc vectors */
     if (idx == 0) {
+#ifdef COMPOSITE
+	if (!noCompositeExtension)
+	    dmxResetComposite();
+#endif
 #ifdef RENDER
-	dmxResetRender();
+	if (!noRenderExtension)
+	    dmxResetRender();
+#endif
+#ifdef MITSHM
+	dmxResetShm();
 #endif
-	dmxResetFonts();
+	dmxResetSelections();
+	dmxResetGrabs();
+	dmxResetProps();
     }
 
-    if (dmxShadowFB) {
-	/* Free the shadow framebuffer */
-	xfree(dmxScreen->shadow);
-    } else {
+    /* Unwrap Shape functions */
+    DMX_UNWRAP(SetShape, dmxScreen, pScreen);
 
-	/* Unwrap Shape functions */
-	DMX_UNWRAP(SetShape, dmxScreen, pScreen);
+    /* Unwrap the pScreen functions */
+    DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
 
-	/* Unwrap the pScreen functions */
-	DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
+    DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
+    DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
 
-	DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
-	DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
-	DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
-	DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
-	DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
-	DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
-	DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
-	DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
-	DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(HandleExposures, dmxScreen, pScreen);
+    DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
 
-	DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
-	DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
+    DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
 
-	DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
+    DMX_UNWRAP(ModifyPixmapHeader, dmxScreen, pScreen);
 
-	DMX_UNWRAP(GetImage, dmxScreen, pScreen);
-	DMX_UNWRAP(GetSpans, dmxScreen, pScreen);
+    DMX_UNWRAP(SetWindowPixmap, dmxScreen, pScreen);
 
-	DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
-	DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
-	DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen);
+    DMX_UNWRAP(GetImage, dmxScreen, pScreen);
+    DMX_UNWRAP(GetSpans, dmxScreen, pScreen);
 
-	DMX_UNWRAP(RealizeFont, dmxScreen, pScreen);
-	DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen);
+    DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
+    DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
+    DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen);
 
-	DMX_UNWRAP(CreateColormap, dmxScreen, pScreen);
-	DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen);
-	DMX_UNWRAP(InstallColormap, dmxScreen, pScreen);
-	DMX_UNWRAP(StoreColors, dmxScreen, pScreen);
-    }
+    DMX_UNWRAP(RealizeFont, dmxScreen, pScreen);
+    DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen);
+
+    DMX_UNWRAP(CreateColormap, dmxScreen, pScreen);
+    DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen);
+    DMX_UNWRAP(InstallColormap, dmxScreen, pScreen);
+    DMX_UNWRAP(StoreColors, dmxScreen, pScreen);
 
     DMX_UNWRAP(SaveScreen, dmxScreen, pScreen);
 
     if (dmxScreen->beDisplay) {
 	dmxBECloseScreen(pScreen);
 
-#if 1
+	/* Close display */
+	dmxCloseDisplay (dmxScreen);
+	dmxScreen->beDisplay = NULL;
+
 	/* Free visuals, depths and pixmap formats here so that they
 	 * won't be freed when a screen is detached, thereby allowing
 	 * the screen to be reattached to be compared to the one
@@ -488,9 +1395,11 @@ Bool dmxCloseScreen(int idx, ScreenPtr pScreen)
 
 	XFree(dmxScreen->bePixmapFormats);
 	dmxScreen->bePixmapFormats = NULL;
-#endif
     }
 
+    if (idx == 0)
+	dmxAbortDisplay ();
+
     DMX_UNWRAP(CloseScreen, dmxScreen, pScreen);
     return pScreen->CloseScreen(idx, pScreen);
 }
@@ -500,15 +1409,21 @@ static Bool dmxSaveScreen(ScreenPtr pScreen, int what)
     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
 
     if (dmxScreen->beDisplay) {
+	if (dmxScreen->scrnWin != DefaultRootWindow (dmxScreen->beDisplay))
+	    return TRUE;
 	switch (what) {
 	case SCREEN_SAVER_OFF:
 	case SCREEN_SAVER_FORCER:
+	    XLIB_PROLOGUE (dmxScreen);
 	    XResetScreenSaver(dmxScreen->beDisplay);
+	    XLIB_EPILOGUE (dmxScreen);
 	    dmxSync(dmxScreen, FALSE);
 	    break;
 	case SCREEN_SAVER_ON:
 	case SCREEN_SAVER_CYCLE:
+	    XLIB_PROLOGUE (dmxScreen);
 	    XActivateScreenSaver(dmxScreen->beDisplay);
+	    XLIB_EPILOGUE (dmxScreen);
 	    dmxSync(dmxScreen, FALSE);
 	    break;
 	}
@@ -516,3 +1431,60 @@ static Bool dmxSaveScreen(ScreenPtr pScreen, int what)
 
     return TRUE;
 }
+
+Bool
+dmxAddSequence (DMXQueue      *q,
+		unsigned long sequence)
+{
+    DMXSequence *s;
+
+    s = malloc (sizeof (DMXSequence));
+    if (!s)
+	return FALSE;
+
+    s->sequence = sequence;
+    s->next     = 0;
+
+    *(q->tail) = s;
+    q->tail = &s->next;
+
+    return TRUE;
+}
+
+void
+dmxClearQueue (DMXQueue *q)
+{
+    while (q->head)
+    {
+	DMXSequence *head = q->head;
+
+	q->head = head->next;
+	free (head);
+    }
+
+    q->tail = &q->head;
+}
+
+Bool
+dmxAddRequest (DMXQueue      *q,
+	       ReplyProcPtr  reply,
+	       unsigned long sequence,
+	       void          *data)
+{
+    DMXRequest *r;
+
+    r = malloc (sizeof (DMXRequest));
+    if (!r)
+	return FALSE;
+
+    r->base.sequence = sequence;
+    r->base.next     = 0;
+    r->reply         = reply;
+    r->data          = data;
+
+    *(q->tail) = &r->base;
+    q->tail = &r->base.next;
+
+    return TRUE;
+}
+
diff --git a/hw/dmx/dmxscrinit.h b/hw/dmx/dmxscrinit.h
index a464235..5ac4c36 100644
--- a/hw/dmx/dmxscrinit.h
+++ b/hw/dmx/dmxscrinit.h
@@ -45,7 +45,16 @@ extern DevPrivateKey dmxScreenPrivateKey;
 
 extern Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[]);
 
-extern void dmxBEScreenInit(int idx, ScreenPtr pScreen);
+extern void dmxBEScreenInit(ScreenPtr pScreen);
 extern void dmxBECloseScreen(ScreenPtr pScreen);
+extern void dmxBEDispatch (ScreenPtr pScreen);
+
+extern Bool dmxAddSequence (DMXQueue *q, unsigned long sequence);
+extern void dmxClearQueue (DMXQueue *q);
+
+extern Bool dmxAddRequest (DMXQueue      *q,
+			   ReplyProcPtr  reply,
+			   unsigned long sequence,
+			   void          *data);
 
 #endif /* DMXSCRINIT_H */
diff --git a/hw/dmx/dmxselection.c b/hw/dmx/dmxselection.c
new file mode 100644
index 0000000..76113f4
--- /dev/null
+++ b/hw/dmx/dmxselection.c
@@ -0,0 +1,1539 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxlog.h"
+#include "dmxatom.h"
+#include "dmxwindow.h"
+#include "dmxscrinit.h"
+#include "dmxsync.h"
+#include "dmxdnd.h"
+#include "dmxselection.h"
+
+#include "selection.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#define DMX_SELECTION_TIMEOUT (30 * 1000) /* 30 seconds */
+
+typedef struct _DMXSelection {
+    struct _DMXSelection *next;
+
+    XID  wid;
+    XID  requestor;
+    Atom selection;
+    Atom target;
+    Atom property;
+    Time time;
+    Bool incr;
+
+    struct {
+	unsigned int in;
+	unsigned int out;
+    } value[MAXSCREENS];
+
+    OsTimerPtr timer;
+} DMXSelection;
+
+static DMXSelection *convHead = NULL;
+static DMXSelection *propHead = NULL;
+static DMXSelection *reqHead  = NULL;
+
+static DMXSelection *
+dmxUnhookSelection (DMXSelection **head,
+		    DMXSelection *s)
+{
+    DMXSelection *p, *prev = NULL;
+
+    for (p = *head; p; p = p->next)
+    {
+	if (p == s)
+	    break;
+
+	prev = p;
+    }
+
+    assert (p);
+
+    if (prev)
+	prev->next = s->next;
+    else
+	*head = s->next;
+
+    s->next = NULL;
+
+    TimerCancel (s->timer);
+
+    return s;
+}
+
+static int
+dmxSelectionDeleteConv (DMXSelection *s)
+{
+    WindowPtr pWin;
+    xEvent    event;
+
+    event.u.u.type = SelectionNotify;
+    event.u.selectionNotify.time = s->time;
+    event.u.selectionNotify.requestor = s->wid;
+    event.u.selectionNotify.selection = s->selection;
+    event.u.selectionNotify.target = s->target;
+    event.u.selectionNotify.property = None;
+
+    if (dixLookupWindow (&pWin,
+			 s->wid,
+			 serverClient,
+			 DixReadAccess) == Success)
+	DeliverEventsToWindow (inputInfo.pointer, pWin, &event, 1,
+			       NoEventMask, NullGrab, 0);
+
+    if (s->timer)
+	TimerFree (s->timer);
+
+    xfree (s);
+    return 0;
+}
+
+static int
+dmxSelectionDeleteProp (DMXSelection *s)
+{
+    int i;
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+	
+	if (s->incr && s->value[i].out)
+	{
+	    const uint32_t value = 0;
+
+	    xcb_change_window_attributes (dmxScreen->connection,
+					  s->value[i].out,
+					  XCB_CW_EVENT_MASK,
+					  &value);
+	}
+    }
+
+    if (s->timer)
+	TimerFree (s->timer);
+
+    xfree (s);
+    return 0;
+}
+
+static int
+dmxSelectionDeleteReq (DMXSelection *s)
+{
+    int i;
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	if (s->value[i].out)
+	{
+	    DMXScreenInfo  *dmxScreen = &dmxScreens[i];
+	    const uint32_t value = 0;
+
+	    xcb_change_window_attributes (dmxScreen->connection,
+					  s->value[i].out,
+					  XCB_CW_EVENT_MASK,
+					  &value);
+	}
+    }
+
+    if (s->wid)
+    {
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    PanoramiXRes *win;
+
+	    win = (PanoramiXRes *) SecurityLookupIDByType (serverClient,
+							   s->wid,
+							   XRT_WINDOW,
+							   DixDestroyAccess);
+
+	    if (win)
+	    {
+		int j;
+
+		FOR_NSCREENS_BACKWARD(j) {
+		    FreeResource (win->info[j].id, RT_NONE);
+		}
+	    }
+	}
+	else
+#endif
+
+	    FreeResource (s->wid, RT_NONE);
+    }
+
+    if (s->timer)
+	TimerFree (s->timer);
+
+    xfree (s);
+    return 0;
+}
+
+static CARD32
+dmxSelectionCallback (OsTimerPtr timer,
+		      CARD32     time,
+		      pointer    arg)
+{
+    DMXSelection *r = (DMXSelection *) arg;
+    DMXSelection *s;
+
+    if (time)
+	dmxLog (dmxWarning,
+		"selection conversion for %s timed out\n",
+		NameForAtom (r->selection));
+
+    for (s = convHead; s; s = s->next)
+	if (s == r)
+	    return dmxSelectionDeleteConv (dmxUnhookSelection (&convHead, s));
+
+    for (s = propHead; s; s = s->next)
+	if (s == r)
+	    return dmxSelectionDeleteProp (dmxUnhookSelection (&propHead, s));
+
+    for (s = reqHead; s; s = s->next)
+	if (s == r)
+	    return dmxSelectionDeleteReq (dmxUnhookSelection (&reqHead, s));
+
+    return 0;
+}
+
+static void
+dmxSelectionResetTimer (DMXSelection *s)
+{
+    s->timer = TimerSet (s->timer,
+			 0,
+			 DMX_SELECTION_TIMEOUT,
+			 dmxSelectionCallback,
+			 s);
+}
+
+static void
+dmxAppendSelection (DMXSelection **head,
+		    DMXSelection *s)
+{
+    DMXSelection *p, *last;
+
+    do {
+	for (last = NULL, p = *head; p; p = p->next)
+	{
+	    /* avoid duplicates */
+	    if (p->selection == s->selection &&
+		p->requestor == s->requestor)
+	    {
+		if (p->timer)
+		    TimerCancel (p->timer);
+
+		dmxSelectionCallback (s->timer, 0, p);
+		break;
+	    }
+
+	    last = p;
+	}
+    } while (p);
+
+    dmxSelectionResetTimer (s);
+
+    if (last)
+	last->next = s;
+    else
+	*head = s;
+}
+
+static Atom
+dmxBESelectionAtom (DMXScreenInfo *dmxScreen,
+		    Atom	  atom)
+{
+    int i;
+
+    for (i = 0; i < dmxSelectionMapNum; i++)
+	if (atom == dmxSelectionMap[i].atom)
+	    return dmxBEAtom (dmxScreen, dmxSelectionMap[i].beAtom);
+
+    return dmxBEAtom (dmxScreen, atom);
+}
+
+static Atom
+dmxSelectionAtom (DMXScreenInfo *dmxScreen,
+		  Atom	        atom)
+{
+    int i;
+
+    for (i = 0; i < dmxSelectionMapNum; i++)
+	if (atom == dmxSelectionMap[i].beAtom)
+	    return dmxAtom (dmxScreen, dmxSelectionMap[i].atom);
+
+    return dmxAtom (dmxScreen, atom);
+}
+
+static void
+dmxBESetSelectionOwner (ScreenPtr pScreen,
+			WindowPtr pWin,
+			Atom      selection)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    Window        window = None;
+
+    if (!dmxScreen->beDisplay)
+	return;
+    
+    if (dmxScreen->selectionOwner != dmxScreen->rootWin)
+	return;
+
+    if (pWin)
+	window = DMX_GET_WINDOW_PRIV(pWin)->window;
+    
+    xcb_set_selection_owner (dmxScreen->connection,
+			     window,
+			     dmxBESelectionAtom (dmxScreen, selection),
+			     0);
+}
+
+static void
+dmxSelectionOwnerReply (ScreenPtr           pScreen,
+			unsigned int        sequence,
+			xcb_generic_reply_t *reply,
+			xcb_generic_error_t *error,
+			void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (reply)
+    {
+	xcb_get_selection_owner_reply_t *xselection =
+	    (xcb_get_selection_owner_reply_t *) reply;
+
+	dmxScreen->getSelectionOwnerResult = xselection->owner;
+    }
+
+    dmxScreen->getSelectionOwner.sequence = 0;
+}
+
+static Bool
+dmxBEGetSelectionOwner (ScreenPtr pScreen,
+			Atom      selection)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    /* reset getSelectionOwner fields */
+    dmxScreen->getSelectionOwner.sequence = 0;
+    dmxScreen->getSelectionOwnerResult = 0;
+
+    if (!dmxScreen->beDisplay)
+	return FALSE;
+
+    if (dmxScreen->selectionOwner != dmxScreen->rootWin)
+	return FALSE;
+
+    dmxScreen->getSelectionOwner =
+	xcb_get_selection_owner (dmxScreen->connection,
+				 dmxBESelectionAtom (dmxScreen, selection));
+
+    dmxAddRequest (&dmxScreen->request,
+		   dmxSelectionOwnerReply,
+		   dmxScreen->getSelectionOwner.sequence,
+		   0);
+
+    return TRUE;
+}
+
+static Window
+dmxBEConvertSelection (WindowPtr pWin,
+		       Atom      selection,
+		       Atom      target,
+		       Atom      property,
+		       Time      time)
+{
+    ScreenPtr     pScreen = pWin->drawable.pScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWin);
+
+    if (!dmxScreen->beDisplay || !pWinPriv->window)
+	return 0;
+
+    if (dmxScreen->selectionOwner != dmxScreen->rootWin)
+	return 0;
+
+    xcb_convert_selection (dmxScreen->connection,
+			   pWinPriv->window,
+			   dmxBESelectionAtom (dmxScreen, selection),
+			   dmxBEAtom (dmxScreen, target),
+			   property ? dmxBEAtom (dmxScreen, property) : None,
+			   0);
+
+    dmxSync (dmxScreen, FALSE);
+
+    return pWinPriv->window;
+}
+
+Window
+dmxBEGetSelectionAdjustedPropertyWindow (WindowPtr pWin)
+{
+    ScreenPtr     pScreen = pWin->drawable.pScreen;
+    dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pWin);
+    DMXSelection  *s;
+
+    if (!pWinPriv->window)
+	return None;
+
+    for (s = reqHead; s; s = s->next)
+	if (s->value[pScreen->myNum].in == pWinPriv->window)
+	    return s->value[pScreen->myNum].out;
+
+    return pWinPriv->window;
+}
+
+void
+dmxSelectionClear (ScreenPtr pScreen,
+		   Window    owner,
+		   Atom      xSelection)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    Atom          selection = dmxSelectionAtom (dmxScreen, xSelection);
+    Selection     *pSel;
+
+    if (!ValidAtom (selection))
+	return;
+
+    if (dixLookupSelection (&pSel,
+			    selection,
+			    serverClient,
+			    DixGetAttrAccess) == Success &&
+	pSel->client != NullClient)
+    {
+	SelectionInfoRec info = { pSel, NullClient, SelectionSetOwner };
+	xEvent           event;
+
+	event.u.u.type = SelectionClear;
+	event.u.selectionClear.time = currentTime.milliseconds;
+	event.u.selectionClear.window = pSel->window;
+	event.u.selectionClear.atom = pSel->selection;
+
+	TryClientEvents (pSel->client, NULL, &event, 1, NoEventMask,
+			 NoEventMask /* CantBeFiltered */, NullGrab);
+
+	pSel->lastTimeChanged = currentTime;
+	pSel->window = dmxScreen->inputOverlayWid;
+	pSel->pWin = NULL;
+	pSel->client = NullClient;
+
+	CallCallbacks (&SelectionCallback, &info);
+
+	pSel->window = None;
+    }
+}
+
+static void
+dmxSelectionPropertyReply (ScreenPtr           pScreen,
+			   unsigned int        sequence,
+			   xcb_generic_reply_t *reply,
+			   xcb_generic_error_t *error,
+			   void                *data)
+{
+    DMXSelection *s;
+
+    for (s = propHead; s; s = s->next)
+	if (s->value[pScreen->myNum].in == sequence)
+	    break;
+
+    if (s)
+    {
+	WindowPtr                pWin = NullWindow;
+	xcb_get_property_reply_t *xproperty =
+	    (xcb_get_property_reply_t *) reply;
+
+	if (dixLookupWindow (&pWin,
+			     s->wid,
+			     serverClient,
+			     DixReadAccess) == Success)
+	{
+	    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+	    xEvent        event;
+
+	    event.u.selectionNotify.property = None;
+
+	    if (reply)
+	    {
+		Atom     type = dmxAtom (dmxScreen, xproperty->type);
+		uint32_t *data = xcb_get_property_value (xproperty);
+		int      length = xcb_get_property_value_length (xproperty);
+
+		/* only 32 bit data types can be translated */
+		if (xproperty->format == 32)
+		{
+		    int i;
+
+		    switch (type) {
+		    case XA_ATOM:
+			for (i = 0; i < length; i++)
+			    data[i] = dmxAtom (dmxScreen, data[i]);
+			break;
+		    case XA_BITMAP:
+		    case XA_PIXMAP:
+		    case XA_COLORMAP:
+		    case XA_CURSOR:
+		    case XA_DRAWABLE:
+		    case XA_FONT:
+		    case XA_VISUALID:
+		    case XA_WINDOW:
+			/* XXX: there's no guarantee that properties of these
+			   types can be converted as all back-end resources
+			   don't exist on this server.
+			*/
+			type = 0;
+		    default:
+			if (type == dmxScreen->atomPairAtom)
+			    for (i = 0; i < length; i++)
+				data[i] = dmxAtom (dmxScreen, data[i]);
+			break;
+		    }
+		}
+
+		if (ValidAtom (type) &&
+		    ChangeWindowProperty (pWin,
+					  s->property,
+					  type,
+					  xproperty->format,
+					  PropModeReplace,
+					  length,
+					  data,
+					  TRUE) == Success)
+		    event.u.selectionNotify.property = s->property;
+	    }
+
+	    if (s->target)
+	    {
+		event.u.u.type = SelectionNotify | 0x80;
+		event.u.selectionNotify.time = s->time;
+		event.u.selectionNotify.requestor = s->wid;
+		event.u.selectionNotify.selection = s->selection;
+		event.u.selectionNotify.target = s->target;
+
+		TryClientEvents (wClient (pWin), NULL, &event, 1, NoEventMask,
+				 NoEventMask /* CantBeFiltered */, NullGrab);
+	    }
+
+	    if (s->incr)
+	    {	
+		/* end of incremental selection transfer when size is 0 */
+		if (xproperty->value_len != 0)
+		{
+		    /* don't send another selection notify event */
+		    s->target = None;
+		    dmxSelectionResetTimer (s);
+		    return;
+		}
+	    }
+	}
+
+	dmxSelectionDeleteProp (dmxUnhookSelection (&propHead, s));
+    }
+}
+
+void
+dmxSelectionNotify (ScreenPtr pScreen,
+		    Window    requestor,
+		    Atom      xSelection,
+		    Atom      xTarget,
+		    Atom      xProperty,
+		    Time      xTime)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    Atom          selection = dmxSelectionAtom (dmxScreen, xSelection);
+    DMXSelection  *s;
+
+    for (s = convHead; s; s = s->next)
+	if (s->value[pScreen->myNum].out == requestor &&
+	    s->selection                 == selection)
+	    break;
+
+    if (s)
+    {
+	xcb_get_property_cookie_t cookie = { 0 };
+	Atom                      property = dmxAtom (dmxScreen, xProperty);
+	Atom                      target = dmxAtom (dmxScreen, xTarget);
+
+	if (ValidAtom (property) && ValidAtom (target))
+	    cookie = xcb_get_property (dmxScreen->connection,
+				       xFalse,
+				       requestor,
+				       xProperty,
+				       XCB_GET_PROPERTY_TYPE_ANY,
+				       0,
+				       0xffffffff);
+
+	if (cookie.sequence)
+	{
+	    const uint32_t value =
+		XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+		XCB_EVENT_MASK_PROPERTY_CHANGE;
+
+	    dmxUnhookSelection (&convHead, s);
+
+	    memset (s->value, 0, sizeof (s->value));
+
+	    s->value[pScreen->myNum].out = requestor;
+	    s->value[pScreen->myNum].in = cookie.sequence;
+
+	    s->property = property;
+	    s->target = target;
+
+	    if (target == dmxScreen->incrAtom)
+		s->incr = TRUE;
+
+	    if (s->incr)
+		xcb_change_window_attributes (dmxScreen->connection,
+					      requestor,
+					      XCB_CW_EVENT_MASK,
+					      &value);
+
+	    dmxAppendSelection (&propHead, s);
+
+	    dmxAddRequest (&dmxScreen->request,
+			   dmxSelectionPropertyReply,
+			   cookie.sequence,
+			   0);
+	}
+	else
+	{
+	    int i;
+	    
+	    s->value[pScreen->myNum].out = 0;
+
+	    for (i = 0; i < dmxNumScreens; i++)
+		if (s->value[i].out)
+		    break;
+
+	    if (i == dmxNumScreens)
+		dmxSelectionDeleteConv (dmxUnhookSelection (&convHead, s));
+	}
+    }
+}
+
+Bool
+dmxSelectionDestroyNotify (ScreenPtr pScreen,
+			   Window    window)
+{
+    DMXSelection *s;
+
+    for (s = reqHead; s; s = s->next)
+	if (s->value[pScreen->myNum].out == window)
+	    break;
+
+    if (s)
+    {
+	dmxSelectionDeleteReq (dmxUnhookSelection (&reqHead, s));
+	return TRUE;
+    }
+
+    for (s = propHead; s; s = s->next)
+	if (s->value[pScreen->myNum].out == window)
+	    break;
+
+    if (s)
+    {
+	s->value[pScreen->myNum].out = None;
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+Bool
+dmxSelectionPropertyNotify (ScreenPtr pScreen,
+			    Window    window,
+			    int       state,
+			    Atom      xProperty,
+			    Time      xTime)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    DMXSelection  *s;
+
+    if (state == XCB_PROPERTY_NEW_VALUE)
+    {
+	for (s = propHead; s; s = s->next)
+	    if (s->value[pScreen->myNum].out == window)
+		break;
+
+	if (s)
+	{
+	    xcb_get_property_cookie_t cookie = { 0 };
+
+	    cookie = xcb_get_property (dmxScreen->connection,
+				       xFalse,
+				       window,
+				       xProperty,
+				       XCB_GET_PROPERTY_TYPE_ANY,
+				       0,
+				       0xffffffff);
+
+	    if (cookie.sequence)
+	    {
+		s->value[pScreen->myNum].in = cookie.sequence;
+		dmxAddRequest (&dmxScreen->request,
+			       dmxSelectionPropertyReply,
+			       cookie.sequence,
+			       0);
+		dmxSelectionResetTimer (s);
+	    }
+	    else
+	    {
+		dmxSelectionDeleteProp (dmxUnhookSelection (&propHead, s));
+	    }
+	}
+    }
+    else
+    {
+	for (s = reqHead; s; s = s->next)
+	    if (s->value[pScreen->myNum].out == window &&
+		s->property                  == dmxAtom (dmxScreen, xProperty))
+		break;
+
+	if (s)
+	{
+	    WindowPtr pWin;
+
+	    if (dixLookupWindow (&pWin,
+				 s->wid,
+				 serverClient,
+				 DixReadAccess) == Success)
+		DeleteProperty (serverClient, pWin, s->property);
+
+	    if (s->incr)
+		TimerCancel (s->timer);
+	    else
+		dmxSelectionDeleteReq (dmxUnhookSelection (&reqHead, s));
+	}
+    }
+
+    return TRUE;
+}
+
+static Bool
+dmxConvertSelection (ScreenPtr    pScreen,
+		     DMXSelection *s,
+		     Window       owner,
+		     int          multipleLength,
+		     uint32_t     *multipleData)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    WindowPtr     pChild0, pChildN;
+    Selection     *pSel = NULL;
+
+    pChild0 = WindowTable[0];
+    pChildN = WindowTable[pScreen->myNum];
+
+    for (;;)
+    {
+	dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pChildN);
+
+	if (pWinPriv->window == owner)
+	{
+	    dixLookupSelection (&pSel,
+				s->selection,
+				serverClient,
+				DixReadAccess);
+	    break;
+	}
+
+	if (pChild0->firstChild)
+	{
+	    pChild0 = pChild0->firstChild;
+	    pChildN = pChildN->firstChild;
+	    continue;
+	}
+
+	while (!pChild0->nextSib && (pChild0 != WindowTable[0]))
+	{
+	    pChild0 = pChild0->parent;
+	    pChildN = pChildN->parent;
+	}
+
+	if (pChild0 == WindowTable[0])
+	    break;
+
+	pChild0 = pChild0->nextSib;
+	pChildN = pChildN->nextSib;
+    }
+
+    if (pSel)
+    {
+	XID       overrideRedirect = TRUE;
+	WindowPtr pProxy = NullWindow;
+	int       result;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    PanoramiXRes *newWin;
+	    int          j;
+
+	    if (!(newWin = (PanoramiXRes *) xalloc (sizeof (PanoramiXRes))))
+		return FALSE;
+
+	    newWin->type = XRT_WINDOW;
+	    newWin->u.win.visibility = VisibilityNotViewable;
+	    newWin->u.win.class = InputOnly;
+	    newWin->u.win.root = FALSE;
+	    for (j = 0; j < PanoramiXNumScreens; j++)
+		newWin->info[j].id = FakeClientID (0);
+
+	    FOR_NSCREENS_BACKWARD(j) {
+		pProxy = CreateWindow (newWin->info[j].id,
+				       dmxScreens[j].pInputOverlayWin,
+				       0, 0, 1, 1, 0, InputOnly, 
+				       CWOverrideRedirect, &overrideRedirect,
+				       0, serverClient, CopyFromParent, 
+				       &result);
+		if (result != Success)
+		    return FALSE;
+		if (!AddResource (pProxy->drawable.id, RT_WINDOW, pProxy))
+		    return FALSE;
+
+		s->value[j].in = DMX_GET_WINDOW_PRIV (pProxy)->window;
+	    }
+	    
+	    AddResource (newWin->info[0].id, XRT_WINDOW, newWin);
+	}
+	else
+#endif
+	
+	{
+	    pProxy = CreateWindow (FakeClientID (0),
+				   dmxScreens[0].pInputOverlayWin,
+				   0, 0, 1, 1, 0, InputOnly, 
+				   CWOverrideRedirect, &overrideRedirect,
+				   0, serverClient, CopyFromParent, 
+				   &result);
+	    if (result != Success)
+		return FALSE;
+	    if (!AddResource (pProxy->drawable.id, RT_WINDOW, pProxy))
+		return FALSE;
+
+	    s->value[0].in = DMX_GET_WINDOW_PRIV (pProxy)->window;
+	}
+	
+	if (pProxy)
+	{
+	    xEvent event;
+
+	    event.u.u.type = SelectionRequest;
+	    event.u.selectionRequest.owner = pSel->window;
+	    event.u.selectionRequest.time = currentTime.milliseconds;
+	    event.u.selectionRequest.requestor = pProxy->drawable.id;
+	    event.u.selectionRequest.selection = s->selection;
+	    event.u.selectionRequest.target = s->target;
+	    event.u.selectionRequest.property = s->property;
+
+	    s->wid       = pProxy->drawable.id;
+	    s->requestor = pProxy->drawable.id;
+
+	    if (TryClientEvents (pSel->client, NULL, &event, 1,
+				 NoEventMask,
+				 NoEventMask /* CantBeFiltered */,
+				 NullGrab))
+	    {
+		if (multipleLength)
+		    ChangeWindowProperty (pProxy,
+					  s->property,
+					  dmxScreen->atomPairAtom,
+					  32,
+					  PropModeReplace,
+					  multipleLength,
+					  multipleData,
+					  TRUE);
+
+		dmxAppendSelection (&reqHead, s);
+		return TRUE;
+	    }
+	}
+
+	dmxSelectionDeleteReq (s);
+    }
+	
+    return FALSE;
+}
+
+static void
+dmxMultipleTargetPropertyReply (ScreenPtr           pScreen,
+				unsigned int        sequence,
+				xcb_generic_reply_t *reply,
+				xcb_generic_error_t *error,
+				void                *data)
+{
+    xcb_selection_notify_event_t xevent;
+    DMXScreenInfo                *dmxScreen = &dmxScreens[pScreen->myNum];
+    DMXSelection                 *s = (DMXSelection  *) data;
+
+    if (reply)
+    {
+	xcb_get_property_reply_t *xproperty =
+	    (xcb_get_property_reply_t *) reply;
+
+	if (xproperty->format == 32)
+	{
+	    uint32_t *data = xcb_get_property_value (xproperty);
+	    int      length = xcb_get_property_value_length (xproperty);
+	    int      i;
+
+	    for (i = 0; i < length; i++)
+	    {
+		data[i] = dmxAtom (dmxScreen, data[i]);
+		if ((i & 1) == 0 && data[i] == dmxScreen->incrAtom)
+		    s->incr = TRUE;
+	    }
+
+	    if (dmxConvertSelection (pScreen, s, s->wid, length, data))
+		return;
+	}
+    }
+
+    xevent.response_type = XCB_SELECTION_NOTIFY;
+    xevent.pad0 = 0;
+    xevent.sequence = 0;
+    xevent.time = s->time;
+    xevent.requestor = s->value[pScreen->myNum].out;
+    xevent.selection = dmxBESelectionAtom (dmxScreen, s->selection);
+    xevent.target = dmxBEAtom (dmxScreen, s->target);
+    xevent.property = 0;
+
+    xcb_send_event (dmxScreen->connection,
+		    FALSE,
+		    s->value[pScreen->myNum].out,
+		    0,
+		    (const char *) &xevent);
+
+    dmxSync (dmxScreen, FALSE);
+
+    free (s);
+}
+
+void
+dmxSelectionRequest (ScreenPtr pScreen,
+		     Window    owner,
+		     Window    requestor,
+		     Atom      xSelection,
+		     Atom      xTarget,
+		     Atom      xProperty,
+		     Time      xTime)
+{
+    xcb_selection_notify_event_t xevent;
+    DMXScreenInfo                *dmxScreen = &dmxScreens[pScreen->myNum];
+    Atom                         selection =
+	dmxSelectionAtom (dmxScreen, xSelection);
+
+    if (ValidAtom (selection))
+    {
+	Atom target = dmxAtom (dmxScreen, xTarget);
+	Atom property = (xProperty) ? dmxAtom (dmxScreen, xProperty) : None;
+
+	if (ValidAtom (target) && ((property == None) || ValidAtom (property)))
+	{
+	    DMXSelection *s;
+
+	    s = xalloc (sizeof (DMXSelection));
+	    if (s)
+	    {
+		s->wid       = 0;
+		s->requestor = 0;
+		s->selection = selection;
+		s->target    = target;
+		s->property  = property;
+		s->time      = xTime;
+		s->incr      = FALSE;
+		s->next      = 0;
+		s->timer     = 0;
+
+		memset (s->value, 0, sizeof (s->value));
+
+		s->value[pScreen->myNum].out = requestor;
+
+		if (target == dmxScreen->multipleAtom)
+		{
+		    if (ValidAtom (property))
+		    {
+			xcb_get_property_cookie_t prop;
+
+			prop = xcb_get_property (dmxScreen->connection,
+						 xFalse,
+						 requestor,
+						 xProperty,
+						 XCB_GET_PROPERTY_TYPE_ANY,
+						 0,
+						 0xffffffff);
+
+			s->wid = owner;
+
+			dmxAddRequest (&dmxScreen->request,
+				       dmxMultipleTargetPropertyReply,
+				       prop.sequence,
+				       (void *) s);
+
+			return;
+		    }
+		}
+		else
+		{
+		    if (dmxConvertSelection (pScreen, s, owner, 0, 0))
+			return;
+		}
+	    }
+
+	    xfree (s);
+	}
+    }
+	
+    xevent.response_type = XCB_SELECTION_NOTIFY;
+    xevent.pad0 = 0;
+    xevent.sequence = 0;
+    xevent.time = xTime;
+    xevent.requestor = requestor;
+    xevent.selection = xSelection;
+    xevent.target = xTarget;
+    xevent.property = 0;
+
+    xcb_send_event (dmxScreen->connection,
+		    FALSE,
+		    requestor,
+		    0,
+		    (const char *) &xevent);
+
+    dmxSync (dmxScreen, FALSE);
+}
+
+void
+dmxSelectionPropertyChangeCheck (WindowPtr pWin,
+				 Atom      property,
+				 int       nUnits)
+{
+    DMXSelection *s;
+
+    if (nUnits == -1)
+    {
+	for (s = reqHead; s; s = s->next)
+	    if (s->requestor == pWin->drawable.id &&
+		s->property  == property)
+		break;
+
+	if (s)
+	{
+	    if (s->incr)
+		TimerCancel (s->timer);
+	    else
+		dmxSelectionDeleteReq (dmxUnhookSelection (&reqHead, s));
+
+	    return;
+	}
+
+	for (s = propHead; s; s = s->next)
+	    if (s->requestor == pWin->drawable.id &&
+		s->property  == property)
+		break;
+
+	if (s && s->incr)
+	{
+	    int i;
+
+	    TimerCancel (s->timer);
+
+	    for (i = 0; i < dmxNumScreens; i++)
+		if (s->value[i].out)
+		    break;
+
+	    /* owner doesn't exist anymore */
+	    if (i == dmxNumScreens)
+	    {
+		ChangeWindowProperty (pWin,
+				      s->property,
+				      XA_ATOM,
+				      32,
+				      PropModeReplace,
+				      0,
+				      NULL,
+				      TRUE);
+
+		dmxSelectionDeleteProp (dmxUnhookSelection (&propHead, s));
+	    }
+	}
+    }
+    else if (nUnits == 0)
+    {
+	for (s = reqHead; s; s = s->next)
+	    if (s->requestor == pWin->drawable.id &&
+		s->property  == property)
+		break;
+
+	/* end of incremental selection conversion */
+	if (s && s->incr)
+	    dmxSelectionDeleteReq (dmxUnhookSelection (&reqHead, s));
+    }
+}
+
+static int (*dmxSaveProcVector[256]) (ClientPtr);
+
+static int
+dmxProcSetSelectionOwner (ClientPtr client)
+{
+    WindowPtr    pOld = NullWindow;
+    WindowPtr    pWin;
+#ifdef PANORAMIX
+    PanoramiXRes *win = NULL;
+#endif
+    Selection    *pSel;
+    int          err;
+    int          i;
+
+    REQUEST(xSetSelectionOwnerReq);
+
+    if (dixLookupSelection (&pSel,
+			    stuff->selection,
+			    serverClient,
+			    DixReadAccess) == Success)
+	pOld = pSel->pWin;
+
+    err = (*dmxSaveProcVector[X_SetSelectionOwner]) (client);
+    if (err != Success)
+	return err;
+
+    if (!pSel && dixLookupSelection (&pSel,
+				     stuff->selection,
+				     serverClient,
+				     DixReadAccess) != Success)
+	return Success;
+
+    if (pSel->pWin)
+    {
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	    win = (PanoramiXRes *) SecurityLookupIDByType (serverClient,
+							   pSel->window,
+							   XRT_WINDOW,
+							   DixReadAccess);
+	else
+#endif
+	    dixLookupWindow (&pWin, pSel->window, serverClient, DixReadAccess);
+    }
+    else if (!pOld)
+    {
+	/* avoid setting selection owner to none on back-end servers
+	   when we're not the current owner */
+	return Success;
+    }
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	ScreenPtr pScreen = screenInfo.screens[i];
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    pWin = NullWindow;
+	    if (win)
+		dixLookupWindow (&pWin,
+				 win->info[i].id,
+				 serverClient,
+				 DixReadAccess);
+
+	    dmxBESetSelectionOwner (pScreen, pWin, pSel->selection);
+	}
+	else
+#endif
+	{
+	    if (pWin && pWin->drawable.pScreen != pScreen)
+		continue;
+
+	    dmxBESetSelectionOwner (pScreen, pWin, pSel->selection);
+	}
+    }
+
+    return Success;
+}
+
+static int
+dmxProcGetSelectionOwner (ClientPtr client)
+{
+    xGetSelectionOwnerReply reply;
+    Selection               *pSel;
+    int                     rc;
+
+    REQUEST(xResourceReq);
+    REQUEST_SIZE_MATCH(xResourceReq);
+
+    if (!ValidAtom (stuff->id))
+    {
+	client->errorValue = stuff->id;
+        return BadAtom;
+    }
+
+    rc = dixLookupSelection (&pSel, stuff->id, client, DixGetAttrAccess);
+    if (rc == Success)
+    {
+	if (pSel->window != None)
+	    return (*dmxSaveProcVector[X_GetSelectionOwner]) (client);
+    }
+    else if (rc != BadMatch)
+    {
+	return rc;
+    }
+
+    reply.type = X_Reply;
+    reply.length = 0;
+    reply.sequenceNumber = client->sequence;
+    reply.owner = None;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	unsigned int sequence;
+	int          j;
+
+	FOR_NSCREENS(j) {
+	    dmxBEGetSelectionOwner (screenInfo.screens[j], stuff->id);
+	}
+
+	do {
+	    dmxDispatch ();
+
+	    sequence = 0;
+
+	    FOR_NSCREENS_BACKWARD(j) {
+		DMXScreenInfo *dmxScreen = &dmxScreens[j];
+
+		if (dmxScreen->getSelectionOwnerResult)
+		    break;
+
+		sequence |= dmxScreen->getSelectionOwner.sequence;
+	    }
+	} while (sequence && j < 0 && dmxWaitForResponse ());
+
+	/* at least one back-end server has an owner for this selection */
+	if (j >= 0)
+	    reply.owner = dmxScreens[0].inputOverlayWid;
+    }
+#endif
+
+    WriteReplyToClient (client, sizeof (xGetSelectionOwnerReply), &reply);
+    return client->noClientException;
+}
+
+static int
+dmxProcConvertSelection (ClientPtr client)
+{
+    DMXSelection *s;
+    Bool         paramsOkay;
+    xEvent       event;
+    WindowPtr    pWin;
+    Selection    *pSel;
+    int          rc;
+#ifdef PANORAMIX
+    PanoramiXRes *win = NULL;
+    int          j;
+#endif
+
+    REQUEST(xConvertSelectionReq);
+    REQUEST_SIZE_MATCH(xConvertSelectionReq);
+
+    rc = dixLookupWindow (&pWin, stuff->requestor, client, DixSetAttrAccess);
+    if (rc != Success)
+        return rc;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	if (!(win = (PanoramiXRes *) SecurityLookupIDByType (serverClient,
+							     stuff->requestor,
+							     XRT_WINDOW,
+							     DixReadAccess)))
+	    return BadImplementation;
+    }
+#endif
+
+    paramsOkay = ValidAtom (stuff->selection) && ValidAtom (stuff->target);
+    paramsOkay &= (stuff->property == None) || ValidAtom (stuff->property);
+    if (!paramsOkay)
+    {
+	client->errorValue = stuff->property;
+        return BadAtom;
+    }
+
+    s = xalloc (sizeof (DMXSelection));
+    if (!s)
+	return BadAlloc;
+
+    s->wid       = 0;
+    s->requestor = stuff->requestor;
+    s->selection = stuff->selection;
+    s->target    = stuff->target;
+    s->property  = stuff->property;
+    s->time      = stuff->time;
+    s->incr      = FALSE;
+    s->next      = 0;
+    s->timer     = 0;
+
+    memset (s->value, 0, sizeof (s->value));
+
+    if (stuff->target == dmxScreens[0].multipleAtom)
+    {
+	PropertyPtr pProp;
+
+	if (dixLookupProperty (&pProp,
+			       pWin,
+			       stuff->property,
+			       serverClient,
+			       DixReadAccess) == Success &&
+	    pProp->format == 32)
+	{
+	    Atom *data = (Atom *) pProp->data;
+	    int  i;
+
+	    for (i = 0; i < pProp->size; i++)
+		if ((i & 1) == 0 && data[i] == dmxScreens[0].incrAtom)
+		    s->incr = TRUE;
+	}
+    }
+
+    rc = dixLookupSelection (&pSel, stuff->selection, client, DixReadAccess);
+    if (rc == Success)
+    {
+	if (pSel->window != None)
+	{
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		FOR_NSCREENS_FORWARD(j) {
+		    if (dixLookupWindow (&pWin,
+					 win->info[j].id,
+					 serverClient,
+					 DixReadAccess) == Success)
+			s->value[j].in = DMX_GET_WINDOW_PRIV (pWin)->window;
+		}
+	    }
+	    else
+#endif
+		s->value[pWin->drawable.pScreen->myNum].in =
+		    DMX_GET_WINDOW_PRIV (pWin)->window;
+
+	    dmxAppendSelection (&reqHead, s);
+
+	    return (*dmxSaveProcVector[X_ConvertSelection]) (client);
+	}
+    }
+    else if (rc != BadMatch)
+    {
+	xfree (s);
+	return rc;
+    }
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	FOR_NSCREENS_FORWARD(j) {
+	    if (dixLookupWindow (&pWin,
+				 win->info[j].id,
+				 serverClient,
+				 DixReadAccess) == Success)
+		s->value[j].out = dmxBEConvertSelection (pWin,
+							 stuff->selection,
+							 stuff->target,
+							 stuff->property,
+							 stuff->time);
+	}
+    }
+    else
+#endif
+	s->value[pWin->drawable.pScreen->myNum].out =
+	    dmxBEConvertSelection (pWin,
+				   stuff->selection,
+				   stuff->target,
+				   stuff->property,
+				   stuff->time);
+
+    for (j = 0; j < dmxNumScreens; j++)
+	if (s->value[j].out)
+	    break;
+
+    if (j < dmxNumScreens)
+    {
+	s->wid = stuff->requestor;
+
+	dmxAppendSelection (&convHead, s);
+
+	return client->noClientException;
+    }
+
+    xfree (s);
+
+    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, NULL, &event, 1, NoEventMask,
+		     NoEventMask /* CantBeFiltered */, NullGrab);
+    return client->noClientException;
+}
+
+static int
+dmxProcSendEvent (ClientPtr client)
+{
+    REQUEST(xSendEventReq);
+    REQUEST_SIZE_MATCH(xSendEventReq);
+
+    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
+    {
+	client->errorValue = stuff->propagate;
+	return BadValue;
+    }
+
+    switch (stuff->event.u.u.type) {
+    case SelectionNotify:
+	if (stuff->eventMask   == NoEventMask   &&
+	    stuff->destination != PointerWindow &&
+	    stuff->destination != InputFocus)
+	{
+	    Atom         property = stuff->event.u.selectionNotify.property;
+	    Atom         target = stuff->event.u.selectionNotify.target;
+	    DMXSelection *s;
+
+	    for (s = reqHead; s; s = s->next)
+		if (s->requestor == stuff->destination &&
+		    s->selection == stuff->event.u.selectionNotify.selection)
+		    break;
+
+	    if (s)
+	    {
+		int i;
+
+		if (target == dmxScreens[0].incrAtom)
+		    s->incr = TRUE;
+
+		s->property = property;
+
+		for (i = 0; i < dmxNumScreens; i++)
+		{
+		    xcb_selection_notify_event_t xevent;
+		    DMXScreenInfo                *dmxScreen = &dmxScreens[i];
+		    const uint32_t               value =
+			XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+			XCB_EVENT_MASK_PROPERTY_CHANGE;
+
+		    if (!s->value[i].out)
+			continue;
+		    
+		    xevent.response_type = XCB_SELECTION_NOTIFY;
+		    xevent.pad0 = 0;
+		    xevent.sequence = 0;
+		    xevent.time = s->time;
+		    xevent.requestor = s->value[i].out;
+		    xevent.selection = dmxBESelectionAtom (dmxScreen,
+							   s->selection);
+		    if (target)
+			xevent.target = dmxBEAtom (dmxScreen, target);
+		    else
+			xevent.target = None;
+
+		    if (property)
+			xevent.property = dmxBEAtom (dmxScreen, property);
+		    else
+			xevent.property = None;
+
+		    xcb_change_window_attributes (dmxScreen->connection,
+						  s->value[i].out,
+						  XCB_CW_EVENT_MASK,
+						  &value);
+
+		    xcb_send_event (dmxScreen->connection,
+				    FALSE,
+				    s->value[i].out,
+				    0,
+				    (const char *) &xevent);
+
+		    dmxSync (dmxScreen, FALSE);
+
+		    dmxSelectionResetTimer (s);
+		    return client->noClientException;
+		}
+
+		dmxSelectionResetTimer (s);
+	    }
+	}
+	break;
+    case ClientMessage:
+	if (stuff->event.u.u.detail != 8 &&
+	    stuff->event.u.u.detail != 16 &&
+	    stuff->event.u.u.detail != 32)
+	{
+	    client->errorValue = stuff->event.u.u.detail;
+	    return BadValue;
+	}
+
+	if (stuff->destination == dmxScreens[0].inputOverlayWid)
+	    dmxDnDClientMessageEvent (&stuff->event);
+
+	break;
+    }
+
+    return (*dmxSaveProcVector[X_SendEvent]) (client);
+}
+
+void
+dmxInitSelections (void)
+{
+    int i;
+
+    for (i = 0; i < 256; i++)
+	dmxSaveProcVector[i] = ProcVector[i];
+
+    ProcVector[X_GetSelectionOwner] = dmxProcGetSelectionOwner;
+    ProcVector[X_SetSelectionOwner] = dmxProcSetSelectionOwner;
+    ProcVector[X_ConvertSelection]  = dmxProcConvertSelection;
+    ProcVector[X_SendEvent]         = dmxProcSendEvent;
+}
+
+void
+dmxResetSelections (void)
+{
+    int i;
+    
+
+    for (i = 0; i < 256; i++)
+	ProcVector[i] = dmxSaveProcVector[i];
+}
diff --git a/hw/dmx/dmxselection.h b/hw/dmx/dmxselection.h
new file mode 100644
index 0000000..afa7762
--- /dev/null
+++ b/hw/dmx/dmxselection.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXSELECTION_H
+#define DMXSELECTION_H
+
+#include "dmx.h"
+#include "propertyst.h"
+
+Window
+dmxBEGetSelectionAdjustedPropertyWindow (WindowPtr pWin);
+
+void
+dmxSelectionClear (ScreenPtr pScreen,
+		   Window    owner,
+		   Atom      xSelection);
+
+void
+dmxSelectionNotify (ScreenPtr pScreen,
+		    Window    requestor,
+		    Atom      xSelection,
+		    Atom      xTarget,
+		    Atom      xProperty,
+		    Time      xTime);
+
+Bool
+dmxSelectionPropertyNotify (ScreenPtr pScreen,
+			    Window    requestor,
+			    int       state,
+			    Atom      xProperty,
+			    Time      xTime);
+
+Bool
+dmxSelectionDestroyNotify (ScreenPtr pScreen,
+			   Window    requestor);
+
+void
+dmxSelectionRequest (ScreenPtr pScreen,
+		     Window    owner,
+		     Window    requestor,
+		     Atom      xSelection,
+		     Atom      xTarget,
+		     Atom      xProperty,
+		     Time      xTime);
+
+void
+dmxSelectionPropertyChangeCheck (WindowPtr pWin,
+				 Atom      property,
+				 int       nUnits);
+
+void
+dmxInitSelections (void);
+
+void
+dmxResetSelections (void);
+
+#endif /* DMXSELECTION_H */
diff --git a/hw/dmx/dmxshm.c b/hw/dmx/dmxshm.c
new file mode 100644
index 0000000..c7b2c25
--- /dev/null
+++ b/hw/dmx/dmxshm.c
@@ -0,0 +1,757 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxshm.h"
+#include "dmxgc.h"
+#include "dmxwindow.h"
+#include "dmxpixmap.h"
+#include "dmxsync.h"
+#include "dmxlog.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "shmint.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#ifdef MITSHM
+
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+unsigned long DMX_SHMSEG;
+
+static dmxShmSegInfoPtr shmSegs = NULL;
+
+extern int (*ProcShmVector[ShmNumberRequests])(ClientPtr);
+
+static int (*dmxSaveProcVector[ShmNumberRequests]) (ClientPtr);
+
+static void dmxShmPutImage (XSHM_PUT_IMAGE_ARGS);
+
+static ShmFuncs dmxFuncs = { NULL, dmxShmPutImage };
+
+void
+ShmRegisterDmxFuncs (ScreenPtr pScreen)
+{
+    ShmRegisterFuncs (pScreen, &dmxFuncs);
+}
+
+static void
+dmxShmPutImage (DrawablePtr  pDraw,
+		GCPtr	     pGC,
+		int	     depth,
+		unsigned int format,
+		int	     w,
+		int	     h,
+		int	     sx,
+		int	     sy,
+		int	     sw,
+		int	     sh,
+		int	     dx,
+		int	     dy,
+		char	     *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pDraw->pScreen->myNum];
+    dmxGCPrivPtr  pGCPriv = DMX_GET_GC_PRIV (pGC);
+    int           vIndex = dmxScreen->beDefVisualIndex;
+    XImage        *image = NULL;
+    Drawable      draw;
+
+    if (pDraw->type == DRAWABLE_WINDOW)
+	draw = (DMX_GET_WINDOW_PRIV ((WindowPtr) (pDraw)))->window;
+    else
+	draw = (DMX_GET_PIXMAP_PRIV ((PixmapPtr) (pDraw)))->pixmap;
+
+    if (!dmxScreen->beDisplay || !draw)
+	return;
+
+    XLIB_PROLOGUE (dmxScreen);
+    image = XCreateImage (dmxScreen->beDisplay,
+			  dmxScreen->beVisuals[vIndex].visual,
+			  depth, format, 0, data, w, h,
+			  BitmapPad (dmxScreen->beDisplay),
+			  (format == ZPixmap) ?
+			  PixmapBytePad (w, depth) : BitmapBytePad (w));
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (image)
+    {
+	RegionRec reg;
+	BoxRec    src, dst;
+	BoxPtr    pBox;
+	int       nBox;
+
+	src.x1 = dx - sx;
+	src.y1 = dy - sy;
+	src.x2 = src.x1 + w;
+	src.y2 = src.y1 + h;
+
+	dst.x1 = dx;
+	dst.y1 = dy;
+	dst.x2 = dst.x1 + sw;
+	dst.y2 = dst.y1 + sh;
+
+	if (src.x1 > dst.x1)
+	    dst.x1 = src.x1;
+	if (src.y1 > dst.y1)
+	    dst.y1 = src.y1;
+	if (src.x2 < dst.x2)
+	    dst.x2 = src.x2;
+	if (src.y2 < dst.y2)
+	    dst.y2 = src.y2;
+
+	REGION_INIT (pGC->pScreen, &reg, &dst, 0);
+
+	if (pGC->pCompositeClip)
+	{
+	    REGION_TRANSLATE (pGC->pScreen, pGC->pCompositeClip,
+			      -pDraw->x, -pDraw->y);
+	    REGION_INTERSECT (pGC->pScreen, &reg, &reg, pGC->pCompositeClip);
+	    REGION_TRANSLATE (pGC->pScreen, pGC->pCompositeClip,
+			      pDraw->x, pDraw->y);
+	}
+
+	nBox = REGION_NUM_RECTS (&reg);
+	pBox = REGION_RECTS (&reg);
+
+	XLIB_PROLOGUE (dmxScreen);
+	while (nBox--)
+	{
+	    XPutImage (dmxScreen->beDisplay, draw, pGCPriv->gc, image,
+		       pBox->x1 - src.x1,
+		       pBox->y1 - src.y1,
+		       pBox->x1,
+		       pBox->y1,
+		       pBox->x2 - pBox->x1,
+		       pBox->y2 - pBox->y1);
+	    pBox++;
+	}
+	XLIB_EPILOGUE (dmxScreen);
+
+	REGION_UNINIT (pGC->pScreen, &reg);
+
+	XFree (image);
+
+	dmxSync (dmxScreen, FALSE);
+    }
+}
+
+void
+dmxBEAttachShmSeg (DMXScreenInfo    *dmxScreen,
+		   dmxShmSegInfoPtr pShmInfo)
+{
+    if (!dmxScreen->beShm)
+	return;
+
+    if (!pShmInfo->shmseg[dmxScreen->index])
+    {
+	pShmInfo->shmseg[dmxScreen->index] =
+	    xcb_generate_id (dmxScreen->connection);
+
+	xcb_shm_attach (dmxScreen->connection,
+			pShmInfo->shmseg[dmxScreen->index],
+			pShmInfo->shmid,
+			pShmInfo->readOnly);
+    }
+}
+
+void
+dmxBEDetachShmSeg (DMXScreenInfo    *dmxScreen,
+		   dmxShmSegInfoPtr pShmInfo)
+{
+    if (!dmxScreen->beShm)
+	return;
+
+    if (pShmInfo->shmseg[dmxScreen->index])
+    {
+	xcb_shm_detach (dmxScreen->connection,
+			pShmInfo->shmseg[dmxScreen->index]);
+
+	pShmInfo->shmseg[dmxScreen->index] = None;
+	pShmInfo->cookie[dmxScreen->index].sequence = 0;
+    }
+}
+
+Bool
+dmxScreenEventCheckShm (ScreenPtr           pScreen,
+			xcb_generic_event_t *event)
+{
+    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
+    dmxShmSegInfoPtr pShmInfo;
+    xcb_shm_seg_t    shmseg = 0;
+    unsigned int     sequence = 0;
+
+    if (!dmxScreen->beShm)
+	return FALSE;
+
+    if (event->response_type)
+    {
+	switch ((event->response_type & ~0x80) - dmxScreen->beShmEventBase) {
+	case XCB_SHM_COMPLETION: {
+	    /* XCB protocol description for XCB_SHM_COMPLETION is wrong */
+	    xShmCompletionEvent *xcompletion =
+		(xShmCompletionEvent *) event;
+
+	    shmseg = xcompletion->shmseg;
+	} break;
+	default:
+	    return FALSE;
+	}
+    }
+    else
+    {
+	sequence = ((xcb_generic_error_t *) event)->sequence;
+    }
+
+    for (pShmInfo = shmSegs; pShmInfo; pShmInfo = pShmInfo->next)
+    {
+	if (shmseg && shmseg != pShmInfo->shmseg[pScreen->myNum])
+	    continue;
+
+	if (!pShmInfo->cookie[pScreen->myNum].sequence)
+	    continue;
+
+	if (sequence && sequence != pShmInfo->cookie[pScreen->myNum].sequence)
+	    continue;
+	    
+	pShmInfo->pendingEvents--;
+	pShmInfo->cookie[pScreen->myNum].sequence = 0;
+    }
+
+    return TRUE;
+}
+
+static int
+dmxFreeShmSeg (pointer value,
+	       XID     id)
+{
+    dmxShmSegInfoPtr *pPrev, pShmInfo = (dmxShmSegInfoPtr) value;
+    int		     i;
+
+    if (--pShmInfo->refcnt)
+	return TRUE;
+
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	if (!dmxScreen->beDisplay)
+	    continue;
+
+	dmxBEDetachShmSeg (dmxScreen, pShmInfo);
+    }
+
+    for (pPrev = &shmSegs; *pPrev != pShmInfo; pPrev = &(*pPrev)->next)
+	;
+    *pPrev = pShmInfo->next;
+
+    xfree (pShmInfo);
+    return Success;
+}
+
+static int
+dmxProcShmAttach (ClientPtr client)
+{
+    dmxShmSegInfoPtr pShmInfo;
+    int		     i, err;
+    REQUEST(xShmAttachReq);
+
+    err = (*dmxSaveProcVector[X_ShmAttach]) (client);
+    if (err != Success)
+	return err;
+
+    for (pShmInfo = shmSegs;
+	 pShmInfo && (pShmInfo->shmid != stuff->shmid);
+	 pShmInfo = pShmInfo->next)
+	;
+    if (pShmInfo)
+    {
+	pShmInfo->refcnt++;
+    }
+    else
+    {
+	pShmInfo = xalloc (sizeof (dmxShmSegInfoRec));
+	if (!pShmInfo)
+	    return Success;
+
+	pShmInfo->refcnt        = 1;
+	pShmInfo->shmid         = stuff->shmid;
+	pShmInfo->readOnly      = stuff->readOnly;
+	pShmInfo->pendingEvents = 0;
+
+	memset (pShmInfo->shmseg, 0, sizeof (pShmInfo->shmseg));
+	memset (pShmInfo->cookie, 0, sizeof (pShmInfo->cookie));
+
+	pShmInfo->next = shmSegs;
+	shmSegs = pShmInfo;
+
+	for (i = 0; i < dmxNumScreens; i++)
+	{
+	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+	    if (!dmxScreen->beDisplay)
+		continue;
+
+	    dmxBEAttachShmSeg (dmxScreen, pShmInfo);
+	}
+    }
+
+    AddResource (stuff->shmseg, DMX_SHMSEG, (pointer) pShmInfo);
+
+    return Success;
+}
+
+static int
+dmxProcShmGetImage (ClientPtr client)
+{
+    DrawablePtr		pDraw;
+    long		lenPer = 0, length;
+    Mask		plane = 0;
+    xShmGetImageReply	xgi;
+    ShmDescPtr		shmdesc;
+    dmxShmSegInfoPtr    pShmInfo;
+    Drawable            draw;
+    int			n, rc;
+
+    REQUEST(xShmGetImageReq);
+
+    REQUEST_SIZE_MATCH(xShmGetImageReq);
+    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap))
+    {
+	client->errorValue = stuff->format;
+        return(BadValue);
+    }
+    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+			   DixReadAccess);
+    if (rc != Success)
+	return rc;
+
+    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
+
+    for (pShmInfo = shmSegs;
+	 pShmInfo && (pShmInfo->shmid != shmdesc->shmid);
+	 pShmInfo = pShmInfo->next)
+	;
+	
+    if (!pShmInfo || !pShmInfo->shmseg[pDraw->pScreen->myNum])
+	return (*dmxSaveProcVector[X_ShmGetImage]) (client);
+
+    if (pDraw->type == DRAWABLE_WINDOW)
+    {
+      if( /* check for being viewable */
+	 !((WindowPtr) pDraw)->realized ||
+	  /* check for being on screen */
+         pDraw->x + stuff->x < 0 ||
+ 	 pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width ||
+         pDraw->y + stuff->y < 0 ||
+         pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height ||
+          /* check for being inside of border */
+         stuff->x < - wBorderWidth((WindowPtr)pDraw) ||
+         stuff->x + (int)stuff->width >
+		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
+         stuff->y < -wBorderWidth((WindowPtr)pDraw) ||
+         stuff->y + (int)stuff->height >
+		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height
+        )
+	    return(BadMatch);
+	xgi.visual = wVisual(((WindowPtr)pDraw));
+	draw = (DMX_GET_WINDOW_PRIV ((WindowPtr) (pDraw)))->window;
+    }
+    else
+    {
+	if (stuff->x < 0 ||
+	    stuff->x+(int)stuff->width > pDraw->width ||
+	    stuff->y < 0 ||
+	    stuff->y+(int)stuff->height > pDraw->height
+	    )
+	    return(BadMatch);
+	xgi.visual = None;
+	draw = (DMX_GET_PIXMAP_PRIV ((PixmapPtr) (pDraw)))->pixmap;
+    }
+    xgi.type = X_Reply;
+    xgi.length = 0;
+    xgi.sequenceNumber = client->sequence;
+    xgi.depth = pDraw->depth;
+    if(stuff->format == ZPixmap)
+    {
+	length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height;
+    }
+    else 
+    {
+	lenPer = PixmapBytePad(stuff->width, 1) * stuff->height;
+	plane = ((Mask)1) << (pDraw->depth - 1);
+	/* only planes asked for */
+	length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1)));
+    }
+
+    if (!draw)
+	return (*dmxSaveProcVector[X_ShmGetImage]) (client);
+
+    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
+    xgi.size = length;
+
+    if (length)
+    {
+	xcb_shm_get_image_cookie_t cookie;
+	xcb_shm_get_image_reply_t  *reply;
+	DMXScreenInfo		   *dmxScreen =
+	    &dmxScreens[pDraw->pScreen->myNum];
+
+	rc = BadValue;
+	cookie = xcb_shm_get_image (dmxScreen->connection, draw,
+				    stuff->x, stuff->y,
+				    stuff->width, stuff->height,
+				    stuff->planeMask, stuff->format,
+				    pShmInfo->shmseg[dmxScreen->index],
+				    stuff->offset);
+	do {
+	    dmxDispatch ();
+
+	    if (xcb_poll_for_reply (dmxScreen->connection,
+				    cookie.sequence,
+				    (void **) &reply,
+				    NULL))
+	    {
+		if (reply)
+		{
+		    rc = Success;
+		    free (reply);
+		}
+		break;
+	    }
+	} while (dmxWaitForResponse () && dmxScreen->alive);
+
+	if (rc != Success)
+	    return (*dmxSaveProcVector[X_ShmGetImage]) (client);
+    }
+
+    if (client->swapped) {
+    	swaps(&xgi.sequenceNumber, n);
+    	swapl(&xgi.length, n);
+	swapl(&xgi.visual, n);
+	swapl(&xgi.size, n);
+    }
+    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
+
+    return(client->noClientException);
+}
+
+static int
+dmxProcShmPutImage (ClientPtr client)
+{
+    GCPtr pGC;
+    DrawablePtr pDraw;
+    long length;
+    ShmDescPtr shmdesc;
+    dmxShmSegInfoPtr pShmInfo;
+    REQUEST(xShmPutImageReq);
+
+    REQUEST_SIZE_MATCH(xShmPutImageReq);
+    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client);
+    if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse))
+	return BadValue;
+    if (stuff->format == XYBitmap)
+    {
+        if (stuff->depth != 1)
+            return BadMatch;
+        length = PixmapBytePad(stuff->totalWidth, 1);
+    }
+    else if (stuff->format == XYPixmap)
+    {
+        if (pDraw->depth != stuff->depth)
+            return BadMatch;
+        length = PixmapBytePad(stuff->totalWidth, 1);
+	length *= stuff->depth;
+    }
+    else if (stuff->format == ZPixmap)
+    {
+        if (pDraw->depth != stuff->depth)
+            return BadMatch;
+        length = PixmapBytePad(stuff->totalWidth, stuff->depth);
+    }
+    else
+    {
+	client->errorValue = stuff->format;
+        return BadValue;
+    }
+
+    /* 
+     * There's a potential integer overflow in this check:
+     * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
+     *                client);
+     * the version below ought to avoid it
+     */
+    if (stuff->totalHeight != 0 && 
+	length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
+	client->errorValue = stuff->totalWidth;
+	return BadValue;
+    }
+    if (stuff->srcX > stuff->totalWidth)
+    {
+	client->errorValue = stuff->srcX;
+	return BadValue;
+    }
+    if (stuff->srcY > stuff->totalHeight)
+    {
+	client->errorValue = stuff->srcY;
+	return BadValue;
+    }
+    if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth)
+    {
+	client->errorValue = stuff->srcWidth;
+	return BadValue;
+    }
+    if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight)
+    {
+	client->errorValue = stuff->srcHeight;
+	return BadValue;
+    }
+
+    for (pShmInfo = shmSegs;
+	 pShmInfo && (pShmInfo->shmid != shmdesc->shmid);
+	 pShmInfo = pShmInfo->next)
+	;
+	
+    if (pShmInfo && pShmInfo->shmseg[pDraw->pScreen->myNum])
+    {
+	DMXScreenInfo  *dmxScreen = &dmxScreens[pDraw->pScreen->myNum];
+	dmxGCPrivPtr   pGCPriv = DMX_GET_GC_PRIV (pGC);
+	xcb_drawable_t draw;
+
+	if (pDraw->type == DRAWABLE_WINDOW)
+	    draw = (DMX_GET_WINDOW_PRIV ((WindowPtr) (pDraw)))->window;
+	else
+	    draw = (DMX_GET_PIXMAP_PRIV ((PixmapPtr) (pDraw)))->pixmap;
+
+	if (dmxScreen->beDisplay && draw)
+	{
+	    pShmInfo->cookie[dmxScreen->index] =
+		xcb_shm_put_image (dmxScreen->connection,
+				   draw,
+				   XGContextFromGC (pGCPriv->gc),
+				   stuff->totalWidth, stuff->totalHeight,
+				   stuff->srcX, stuff->srcY,
+				   stuff->srcWidth, stuff->srcHeight,
+				   stuff->dstX, stuff->dstY,
+				   stuff->depth,
+				   stuff->format,
+				   TRUE,
+				   pShmInfo->shmseg[dmxScreen->index],
+				   stuff->offset);
+
+	    pShmInfo->pendingEvents++;
+	}
+    }
+    else
+    {
+	dmxShmPutImage (pDraw, pGC, stuff->depth, stuff->format,
+			stuff->totalWidth, stuff->totalHeight,
+			stuff->srcX, stuff->srcY,
+			stuff->srcWidth, stuff->srcHeight,
+			stuff->dstX, stuff->dstY,
+			shmdesc->addr + stuff->offset);
+    }
+
+    if (!pDraw->pScreen->myNum)
+    {
+	/* we could handle this completely asynchrounsly and continue to
+	   process client requests until all pending completion events
+	   have been collected but some clients seem to assume that
+	   the server is done using the shared memory segment once it
+	   has processed the request */
+	if (pShmInfo)
+	{
+	    /* wait for all back-end servers to complete */
+	    do {
+		dmxDispatch ();
+	    } while (pShmInfo->pendingEvents && dmxWaitForResponse ());
+	}
+    }
+
+    if (stuff->sendEvent)
+    {
+	xShmCompletionEvent ev;
+
+	ev.type = ShmCompletionCode;
+	ev.drawable = stuff->drawable;
+	ev.sequenceNumber = client->sequence;
+	ev.minorEvent = X_ShmPutImage;
+	ev.majorEvent = ShmReqCode;
+	ev.shmseg = stuff->shmseg;
+	ev.offset = stuff->offset;
+	WriteEventsToClient(client, 1, (xEvent *) &ev);
+    }
+
+    return (client->noClientException);
+}
+
+void
+dmxBEShmScreenInit (ScreenPtr pScreen)
+{
+    DMXScreenInfo             *dmxScreen = &dmxScreens[pScreen->myNum];
+    xcb_generic_error_t       *error;
+    xcb_shm_seg_t             shmseg;
+    xcb_pixmap_t              pixmap = 0;
+    uint32_t                  shmid;
+    static char               key[] = { 'x', 'd', 'm', 'x' };
+    char                      *shmaddr;
+    xcb_shm_get_image_reply_t *reply;
+    XlibGC                    gc;
+    XGCValues                 gcvals;
+    unsigned long             mask;
+    int                       i;
+
+    dmxScreen->beShm = FALSE;
+
+    shmid = shmget (IPC_PRIVATE, sizeof (key), IPC_CREAT | 0600);
+    if (shmid == -1)
+	return;
+
+    shmaddr = shmat (shmid, NULL, 0);
+    if (shmaddr == (char *) -1)
+    {
+	shmctl (shmid, IPC_RMID, NULL);
+	return;
+    }
+
+    memset (shmaddr, 0, sizeof (key));
+
+    shmseg = xcb_generate_id (dmxScreen->connection);
+    error  = xcb_request_check (dmxScreen->connection,
+				xcb_shm_attach_checked (dmxScreen->connection,
+							shmseg,
+							shmid,
+							FALSE));
+    if (error)
+    {
+	free (error);
+	shmdt (shmaddr);
+	shmctl (shmid, IPC_RMID, NULL);
+	return;
+    }
+
+    mask = (GCFunction | GCPlaneMask | GCClipMask | GCGraphicsExposures);
+
+    gcvals.function           = GXcopy;
+    gcvals.plane_mask         = AllPlanes;
+    gcvals.clip_mask          = None;
+    gcvals.foreground         = 0;
+    gcvals.graphics_exposures = FALSE;
+
+    pixmap = xcb_generate_id (dmxScreen->connection);
+    xcb_create_pixmap (dmxScreen->connection,
+		       8,
+		       pixmap,
+		       dmxScreen->scrnWin,
+		       sizeof (key),
+		       1);
+
+    XLIB_PROLOGUE (dmxScreen);
+    gc = XCreateGC (dmxScreen->beDisplay, pixmap, mask, &gcvals);
+    if (gc)
+    {
+	for (i = 0; i < sizeof (key); i++)
+	{
+	    gcvals.foreground = key[i];
+	    XChangeGC (dmxScreen->beDisplay, gc, GCForeground, &gcvals);
+	    XFillRectangle (dmxScreen->beDisplay, pixmap, gc, i, 0, 1, 1);
+	}
+
+	XFreeGC (dmxScreen->beDisplay, gc);
+    }
+    XLIB_EPILOGUE (dmxScreen);
+
+    reply =
+	xcb_shm_get_image_reply (dmxScreen->connection,
+				 xcb_shm_get_image (dmxScreen->connection,
+						    pixmap,
+						    0, 0,
+						    sizeof (key), 1,
+						    0xff,
+						    XCB_IMAGE_FORMAT_Z_PIXMAP,
+						    shmseg,
+						    0),
+				 NULL);
+
+    xcb_free_pixmap (dmxScreen->connection, pixmap);
+    
+    if (!reply)
+    {
+	xcb_shm_detach (dmxScreen->connection, shmseg);
+	shmdt (shmaddr);
+	shmctl (shmid, IPC_RMID, NULL);
+	return;
+    }
+
+    free (reply);
+
+    for (i = 0; i < sizeof (key); i++)
+	if (shmaddr[i] != key[i])
+	    break;
+
+    xcb_shm_detach (dmxScreen->connection, shmseg);
+    shmdt (shmaddr);
+    shmctl (shmid, IPC_RMID, NULL);
+
+    if (i < sizeof (key))
+	return;
+
+    dmxScreen->beShm = TRUE;
+    dmxScreen->beShmEventBase = XShmGetEventBase (dmxScreen->beDisplay);
+    dmxLogOutput (dmxScreen, "Using MIT-SHM extension\n");
+}
+
+void dmxInitShm (void)
+{
+    int i;
+
+    DMX_SHMSEG = CreateNewResourceType (dmxFreeShmSeg);
+
+    for (i = 0; i < ShmNumberRequests; i++)
+	dmxSaveProcVector[i] = ProcShmVector[i];
+
+    ProcShmVector[X_ShmAttach]   = dmxProcShmAttach;
+    ProcShmVector[X_ShmGetImage] = dmxProcShmGetImage;
+    ProcShmVector[X_ShmPutImage] = dmxProcShmPutImage;
+}
+
+void dmxResetShm (void)
+{
+    int i;
+
+    for (i = 0; i < ShmNumberRequests; i++)
+	ProcShmVector[i] = dmxSaveProcVector[i];
+}
+
+#endif
diff --git a/hw/dmx/dmxshm.h b/hw/dmx/dmxshm.h
new file mode 100644
index 0000000..69577f0
--- /dev/null
+++ b/hw/dmx/dmxshm.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXSHM_H
+#define DMXSHM_H
+
+#ifdef MITSHM
+
+#include <X11/extensions/XShm.h>
+#include <xcb/shm.h>
+
+typedef struct _dmxShmSegInfo {
+    struct _dmxShmSegInfo *next;
+    uint32_t              shmid;
+    int                   refcnt;
+    uint8_t               readOnly;
+    uint32_t              pendingEvents;
+    xcb_shm_seg_t         shmseg[MAXSCREENS];
+    xcb_void_cookie_t     cookie[MAXSCREENS];
+} dmxShmSegInfoRec, *dmxShmSegInfoPtr;
+
+extern unsigned long DMX_SHMSEG;
+
+extern void ShmRegisterDmxFuncs (ScreenPtr pScreen);
+
+extern void dmxBEAttachShmSeg (DMXScreenInfo    *dmxScreen,
+			       dmxShmSegInfoPtr pShmInfo);
+extern void dmxBEDetachShmSeg (DMXScreenInfo    *dmxScreen,
+			       dmxShmSegInfoPtr pShmInfo);
+
+extern Bool dmxScreenEventCheckShm (ScreenPtr           pScreen,
+				    xcb_generic_event_t *event);
+
+extern void dmxBEShmScreenInit (ScreenPtr pScreen);
+
+extern void dmxInitShm (void);
+extern void dmxResetShm (void);
+#endif
+
+#endif /* DMXSHM_H */
diff --git a/hw/dmx/dmxsync.c b/hw/dmx/dmxsync.c
index c1aa431..c413b9b 100644
--- a/hw/dmx/dmxsync.c
+++ b/hw/dmx/dmxsync.c
@@ -54,54 +54,119 @@
 #include "dmxsync.h"
 #include "dmxstat.h"
 #include "dmxlog.h"
+#include "dmxextension.h"
+#include "dmxscrinit.h"
 #include <sys/time.h>
 
 static int        dmxSyncInterval = 100; /* Default interval in milliseconds */
-static OsTimerPtr dmxSyncTimer;
-static int        dmxSyncPending;
+static OsTimerPtr dmxSyncTimer = NULL;
+static OsTimerPtr dmxActiveSyncTimer = NULL;
+static int        dmxSyncPending = 0;
+static int        dmxSyncRequest = 0;
 
-static void dmxDoSync(DMXScreenInfo *dmxScreen)
+/* dispatch all pending back-end server responses */
+void
+dmxDispatch (void)
 {
-    dmxScreen->needsSync = FALSE;
-
-    if (!dmxScreen->beDisplay)
-	return; /* FIXME: Is this correct behavior for sync stats? */
+    int i;
 
-    if (!dmxStatInterval) {
-        XSync(dmxScreen->beDisplay, False);
-    } else {
-        struct timeval start, stop;
-        
-        gettimeofday(&start, 0);
-        XSync(dmxScreen->beDisplay, False);
-        gettimeofday(&stop, 0);
-        dmxStatSync(dmxScreen, &stop, &start, dmxSyncPending);
-    }
+    for (i = 0; i < dmxNumScreens; i++)
+	if (dmxScreens[i].alive)
+	    dmxBEDispatch (screenInfo.screens[i]);
 }
 
-static CARD32 dmxSyncCallback(OsTimerPtr timer, CARD32 time, pointer arg)
+/* non-blocking wait for back-end server response. returns 0 when no
+   more reponses can arrive */
+int
+dmxWaitForResponse (void)
 {
-    int           i;
+    fd_set rfds;
+    int    nfd = 0;
+    int    i, ret = 0;
 
-    if (dmxSyncPending) {
-        for (i = 0; i < dmxNumScreens; i++) {
-            DMXScreenInfo *dmxScreen = &dmxScreens[i];
-            if (dmxScreen->needsSync) dmxDoSync(dmxScreen);
-        }
+    FD_ZERO (&rfds);
+     
+    for (i = 0; i < dmxNumScreens; i++)
+    {
+	if (dmxScreens[i].alive)
+	{
+	    xcb_flush (dmxScreens[i].connection);
+
+	    if (xcb_connection_has_error (dmxScreens[i].connection))
+	    {
+		dmxScreens[i].alive = FALSE;
+		ret = -1;
+	    }
+	    else
+	    {
+		FD_SET (dmxScreens[i].fd, &rfds);
+
+		if (dmxScreens[i].fd > nfd)
+		    nfd = dmxScreens[i].fd;
+	    }
+	}
     }
-    dmxSyncPending = 0;
-    return 0;                   /* Do not place on queue again */
+
+    if (ret == 0 && nfd)
+    {
+	do {
+	    ret = select (nfd + 1, &rfds, 0, 0, 0);
+	} while (ret == -1 && errno == EINTR);
+
+	/* screens with broken connections are detached in the
+	   block handler */
+    }
+
+    return nfd;
 }
 
-static void dmxSyncBlockHandler(pointer blockData, OSTimePtr pTimeout,
-                                pointer pReadMask)
+static void dmxDoSync(DMXScreenInfo *dmxScreen)
 {
-    TimerForce(dmxSyncTimer);
+    dmxScreen->needsSync = FALSE;
+
+    if (!dmxScreen->alive)
+	return; /* FIXME: Is this correct behavior for sync stats? */
+
+    if (dmxScreen->sync.sequence)
+	return;
+
+    dmxScreen->sync = xcb_get_input_focus (dmxScreen->connection);
+    dmxAddRequest (&dmxScreen->request,
+		   dmxScreenSyncReply,
+		   dmxScreen->sync.sequence,
+		   0);
+    dmxSyncRequest++;
 }
 
-static void dmxSyncWakeupHandler(pointer blockData, int result,
-                                 pointer pReadMask)
+static CARD32 dmxSyncCallback(OsTimerPtr timer, CARD32 time, pointer arg)
 {
+    int i;
+
+    /* make sure TimerFree is not called from while waiting for
+       pending replies */
+    dmxActiveSyncTimer = NULL;
+
+    /* wait for all pending sync replies */
+    do {
+	dmxDispatch ();
+    } while (dmxSyncRequest && dmxWaitForResponse ());
+
+    if (dmxSyncPending)
+    {
+	for (i = 0; i < dmxNumScreens; i++)
+	    if (dmxScreens[i].needsSync)
+		dmxDoSync (&dmxScreens[i]);
+
+	dmxSyncPending = 0;
+
+	if (dmxSyncRequest)
+	{
+	    dmxActiveSyncTimer = timer;
+	    return dmxSyncInterval;
+	}
+    }
+
+    return 0;                   /* Do not place on queue again */
 }
 
 /** Request the XSync() batching optimization with the specified \a
@@ -124,9 +189,6 @@ void dmxSyncActivate(const char *interval)
 void dmxSyncInit(void)
 {
     if (dmxSyncInterval) {
-        RegisterBlockAndWakeupHandlers(dmxSyncBlockHandler,
-                                       dmxSyncWakeupHandler,
-                                       NULL);
         dmxLog(dmxInfo, "XSync batching with %d ms interval\n",
                dmxSyncInterval);
     } else {
@@ -159,35 +221,82 @@ void dmxSync(DMXScreenInfo *dmxScreen, Bool now)
              * 2) freed, if it was on a queue (dmxSyncPending != 0), or
              * 3) allocated, if it wasn't on a queue (dmxSyncPending == 0)
              */
-            if (dmxSyncTimer && !dmxSyncPending) xfree(dmxSyncTimer);
+            if (dmxSyncTimer && !dmxActiveSyncTimer) xfree(dmxSyncTimer);
             dmxSyncTimer  = NULL;
-            now           = TRUE;
+            now           = FALSE;
             dmxGeneration = serverGeneration;
         }
-                                /* Queue sync */
+
+	/* Queue sync */
         if (dmxScreen) {
+	    if (now && dmxScreen->inDispatch)
+	    {
+		dmxLog (dmxWarning,
+			"Immediate sync from within back-end dispatch\n");
+		free (xcb_get_input_focus_reply
+		      (dmxScreen->connection,
+		       xcb_get_input_focus (dmxScreen->connection),
+		       NULL));
+		return;
+	    }
             dmxScreen->needsSync = TRUE;
             ++dmxSyncPending;
         }
 
-                                /* Do sync or set time for later */
-        if (now || !dmxScreen) {
-            if (!TimerForce(dmxSyncTimer)) dmxSyncCallback(NULL, 0, NULL);
-            /* At this point, dmxSyncPending == 0 because
-             * dmxSyncCallback must have been called. */
-            if (dmxSyncPending)
-                dmxLog(dmxFatal, "dmxSync(%s,%d): dmxSyncPending = %d\n",
-                       dmxScreen ? dmxScreen->name : "", now, dmxSyncPending);
-        } else {
-            dmxScreen->needsSync = TRUE;
-            if (dmxSyncPending == 1)
-                dmxSyncTimer = TimerSet(dmxSyncTimer, 0, dmxSyncInterval,
-                                        dmxSyncCallback, NULL);
+	/* Do sync or set time for later */
+        if (now || !dmxScreen)
+	{
+	    if (dmxActiveSyncTimer)
+	    {
+		TimerCancel (dmxActiveSyncTimer);
+		dmxActiveSyncTimer = NULL;
+	    }
+
+	    while (dmxSyncRequest || dmxSyncPending)
+		dmxSyncCallback (NULL, 0, NULL);
         }
-    } else {
-                                /* If dmxSyncInterval is not being used,
-                                 * then all the backends are already
-                                 * up-to-date. */
-        if (dmxScreen) dmxDoSync(dmxScreen);
+	else if (!dmxActiveSyncTimer)
+	{
+	    dmxActiveSyncTimer = TimerSet (dmxSyncTimer,
+					   0,
+					   dmxSyncInterval,
+					   dmxSyncCallback,
+					   NULL);
+	}
+    }
+    else
+    {
+	/* If dmxSyncInterval is not being used,
+	 * then all the backends are already
+	 * up-to-date. */
+        if (dmxScreen)
+	{
+	    dmxDoSync (dmxScreen);
+	    dmxSyncCallback (NULL, 0, NULL);
+	}
+    }
+}
+
+/* error or reply doesn't matter, all we need is some response
+   from the back-end server */
+void
+dmxScreenSyncReply (ScreenPtr           pScreen,
+		    unsigned int        sequence,
+		    xcb_generic_reply_t *reply,
+		    xcb_generic_error_t *error,
+		    void                *data)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    if (dmxScreen->sync.sequence)
+    {
+	dmxScreen->sync.sequence = 0;
+	dmxSyncRequest--;
+
+	if (dmxSyncRequest == 0 && dmxSyncPending == 0 && dmxActiveSyncTimer)
+	{
+	    TimerCancel (dmxActiveSyncTimer);
+	    dmxActiveSyncTimer = NULL;
+	}
     }
 }
diff --git a/hw/dmx/dmxsync.h b/hw/dmx/dmxsync.h
index b80f54a..0d48a43 100644
--- a/hw/dmx/dmxsync.h
+++ b/hw/dmx/dmxsync.h
@@ -37,7 +37,14 @@
 #ifndef _DMXSYNC_H_
 #define _DMXSYNC_H_
 
+extern void dmxDispatch (void);
+extern int  dmxWaitForResponse (void);
 extern void dmxSyncActivate(const char *interval);
 extern void dmxSyncInit(void);
 extern void dmxSync(DMXScreenInfo *dmxScreen, Bool now);
+extern void dmxScreenSyncReply (ScreenPtr           pScreen,
+				unsigned int        sequence,
+				xcb_generic_reply_t *reply,
+				xcb_generic_error_t *error,
+				void                *data);
 #endif
diff --git a/hw/dmx/dmxvisual.c b/hw/dmx/dmxvisual.c
index 7b8771f..0d90ae1 100644
--- a/hw/dmx/dmxvisual.c
+++ b/hw/dmx/dmxvisual.c
@@ -93,7 +93,7 @@ Visual *dmxLookupVisual(ScreenPtr pScreen, VisualPtr pVisual)
     for (i = 0; i < dmxScreen->beNumVisuals; i++) {
 	if (pVisual->class == dmxScreen->beVisuals[i].class &&
 	    pVisual->bitsPerRGBValue == dmxScreen->beVisuals[i].bits_per_rgb &&
-	    pVisual->ColormapEntries == dmxScreen->beVisuals[i].colormap_size &&
+	    pVisual->ColormapEntries <= dmxScreen->beVisuals[i].colormap_size &&
 	    pVisual->nplanes == dmxScreen->beVisuals[i].depth &&
 	    pVisual->redMask == dmxScreen->beVisuals[i].red_mask &&
 	    pVisual->greenMask == dmxScreen->beVisuals[i].green_mask &&
diff --git a/hw/dmx/dmxwindow.c b/hw/dmx/dmxwindow.c
index 24acc08..3a0ab16 100644
--- a/hw/dmx/dmxwindow.c
+++ b/hw/dmx/dmxwindow.c
@@ -46,11 +46,25 @@
 #include "dmxvisual.h"
 #include "dmxinput.h"
 #include "dmxextension.h"
+#include "dmxscrinit.h"
+#include "dmxcursor.h"
+#include "dmxfont.h"
+#include "dmxatom.h"
+#include "dmxprop.h"
+#include "dmxselection.h"
+#include "dmxdnd.h"
 #ifdef RENDER
 #include "dmxpict.h"
 #endif
 
 #include "windowstr.h"
+#include "propertyst.h"
+#include "dixfont.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
 
 static void dmxDoRestackWindow(WindowPtr pWindow);
 static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
@@ -59,6 +73,12 @@ static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
 
 static void dmxDoSetShape(WindowPtr pWindow);
 
+static void
+dmxDoRedirectWindow(WindowPtr pWindow);
+
+static void
+dmxDoUpdateWindowPixmap(WindowPtr pWindow);
+
 /** Initialize the private area for the window functions. */
 Bool dmxInitWindow(ScreenPtr pScreen)
 {
@@ -76,24 +96,20 @@ Window dmxCreateRootWindow(WindowPtr pWindow)
     dmxWinPrivPtr         pWinPriv  = DMX_GET_WINDOW_PRIV(pWindow);
     Window                parent;
     Visual               *visual;
-    unsigned long         mask;
+    unsigned long         mask = 0;
     XSetWindowAttributes  attribs;
     ColormapPtr           pCmap;
     dmxColormapPrivPtr    pCmapPriv;
+    Window                win = None;
+    int                   w = pWindow->drawable.width;
+    int                   h = pWindow->drawable.height;
 
-    /* Create root window */
-
-    parent = dmxScreen->scrnWin; /* This is our "Screen" window */
-    visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual;
-
-    pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP);
-    pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
+    /* Avoid to create windows on back-end servers with virtual framebuffer */
+    if (dmxScreen->virtualFb)
+	return None;
 
-    mask = CWEventMask | CWBackingStore | CWColormap | CWBorderPixel;
-    attribs.event_mask    = ExposureMask;
-    attribs.backing_store = NotUseful;
-    attribs.colormap      = pCmapPriv->cmap;
-    attribs.border_pixel  = 0;
+    mask = CWEventMask;
+    attribs.event_mask = dmxScreen->rootEventMask;
 
     /* Incorporate new attributes, if needed */
     if (pWinPriv->attribMask) {
@@ -101,41 +117,56 @@ Window dmxCreateRootWindow(WindowPtr pWindow)
 	mask |= pWinPriv->attribMask;
     }
 
-    return XCreateWindow(dmxScreen->beDisplay,
-			 parent,
-			 pWindow->origin.x - wBorderWidth(pWindow),
-			 pWindow->origin.y - wBorderWidth(pWindow),
-			 pWindow->drawable.width,
-			 pWindow->drawable.height,
-			 pWindow->borderWidth,
-			 pWindow->drawable.depth,
-			 pWindow->drawable.class,
-			 visual,
-			 mask,
-			 &attribs);
-}
+    /* Create root window */
+    parent = dmxScreen->scrnWin; /* This is our "Screen" window */
+    visual = dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual;
 
-/** Change the location and size of the "screen" window.  Called from
- *  #dmxReconfigureScreenWindow(). */
-void dmxResizeScreenWindow(ScreenPtr pScreen,
-			   int x, int y, int w, int h)
-{
-    DMXScreenInfo  *dmxScreen = &dmxScreens[pScreen->myNum];
-    unsigned int    m;
-    XWindowChanges  c;
+    pCmap = (ColormapPtr)LookupIDByType(wColormap(pWindow), RT_COLORMAP);
+    pCmapPriv = DMX_GET_COLORMAP_PRIV(pCmap);
 
-    if (!dmxScreen->beDisplay)
-	return;
+    mask |= CWBackingStore | CWColormap | CWBorderPixel | CWOverrideRedirect;
+    attribs.backing_store     = NotUseful;
+    attribs.colormap          = pCmapPriv->cmap;
+    attribs.border_pixel      = 0;
+    attribs.override_redirect = TRUE;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	w = PanoramiXPixWidth;
+	h = PanoramiXPixHeight;
+    }
+#endif
 
-    /* Handle resizing on back-end server */
-    m = CWX | CWY | CWWidth | CWHeight;
-    c.x = x;
-    c.y = y;
-    c.width = w;
-    c.height = h;
+    XLIB_PROLOGUE (dmxScreen);
+    win = XCreateWindow(dmxScreen->beDisplay,
+			parent,
+			pWindow->origin.x - wBorderWidth(pWindow),
+			pWindow->origin.y - wBorderWidth(pWindow),
+			w,
+			h,
+			pWindow->borderWidth,
+			pWindow->drawable.depth,
+			pWindow->drawable.class,
+			visual,
+			mask,
+			&attribs);
+    XChangeProperty (dmxScreen->beDisplay, win,
+		     XInternAtom (dmxScreen->beDisplay, "DMX_NAME", False),
+		     XA_STRING, 8,
+		     PropModeReplace,
+		     (unsigned char *) dmxDigest,
+		     strlen (dmxDigest));
+    XLIB_EPILOGUE (dmxScreen);
+
+    dmxBEDnDRootWindowUpdate (pWindow->drawable.pScreen, win);
+
+    return win;
+}
 
-    XConfigureWindow(dmxScreen->beDisplay, dmxScreen->scrnWin, m, &c);
-    dmxSync(dmxScreen, False);
+static void dmxSetIgnore (DMXScreenInfo *dmxScreen, unsigned int sequence)
+{
+    dmxAddSequence (&dmxScreen->ignore, sequence);
 }
 
 /** Change the location and size of the "root" window.  Called from
@@ -148,6 +179,9 @@ void dmxResizeRootWindow(WindowPtr pRoot,
     unsigned int    m;
     XWindowChanges  c;
 
+    if (!pWinPriv->window)
+	return;
+
     /* Handle resizing on back-end server */
     if (dmxScreen->beDisplay) {
 	m = CWX | CWY | CWWidth | CWHeight;
@@ -156,18 +190,31 @@ void dmxResizeRootWindow(WindowPtr pRoot,
 	c.width = (w > 0) ? w : 1;
 	c.height = (h > 0) ? h : 1;
 
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+	XLIB_EPILOGUE (dmxScreen);
     }
 
     if (w == 0 || h == 0) {
 	if (pWinPriv->mapped) {
 	    if (dmxScreen->beDisplay)
+	    {
+		XLIB_PROLOGUE (dmxScreen);
+		dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 		XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
+		XLIB_EPILOGUE (dmxScreen);
+	    }
 	    pWinPriv->mapped = FALSE;
 	}
     } else if (!pWinPriv->mapped) {
 	if (dmxScreen->beDisplay)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	    XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
 	pWinPriv->mapped = TRUE;
     }
 
@@ -215,6 +262,12 @@ static Window dmxCreateNonRootWindow(WindowPtr pWindow)
     unsigned long         mask = 0L;
     XSetWindowAttributes  attribs;
     dmxWinPrivPtr         pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
+    Window                win = None;
+    int                   x, y, w, h, bw;
+
+    /* Avoid to create windows on back-end servers with virtual framebuffer */
+    if (dmxScreen->virtualFb)
+	return None;
 
     /* Create window on back-end server */
 
@@ -228,6 +281,9 @@ static Window dmxCreateNonRootWindow(WindowPtr pWindow)
 	parent = pParentPriv->window;
     }
 
+    mask |= CWEventMask;
+    attribs.event_mask = ExposureMask | SubstructureRedirectMask;
+
     /* Incorporate new attributes, if needed */
     if (pWinPriv->attribMask) {
 	dmxDoChangeWindowAttributes(pWindow, &pWinPriv->attribMask, &attribs);
@@ -254,18 +310,37 @@ static Window dmxCreateNonRootWindow(WindowPtr pWindow)
        be created on top of the stack, so we must restack the windows */
     pWinPriv->restacked = (pWindow->prevSib != NullWindow);
 
-    return XCreateWindow(dmxScreen->beDisplay,
-			 parent,
-			 pWindow->origin.x - wBorderWidth(pWindow),
-			 pWindow->origin.y - wBorderWidth(pWindow),
-			 pWindow->drawable.width,
-			 pWindow->drawable.height,
-			 pWindow->borderWidth,
-			 pWindow->drawable.depth,
-			 pWindow->drawable.class,
-			 pWinPriv->visual,
-			 mask,
-			 &attribs);
+    if (pWindow != dmxScreen->pInputOverlayWin)
+    {
+	x = pWindow->origin.x - wBorderWidth(pWindow);
+	y = pWindow->origin.y - wBorderWidth(pWindow);
+	w = pWindow->drawable.width;
+	h = pWindow->drawable.height;
+	bw = pWindow->borderWidth;
+    }
+    else
+    {
+	x = y = -1;
+	w = h = 1;
+	bw = 0;
+    }
+
+    XLIB_PROLOGUE (dmxScreen);
+    win = XCreateWindow(dmxScreen->beDisplay,
+			parent,
+			x,
+			y,
+			w,
+			h,
+			bw,
+			pWindow->drawable.depth,
+			pWindow->drawable.class,
+			pWinPriv->visual,
+			mask,
+			&attribs);
+    XLIB_EPILOGUE (dmxScreen);
+
+    return win;
 }
 
 /** This function handles lazy window creation and realization.  Window
@@ -285,15 +360,29 @@ void dmxCreateAndRealizeWindow(WindowPtr pWindow, Bool doSync)
 
     if (!dmxScreen->beDisplay) return;
 
-    pWinPriv->window = dmxCreateNonRootWindow(pWindow);
-    if (pWinPriv->restacked) dmxDoRestackWindow(pWindow);
-    if (pWinPriv->isShaped) dmxDoSetShape(pWindow);
+    if (!pWindow->parent)
+	dmxScreen->rootWin = pWinPriv->window = dmxCreateRootWindow(pWindow);
+    else
+	pWinPriv->window = dmxCreateNonRootWindow(pWindow);
+    if (pWinPriv->window)
+    {
+	if (pWinPriv->redirected) dmxDoRedirectWindow(pWindow);
+	if (pWinPriv->restacked) dmxDoRestackWindow(pWindow);
+	if (pWinPriv->isShaped) dmxDoSetShape(pWindow);
 #ifdef RENDER
-    if (pWinPriv->hasPict) dmxCreatePictureList(pWindow);
+	if (pWinPriv->hasPict) dmxCreatePictureList(pWindow);
 #endif
-    if (pWinPriv->mapped) XMapWindow(dmxScreen->beDisplay,
-				      pWinPriv->window);
-    if (doSync) dmxSync(dmxScreen, False);
+	if (pWinPriv->mapped)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
+	    XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
+	    XLIB_EPILOGUE (dmxScreen);
+
+	    if (pWinPriv->beRedirected) dmxDoUpdateWindowPixmap (pWindow);
+	}
+	if (doSync) dmxSync(dmxScreen, False);
+    }
 }
 
 /** Create \a pWindow on the back-end server.  If the lazy window
@@ -308,16 +397,16 @@ Bool dmxCreateWindow(WindowPtr pWindow)
     Bool                  ret = TRUE;
 
     DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
-#if 0
+
     if (pScreen->CreateWindow)
 	ret = pScreen->CreateWindow(pWindow);
-#endif
 
     /* Set up the defaults */
     pWinPriv->window     = (Window)0;
     pWinPriv->offscreen  = TRUE;
     pWinPriv->mapped     = FALSE;
     pWinPriv->restacked  = FALSE;
+    pWinPriv->redirected = FALSE;
     pWinPriv->attribMask = 0;
     pWinPriv->isShaped   = FALSE;
 #ifdef RENDER
@@ -328,29 +417,14 @@ Bool dmxCreateWindow(WindowPtr pWindow)
     pWinPriv->barrier    = 0;
 #endif
 
+    pWinPriv->beRedirected = FALSE;
+
     if (dmxScreen->beDisplay) {
 	/* Only create the root window at this stage -- non-root windows are
 	   created when they are mapped and are on-screen */
 	if (!pWindow->parent) {
-	    dmxScreen->rootWin = pWinPriv->window
-		= dmxCreateRootWindow(pWindow);
-	    if (dmxScreen->scrnX         != dmxScreen->rootX
-		|| dmxScreen->scrnY      != dmxScreen->rootY
-		|| dmxScreen->scrnWidth  != dmxScreen->rootWidth
-		|| dmxScreen->scrnHeight != dmxScreen->rootHeight) {
-		dmxResizeRootWindow(pWindow,
-				    dmxScreen->rootX,
-				    dmxScreen->rootY,
-				    dmxScreen->rootWidth,
-				    dmxScreen->rootHeight);
-		dmxUpdateScreenResources(screenInfo.screens[dmxScreen->index],
-					 dmxScreen->rootX,
-					 dmxScreen->rootY,
-					 dmxScreen->rootWidth,
-					 dmxScreen->rootHeight);
-		pWindow->origin.x = dmxScreen->rootX;
-		pWindow->origin.y = dmxScreen->rootY;
-	    }
+	    dmxScreen->rootWin = pWinPriv->window =
+		dmxCreateRootWindow(pWindow);
 	} else {
 	    dmxGetDefaultWindowAttributes(pWindow,
 					  &pWinPriv->cmap,
@@ -382,8 +456,15 @@ Bool dmxBEDestroyWindow(WindowPtr pWindow)
     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
     dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
 
+    pWinPriv->beRedirected = FALSE;
+
     if (pWinPriv->window) {
-	XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window);
+	if (dmxScreen->scrnWin)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    XDestroyWindow(dmxScreen->beDisplay, pWinPriv->window);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
 	pWinPriv->window = (Window)0;
 	return TRUE;
     }
@@ -419,10 +500,9 @@ Bool dmxDestroyWindow(WindowPtr pWindow)
 	pWinPriv->windowDestroyed(pWindow);
 #endif
 
-#if 0
     if (pScreen->DestroyWindow)
 	ret = pScreen->DestroyWindow(pWindow);
-#endif
+
     DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
 
     return ret;
@@ -439,10 +519,8 @@ Bool dmxPositionWindow(WindowPtr pWindow, int x, int y)
     XWindowChanges  c;
 
     DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
-#if 0
     if (pScreen->PositionWindow)
 	ret = pScreen->PositionWindow(pWindow, x, y);
-#endif
 
     /* Determine if the window is completely off the visible portion of
        the screen */
@@ -452,7 +530,7 @@ Bool dmxPositionWindow(WindowPtr pWindow, int x, int y)
        been created yet, create it and map it */
     if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
 	dmxCreateAndRealizeWindow(pWindow, TRUE);
-    } else if (pWinPriv->window) {
+    } else if (pWinPriv->window && pWindow != dmxScreen->pInputOverlayWin) {
 	/* Position window on back-end server */
 	m = CWX | CWY | CWWidth | CWHeight;
 	c.x = pWindow->origin.x - wBorderWidth(pWindow);
@@ -464,7 +542,10 @@ Bool dmxPositionWindow(WindowPtr pWindow, int x, int y)
 	    c.border_width = pWindow->borderWidth;
 	}
 
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, False);
     }
 
@@ -539,7 +620,12 @@ static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
 	*mask &= ~CWBackingPixel; /* Backing store not supported */
 
     if (*mask & CWOverrideRedirect)
-	attribs->override_redirect = pWindow->overrideRedirect;
+    {
+	if (pWindow->parent)
+	    attribs->override_redirect = pWindow->overrideRedirect;
+	else
+	    *mask &= ~CWOverrideRedirect;
+    }
 
     if (*mask & CWSaveUnder)
 	*mask &= ~CWSaveUnder; /* Save unders not supported */
@@ -560,7 +646,21 @@ static void dmxDoChangeWindowAttributes(WindowPtr pWindow,
     }
 
     if (*mask & CWCursor)
-	*mask &= ~CWCursor; /* Handled by the cursor code */
+    {
+	ScreenPtr pScreen = pWindow->drawable.pScreen;
+
+	if (pWindow->cursorIsNone)
+	{
+	    attribs->cursor = None;
+	}
+	else
+	{
+	    dmxCursorPrivPtr pCursorPriv =
+		DMX_GET_CURSOR_PRIV (wCursor (pWindow), pScreen);
+
+	    attribs->cursor = pCursorPriv->cursor;
+	}
+    }
 }
 
 /** Change the window attributes of \a pWindow. */
@@ -568,16 +668,9 @@ Bool dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask)
 {
     ScreenPtr             pScreen = pWindow->drawable.pScreen;
     DMXScreenInfo        *dmxScreen = &dmxScreens[pScreen->myNum];
-    Bool                  ret = TRUE;
     dmxWinPrivPtr         pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
     XSetWindowAttributes  attribs;
 
-    DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
-#if 0
-    if (pScreen->ChangeWindowAttributes)
-	ret = pScreen->ChangeWindowAttributes(pWindow, mask);
-#endif
-
     /* Change window attribs on back-end server */
     dmxDoChangeWindowAttributes(pWindow, &mask, &attribs);
 
@@ -585,15 +678,14 @@ Bool dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask)
     pWinPriv->attribMask |= mask;
 
     if (mask && pWinPriv->window) {
+	XLIB_PROLOGUE (dmxScreen);
 	XChangeWindowAttributes(dmxScreen->beDisplay, pWinPriv->window,
 				mask, &attribs);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, False);
     }
 
-    DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
-	     pScreen);
-
-    return ret;
+    return TRUE;
 }
 
 /** Realize \a pWindow on the back-end server.  If the lazy window
@@ -607,10 +699,8 @@ Bool dmxRealizeWindow(WindowPtr pWindow)
     dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
 
     DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
-#if 0
     if (pScreen->RealizeWindow)
 	ret = pScreen->RealizeWindow(pWindow);
-#endif
 
     /* Determine if the window is completely off the visible portion of
        the screen */
@@ -624,16 +714,27 @@ Bool dmxRealizeWindow(WindowPtr pWindow)
 
     if (pWinPriv->window) {
 	/* Realize window on back-end server */
-	XMapWindow(dmxScreen->beDisplay, pWinPriv->window);
-	dmxSync(dmxScreen, False);
+
+	dmxDoRedirectWindow (pWindow);
+
+	if (MapUnmapEventsEnabled (pWindow))
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
+	    XMapWindow (dmxScreen->beDisplay, pWinPriv->window);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+
+	dmxDoUpdateWindowPixmap (pWindow);
     }
 
+    dmxSync(dmxScreen, False);
+
     /* Let the other functions know that the window is now mapped */
     pWinPriv->mapped = TRUE;
 
     DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
 
-    dmxUpdateWindowInfo(DMX_UPDATE_REALIZE, pWindow);
     return ret;
 }
 
@@ -646,14 +747,27 @@ Bool dmxUnrealizeWindow(WindowPtr pWindow)
     dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
 
     DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
-#if 0
     if (pScreen->UnrealizeWindow)
 	ret = pScreen->UnrealizeWindow(pWindow);
-#endif
 
     if (pWinPriv->window) {
 	/* Unrealize window on back-end server */
-	XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
+
+	XLIB_PROLOGUE (dmxScreen);
+	if (MapUnmapEventsEnabled (pWindow))
+	{
+	    dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
+	    XUnmapWindow(dmxScreen->beDisplay, pWinPriv->window);
+	}
+
+	if (pWinPriv->beRedirected)
+	{
+	    XCompositeUnredirectWindow (dmxScreen->beDisplay,
+					pWinPriv->window,
+					CompositeRedirectAutomatic);
+	    pWinPriv->beRedirected = FALSE;
+	}
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, False);
     }
 
@@ -669,7 +783,6 @@ Bool dmxUnrealizeWindow(WindowPtr pWindow)
 
     DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
 
-    dmxUpdateWindowInfo(DMX_UPDATE_UNREALIZE, pWindow);
     return ret;
 }
 
@@ -687,7 +800,10 @@ static void dmxDoRestackWindow(WindowPtr pWindow)
 	m = CWStackMode;
 	c.sibling = (Window)0;
 	c.stack_mode = Below;
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+	XLIB_EPILOGUE (dmxScreen);
     } else {
 	/* Window is not at the bottom of the stack */
 	dmxWinPrivPtr  pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
@@ -706,7 +822,10 @@ static void dmxDoRestackWindow(WindowPtr pWindow)
 		m = CWStackMode;
 		c.sibling = (Window)0;
 		c.stack_mode = Below;
+		XLIB_PROLOGUE (dmxScreen);
+		dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 		XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+		XLIB_EPILOGUE (dmxScreen);
 		return;
 	    }
 	    pNextSibPriv = DMX_GET_WINDOW_PRIV(pNextSib);
@@ -715,7 +834,10 @@ static void dmxDoRestackWindow(WindowPtr pWindow)
 	m = CWStackMode | CWSibling;
 	c.sibling = pNextSibPriv->window;
 	c.stack_mode = Above;
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+	XLIB_EPILOGUE (dmxScreen);
     }
 }
 
@@ -728,10 +850,8 @@ void dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib)
     dmxWinPrivPtr   pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
 
     DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
-#if 0
     if (pScreen->RestackWindow)
 	pScreen->RestackWindow(pWindow, pOldNextSib);
-#endif
 
     if (pOldNextSib != pWindow->nextSib) {
 	/* Track restacking for lazy window creation optimization */
@@ -745,48 +865,6 @@ void dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib)
     }
 
     DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
-    dmxUpdateWindowInfo(DMX_UPDATE_RESTACK, pWindow);
-}
-
-static Bool dmxWindowExposurePredicate(Display *dpy, XEvent *ev, XPointer ptr)
-{
-    return (ev->type == Expose && ev->xexpose.window == *(Window *)ptr);
-}
-
-/** Handle exposures on \a pWindow.  Since window exposures are handled
- *  in DMX, the events that are generated by the back-end server are
- *  redundant, so we eat them here. */
-void dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn,
-			RegionPtr other_exposed)
-{
-    ScreenPtr      pScreen = pWindow->drawable.pScreen;
-    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
-    dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
-    XEvent         ev;
-
-    DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
-
-    dmxSync(dmxScreen, False);
-
-    if (pWinPriv->window) {
-	while (XCheckIfEvent(dmxScreen->beDisplay, &ev,
-			     dmxWindowExposurePredicate,
-			     (XPointer)&pWinPriv->window)) {
-	    /* Handle expose events -- this should not be necessary
-	       since the base window in which the root window was
-	       created is guaranteed to be on top (override_redirect),
-	       so we should just swallow these events.  If for some
-	       reason the window is not on top, then we'd need to
-	       collect these events and send them to the client later
-	       (e.g., during the block handler as Xnest does). */
-	}
-    }
-
-#if 1
-    if (pScreen->WindowExposures)
-	pScreen->WindowExposures(pWindow, prgn, other_exposed);
-#endif
-    DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
 }
 
 /** Move \a pWindow on the back-end server.  Determine whether or not it
@@ -794,17 +872,7 @@ void dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn,
  *  lazy window creation optimization is enabled. */
 void dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 {
-    ScreenPtr       pScreen = pWindow->drawable.pScreen;
-    DMXScreenInfo  *dmxScreen = &dmxScreens[pScreen->myNum];
-    dmxWinPrivPtr   pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
-    unsigned int    m;
-    XWindowChanges  c;
-
-    DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
-#if 0
-    if (pScreen->CopyWindow)
-	pScreen->CopyWindow(pWindow, ptOldOrg, prgnSrc);
-#endif
+    dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
 
     /* Determine if the window is completely off the visible portion of
        the screen */
@@ -814,20 +882,7 @@ void dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
        been created yet, create it and map it */
     if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
 	dmxCreateAndRealizeWindow(pWindow, TRUE);
-    } else if (pWinPriv->window) {
-	/* Move window on back-end server */
-	m = CWX | CWY | CWWidth | CWHeight;
-	c.x = pWindow->origin.x - wBorderWidth(pWindow);
-	c.y = pWindow->origin.y - wBorderWidth(pWindow);
-	c.width = pWindow->drawable.width;
-	c.height = pWindow->drawable.height;
-
-	XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
-	dmxSync(dmxScreen, False);
     }
-
-    DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
-    dmxUpdateWindowInfo(DMX_UPDATE_COPY, pWindow);
 }
 
 /** Resize \a pWindow on the back-end server.  Determine whether or not
@@ -847,10 +902,8 @@ void dmxResizeWindow(WindowPtr pWindow, int x, int y,
 	pSibPriv = DMX_GET_WINDOW_PRIV(pSib);
 
     DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
-#if 1
     if (pScreen->ResizeWindow)
 	pScreen->ResizeWindow(pWindow, x, y, w, h, pSib);
-#endif
 
     /* Determine if the window is completely off the visible portion of
        the screen */
@@ -860,7 +913,7 @@ void dmxResizeWindow(WindowPtr pWindow, int x, int y,
        been created yet, create it and map it */
     if (!pWinPriv->window && pWinPriv->mapped && !pWinPriv->offscreen) {
 	dmxCreateAndRealizeWindow(pWindow, TRUE);
-    } else if (pWinPriv->window) {
+    } else if (pWinPriv->window && pWindow != dmxScreen->pInputOverlayWin) {
 	/* Handle resizing on back-end server */
 	m = CWX | CWY | CWWidth | CWHeight;
 	c.x = pWindow->origin.x - wBorderWidth(pWindow);
@@ -868,12 +921,14 @@ void dmxResizeWindow(WindowPtr pWindow, int x, int y,
 	c.width = pWindow->drawable.width;
 	c.height = pWindow->drawable.height;
 
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, False);
     }
 
     DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
-    dmxUpdateWindowInfo(DMX_UPDATE_RESIZE, pWindow);
 }
 
 /** Reparent \a pWindow on the back-end server. */
@@ -885,10 +940,8 @@ void dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent)
     dmxWinPrivPtr  pParentPriv = DMX_GET_WINDOW_PRIV(pWindow->parent);
 
     DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
-#if 0
     if (pScreen->ReparentWindow)
 	pScreen->ReparentWindow(pWindow, pPriorParent);
-#endif
 
     if (pWinPriv->window) {
 	if (!pParentPriv->window) {
@@ -896,15 +949,16 @@ void dmxReparentWindow(WindowPtr pWindow, WindowPtr pPriorParent)
 	}
 
 	/* Handle reparenting on back-end server */
+	XLIB_PROLOGUE (dmxScreen);
 	XReparentWindow(dmxScreen->beDisplay, pWinPriv->window,
 			pParentPriv->window,
 			pWindow->origin.x - wBorderWidth(pWindow),
 			pWindow->origin.x - wBorderWidth(pWindow));
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, False);
     }
 
     DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
-    dmxUpdateWindowInfo(DMX_UPDATE_REPARENT, pWindow);
 }
 
 /** Change border width for \a pWindow to \a width pixels. */
@@ -917,19 +971,20 @@ void dmxChangeBorderWidth(WindowPtr pWindow, unsigned int width)
     XWindowChanges  c;
 
     DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
-#if 1
     if (pScreen->ChangeBorderWidth)
 	pScreen->ChangeBorderWidth(pWindow, width);
-#endif
 
     /* NOTE: Do we need to check for on/off screen here? */
 
-    if (pWinPriv->window) {
+    if (pWinPriv->window && pWindow != dmxScreen->pInputOverlayWin) {
 	/* Handle border width change on back-end server */
 	m = CWBorderWidth;
 	c.border_width = width;
 
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XConfigureWindow(dmxScreen->beDisplay, pWinPriv->window, m, &c);
+	XLIB_EPILOGUE (dmxScreen);
 	dmxSync(dmxScreen, False);
     }
 
@@ -960,14 +1015,20 @@ static void dmxDoSetShape(WindowPtr pWindow)
 	    pBox++;
 	    pRect++;
 	}
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
 				ShapeBounding, 0, 0,
 				pRectFirst, nRect,
 				ShapeSet, YXBanded);
+	XLIB_EPILOGUE (dmxScreen);
 	xfree(pRectFirst);
     } else {
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
 			  ShapeBounding, 0, 0, None, ShapeSet);
+	XLIB_EPILOGUE (dmxScreen);
     }
 
     /* Next, set the clip shape */
@@ -983,19 +1044,48 @@ static void dmxDoSetShape(WindowPtr pWindow)
 	    pBox++;
 	    pRect++;
 	}
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
 				ShapeClip, 0, 0,
 				pRectFirst, nRect,
 				ShapeSet, YXBanded);
+	XLIB_EPILOGUE (dmxScreen);
 	xfree(pRectFirst);
     } else {
+	XLIB_PROLOGUE (dmxScreen);
+	dmxSetIgnore (dmxScreen, NextRequest (dmxScreen->beDisplay));
 	XShapeCombineMask(dmxScreen->beDisplay, pWinPriv->window,
 			  ShapeClip, 0, 0, None, ShapeSet);
+	XLIB_EPILOGUE (dmxScreen);
     }
 
-    if (XShapeInputSelected(dmxScreen->beDisplay, pWinPriv->window)) {
-	ErrorF("Input selected for window %x on Screen %d\n",
-	       (unsigned int)pWinPriv->window, pScreen->myNum);
+    if (wInputShape (pWindow)) {
+	pBox = REGION_RECTS(wInputShape(pWindow));
+	nRect = nBox = REGION_NUM_RECTS(wInputShape(pWindow));
+	pRectFirst = pRect = xalloc(nRect * sizeof(*pRect));
+	while (nBox--) {
+	    pRect->x      = pBox->x1;
+	    pRect->y      = pBox->y1;
+	    pRect->width  = pBox->x2 - pBox->x1;
+	    pRect->height = pBox->y2 - pBox->y1;
+	    pBox++;
+	    pRect++;
+	}
+	XLIB_PROLOGUE (dmxScreen);
+	XShapeCombineRectangles(dmxScreen->beDisplay, pWinPriv->window,
+				ShapeInput, 0, 0,
+				pRectFirst, nRect,
+				ShapeSet, YXBanded);
+	XLIB_EPILOGUE (dmxScreen);
+	xfree(pRectFirst);
+    }
+    else
+    {
+	XLIB_PROLOGUE (dmxScreen);
+	XShapeCombineMask (dmxScreen->beDisplay, pWinPriv->window,
+			   ShapeInput, 0, 0, None, ShapeSet);
+	XLIB_EPILOGUE (dmxScreen);
     }
 }
 
@@ -1007,18 +1097,375 @@ void dmxSetShape(WindowPtr pWindow)
     dmxWinPrivPtr   pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
 
     DMX_UNWRAP(SetShape, dmxScreen, pScreen);
-#if 1
     if (pScreen->SetShape)
 	pScreen->SetShape(pWindow);
-#endif
 
     if (pWinPriv->window) {
 	/* Handle setting the current shape on the back-end server */
 	dmxDoSetShape(pWindow);
 	dmxSync(dmxScreen, False);
-    } else {
-	pWinPriv->isShaped = TRUE;
     }
 
+    pWinPriv->isShaped = TRUE;
+
     DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
 }
+
+static void
+dmxDoRedirectWindow(WindowPtr pWindow)
+{
+    ScreenPtr      pScreen = pWindow->drawable.pScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+    if (pWinPriv->window && pWinPriv->redirected && !pWinPriv->beRedirected)
+    {
+	XLIB_PROLOGUE (dmxScreen);
+	XCompositeRedirectWindow (dmxScreen->beDisplay,
+				  pWinPriv->window,
+				  CompositeRedirectAutomatic);
+	XLIB_EPILOGUE (dmxScreen);
+	pWinPriv->beRedirected = TRUE;
+    }
+}
+
+static void
+dmxDoUpdateWindowPixmap(WindowPtr pWindow)
+{
+    ScreenPtr      pScreen = pWindow->drawable.pScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV(pWindow);
+
+    if (pWinPriv->window && pWinPriv->beRedirected)
+    {
+	PixmapPtr pPixmap;
+
+	pPixmap = (*pScreen->GetWindowPixmap) (pWindow);
+	if (pPixmap)
+	{
+	    dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV (pPixmap);
+
+	    if (pPixPriv->pixmap)
+	    {
+		XLIB_PROLOGUE (dmxScreen);
+		XFreePixmap (dmxScreen->beDisplay, pPixPriv->pixmap);
+		XLIB_EPILOGUE (dmxScreen);
+		pPixPriv->pixmap = None;
+	    }
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    pPixPriv->pixmap =
+		XCompositeNameWindowPixmap (dmxScreen->beDisplay,
+					    pWinPriv->window);
+	    XLIB_EPILOGUE (dmxScreen);
+	}
+    }
+}
+
+static void
+dmxTranslateWindowProperty (WindowPtr     pWindow,
+			    char	  type,
+			    unsigned char *data,
+			    unsigned char *output)
+{
+    ScreenPtr     pScreen = pWindow->drawable.pScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    switch (type) {
+    case 'a':
+    case 'A': {
+	Atom *src = (Atom *) data;
+	Atom *dst = (Atom *) output;
+
+	*dst = dmxBEAtom (dmxScreen, *src);
+    } break;
+    case 'p':
+    case 'P': {
+	XID       *src = (XID *) data;
+	XID       *dst = (XID *) output;
+	PixmapPtr pPixmap;
+	XID       id = *src;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    PanoramiXRes *res;
+
+	    if (dixLookupResource ((pointer *) &res,
+				   id,
+				   XRT_PIXMAP,
+				   serverClient,
+				   DixReadAccess) == Success)
+		id = res->info[pScreen->myNum].id;
+	}
+#endif
+
+	if (dixLookupResource ((pointer *) &pPixmap,
+			       id,
+			       RT_PIXMAP,
+			       serverClient,
+			       DixReadAccess) == Success)
+	    *dst = (DMX_GET_PIXMAP_PRIV (pPixmap))->pixmap;
+	else
+	    *dst = 0;
+    } break;
+    case 'm':
+    case 'M': {
+	XID         *src = (XID *) data;
+	XID         *dst = (XID *) output;
+	ColormapPtr pColormap;
+	XID         id = *src;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    PanoramiXRes *res;
+
+	    if (dixLookupResource ((pointer *) &res,
+				   id,
+				   XRT_COLORMAP,
+				   serverClient,
+				   DixReadAccess) == Success)
+		id = res->info[pScreen->myNum].id;
+	}
+#endif
+
+	if (dixLookupResource ((pointer *) &pColormap,
+			       id,
+			       RT_COLORMAP,
+			       serverClient,
+			       DixReadAccess) == Success)
+	    *dst = (DMX_GET_COLORMAP_PRIV (pColormap))->cmap;
+	else
+	    *dst = 0;
+    } break;
+    case 'c':
+    case 'C': {
+	XID       *src = (XID *) data;
+	XID       *dst = (XID *) output;
+	CursorPtr pCursor;
+
+	if (dixLookupResource ((pointer *) &pCursor,
+			       *src,
+			       RT_CURSOR,
+			       serverClient,
+			       DixReadAccess) == Success)
+	    *dst = (DMX_GET_CURSOR_PRIV (pCursor, pScreen))->cursor;
+	else
+	    *dst = 0;
+    } break;
+    case 'd':
+    case 'D': {
+	XID         *src = (XID *) data;
+	XID         *dst = (XID *) output;
+	DrawablePtr pDrawable;
+	XID         id = *src;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    PanoramiXRes *res;
+
+	    if (dixLookupResource ((pointer *) &res,
+				   id,
+				   XRC_DRAWABLE,
+				   serverClient,
+				   DixReadAccess) == Success)
+		id = res->info[pScreen->myNum].id;
+	}
+#endif
+
+	if (dixLookupResource ((pointer *) &pDrawable,
+			       id,
+			       RC_DRAWABLE,
+			       serverClient,
+			       DixReadAccess) == Success)
+	{
+	    if (pDrawable->type == DRAWABLE_WINDOW)
+	    {
+		WindowPtr pWin = (WindowPtr) pDrawable;
+
+		*dst = (DMX_GET_WINDOW_PRIV (pWin))->window;
+	    }
+	    else
+	    {
+		PixmapPtr pPixmap = (PixmapPtr) pDrawable;
+
+		*dst = (DMX_GET_PIXMAP_PRIV (pPixmap))->pixmap;
+	    }
+	}
+	else
+	    *dst = 0;
+    } break;
+    case 'f':
+    case 'F': {
+	XID     *src = (XID *) data;
+	XID     *dst = (XID *) output;
+	FontPtr pFont;
+
+	if (dixLookupResource ((pointer *) &pFont,
+			       *src,
+			       RT_FONT,
+			       serverClient,
+			       DixReadAccess) == Success)
+	{
+	    dmxFontPrivPtr pFontPriv =
+		FontGetPrivate (pFont, dmxFontPrivateIndex);
+
+	    *dst = pFontPriv->font[pScreen->myNum]->fid;
+	}
+	else
+	    *dst = 0;
+    } break;
+    case 'v':
+    case 'V': {
+	XID    *src = (XID *) data;
+	XID    *dst = (XID *) output;
+	Visual *visual;
+
+	visual = dmxLookupVisualFromID (pScreen, *src);
+	if (visual)
+	    *dst = XVisualIDFromVisual (visual);
+	else
+	    *dst = 0;
+    } break;
+    case 'w':
+    case 'W': {
+	XID       *src = (XID *) data;
+	XID       *dst = (XID *) output;
+	WindowPtr pWin;
+	XID       id = *src;
+
+#ifdef PANORAMIX
+	if (!noPanoramiXExtension)
+	{
+	    PanoramiXRes *res;
+
+	    if (dixLookupResource ((pointer *) &res,
+				   id,
+				   XRT_WINDOW,
+				   serverClient,
+				   DixReadAccess) == Success)
+		id = res->info[pScreen->myNum].id;
+	}
+#endif
+
+	if (dixLookupResource ((pointer *) &pWin,
+			       id,
+			       RT_WINDOW,
+			       serverClient,
+			       DixReadAccess) == Success)
+	    *dst = (DMX_GET_WINDOW_PRIV (pWin))->window;
+	else
+	    *dst = 0;
+    } break;
+    default:
+	*((CARD32 *) output) = *((CARD32 *) data);
+	break;
+    }
+}
+
+void
+dmxBESetWindowProperty (WindowPtr   pWindow,
+			PropertyPtr pProp)
+{
+    ScreenPtr      pScreen = pWindow->drawable.pScreen;
+    DMXScreenInfo  *dmxScreen = &dmxScreens[pScreen->myNum];
+    unsigned char  *data = pProp->data;
+    const char     *format = NULL;
+    Window         window;
+    int		   i;
+
+    window = dmxBEGetSelectionAdjustedPropertyWindow (pWindow);
+    if (!window)
+	return;
+
+    /* only 32 bit data types can be translated */
+    if (pProp->format == 32)
+    {
+	switch (pProp->type) {
+	case XA_ATOM:
+	    format = "a..";
+	    break;
+	case XA_BITMAP:
+	case XA_PIXMAP:
+	    format = "p..";
+	    break;
+	case XA_COLORMAP:
+	    format = "m..";
+	    break;
+	case XA_CURSOR:
+	    format = "c..";
+	    break;
+	case XA_DRAWABLE:
+	    format = "d..";
+	    break;
+	case XA_FONT:
+	    format = "f..";
+	    break;
+	case XA_VISUALID:
+	    format = "v..";
+	    break;
+	case XA_WINDOW:
+	    format = "w..";
+	    break;
+	default:
+	    for (i = 0; i < dmxPropTransNum; i++)
+	    {
+		if (pProp->type == dmxPropTrans[i].type)
+		{
+		    format = dmxPropTrans[i].format;
+		    break;
+		}
+	    }
+	}
+    }
+
+    if (format)
+    {
+	unsigned char *dst, *src = data;
+
+	dst = xalloc (pProp->size * (pProp->format >> 3));
+	if (dst)
+	{
+	    int j;
+
+	    i = j = 0;
+	    data = dst;
+
+	    while (format[j] != '\0')
+	    {
+		if (i++ == pProp->size)
+		    break;
+
+		if (format[j] == '.')
+		    j = 0;
+
+		dmxTranslateWindowProperty (pWindow, format[j++], src, dst);
+
+		src += (pProp->format >> 3);
+		dst += (pProp->format >> 3);
+	    }
+
+	    if (i < pProp->size)
+		memcpy (dst, src, (pProp->size - i) * (pProp->format >> 3));
+	}
+    }
+
+    XLIB_PROLOGUE (dmxScreen);
+    XChangeProperty (dmxScreen->beDisplay,
+		     window,
+		     dmxBEAtom (dmxScreen, pProp->propertyName),
+		     dmxBEAtom (dmxScreen, pProp->type),
+		     pProp->format,
+		     PropModeReplace,
+		     data,
+		     pProp->size);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (data != pProp->data)
+	xfree (data);
+
+    dmxSync (dmxScreen, FALSE);
+}
+
diff --git a/hw/dmx/dmxwindow.h b/hw/dmx/dmxwindow.h
index 353d0a3..5147cf2 100644
--- a/hw/dmx/dmxwindow.h
+++ b/hw/dmx/dmxwindow.h
@@ -38,6 +38,7 @@
 #define DMXWINDOW_H
 
 #include "windowstr.h"
+#include "property.h"
 
 /** Window private area. */
 typedef struct _dmxWinPriv {
@@ -45,6 +46,7 @@ typedef struct _dmxWinPriv {
     Bool           offscreen;
     Bool           mapped;
     Bool           restacked;
+    Bool           redirected;
     unsigned long  attribMask;
     Colormap       cmap;
     Visual        *visual;
@@ -58,6 +60,7 @@ typedef struct _dmxWinPriv {
     void         (*windowDestroyed)(WindowPtr);
     void         (*windowUnmapped)(WindowPtr);
 #endif
+    Bool           beRedirected;
 } dmxWinPrivRec, *dmxWinPrivPtr;
 
 
@@ -77,8 +80,6 @@ extern Bool dmxChangeWindowAttributes(WindowPtr pWindow, unsigned long mask);
 extern Bool dmxRealizeWindow(WindowPtr pWindow);
 extern Bool dmxUnrealizeWindow(WindowPtr pWindow);
 extern void dmxRestackWindow(WindowPtr pWindow, WindowPtr pOldNextSib);
-extern void dmxWindowExposures(WindowPtr pWindow, RegionPtr prgn,
-			       RegionPtr other_exposed);
 extern void dmxCopyWindow(WindowPtr pWindow, DDXPointRec ptOldOrg,
 			  RegionPtr prgnSrc);
 
@@ -95,6 +96,8 @@ extern void dmxResizeRootWindow(WindowPtr pRoot,
 
 extern Bool dmxBEDestroyWindow(WindowPtr pWindow);
 
+extern void dmxBESetWindowProperty(WindowPtr pWindow, PropertyPtr pProp);
+
 /* Support for shape extension */
 extern void dmxSetShape(WindowPtr pWindow);
 
diff --git a/hw/dmx/dmxxlibio.h b/hw/dmx/dmxxlibio.h
new file mode 100644
index 0000000..6c5d188
--- /dev/null
+++ b/hw/dmx/dmxxlibio.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2007 David Reveman
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * David Reveman not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * David Reveman makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DAVID REVEMAN 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMX_XLIBIO_H
+#define DMX_XLIBIO_H
+
+#include <setjmp.h>
+
+extern jmp_buf _dmx_jumpbuf;
+extern int     _dmx_io_error;
+extern int     _dmx_jumpbuf_set;
+
+#define XLIB_PROLOGUE(_dmxScreen)			\
+    do {						\
+	_dmx_io_error = 0;				\
+	_dmx_jumpbuf_set = 1;				\
+	setjmp (_dmx_jumpbuf);				\
+	if (_dmx_io_error)				\
+	{						\
+	    (_dmxScreen)->alive = FALSE;		\
+	}						\
+	else if ((_dmxScreen)->alive)			\
+	{
+
+#define XLIB_EPILOGUE(_dmxScreen)	\
+    }					\
+	_dmx_jumpbuf_set = 0;		\
+	} while (0)
+
+#endif
diff --git a/hw/dmx/dmxxv.c b/hw/dmx/dmxxv.c
new file mode 100644
index 0000000..03108b0
--- /dev/null
+++ b/hw/dmx/dmxxv.c
@@ -0,0 +1,734 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#ifdef XV
+#include "dmx.h"
+#include "dmxsync.h"
+#include "dmxgc.h"
+#include "dmxwindow.h"
+#include "dmxvisual.h"
+#include "dmxlog.h"
+#include "dmxxv.h"
+
+#include "xvdix.h"
+#include "gcstruct.h"
+#include "dixstruct.h"
+#include "servermd.h"
+#include "pixmapstr.h"
+
+typedef struct _dmxXvAdaptor {
+    int base;
+    int n;
+} dmxXvAdaptorRec, *dmxXvAdaptorPtr;
+
+typedef struct _dmxXvPort {
+    int      id;
+    XvPortID port;
+    XvImage  *image;
+} dmxXvPortRec, *dmxXvPortPtr;
+
+#define DMX_GET_XV_SCREEN(pScreen)			    \
+    ((XvScreenPtr) dixLookupPrivate (&pScreen->devPrivates, \
+				     XvGetScreenKey ()))
+
+#define DMX_XV_SCREEN(pScreen)				\
+    XvScreenPtr pXvScreen = DMX_GET_XV_SCREEN (pScreen)
+
+#define DMX_GET_XV_ADAPTOR_PRIV(pAdaptor)		\
+    ((dmxXvAdaptorPtr) ((pAdaptor)->devPriv.ptr))
+
+#define DMX_XV_ADAPTOR_PRIV(pAdaptor)					\
+    dmxXvAdaptorPtr pAdaptorPriv = DMX_GET_XV_ADAPTOR_PRIV (pAdaptor)
+
+#define DMX_GET_XV_PORT_PRIV(pPort)		\
+    ((dmxXvPortPtr) ((pPort)->devPriv.ptr))
+
+#define DMX_XV_PORT_PRIV(pPort)				  \
+    dmxXvPortPtr pPortPriv = DMX_GET_XV_PORT_PRIV (pPort)
+
+#define DMX_XV_NUM_PORTS 32
+
+#define DMX_XV_IMAGE_MAX_WIDTH  2046
+#define DMX_XV_IMAGE_MAX_HEIGHT 2046
+
+#define DMX_FOURCC(a, b, c, d)					\
+    ((a) | (b) << 8 | (c) << 16 | ((unsigned int) (d)) << 24)
+
+#define DMX_FOURCC_YUY2 DMX_FOURCC ('Y', 'U', 'Y', '2')
+#define DMX_FOURCC_YV12 DMX_FOURCC ('Y', 'V', '1', '2')
+
+static XvImageRec xvImages[] = {
+    {
+	DMX_FOURCC_YUY2, XvYUV, BITMAP_BIT_ORDER,
+	{
+	    'Y','U','Y','2',
+	    0x00, 0x00, 0x00, 0x10, 0x80, 0x00,
+	    0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
+	},
+	16, XvPacked, 1,
+	0, 0, 0, 0,
+	8, 8, 8,  1, 2, 2,  1, 1, 1,
+	{
+	    'Y', 'U', 'Y', 'V',
+	    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+	},
+	XvTopToBottom
+    }, {
+	DMX_FOURCC_YV12, XvYUV, BITMAP_BIT_ORDER,
+	{
+	    'Y', 'V', '1', '2',
+	    0x00, 0x00, 0x00, 0x10, 0x80, 0x00,
+	    0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71
+	},
+	12, XvPlanar, 3,
+	0, 0, 0, 0,
+	8, 8, 8,  1, 2, 2,  1, 2, 2,
+	{
+	    'Y', 'V', 'U', 0,
+	    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+	},
+	XvTopToBottom
+    }
+};
+
+static int
+dmxXvFreePort (XvPortPtr pPort)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pPort->pAdaptor->pScreen->myNum];
+
+    DMX_XV_PORT_PRIV (pPort);
+
+    if (pPortPriv->port)
+    {
+	XLIB_PROLOGUE (dmxScreen);
+	XvUngrabPort (dmxScreen->beDisplay, pPortPriv->port, CurrentTime);
+	XLIB_EPILOGUE (dmxScreen);
+
+	pPortPriv->port = 0;
+    }
+
+    if (pPortPriv->image)
+    {
+	XFree (pPortPriv->image);
+	pPortPriv->image = NULL;
+    }
+
+    pPortPriv->id = 0;
+
+    return Success;
+}
+
+static int
+dmxXvStopVideo (ClientPtr   client,
+		XvPortPtr   pPort,
+		DrawablePtr pDrawable)
+{
+    return Success;
+}
+
+static int
+dmxSetPortAttribute (ClientPtr client,
+		     XvPortPtr pPort,
+		     Atom      atom,
+		     INT32     value)
+{
+    return BadMatch;
+}
+
+static int
+dmxGetPortAttribute (ClientPtr client,
+		     XvPortPtr pPort,
+		     Atom      atom,
+		     INT32     *value)
+{
+    return BadMatch;
+}
+
+static int
+dmxXvQueryBestSize (ClientPtr	 client,
+		    XvPortPtr	 pPort,
+		    CARD8	 motion,
+		    CARD16	 srcWidth,
+		    CARD16	 srcHeight,
+		    CARD16	 dstWidth,
+		    CARD16	 dstHeight,
+		    unsigned int *pWidth,
+		    unsigned int *pHeight)
+{
+    *pWidth  = dstWidth;
+    *pHeight = dstHeight;
+
+    return Success;
+}
+
+static int
+dmxXvPutImage (ClientPtr     client,
+	       DrawablePtr   pDrawable,
+	       XvPortPtr     pPort,
+	       GCPtr	     pGC,
+	       INT16	     srcX,
+	       INT16	     srcY,
+	       CARD16	     srcWidth,
+	       CARD16	     srcHeight,
+	       INT16	     dstX,
+	       INT16	     dstY,
+	       CARD16	     dstWidth,
+	       CARD16	     dstHeight,
+	       XvImagePtr    pImage,
+	       unsigned char *data,
+	       Bool	     sync,
+	       CARD16	     width,
+	       CARD16	     height)
+{
+    ScreenPtr     pScreen = pDrawable->pScreen;
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV ((WindowPtr) pDrawable);
+    dmxGCPrivPtr  pGCPriv = DMX_GET_GC_PRIV (pGC);
+
+    DMX_XV_PORT_PRIV (pPort);
+
+    if (pPortPriv->id != pImage->id)
+    {
+	int p, j;
+
+	DMX_XV_ADAPTOR_PRIV (pPort->pAdaptor);
+
+	for (p = pAdaptorPriv->base;
+	     p < pAdaptorPriv->base + pAdaptorPriv->n;
+	     p++)
+	{
+	    XvImageFormatValues	*fo = NULL;
+	    int                 formats;
+
+	    XLIB_PROLOGUE (dmxScreen);
+	    fo = XvListImageFormats (dmxScreen->beDisplay, p, &formats);
+	    XLIB_EPILOGUE (dmxScreen);
+
+	    if (fo)
+	    {
+		for (j = 0; j < formats; j++)
+		    if (fo[j].id == pImage->id)
+			break;
+
+		XFree (fo);
+
+		if (j < formats)
+		{
+		    if (p != pPortPriv->port)
+		    {
+			int ret = !Success;
+
+			XLIB_PROLOGUE (dmxScreen);
+			ret = XvGrabPort (dmxScreen->beDisplay,
+					  p,
+					  CurrentTime);
+			XLIB_EPILOGUE (dmxScreen);
+
+			if (ret == Success)
+			    break;
+		    }
+		    else
+			break;
+		}
+
+	    }
+	}
+
+	pPortPriv->id = pImage->id;
+
+	if (pPortPriv->image)
+	{
+	    XFree (pPortPriv->image);
+	    pPortPriv->image = NULL;
+	}
+
+	if (pPortPriv->port && p != pPortPriv->port)
+	{
+	    XLIB_PROLOGUE (dmxScreen);
+	    XvUngrabPort (dmxScreen->beDisplay, pPortPriv->port, CurrentTime);
+	    XLIB_EPILOGUE (dmxScreen);
+
+	    pPortPriv->port = 0;
+	}
+
+	if (p < pAdaptorPriv->base + pAdaptorPriv->n)
+	{
+	    pPortPriv->port = p;
+	}
+	else if (pAdaptorPriv->n)
+	{
+	    dmxLog (dmxWarning,
+		    "XVIDEO: failed to allocated port "
+		    "for image format: 0x%x\n", pImage->id);
+	}
+    }
+    else if (pPortPriv->image)
+    {
+	if (width  != pPortPriv->image->width ||
+	    height != pPortPriv->image->height)
+	{
+	    XFree (pPortPriv->image);
+	    pPortPriv->image = NULL;
+	}
+    }
+
+    if (!pPortPriv->image && pPortPriv->port)
+    {
+	XLIB_PROLOGUE (dmxScreen);
+	pPortPriv->image = XvCreateImage (dmxScreen->beDisplay,
+					  pPortPriv->port,
+					  pImage->id,
+					  NULL,
+					  width, 
+					  height);
+	XLIB_EPILOGUE (dmxScreen);
+
+	if (!pPortPriv->image)
+	    return BadAlloc;
+
+	dmxLogOutput (dmxScreen,
+		      "XVIDEO: created 0x%x image with dimensions %dx%d\n",
+		      pImage->id, width, height);
+    }
+
+    if (pPortPriv->image)
+    {
+	pPortPriv->image->data = (char *) data;
+
+	XLIB_PROLOGUE (dmxScreen);
+	XvPutImage (dmxScreen->beDisplay,
+		    pPortPriv->port,
+		    pWinPriv->window,
+		    pGCPriv->gc,
+		    pPortPriv->image,
+		    srcX, srcY, srcWidth, srcHeight,
+		    dstX, dstY, dstWidth, dstHeight);
+	XLIB_EPILOGUE (dmxScreen);
+
+	dmxSync (dmxScreen, FALSE);
+    }
+
+    return Success;
+}
+
+static int
+dmxXvQueryImageAttributes (ClientPtr  client,
+			   XvPortPtr  pPort,
+			   XvImagePtr pImage,
+			   CARD16     *width,
+			   CARD16     *height,
+			   int	      *pitches,
+			   int	      *offsets)
+{
+    if (*width > DMX_XV_IMAGE_MAX_WIDTH)
+	*width = DMX_XV_IMAGE_MAX_WIDTH;
+
+    if (*height > DMX_XV_IMAGE_MAX_HEIGHT)
+	*height = DMX_XV_IMAGE_MAX_HEIGHT;
+
+    *width = (*width + 7) & ~7;
+
+    switch (pImage->id) {
+    case DMX_FOURCC_YUY2:
+	if (offsets)
+	    offsets[0] = 0;
+
+	if (pitches)
+	    pitches[0] = *width * 2;
+
+	return *width * *height * 2;
+    case DMX_FOURCC_YV12:
+	*height = (*height + 1) & ~1;
+
+	if (offsets)
+	{
+	    offsets[0] = 0;
+	    offsets[1] = *width * *height;
+	    offsets[2] = *width * *height + (*width >> 1) * (*height >> 1);
+	}
+
+	if (pitches)
+	{
+	    pitches[0] = *width;
+	    pitches[1] = pitches[2] = *width >> 1;
+	}
+
+	return *width * *height + (*width >> 1) * *height;
+    default:
+	return 0;
+    }
+}
+
+static void
+dmxXvFreeAdaptor (XvAdaptorPtr pAdaptor)
+{
+    xfree (pAdaptor->pEncodings);
+    xfree (pAdaptor->pFormats);
+
+    if (pAdaptor->pPorts)
+	xfree (pAdaptor->pPorts);
+}
+
+static Bool
+dmxXvInitAdaptors (ScreenPtr pScreen)
+{
+    dmxXvAdaptorPtr pAdaptorPriv;
+    XvAdaptorPtr    pAdaptor;
+    dmxXvPortPtr    pPortPriv;
+    XvPortPtr       pPort;
+    XvFormatPtr     pFormat;
+    XvEncodingPtr   pEncoding;
+    XvImagePtr      pImages;
+    int		    i, j, nImages = 0;
+    DMXScreenInfo   *dmxScreen = &dmxScreens[pScreen->myNum];
+
+    DMX_XV_SCREEN (pScreen);
+
+    pXvScreen->nAdaptors = 0;
+    pXvScreen->pAdaptors = NULL;
+
+    pImages = xalloc (sizeof (xvImages));
+    if (!pImages)
+	return FALSE;
+
+    for (i = 0; i < dmxXvImageFormatsNum; i++)
+    {
+	for (j = 0; j < sizeof (xvImages) / sizeof (XvImageRec); j++)
+	{
+	    char imageName[5];
+
+	    sprintf (imageName, "%c%c%c%c",
+		     xvImages[j].id & 0xff,
+		     (xvImages[j].id >> 8) & 0xff,
+		     (xvImages[j].id >> 16) & 0xff,
+		     (xvImages[j].id >> 24) & 0xff);
+
+	    if (strcmp (imageName, dmxXvImageFormats[i]) == 0 ||
+		strtol (dmxXvImageFormats[i], NULL, 0) == xvImages[j].id)
+	    {
+		dmxLogOutput (dmxScreen, "XVIDEO: using image format: \n");
+		dmxLogOutput (dmxScreen,"      id: 0x%x", xvImages[j].id);
+		if (isprint (imageName[0]) && isprint (imageName[1]) &&
+		    isprint (imageName[2]) && isprint (imageName[3])) 
+		    dmxLogOutputCont (dmxScreen, " (%s)\n", imageName);
+		else
+		    dmxLogOutputCont (dmxScreen, "\n", imageName);
+
+		dmxLogOutput (dmxScreen, "        bits per pixel: %i\n",
+			      xvImages[j].bits_per_pixel);
+		dmxLogOutput (dmxScreen, "        number of planes: %i\n",
+			      xvImages[j].num_planes);
+
+		dmxLogOutput (dmxScreen, "        type: %s (%s)\n",
+			      (xvImages[j].type == XvRGB) ? "RGB" : "YUV",
+			      (xvImages[j].format == XvPacked) ?
+			      "packed" : "planar");
+
+		if (xvImages[j].type == XvRGB)
+		{
+		    dmxLogOutput (dmxScreen, "        depth: %i\n",
+				  xvImages[j].depth);
+		    dmxLogOutput (dmxScreen,
+				  "        red, green, blue masks: "
+				  "0x%x, 0x%x, 0x%x\n",
+				  xvImages[j].red_mask,
+				  xvImages[j].green_mask,
+				  xvImages[j].blue_mask);
+		}
+
+		pImages[nImages++] = xvImages[j];
+		break;
+	    }
+	}
+
+	if (j == sizeof (xvImages) / sizeof (XvImageRec))
+	{
+	    dmxLogOutput (dmxScreen,
+			  "XVIDEO: unsupported image format %s\n",
+			  dmxXvImageFormats[i]);
+	}
+    }
+
+    if (!nImages)
+    {
+	dmxLogOutput (dmxScreen, "XVIDEO: no supported image formats "
+		      "enabled\n");
+	xfree (pImages);
+	return TRUE;
+    }
+
+    pAdaptor = Xcalloc (1, sizeof (XvAdaptorRec) + sizeof (dmxXvAdaptorRec));
+    pAdaptorPriv = (dmxXvAdaptorPtr) (pAdaptor + 1);
+    if (!pAdaptor)
+	return FALSE;
+
+    pAdaptor->type    = XvInputMask | XvImageMask;
+    pAdaptor->pScreen = pScreen;
+
+    pAdaptor->ddFreePort	     = dmxXvFreePort;
+    pAdaptor->ddStopVideo	     = dmxXvStopVideo;
+    pAdaptor->ddSetPortAttribute     = dmxSetPortAttribute;
+    pAdaptor->ddGetPortAttribute     = dmxGetPortAttribute;
+    pAdaptor->ddPutImage	     = dmxXvPutImage;
+    pAdaptor->ddQueryBestSize	     = dmxXvQueryBestSize;
+    pAdaptor->ddQueryImageAttributes = dmxXvQueryImageAttributes;
+
+    pAdaptor->name = "DMX Video";
+
+    pEncoding = Xcalloc (1, sizeof (XvEncodingRec));
+    if (!pEncoding)
+	return FALSE;
+
+    pEncoding->id      = 0;
+    pEncoding->pScreen = pScreen;
+    pEncoding->name    = "XV_IMAGE";
+
+    pEncoding->width  = DMX_XV_IMAGE_MAX_WIDTH;
+    pEncoding->height = DMX_XV_IMAGE_MAX_HEIGHT;
+
+    pEncoding->rate.numerator	= 1;
+    pEncoding->rate.denominator = 1;
+
+    pAdaptor->nEncodings = 1;
+    pAdaptor->pEncodings = pEncoding;
+
+    pAdaptor->nImages = nImages;
+    pAdaptor->pImages = pImages;
+
+    pAdaptor->nAttributes = 0;
+    pAdaptor->pAttributes = 0;
+
+    pFormat = Xcalloc (1, sizeof (XvFormatRec));
+    if (!pFormat)
+	return FALSE;
+
+    pFormat->depth  = pScreen->rootDepth;
+    pFormat->visual = pScreen->rootVisual;
+
+    pAdaptor->nFormats = 1;
+    pAdaptor->pFormats = pFormat;
+
+    pPort = Xcalloc (DMX_XV_NUM_PORTS,
+		     sizeof (XvPortRec) + sizeof (dmxXvPortRec));
+    pPortPriv = (dmxXvPortPtr) (pPort + DMX_XV_NUM_PORTS);
+    if (!pPort)
+	return FALSE;
+
+    for (i = 0; i < DMX_XV_NUM_PORTS; i++)
+    {
+	pPort[i].id = FakeClientID (0);
+
+	if (!AddResource (pPort[i].id, XvGetRTPort (), &pPort[i]))
+	    return FALSE;
+
+	pPort[i].pAdaptor    = pAdaptor;
+	pPort[i].pNotify     = (XvPortNotifyPtr) 0;
+	pPort[i].pDraw	     = (DrawablePtr) 0;
+	pPort[i].client      = (ClientPtr) 0;
+	pPort[i].grab.client = (ClientPtr) 0;
+	pPort[i].time	     = currentTime;
+	pPort[i].devPriv.ptr = pPortPriv + i;
+    }
+
+    pAdaptor->nPorts      = DMX_XV_NUM_PORTS;
+    pAdaptor->pPorts      = pPort;
+    pAdaptor->base_id     = pPort->id;
+    pAdaptor->devPriv.ptr = pAdaptorPriv;
+
+    pXvScreen->pAdaptors = pAdaptor;
+    pXvScreen->nAdaptors = 1;
+
+    return TRUE;
+}
+
+static Bool
+dmxXvCloseScreen (int i, ScreenPtr pScreen)
+{
+    int	j;
+
+    DMX_XV_SCREEN (pScreen);
+
+    for (j = 0; j < pXvScreen->nAdaptors; j++)
+	dmxXvFreeAdaptor (&pXvScreen->pAdaptors[j]);
+
+    if (pXvScreen->pAdaptors)
+	xfree (pXvScreen->pAdaptors);
+
+    return TRUE;
+}
+
+static int
+dmxXvQueryAdaptors (ScreenPtr	 pScreen,
+		    XvAdaptorPtr *pAdaptors,
+		    int		 *nAdaptors)
+{
+    DMX_XV_SCREEN (pScreen);
+
+    *nAdaptors = pXvScreen->nAdaptors;
+    *pAdaptors = pXvScreen->pAdaptors;
+
+    return Success;
+}
+
+void
+dmxBEXvScreenInit (ScreenPtr pScreen)
+{
+    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+    XvAdaptorInfo *ai;
+    unsigned int  nAdaptors;
+    int           i, j, k, l, ret = !Success;
+
+    DMX_XV_SCREEN (pScreen);
+
+    XLIB_PROLOGUE (dmxScreen);
+    ret = XvQueryAdaptors (dmxScreen->beDisplay,
+			   DefaultRootWindow (dmxScreen->beDisplay),
+			   &nAdaptors,
+			   &ai);
+    XLIB_EPILOGUE (dmxScreen);
+
+    if (ret != Success)
+    {
+	dmxLogOutput (dmxScreen,
+		      "XVIDEO: back-end support unavailable. "
+		      "XvQueryAdaptors returned %d\n",
+		      ret);
+	return;
+    }
+
+    for (i = 0; i < pXvScreen->nAdaptors; i++)
+    {
+	XvAdaptorPtr pAdaptor = &pXvScreen->pAdaptors[i];
+
+	DMX_XV_ADAPTOR_PRIV (pAdaptor);
+
+	for (j = 0; j < nAdaptors; j++)
+	{
+	    if ((pAdaptor->type & ai[j].type) != pAdaptor->type)
+		continue;
+
+	    for (k = 0; k < pAdaptor->nFormats; k++)
+	    {
+		Visual   *visual;
+		VisualID vid;
+		int      depth = pAdaptor->pFormats[k].depth;
+
+		visual = dmxLookupVisualFromID (pScreen,
+						pAdaptor->pFormats[k].visual);
+		if (visual)
+		    vid = XVisualIDFromVisual (visual);
+		else
+		    vid = 0;
+		    
+		for (l = 0; l < ai[j].num_formats; l++)
+		{
+		    if (ai[j].formats[l].depth     == depth &&
+			ai[j].formats[l].visual_id == vid)
+			break;
+		}
+
+		if (l == ai[j].num_formats)
+		    break;
+	    }
+
+	    if (k < pAdaptor->nFormats)
+		continue;
+
+	    dmxLogOutput (dmxScreen,
+			  "XVIDEO: Using back-end adaptor:\n"
+			  "  name:        %s\n"
+			  "  type:        %s%s%s%s%s\n"
+			  "  ports:       %ld\n"
+			  "  first port:  %ld\n",
+			  ai[j].name,
+			  (ai[j].type & XvInputMask)	? "input | "	: "",
+			  (ai[j].type & XvOutputMask)	? "output | "	: "",
+			  (ai[j].type & XvVideoMask)	? "video | "	: "",
+			  (ai[j].type & XvStillMask)	? "still | "	: "",
+			  (ai[j].type & XvImageMask)	? "image"	: "",
+			  ai[j].num_ports,
+			  ai[j].base_id);
+
+	    pAdaptorPriv->base = ai[j].base_id;
+	    pAdaptorPriv->n    = ai[j].num_ports;
+	    break;
+	}
+
+	if (j == nAdaptors)
+	    dmxLogOutput (dmxScreen, "XVIDEO: No usable back-end adaptors "
+			  "found for '%s'\n", pAdaptor->name);
+    }
+
+    if (nAdaptors > 0)
+	XvFreeAdaptorInfo (ai);
+}
+
+void
+dmxBEXvScreenFini (ScreenPtr pScreen)
+{
+    int i, j;
+
+    DMX_XV_SCREEN (pScreen);
+
+    for (i = 0; i < pXvScreen->nAdaptors; i++)
+    {
+	DMX_XV_ADAPTOR_PRIV (&pXvScreen->pAdaptors[i]);
+
+	for (j = 0; j < pXvScreen->pAdaptors[i].nPorts; j++)
+	    dmxXvFreePort (&pXvScreen->pAdaptors[i].pPorts[j]);
+
+	pAdaptorPriv->base = 0;
+	pAdaptorPriv->n    = 0;
+    }
+}
+
+Bool
+dmxXvScreenInit (ScreenPtr pScreen)
+{
+    XvScreenPtr pXvScreen;
+    int		status;
+
+    status = XvScreenInit (pScreen);
+    if (status != Success)
+	return FALSE;
+
+    pXvScreen = DMX_GET_XV_SCREEN (pScreen);
+    pXvScreen->ddCloseScreen   = dmxXvCloseScreen;
+    pXvScreen->ddQueryAdaptors = dmxXvQueryAdaptors;
+    pXvScreen->devPriv.ptr     = (pointer) 0;
+
+    if (!dmxXvInitAdaptors (pScreen))
+	return FALSE;
+
+    return TRUE;
+}
+
+#endif
diff --git a/hw/dmx/dmxxv.h b/hw/dmx/dmxxv.h
new file mode 100644
index 0000000..b3ca5a2
--- /dev/null
+++ b/hw/dmx/dmxxv.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#ifndef DMXXV_H
+#define DMXXV_H
+
+extern Bool dmxXvScreenInit (ScreenPtr pScreen);
+extern void dmxBEXvScreenInit (ScreenPtr pScreen);
+extern void dmxBEXvScreenFini (ScreenPtr pScreen);
+
+#endif /* DMXXV_H */
diff --git a/hw/dmx/examples/Makefile.am b/hw/dmx/examples/Makefile.am
index d814339..757dc4d 100644
--- a/hw/dmx/examples/Makefile.am
+++ b/hw/dmx/examples/Makefile.am
@@ -1,13 +1,9 @@
-if DMX_BUILD_USB 
-# Requires <linux/input.h>
-EV_PROG = ev
-endif
-
 bin_PROGRAMS = \
 	xdmx dmxwininfo dmxreconfig dmxresize \
 	dmxaddscreen dmxrmscreen \
-	dmxaddinput dmxrminput
-noinst_PROGRAMS = xinput xtest evi res xled xbell $(EV_PROG)
+	dmxaddinput dmxrminput \
+	dmxconnect
+noinst_PROGRAMS = xinput xtest evi res xled xbell
 
 xdmx_SOURCES = xdmx.c
 xdmx_LDADD = @DMXEXAMPLES_DEP_LIBS@
@@ -41,6 +37,10 @@ dmxrminput_SOURCES = dmxrminput.c
 dmxrminput_LDADD = @DMXEXAMPLES_DEP_LIBS@
 dmxrminput_CFLAGS = @DMXEXAMPLES_DEP_CFLAGS@
 
+dmxconnect_SOURCES = dmxconnect.c
+dmxconnect_LDADD = @DBUSEXAMPLES_DEP_LIBS@
+dmxconnect_CFLAGS = @DBUSEXAMPLES_DEP_CFLAGS@ -I$(top_srcdir)/hw/dmx
+
 xinput_SOURCES = xinput.c
 xinput_LDADD = @DMXXIEXAMPLES_DEP_LIBS@
 xinput_CFLAGS = @DMXXIEXAMPLES_DEP_CFLAGS@
@@ -64,7 +64,3 @@ xled_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@
 xbell_SOURCES = xbell.c
 xbell_LDADD = @X11EXAMPLES_DEP_LIBS@
 xbell_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@
-
-ev_SOURCES = ev.c
-ev_LDADD = 
-ev_CFLAGS = 
diff --git a/hw/dmx/examples/dmxaddinput.c b/hw/dmx/examples/dmxaddinput.c
index dcfd4f5..c2eecf3 100644
--- a/hw/dmx/examples/dmxaddinput.c
+++ b/hw/dmx/examples/dmxaddinput.c
@@ -46,29 +46,25 @@ int main(int argc, char **argv)
     int                  status;
 
     if (argc != 5) {
-        printf("Usage: %s display c|b name|screen isCore\n", argv[0]);
+        fprintf(stderr, "Usage: %s display c|b name|screen isCore\n", argv[0]);
         return -1;
     }
 
     if (!(display = XOpenDisplay(argv[1]))) {
-        printf("Cannot open display %s\n", argv[1]);
+        fprintf(stderr, "Cannot open display %s\n", argv[1]);
         return -1;
     }
 
     if (!DMXQueryExtension(display, &event_base, &error_base)) {
-        printf("DMX extension not present\n");
+        fprintf(stderr, "DMX extension not present\n");
         return -1;
     }
-    printf("DMX extension present: event_base = %d, error_base = %d\n",
-           event_base, error_base);
 
     if (!DMXQueryVersion(display,
                          &major_version, &minor_version, &patch_version)) {
-        printf("Could not get extension version\n");
+        fprintf(stderr, "Could not get extension version\n");
         return -1;
     }
-    printf("Extension version: %d.%d patch %d\n",
-           major_version, minor_version, patch_version);
 
     if (argv[2][0] == 'c') {
         status = DMXAddConsoleInput(display, argv[3], atoi(argv[4]), &id);
@@ -76,8 +72,8 @@ int main(int argc, char **argv)
         status = DMXAddBackendInput(display, atoi(argv[3]), atoi(argv[4]),&id);
     }
 
-    printf("status = %d, id = %d\n", status, id);
+    printf ("%d", id);
 
     XCloseDisplay(display);
-    return 0;
+    return status ? 0 : -1;
 }
diff --git a/hw/dmx/examples/dmxaddscreen.c b/hw/dmx/examples/dmxaddscreen.c
index 8e60872..9c93c9c 100644
--- a/hw/dmx/examples/dmxaddscreen.c
+++ b/hw/dmx/examples/dmxaddscreen.c
@@ -48,12 +48,12 @@ int main(int argc, char **argv)
     unsigned int         mask = 0;
 
     if (argc != 4 && argc != 14) {
-        printf("Usage: %s display screenNum displayName [scrnx scrny scrnw scrnh rootx rooty rootw rooth originx originy]\n", argv[0]);
+        fprintf(stderr, "Usage: %s display screenNum displayName [scrnx scrny scrnw scrnh rootx rooty rootw rooth originx originy]\n", argv[0]);
         return -1;
     }
 
     if (!(display = XOpenDisplay(argv[1]))) {
-        printf("Cannot open display %s\n", argv[1]);
+        fprintf(stderr, "Cannot open display %s\n", argv[1]);
         return -1;
     }
 
@@ -83,23 +83,25 @@ int main(int argc, char **argv)
     }
 
     if (!DMXQueryExtension(display, &event_base, &error_base)) {
-        printf("DMX extension not present\n");
+        fprintf(stderr, "DMX extension not present\n");
         return -1;
     }
-    printf("DMX extension present: event_base = %d, error_base = %d\n",
-           event_base, error_base);
 
     if (!DMXQueryVersion(display,
                          &major_version, &minor_version, &patch_version)) {
-        printf("Could not get extension version\n");
+        fprintf(stderr, "Could not get extension version\n");
         return -1;
     }
-    printf("Extension version: %d.%d patch %d\n",
-           major_version, minor_version, patch_version);
 
     if (!DMXAddScreen(display, argv[3], mask, &attr, &screenNum))
-	printf("Failed to add %s as screen #%d\n", argv[2], screenNum);
-    
+    {
+	fprintf(stderr, "Failed to add %s as screen #%d\n", argv[3], screenNum);
+	XCloseDisplay(display);
+	return -1;
+    }
+
+    printf ("%d", screenNum);
+
     XCloseDisplay(display);
     return 0;
 }
diff --git a/hw/dmx/examples/dmxconnect.c b/hw/dmx/examples/dmxconnect.c
new file mode 100644
index 0000000..194d301
--- /dev/null
+++ b/hw/dmx/examples/dmxconnect.c
@@ -0,0 +1,884 @@
+/*
+ * Copyright © 2008 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+/*
+ * X authentication and transport code adopted from libxcb
+ * 
+ * Copyright (C) 2001-2004 Bart Massey and Jamey Sharp.
+ */
+
+#include <dbus/dbus.h>
+#include <stdio.h>
+
+#include <X11/Xauth.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#ifdef DNETCONN
+#include <netdnet/dnetdb.h>
+#include <netdnet/dn.h>
+#endif
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <xcb/xcb.h>
+
+#ifdef HASXDMAUTH
+#include <X11/Xdmcp.h>
+#endif
+
+#include "dmxdbus.h"
+
+enum auth_protos {
+#ifdef HASXDMAUTH
+    AUTH_XA1,
+#endif
+    AUTH_MC1,
+    N_AUTH_PROTOS
+};
+
+static char *authnames[N_AUTH_PROTOS] = {
+#ifdef HASXDMAUTH
+    "XDM-AUTHORIZATION-1",
+#endif
+    "MIT-MAGIC-COOKIE-1",
+};
+
+static size_t memdup(char **dst, void *src, size_t len)
+{
+    if(len)
+	*dst = malloc(len);
+    else
+	*dst = 0;
+    if(!*dst)
+	return 0;
+    memcpy(*dst, src, len);
+    return len;
+}
+
+static int authname_match(enum auth_protos kind, char *name, int namelen)
+{
+    if(strlen(authnames[kind]) != namelen)
+	return 0;
+    if(memcmp(authnames[kind], name, namelen))
+	return 0;
+    return 1;
+}
+
+#define SIN6_ADDR(s) (&((struct sockaddr_in6 *)s)->sin6_addr)
+
+static Xauth *get_authptr(struct sockaddr *sockname, unsigned int socknamelen,
+                          int display)
+{
+    char *addr = 0;
+    int addrlen = 0;
+    unsigned short family;
+    char hostnamebuf[256];   /* big enough for max hostname */
+    char dispbuf[40];   /* big enough to hold more than 2^64 base 10 */
+    int authnamelens[N_AUTH_PROTOS];
+    int i;
+
+    family = FamilyLocal; /* 256 */
+    switch(sockname->sa_family)
+    {
+#ifdef AF_INET6
+    case AF_INET6:
+        addr = (char *) SIN6_ADDR(sockname);
+        addrlen = sizeof(*SIN6_ADDR(sockname));
+        if(!IN6_IS_ADDR_V4MAPPED(SIN6_ADDR(sockname)))
+        {
+            if(!IN6_IS_ADDR_LOOPBACK(SIN6_ADDR(sockname)))
+                family = XCB_FAMILY_INTERNET_6;
+            break;
+        }
+        addr += 12;
+        /* if v4-mapped, fall through. */
+#endif
+    case AF_INET:
+        if(!addr)
+            addr = (char *) &((struct sockaddr_in *)sockname)->sin_addr;
+        addrlen = sizeof(((struct sockaddr_in *)sockname)->sin_addr);
+        if(*(in_addr_t *) addr != htonl(INADDR_LOOPBACK))
+            family = XCB_FAMILY_INTERNET;
+        break;
+    case AF_UNIX:
+        break;
+    default:
+        return 0;   /* cannot authenticate this family */
+    }
+
+    snprintf(dispbuf, sizeof(dispbuf), "%d", display);
+
+    if (family == FamilyLocal) {
+        if (gethostname(hostnamebuf, sizeof(hostnamebuf)) == -1)
+            return 0;   /* do not know own hostname */
+        addr = hostnamebuf;
+        addrlen = strlen(addr);
+    }
+
+    for (i = 0; i < N_AUTH_PROTOS; i++)
+	authnamelens[i] = strlen(authnames[i]);
+    return XauGetBestAuthByAddr (family,
+                                 (unsigned short) addrlen, addr,
+                                 (unsigned short) strlen(dispbuf), dispbuf,
+                                 N_AUTH_PROTOS, authnames, authnamelens);
+}
+
+#ifdef HASXDMAUTH
+static int next_nonce(void)
+{
+    static int nonce = 0;
+    static pthread_mutex_t nonce_mutex = PTHREAD_MUTEX_INITIALIZER;
+    int ret;
+    pthread_mutex_lock(&nonce_mutex);
+    ret = nonce++;
+    pthread_mutex_unlock(&nonce_mutex);
+    return ret;
+}
+
+static void do_append(char *buf, int *idxp, void *val, size_t valsize) {
+    memcpy(buf + *idxp, val, valsize);
+    *idxp += valsize;
+}
+#endif
+     
+static int compute_auth(xcb_auth_info_t *info, Xauth *authptr, struct sockaddr *sockname)
+{
+    if (authname_match(AUTH_MC1, authptr->name, authptr->name_length)) {
+        info->datalen = memdup(&info->data, authptr->data, authptr->data_length);
+        if(!info->datalen)
+            return 0;
+        return 1;
+    }
+#ifdef HASXDMAUTH
+#define APPEND(buf,idx,val) do_append((buf),&(idx),&(val),sizeof(val))
+    if (authname_match(AUTH_XA1, authptr->name, authptr->name_length)) {
+	int j;
+
+	info->data = malloc(192 / 8);
+	if(!info->data)
+	    return 0;
+
+	for (j = 0; j < 8; j++)
+	    info->data[j] = authptr->data[j];
+	switch(sockname->sa_family) {
+        case AF_INET:
+            /*block*/ {
+	    struct sockaddr_in *si = (struct sockaddr_in *) sockname;
+	    APPEND(info->data, j, si->sin_addr.s_addr);
+	    APPEND(info->data, j, si->sin_port);
+	}
+	break;
+#ifdef AF_INET6
+        case AF_INET6:
+            /*block*/ {
+            struct sockaddr_in6 *si6 = (struct sockaddr_in6 *) sockname;
+            if(IN6_IS_ADDR_V4MAPPED(SIN6_ADDR(sockname)))
+            {
+                APPEND(info->data, j, si6->sin6_addr.s6_addr[12]);
+                APPEND(info->data, j, si6->sin6_port);
+            }
+            else
+            {
+                /* XDM-AUTHORIZATION-1 does not handle IPv6 correctly.  Do the
+                   same thing Xlib does: use all zeroes for the 4-byte address
+                   and 2-byte port number. */
+                uint32_t fakeaddr = 0;
+                uint16_t fakeport = 0;
+                APPEND(info->data, j, fakeaddr);
+                APPEND(info->data, j, fakeport);
+            }
+        }
+        break;
+#endif
+        case AF_UNIX:
+            /*block*/ {
+	    uint32_t fakeaddr = htonl(0xffffffff - next_nonce());
+	    uint16_t fakeport = htons(getpid());
+	    APPEND(info->data, j, fakeaddr);
+	    APPEND(info->data, j, fakeport);
+	}
+	break;
+        default:
+            free(info->data);
+            return 0;   /* do not know how to build this */
+	}
+	{
+	    uint32_t now = htonl(time(0));
+	    APPEND(info->data, j, now);
+	}
+	assert(j <= 192 / 8);
+	while (j < 192 / 8)
+	    info->data[j++] = 0;
+	info->datalen = j;
+	XdmcpWrap ((unsigned char *) info->data, (unsigned char *) authptr->data + 8, (unsigned char *) info->data, info->datalen);
+	return 1;
+    }
+#undef APPEND
+#endif
+
+    return 0;   /* Unknown authorization type */
+}
+
+int _get_auth_info (int fd, xcb_auth_info_t *info, int display)
+{
+    /* code adapted from Xlib/ConnDis.c, xtrans/Xtranssocket.c,
+       xtrans/Xtransutils.c */
+    char sockbuf[sizeof(struct sockaddr) + MAXPATHLEN];
+    unsigned int socknamelen = sizeof(sockbuf);   /* need extra space */
+    struct sockaddr *sockname = (struct sockaddr *) &sockbuf;
+    Xauth *authptr = 0;
+    int ret = 1;
+
+    if (getpeername(fd, sockname, &socknamelen) == -1)
+        return 0;  /* can only authenticate sockets */
+
+    authptr = get_authptr(sockname, socknamelen, display);
+    if (authptr == 0)
+        return 0;   /* cannot find good auth data */
+
+    info->namelen = memdup(&info->name, authptr->name, authptr->name_length);
+    if(info->namelen)
+	ret = compute_auth(info, authptr, sockname);
+    if(!ret)
+    {
+	free(info->name);
+	info->name = 0;
+	info->namelen = 0;
+    }
+    XauDisposeAuth(authptr);
+    return ret;
+}
+
+static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port);
+static int _xcb_open_unix(char *protocol, const char *file);
+#ifdef DNETCONN
+static int _xcb_open_decnet(const char *host, char *protocol, const unsigned short port);
+#endif
+
+static int _xcb_open(char *host, char *protocol, const int display)
+{
+    int fd;
+    static const char base[] = "/tmp/.X11-unix/X";
+    char file[sizeof(base) + 20];
+
+    if(*host)
+    {
+#ifdef DNETCONN
+        /* DECnet displays have two colons, so _xcb_parse_display will have
+           left one at the end.  However, an IPv6 address can end with *two*
+           colons, so only treat this as a DECnet display if host ends with
+           exactly one colon. */
+        char *colon = strchr(host, ':');
+        if(colon && *(colon+1) == '\0')
+        {
+            *colon = '\0';
+            return _xcb_open_decnet(host, protocol, display);
+        }
+        else
+#endif
+            if (protocol
+                || strcmp("unix",host)) { /* follow the old unix: rule */
+
+                /* display specifies TCP */
+                unsigned short port = X_TCP_PORT + display;
+                return _xcb_open_tcp(host, protocol, port);
+            }
+    }
+
+    /* display specifies Unix socket */
+    snprintf(file, sizeof(file), "%s%d", base, display);
+    return  _xcb_open_unix(protocol, file);
+
+
+    return fd;
+}
+
+#ifdef DNETCONN
+static int _xcb_open_decnet(const char *host, const char *protocol, const unsigned short port)
+{
+    int fd;
+    struct sockaddr_dn addr;
+    struct accessdata_dn accessdata;
+    struct nodeent *nodeaddr = getnodebyname(host);
+
+    if(!nodeaddr)
+        return -1;
+    if (protocol && strcmp("dnet",protocol))
+        return -1;
+    addr.sdn_family = AF_DECnet;
+
+    addr.sdn_add.a_len = nodeaddr->n_length;
+    memcpy(addr.sdn_add.a_addr, nodeaddr->n_addr, addr.sdn_add.a_len);
+
+    sprintf((char *)addr.sdn_objname, "X$X%d", port);
+    addr.sdn_objnamel = strlen((char *)addr.sdn_objname);
+    addr.sdn_objnum = 0;
+
+    fd = socket(PF_DECnet, SOCK_STREAM, 0);
+    if(fd == -1)
+        return -1;
+
+    memset(&accessdata, 0, sizeof(accessdata));
+    sprintf((char*)accessdata.acc_acc, "%d", getuid());
+    accessdata.acc_accl = strlen((char *)accessdata.acc_acc);
+    setsockopt(fd, DNPROTO_NSP, SO_CONACCESS, &accessdata, sizeof(accessdata));
+
+    if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
+        return -1;
+    return fd;
+}
+#endif
+
+static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port)
+{
+    int fd = -1;
+    struct addrinfo hints = { 0
+#ifdef AI_ADDRCONFIG
+                              | AI_ADDRCONFIG
+#endif
+#ifdef AI_NUMERICSERV
+                              | AI_NUMERICSERV
+#endif
+                              , AF_UNSPEC, SOCK_STREAM };
+    char service[6]; /* "65535" with the trailing '\0' */
+    struct addrinfo *results, *addr;
+    char *bracket;
+
+    if (protocol && strcmp("tcp",protocol))
+        return -1;
+
+#ifdef AF_INET6
+    /* Allow IPv6 addresses enclosed in brackets. */
+    if(host[0] == '[' && (bracket = strrchr(host, ']')) && bracket[1] == '\0')
+    {
+        *bracket = '\0';
+        ++host;
+        hints.ai_flags |= AI_NUMERICHOST;
+        hints.ai_family = AF_INET6;
+    }
+#endif
+
+    snprintf(service, sizeof(service), "%hu", port);
+    if(getaddrinfo(host, service, &hints, &results))
+        /* FIXME: use gai_strerror, and fill in error connection */
+        return -1;
+
+    for(addr = results; addr; addr = addr->ai_next)
+    {
+        fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+        if(fd >= 0 && connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
+            break;
+        fd = -1;
+    }
+    freeaddrinfo(results);
+    return fd;
+}
+
+static int _xcb_open_unix(char *protocol, const char *file)
+{
+    int fd;
+    struct sockaddr_un addr;
+
+    if (protocol && strcmp("unix",protocol))
+        return -1;
+
+    strcpy(addr.sun_path, file);
+    addr.sun_family = AF_UNIX;
+#if HAVE_SOCKADDR_SUN_LEN
+    addr.sun_len = SUN_LEN(&addr);
+#endif
+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if(fd == -1)
+        return -1;
+    if(connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
+        return -1;
+    return fd;
+}
+
+xcb_connection_t *
+connect_to_display (const char      *name,
+		    xcb_auth_info_t *auth)
+{
+    int fd, len, screen, display = 0;
+    char *host;
+    char *protocol = NULL;
+    char *slash;
+    xcb_connection_t *c;
+
+    slash = strrchr(name, '/');
+    if (slash) {
+        len = slash - name;
+	protocol = malloc(len + 1);
+	if(!protocol)
+	    return 0;
+	memcpy (protocol, name, len);
+	(protocol)[len] = '\0';
+    }
+
+    if (!xcb_parse_display (name, &host, &display, &screen))
+        return NULL;
+
+    fd = _xcb_open (host, protocol, display);
+    free (host);
+
+    if (fd == -1)
+        return NULL;
+
+    if (_get_auth_info (fd, auth, display))
+    {
+        c = xcb_connect_to_fd (fd, auth);
+    }
+    else
+    {
+        c = xcb_connect_to_fd (fd, 0);
+	auth->name = NULL;
+	auth->data = NULL;
+    }
+
+    return c;
+}
+
+void
+append_auth_info (DBusMessageIter *iter,
+		  xcb_auth_info_t *auth)
+{
+    DBusMessageIter subiter;
+    int             i;
+
+    dbus_message_iter_open_container (iter,
+				      DBUS_TYPE_ARRAY,
+				      DBUS_TYPE_BYTE_AS_STRING,
+				      &subiter);
+    for (i = 0; i < auth->namelen; i++)
+	dbus_message_iter_append_basic (&subiter,
+					DBUS_TYPE_BYTE,
+					&auth->name[i]);
+    dbus_message_iter_close_container (iter, &subiter);
+
+    dbus_message_iter_open_container (iter,
+				      DBUS_TYPE_ARRAY,
+				      DBUS_TYPE_BYTE_AS_STRING,
+				      &subiter);
+    for (i = 0; i < auth->datalen; i++)
+	dbus_message_iter_append_basic (&subiter,
+					DBUS_TYPE_BYTE,
+					&auth->data[i]);
+    dbus_message_iter_close_container (iter, &subiter);
+}
+
+static const unsigned int hexvalues[256] = {
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 9 */
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 19 */
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 29 */
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 39 */
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, /* 49 */
+    0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0, 0x0, /* 59 */
+    0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xb, 0xb, 0xd, 0xe, /* 69 */
+    0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 79 */
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 89 */
+    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xb, 0xc, /* 99 */
+    0xd, 0xe, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+};
+
+int
+main (int argc, char **argv)
+{
+    DBusError        err;
+    DBusConnection   *conn;
+    DBusMessage      *message;
+    DBusMessage      *reply;
+    DBusMessageIter  iter;
+    int              i, ret, fd, len, screen_num, display = 0;
+    char             *host;
+    char             *protocol = NULL;
+    char             *slash;
+    xcb_connection_t *c = NULL;
+    xcb_auth_info_t  auth = { 0 };
+    char	     *displayname = NULL;
+    char	     *name = NULL;
+    char	     *auth_name = NULL;
+    char	     *auth_data = NULL;
+    int              dmxdisplay = 0;
+    int              dmxscreen = -1;
+    int              viewonly = 0;
+    uint32_t         window = 0;
+    uint32_t         screen = 0;
+    dbus_bool_t      core = TRUE;
+    char             dest[256];
+    char             path[256];
+    uint32_t         index;
+
+    for (i = 1; i < argc; i++)
+    {
+	if (*argv[i] == '-')
+	{   
+	    if (strcmp (argv[i], "-display") == 0)
+	    {
+		if (++i < argc)
+		    dmxdisplay = strtol (argv[i], NULL, 0);
+	    }
+	    else if (strcmp (argv[i], "-screen") == 0)
+	    {
+		if (++i < argc)
+		    dmxscreen = strtol (argv[i], NULL, 0);
+	    }
+	    else if (strcmp (argv[i], "-window") == 0)
+	    {
+		if (++i < argc)
+		    window = strtol (argv[i], NULL, 0);
+	    }
+	    else if (strcmp (argv[i], "-name") == 0)
+	    {
+		if (++i < argc)
+		    name = argv[i];
+	    }
+	    else if (strcmp (argv[i], "-authtype") == 0)
+	    {
+		if (++i < argc)
+		    auth_name = argv[i];
+	    }
+	    else if (strcmp (argv[i], "-authdata") == 0)
+	    {
+		if (++i < argc)
+		    auth_data = argv[i];
+	    }
+	    else if (strcmp (argv[i], "-viewonly") == 0)
+	    {
+		viewonly = TRUE;
+	    }
+	    else
+	    {
+		break;
+	    }
+	}
+	else if (!displayname)
+	{
+	    displayname = argv[i];
+	}
+    }
+
+    if (i < argc || !displayname)
+    {
+	fprintf (stderr,
+		 "usage: %s "
+		 "[-display <Xdmx-display>] "
+		 "[-screen <Xdmx-screen>] "
+		 "[-window <wid>] "
+		 "[-name <name>] "
+		 "[-authtype <protoname>] "
+		 "[-authdata <hexkey>] "
+		 "[-viewonly] "
+		 "host[:port]\n",
+		 argv[0]);
+	return 1;
+    }
+
+    dbus_error_init (&err);
+
+    conn = dbus_bus_get (DBUS_BUS_SYSTEM, &err);
+    if (dbus_error_is_set (&err))
+    {
+	fprintf (stderr, "DBus Error: %s\n", err.message);
+	dbus_error_free (&err);
+
+	return 1;
+    }
+
+    if (!xcb_parse_display (displayname, &host, &display, &screen_num))
+    {
+	fprintf (stderr, "Bad display name: %s\n", displayname);
+        return 1;
+    }
+
+    if (!name)
+    {
+	name = host;
+	if (!name)
+	    name = "localhost";
+    }
+
+    slash = strrchr(displayname, '/');
+    if (slash) {
+        len = slash - displayname;
+	protocol = malloc(len + 1);
+	if(!protocol)
+	{
+	    fprintf (stderr, "Not enough memory\n");
+	    free (host);
+	    return 1;
+	}
+	memcpy (protocol, displayname, len);
+	(protocol)[len] = '\0';
+    }
+
+    fd = _xcb_open (host, protocol, display);
+
+    if (protocol)
+	free (protocol);
+
+    if (fd == -1)
+    {
+	fprintf (stderr, "Can't open socket: %s\n", displayname);
+	free (host);
+        return 1;
+    }
+
+    auth.namelen = 0;
+    auth.datalen = 0;
+
+    if (auth_name && auth_data)
+    {
+	char *data, *ptr, *hexdata = auth_data;
+	int  size;
+
+	size = strlen (hexdata) / 2;
+	data = ptr = malloc (size);
+	if (data)
+	{
+	    int j;
+
+	    for (j = 0; j < size; j++)
+	    {
+		*ptr++ = (char)
+		    ((hexvalues[(int) hexdata[0]] * 16) +
+		     (hexvalues[(int) hexdata[1]]));
+		hexdata += 2;
+	    }
+
+	    auth.namelen = strlen (auth_name);
+	    auth.name    = strdup (auth_name);
+
+	    auth.datalen = size;
+	    auth.data    = data;
+
+	    c = xcb_connect_to_fd (fd, &auth);
+	    if (!c)
+	    {
+		free (auth.name);
+		free (auth.data);
+		auth.namelen = 0;
+		auth.datalen = 0;
+	    }
+	}
+    }
+
+    if (!c)
+    {
+	if (_get_auth_info (fd, &auth, display))
+	{
+	    c = xcb_connect_to_fd (fd, &auth);
+	    if (!c)
+	    {
+		free (auth.name);
+		free (auth.data);
+		auth.namelen = 0;
+		auth.datalen = 0;
+	    }
+	}
+	else
+	{
+	    c = xcb_connect_to_fd (fd, 0);
+	}
+
+	if (!c)
+	{
+	    fprintf (stderr, "Can't open display: %s\n", displayname);
+	    free (host);
+	    return 1;
+	}
+    }
+
+    sprintf (dest, "org.x.config.display%d", dmxdisplay);
+    sprintf (path, "/org/x/config/dmx/%d", dmxdisplay);
+
+    if (!name)
+	name = host;
+
+    if (dmxscreen >= 0)
+	screen = dmxscreen;
+
+    do
+    {
+	message = dbus_message_new_method_call (dest,
+						path,
+						"org.x.config.dmx",
+						"attachScreen");
+	if (!message)
+	{
+	    dbus_set_error (&err,
+			    DBUS_ERROR_NO_MEMORY,
+			    "Not enough memory");
+	    break;
+	}
+
+	dbus_message_iter_init_append (message, &iter);
+
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_UINT32,
+					&screen);
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_STRING,
+					&displayname);
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_STRING,
+					&name);
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_UINT32,
+					&window);
+
+	append_auth_info (&iter, &auth);
+
+	reply = dbus_connection_send_with_reply_and_block (conn,
+							   message,
+							   -1,
+							   &err);
+
+	dbus_message_unref (message);
+
+	if (dbus_error_is_set (&err))
+	{
+	    if (dmxscreen < 0)
+	    {
+		if (strcmp (err.name, DMX_ERROR_SCREEN_IN_USE) == 0)
+		{
+		    dbus_error_free (&err);
+		    dbus_error_init (&err);
+
+		    screen++; /* try next screen */
+		}
+		else
+		{
+		    if (strcmp (err.name, DMX_ERROR_INVALID_SCREEN) == 0)
+		    {
+			dbus_error_free (&err);
+			dbus_error_init (&err);
+
+			dbus_set_error (&err,
+					DMX_ERROR_SCREEN_IN_USE,
+					"No available screens on display %d",
+					dmxdisplay);
+		    }
+
+		    break;
+		}
+	    }
+	    else
+	    {
+		break;
+	    }
+	}
+    } while (!reply);
+
+    xcb_disconnect (c);
+
+    if (dbus_error_is_set (&err))
+    {
+	fprintf (stderr, "Error: %s\n", err.message);
+	dbus_error_free (&err);
+
+	return 1;
+    }
+
+    dbus_message_unref (reply);
+
+    /* failing to add input is not an error */
+    if (!viewonly)
+    {
+	message = dbus_message_new_method_call (dest,
+						path,
+						"org.x.config.dmx",
+						"addInput");
+	if (!message)
+	{
+	    fprintf (stderr, "Warning: addInput: Not enough memory\n");
+	    return 0;
+	}
+
+	dbus_message_iter_init_append (message, &iter);
+
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_UINT32,
+					&screen);
+
+	dbus_message_iter_append_basic (&iter,
+					DBUS_TYPE_BOOLEAN,
+					&core);
+
+	reply = dbus_connection_send_with_reply_and_block (conn,
+							   message,
+							   -1,
+							   &err);
+
+	dbus_message_unref (message);
+
+	if (dbus_error_is_set (&err))
+	{
+	    fprintf (stderr, "Warning: addInput: %s\n", err.message);
+	    dbus_error_free (&err);
+
+	    return 0;
+	}
+
+	dbus_message_unref (reply);
+    }
+
+    message = dbus_message_new_method_call (dest,
+					    path,
+					    "org.x.config.dmx",
+					    "enableScreen");
+    if (!message)
+    {
+	fprintf (stderr, "Warning: enableScreen: Not enough memory\n");
+	return 0;
+    }
+
+    dbus_message_iter_init_append (message, &iter);
+
+    dbus_message_iter_append_basic (&iter,
+				    DBUS_TYPE_UINT32,
+				    &screen);
+
+    if (dbus_connection_send (conn, message, NULL))
+	dbus_connection_flush (conn);
+    else
+        fprintf (stderr, "Warning: enableScreen failed\n");
+
+    dbus_message_unref (message);
+
+    return 0;
+}
diff --git a/hw/dmx/examples/dmxresize.c b/hw/dmx/examples/dmxresize.c
index caed91d..6110b97 100644
--- a/hw/dmx/examples/dmxresize.c
+++ b/hw/dmx/examples/dmxresize.c
@@ -100,5 +100,5 @@ int main(int argc, char **argv)
     }
     
     XCloseDisplay(display);
-    return 0;
+    return (status == Success) ? 0 : -1;
 }
diff --git a/hw/dmx/examples/dmxrminput.c b/hw/dmx/examples/dmxrminput.c
index ef62cab..defe68d 100644
--- a/hw/dmx/examples/dmxrminput.c
+++ b/hw/dmx/examples/dmxrminput.c
@@ -74,5 +74,5 @@ int main(int argc, char **argv)
     printf("status = %d\n", status);
 
     XCloseDisplay(display);
-    return 0;
+    return status ? 0 : -1;
 }
diff --git a/hw/dmx/examples/dmxrmscreen.c b/hw/dmx/examples/dmxrmscreen.c
index fecf0f6..59a38d6 100644
--- a/hw/dmx/examples/dmxrmscreen.c
+++ b/hw/dmx/examples/dmxrmscreen.c
@@ -73,8 +73,12 @@ int main(int argc, char **argv)
            major_version, minor_version, patch_version);
 
     if (!DMXRemoveScreen(display, screenNum))
+    {
         printf("Failed to remove screen #%d\n", screenNum);
-    
+	XCloseDisplay(display);
+	return -1;
+    }
+
     XCloseDisplay(display);
     return 0;
 }
diff --git a/hw/dmx/examples/xinput.c b/hw/dmx/examples/xinput.c
index 74353a9..c930e17 100644
--- a/hw/dmx/examples/xinput.c
+++ b/hw/dmx/examples/xinput.c
@@ -77,7 +77,8 @@ static void printdmxinfo(Display *display, int id)
     case DMXBackendInputType:
         if (iinf.physicalId >= 0) {
             if ((backend = XOpenDisplay(iinf.name))) {
-                XExtensionVersion *ext = XGetExtensionVersion(backend, INAME);
+                XExtensionVersion *ext =
+		    XQueryInputVersion (backend, XI_2_Major, XI_2_Minor);
                 if (ext && ext != (XExtensionVersion *)NoSuchExtension) {
                     int count, i;
                     XDeviceInfo *devInfo = XListInputDevices(backend, &count);
@@ -136,7 +137,7 @@ int main(int argc, char **argv)
         return -1;
     }
 
-    ext = XGetExtensionVersion(display, INAME);
+    ext = XQueryInputVersion (display, XI_2_Major, XI_2_Minor);
     if (!ext || ext == (XExtensionVersion *)NoSuchExtension) {
         printf("No XInputExtension\n");
         return -1;
diff --git a/hw/dmx/glxProxy/glxsingle.c b/hw/dmx/glxProxy/glxsingle.c
index 27a27c3..8a4fa48 100644
--- a/hw/dmx/glxProxy/glxsingle.c
+++ b/hw/dmx/glxProxy/glxsingle.c
@@ -826,10 +826,10 @@ int __glXDisp_ReadPixels(__GLXclientState *cl, GLbyte *pc)
        for (s=from_screen; s<=to_screen; s++) {
 	  DMXScreenInfo *dmxScreen = &dmxScreens[s];
 	  Display *dpy = GetBackEndDisplay(cl,s);
-	  int scr_x1 = dmxScreen->rootXOrigin;
-	  int scr_x2 = dmxScreen->rootXOrigin + dmxScreen->scrnWidth - 1;
-	  int scr_y1 = dmxScreen->rootYOrigin;
-	  int scr_y2 = dmxScreen->rootYOrigin + dmxScreen->scrnHeight - 1;
+	  int scr_x1 = 0;
+	  int scr_x2 = dmxScreen->scrnWidth - 1;
+	  int scr_y1 = 0;
+	  int scr_y2 = dmxScreen->scrnHeight - 1;
 	  int wx1, wx2, wy1, wy2;
 	  int sx, sy, sw, sh;
 	  int npixels;
diff --git a/hw/kdrive/fake/Makefile.am b/hw/kdrive/fake/Makefile.am
index 76ed9fc..3c1464b 100644
--- a/hw/kdrive/fake/Makefile.am
+++ b/hw/kdrive/fake/Makefile.am
@@ -18,8 +18,7 @@ Xfake_SOURCES = \
 
 Xfake_LDADD = 						\
 	libfake.a					\
-	@KDRIVE_LIBS@					\
-        @XSERVER_LIBS@
+	@KDRIVE_LIBS@
 
 Xfake_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
 
diff --git a/hw/kdrive/fake/fake.c b/hw/kdrive/fake/fake.c
index d77c4f1..a7b3425 100644
--- a/hw/kdrive/fake/fake.c
+++ b/hw/kdrive/fake/fake.c
@@ -59,8 +59,10 @@ fakeScreenInitialize (KdScreenInfo *screen, FakeScrPriv *scrpriv)
 {
     if (!screen->width || !screen->height)
     {
-	screen->width = 1024;
-	screen->height = 768;
+	screen->width = 800;
+	screen->height = 600;
+	screen->width_mm = 212;
+	screen->height_mm = 159;
 	screen->rate = 72;
     }
 
@@ -70,7 +72,7 @@ fakeScreenInitialize (KdScreenInfo *screen, FakeScrPriv *scrpriv)
 	screen->height = 1;
     
     if (!screen->fb[0].depth)
-	screen->fb[0].depth = 16;
+	screen->fb[0].depth = 24;
 
     if (screen->fb[0].depth <= 8)
     {
diff --git a/hw/kdrive/fake/fakeinit.c b/hw/kdrive/fake/fakeinit.c
index 2cfcbed..65699b9 100644
--- a/hw/kdrive/fake/fakeinit.c
+++ b/hw/kdrive/fake/fakeinit.c
@@ -78,6 +78,72 @@ OsVendorInit (void)
     KdOsInit (&FakeOsFuncs);
 }
 
+static Bool
+fakeRealizeCursor (DeviceIntPtr pDev,
+		   ScreenPtr    pScreen,
+		   CursorPtr    pCursor)
+{
+    return TRUE;
+}
+
+static Bool
+fakeUnrealizeCursor (DeviceIntPtr pDev,
+		     ScreenPtr    pScreen,
+		     CursorPtr    pCursor)
+{
+    return TRUE;
+}
+
+static void
+fakeSetCursor (DeviceIntPtr pDev,
+	       ScreenPtr    pScreen,
+	       CursorPtr    pCursor,
+	       int          x,
+	       int          y)
+{
+}
+
+static void
+fakeMoveCursor (DeviceIntPtr pDev,
+		ScreenPtr    pScreen,
+		int          x,
+		int          y)
+{
+}
+
+static Bool
+fakeDeviceCursorInitialize (DeviceIntPtr pDev,
+			    ScreenPtr    pScreen)
+{
+    return TRUE;
+}
+
+static void
+fakeDeviceCursorCleanup (DeviceIntPtr pDev,
+			 ScreenPtr    pScreen)
+{
+}
+
+static miPointerSpriteFuncRec fakePointerSpriteFuncs = {
+    fakeRealizeCursor,
+    fakeUnrealizeCursor,
+    fakeSetCursor,
+    fakeMoveCursor,
+    fakeDeviceCursorInitialize,
+    fakeDeviceCursorCleanup
+};
+
+static Bool
+fakeCursorInit (ScreenPtr pScreen)
+{
+    miPointerInitialize (pScreen,
+			 &fakePointerSpriteFuncs,
+			 &kdPointerScreenFuncs,
+			 FALSE);
+
+    return TRUE;
+}
+
 KdCardFuncs	fakeFuncs = {
     fakeCardInit,	    /* cardinit */
     fakeScreenInit,	    /* scrinit */
@@ -91,8 +157,8 @@ KdCardFuncs	fakeFuncs = {
     fakeRestore,	    /* restore */
     fakeScreenFini,	    /* scrfini */
     fakeCardFini,	    /* cardfini */
-    
-    0,			    /* initCursor */
+
+    fakeCursorInit,         /* initCursor */
     0,			    /* enableCursor */
     0,			    /* disableCursor */
     0,			    /* finiCursor */
diff --git a/hw/kdrive/fake/os.c b/hw/kdrive/fake/os.c
index 76cd9e7..221a7c1 100644
--- a/hw/kdrive/fake/os.c
+++ b/hw/kdrive/fake/os.c
@@ -25,15 +25,248 @@
 #endif
 #include "fake.h"
 
+#include <errno.h>
+#include <signal.h>
+#include <linux/vt.h>
+#include <linux/kd.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+static int  vtno;
+int  LinuxConsoleFd;
+static int  activeVT;
+static Bool enabled;
+
+static void
+LinuxVTRequest (int sig)
+{
+    kdSwitchPending = TRUE;
+}
+
+/* Check before chowning -- this avoids touching the file system */
+static void
+LinuxCheckChown (char *file)
+{
+    struct stat	    st;
+    __uid_t	    u;
+    __gid_t	    g;
+
+    if (stat (file, &st) < 0)
+	return;
+    u = getuid ();
+    g = getgid ();
+    if (st.st_uid != u || st.st_gid != g)
+	chown (file, u, g);
+}
+
+static int
+LinuxInit (void)
+{
+    int fd = -1;
+    char vtname[11];
+    struct vt_stat vts;
+
+    LinuxConsoleFd = -1;
+    /* check if we're run with euid==0 */
+    if (geteuid() != 0)
+    {
+	FatalError("LinuxInit: Server must be suid root\n");
+    }
+
+    vtno = kdVirtualTerminal;
+
+    close(fd);
+
+    sprintf(vtname,"/dev/tty%d",vtno); /* /dev/tty1-64 */
+
+    if ((LinuxConsoleFd = open(vtname, O_RDWR|O_NDELAY, 0)) < 0)
+    {
+	FatalError("LinuxInit: Cannot open %s (%s)\n",
+		   vtname, strerror(errno));
+    }
+
+    /* change ownership of the vt */
+    LinuxCheckChown (vtname);
+
+    /*
+     * the current VT device we're running on is not "console", we want
+     * to grab all consoles too
+     *
+     * Why is this needed?
+     */
+    LinuxCheckChown ("/dev/tty0");
+    /*
+     * Linux doesn't switch to an active vt after the last close of a vt,
+     * so we do this ourselves by remembering which is active now.
+     */
+    memset (&vts, '\0', sizeof (vts));	/* valgrind */
+    if (ioctl(LinuxConsoleFd, VT_GETSTATE, &vts) == 0)
+    {
+	activeVT = vts.v_active;
+    }
+
+    return 1;
+}
+
+static void
+LinuxSetSwitchMode (int mode)
+{
+    struct sigaction	act;
+    struct vt_mode	VT;
+
+    if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) < 0)
+    {
+	FatalError ("LinuxInit: VT_GETMODE failed\n");
+    }
+
+    if (mode == VT_PROCESS)
+    {
+	act.sa_handler = LinuxVTRequest;
+	sigemptyset (&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction (SIGUSR1, &act, 0);
+
+	VT.mode = mode;
+	VT.relsig = SIGUSR1;
+	VT.acqsig = SIGUSR1;
+    }
+    else
+    {
+	act.sa_handler = SIG_IGN;
+	sigemptyset (&act.sa_mask);
+	act.sa_flags = 0;
+	sigaction (SIGUSR1, &act, 0);
+
+	VT.mode = mode;
+	VT.relsig = 0;
+	VT.acqsig = 0;
+    }
+    if (ioctl(LinuxConsoleFd, VT_SETMODE, &VT) < 0)
+    {
+	FatalError("LinuxInit: VT_SETMODE failed\n");
+    }
+}
+
+#ifdef FNONBLOCK
+#define NOBLOCK FNONBLOCK
+#else
+#define NOBLOCK FNDELAY
+#endif
+
+static void
+LinuxEnable (void)
+{
+    if (enabled)
+	return;
+    if (kdSwitchPending)
+    {
+	kdSwitchPending = FALSE;
+	ioctl (LinuxConsoleFd, VT_RELDISP, VT_ACKACQ);
+    }
+
+    /*
+     * now get the VT
+     */
+    LinuxSetSwitchMode (VT_AUTO);
+    if (ioctl(LinuxConsoleFd, VT_ACTIVATE, vtno) != 0)
+    {
+	FatalError("LinuxInit: VT_ACTIVATE failed\n");
+    }
+    if (ioctl(LinuxConsoleFd, VT_WAITACTIVE, vtno) != 0)
+    {
+	FatalError("LinuxInit: VT_WAITACTIVE failed\n");
+    }
+    LinuxSetSwitchMode (VT_PROCESS);
+    if (ioctl(LinuxConsoleFd, KDSETMODE, KD_GRAPHICS) < 0)
+    {
+	FatalError("LinuxInit: KDSETMODE KD_GRAPHICS failed\n");
+    }
+    enabled = TRUE;
+}
+
+static void
+LinuxDisable (void)
+{
+    ioctl(LinuxConsoleFd, KDSETMODE, KD_TEXT);  /* Back to text mode ... */
+    if (kdSwitchPending)
+    {
+	kdSwitchPending = FALSE;
+	ioctl (LinuxConsoleFd, VT_RELDISP, 1);
+    }
+    enabled = FALSE;
+}
+
+static void
+LinuxFini (void)
+{
+    struct vt_mode   VT;
+    struct vt_stat  vts;
+    int		    fd;
+
+    if (LinuxConsoleFd < 0)
+	return;
+
+    if (ioctl(LinuxConsoleFd, VT_GETMODE, &VT) != -1)
+    {
+	VT.mode = VT_AUTO;
+	ioctl(LinuxConsoleFd, VT_SETMODE, &VT); /* set dflt vt handling */
+    }
+    memset (&vts, '\0', sizeof (vts));	/* valgrind */
+    ioctl (LinuxConsoleFd, VT_GETSTATE, &vts);
+    if (vtno == vts.v_active)
+    {
+	/*
+	 * Find a legal VT to switch to, either the one we started from
+	 * or the lowest active one that isn't ours
+	 */
+	if (activeVT < 0 ||
+	    activeVT == vts.v_active ||
+	    !(vts.v_state & (1 << activeVT)))
+	{
+	    for (activeVT = 1; activeVT < 16; activeVT++)
+		if (activeVT != vtno && (vts.v_state & (1 << activeVT)))
+		    break;
+	    if (activeVT == 16)
+		activeVT = -1;
+	}
+	/*
+	 * Perform a switch back to the active VT when we were started
+	 */
+	if (activeVT >= -1)
+	{
+	    ioctl (LinuxConsoleFd, VT_ACTIVATE, activeVT);
+	    ioctl (LinuxConsoleFd, VT_WAITACTIVE, activeVT);
+	    activeVT = -1;
+	}
+    }
+    close(LinuxConsoleFd);                /* make the vt-manager happy */
+    LinuxConsoleFd = -1;
+    fd = open ("/dev/tty0", O_RDWR|O_NDELAY, 0);
+    if (fd >= 0)
+    {
+	memset (&vts, '\0', sizeof (vts));	/* valgrind */
+	ioctl (fd, VT_GETSTATE, &vts);
+	if (ioctl (fd, VT_DISALLOCATE, vtno) < 0)
+	    fprintf (stderr, "Can't deallocate console %d %s\n", vtno, strerror(errno));
+	close (fd);
+    }
+    return;
+}
+
 static int
 FakeInit (void)
 {
+    if (kdVirtualTerminal >= 0)
+	return LinuxInit ();
+
     return 1;
 }
 
 static void
 FakeEnable (void)
 {
+    if (kdVirtualTerminal >= 0)
+	LinuxEnable ();
 }
 
 static Bool
@@ -45,11 +278,15 @@ FakeSpecialKey (KeySym sym)
 static void
 FakeDisable (void)
 {
+    if (kdVirtualTerminal >= 0)
+	LinuxDisable ();
 }
 
 static void
 FakeFini (void)
 {
+    if (kdVirtualTerminal >= 0)
+	return LinuxFini ();
 }
 
 KdOsFuncs   FakeOsFuncs = {
diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c
index e31cc25..f96c2e8 100644
--- a/hw/kdrive/src/kdrive.c
+++ b/hw/kdrive/src/kdrive.c
@@ -55,7 +55,7 @@ typedef struct _kdDepths {
 
 KdDepths    kdDepths[] = {
     { 1, 1 },
-    { 4, 4 },
+    { 4, 8 },
     { 8, 8 },
     { 15, 16 },
     { 16, 16 },
@@ -1394,6 +1394,7 @@ OsVendorFatalError(void)
 int
 DPMSSet(ClientPtr client, int level)
 {
+    return -1;
 }
 
 int
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 6400b69..1616191 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -406,6 +406,9 @@
 /* Support HAL for hotplug */
 #undef CONFIG_HAL
 
+/* Support Avahi */
+#undef HAVE_AVAHI
+
 /* Use only built-in fonts */
 #undef BUILTIN_FONTS
 
diff --git a/include/window.h b/include/window.h
index 04cbe26..0b08548 100644
--- a/include/window.h
+++ b/include/window.h
@@ -268,5 +268,7 @@ extern void DisableMapUnmapEvents(
     WindowPtr /* pWin */ );
 extern void EnableMapUnmapEvents(
     WindowPtr /* pWin */ );
+extern Bool MapUnmapEventsEnabled(
+    WindowPtr /* pWin */ );
 
 #endif /* WINDOW_H */
diff --git a/mi/miinitext.c b/mi/miinitext.c
index 6516f43..22ecbe1 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -49,6 +49,10 @@ SOFTWARE.
 #include <dix-config.h>
 #endif
 
+#ifndef XINPUT
+#define XINPUT
+#endif
+
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
 #endif
diff --git a/miext/damage/damage.c b/miext/damage/damage.c
index 56864c5..9155e98 100755
--- a/miext/damage/damage.c
+++ b/miext/damage/damage.c
@@ -1411,11 +1411,17 @@ damageText (DrawablePtr	    pDrawable,
 	damageDamageChars (pDrawable, pGC->font, x + pDrawable->x, y + pDrawable->y, n,
 			   charinfo, imageblt, pGC->subWindowMode);
 	if (imageblt)
-	    (*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
-				       FONTGLYPHS(pGC->font));
+	{
+	    if (pGC->ops->ImageGlyphBlt)
+		(*pGC->ops->ImageGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
+					   FONTGLYPHS(pGC->font));
+	}
 	else
-	    (*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
-				      FONTGLYPHS(pGC->font));
+	{
+	    if (pGC->ops->PolyGlyphBlt)
+		(*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, n, charinfo,
+					  FONTGLYPHS(pGC->font));
+	}
     }
     xfree(charinfo);
     return x + w;
@@ -1432,8 +1438,12 @@ damagePolyText8(DrawablePtr pDrawable,
     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 
     if (checkGCDamage (pDrawable, pGC))
+    {
 	x = damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
 		    Linear8Bit, TT_POLY8);
+	if (!pGC->ops->PolyGlyphBlt)
+	    (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
+    }
     else
 	x = (*pGC->ops->PolyText8)(pDrawable, pGC, x, y, count, chars);
     damageReportPostOp (pDrawable);
@@ -1452,9 +1462,13 @@ damagePolyText16(DrawablePtr	pDrawable,
     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 
     if (checkGCDamage (pDrawable, pGC))
+    {
 	x = damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
 		    FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
 		    TT_POLY16);
+	if (!pGC->ops->PolyGlyphBlt)
+	    (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
+    }
     else
 	x = (*pGC->ops->PolyText16)(pDrawable, pGC, x, y, count, chars);
     damageReportPostOp (pDrawable);
@@ -1473,8 +1487,12 @@ damageImageText8(DrawablePtr	pDrawable,
     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 
     if (checkGCDamage (pDrawable, pGC))
+    {
 	damageText (pDrawable, pGC, x, y, (unsigned long) count, chars,
 		    Linear8Bit, TT_IMAGE8);
+	if (!pGC->ops->ImageGlyphBlt)
+	    (*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
+    }
     else
 	(*pGC->ops->ImageText8)(pDrawable, pGC, x, y, count, chars);
     damageReportPostOp (pDrawable);
@@ -1492,9 +1510,13 @@ damageImageText16(DrawablePtr	pDrawable,
     DAMAGE_GC_OP_PROLOGUE(pGC, pDrawable);
 
     if (checkGCDamage (pDrawable, pGC))
+    {
 	damageText (pDrawable, pGC, x, y, (unsigned long) count, (char *) chars,
 		    FONTLASTROW(pGC->font) == 0 ? Linear16Bit : TwoD16Bit,
 		    TT_IMAGE16);
+	if (!pGC->ops->ImageGlyphBlt)
+	    (*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
+    }
     else
 	(*pGC->ops->ImageText16)(pDrawable, pGC, x, y, count, chars);
     damageReportPostOp (pDrawable);
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 7c22437..d7da059 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -24,6 +24,10 @@
 #include "swaprep.h"
 #include "registry.h"
 
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+#endif
+
 RESTYPE	RRCrtcType;
 
 /*
@@ -795,13 +799,23 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	{
 	    int source_width = mode->mode.width;
 	    int	source_height = mode->mode.height;
+	    int w = pScreen->width;
+	    int h = pScreen->height;
+
+#ifdef PANORAMIX
+	    if (!noPanoramiXExtension)
+	    {
+		w = PanoramiXPixWidth;
+		h = PanoramiXPixHeight;
+	    }
+#endif
 
 	    if ((rotation & 0xf) == RR_Rotate_90 || (rotation & 0xf) == RR_Rotate_270)
 	    {
 		source_width = mode->mode.height;
 		source_height = mode->mode.width;
 	    }
-	    if (stuff->x + source_width > pScreen->width)
+	    if (stuff->x + source_width > w)
 	    {
 		client->errorValue = stuff->x;
 		if (outputs)
@@ -809,7 +823,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 		return BadValue;
 	    }
 	    
-	    if (stuff->y + source_height > pScreen->height)
+	    if (stuff->y + source_height > h)
 	    {
 		client->errorValue = stuff->y;
 		if (outputs)
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index f391973..f51094e 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -22,6 +22,10 @@
 
 #include "randrstr.h"
 
+#ifdef PANORAMIX
+#include "panoramiXsrv.h"
+#endif
+
 extern char	*ConnectionInfo;
 
 static int padlength[4] = {0, 3, 2, 1};
@@ -44,6 +48,16 @@ RREditConnectionInfo (ScreenPtr pScreen)
     xVisualType	    *visual;
     int		    screen = 0;
     int		    d;
+    int             w = pScreen->width;
+    int             h = pScreen->height;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	w = PanoramiXPixWidth;
+	h = PanoramiXPixHeight;
+    }
+#endif
 
     connSetup = (xConnSetup *) ConnectionInfo;
     vendor = (char *) connSetup + sizeof (xConnSetup);
@@ -66,8 +80,8 @@ RREditConnectionInfo (ScreenPtr pScreen)
 	root = (xWindowRoot *) ((char *) depth);
 	screen++;
     }
-    root->pixWidth = pScreen->width;
-    root->pixHeight = pScreen->height;
+    root->pixWidth = w;
+    root->pixHeight = h;
     root->mmWidth = pScreen->mmWidth;
     root->mmHeight = pScreen->mmHeight;
 }
@@ -77,6 +91,8 @@ RRSendConfigNotify (ScreenPtr pScreen)
 {
     WindowPtr	pWin = WindowTable[pScreen->myNum];
     xEvent	event;
+    int         w = pWin->drawable.width;
+    int         h = pWin->drawable.height;
 
     event.u.u.type = ConfigureNotify;
     event.u.configureNotify.window = pWin->drawable.id;
@@ -84,10 +100,16 @@ RRSendConfigNotify (ScreenPtr pScreen)
     event.u.configureNotify.x = 0;
     event.u.configureNotify.y = 0;
 
-    /* XXX xinerama stuff ? */
-    
-    event.u.configureNotify.width = pWin->drawable.width;
-    event.u.configureNotify.height = pWin->drawable.height;
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	w = PanoramiXPixWidth;
+	h = PanoramiXPixHeight;
+    }
+#endif
+
+    event.u.configureNotify.width = w;
+    event.u.configureNotify.height = h;
     event.u.configureNotify.borderWidth = wBorderWidth (pWin);
     event.u.configureNotify.override = pWin->overrideRedirect;
     DeliverEvents(pWin, &event, 1, NullWindow);
@@ -100,6 +122,16 @@ RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
     xRRScreenChangeNotifyEvent	se;
     RRCrtcPtr	crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
     WindowPtr	pRoot = WindowTable[pScreen->myNum];
+    int         w = pScreen->width;
+    int         h = pScreen->height;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	w = PanoramiXPixWidth;
+	h = PanoramiXPixHeight;
+    }
+#endif
     
     se.type = RRScreenChangeNotify + RREventBase;
     se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0);
@@ -118,13 +150,13 @@ RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
     se.sizeID = RR10CurrentSizeID (pScreen);
 
     if (se.rotation & (RR_Rotate_90 | RR_Rotate_270)) {
-	se.widthInPixels = pScreen->height;
-	se.heightInPixels = pScreen->width;
+	se.widthInPixels = h;
+	se.heightInPixels = w;
 	se.widthInMillimeters = pScreen->mmHeight;
 	se.heightInMillimeters = pScreen->mmWidth;
     } else {
-	se.widthInPixels = pScreen->width;
-	se.heightInPixels = pScreen->height;
+	se.widthInPixels = w;
+	se.heightInPixels = h;
 	se.widthInMillimeters = pScreen->mmWidth;
 	se.heightInMillimeters = pScreen->mmHeight;
     }
@@ -140,19 +172,31 @@ RRDeliverScreenEvent (ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
 void
 RRScreenSizeNotify (ScreenPtr	pScreen)
 {
+    int w = pScreen->width;
+    int h = pScreen->height;
+
     rrScrPriv(pScreen);
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	w = PanoramiXPixWidth;
+	h = PanoramiXPixHeight;
+    }
+#endif
+
     /*
      * Deliver ConfigureNotify events when root changes
      * pixel size
      */
-    if (pScrPriv->width == pScreen->width &&
-	pScrPriv->height == pScreen->height &&
+    if (pScrPriv->width == w &&
+	pScrPriv->height == h &&
 	pScrPriv->mmWidth == pScreen->mmWidth &&
 	pScrPriv->mmHeight == pScreen->mmHeight)
 	return;
     
-    pScrPriv->width = pScreen->width;
-    pScrPriv->height = pScreen->height;
+    pScrPriv->width = w;
+    pScrPriv->height = h;
     pScrPriv->mmWidth = pScreen->mmWidth;
     pScrPriv->mmHeight = pScreen->mmHeight;
     pScrPriv->changed = TRUE;
@@ -741,7 +785,7 @@ ProcRRSetScreenConfig (ClientPtr client)
     RRModePtr		    mode;
     RR10DataPtr		    pData = NULL;
     RRScreenSizePtr    	    pSize;
-    int			    width, height;
+    int			    width, height, w, h;
     
     UpdateCurrentTime ();
 
@@ -896,7 +940,19 @@ ProcRRSetScreenConfig (ClientPtr client)
 	width = mode->mode.height;
 	height = mode->mode.width;
     }
-    if (width != pScreen->width || height != pScreen->height)
+
+    w = pScreen->width;
+    h = pScreen->height;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	w = PanoramiXPixWidth;
+	h = PanoramiXPixHeight;
+    }
+#endif
+
+    if (width != w || height != h)
     {
 	int	c;
 
@@ -960,6 +1016,16 @@ RR10CurrentSizeID (ScreenPtr pScreen)
 {
     CARD16	sizeID = 0xffff;
     RROutputPtr output = RRFirstOutput (pScreen);
+    int         w = pScreen->width;
+    int         h = pScreen->height;
+
+#ifdef PANORAMIX
+    if (!noPanoramiXExtension)
+    {
+	w = PanoramiXPixWidth;
+	h = PanoramiXPixHeight;
+    }
+#endif
     
     if (output)
     {
@@ -968,8 +1034,8 @@ RR10CurrentSizeID (ScreenPtr pScreen)
 	{
 	    int i;
 	    for (i = 0; i < data->nsize; i++)
-		if (data->sizes[i].width == pScreen->width &&
-		    data->sizes[i].height == pScreen->height)
+		if (data->sizes[i].width == w &&
+		    data->sizes[i].height == h)
 		{
 		    sizeID = (CARD16) i;
 		    break;
diff --git a/render/animcur.c b/render/animcur.c
index 362607f..354987c 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -47,16 +47,6 @@
 #include "inputstr.h"
 #include "xace.h"
 
-typedef struct _AnimCurElt {
-    CursorPtr	pCursor;    /* cursor to show */
-    CARD32	delay;	    /* in ms */
-} AnimCurElt;
-
-typedef struct _AnimCur {
-    int		nelt;	    /* number of elements in the elts array */
-    AnimCurElt	*elts;	    /* actually allocated right after the structure */
-} AnimCurRec, *AnimCurPtr;
-
 typedef struct _AnimScrPriv {
     CursorPtr			pCursor;
     int				elt;
@@ -86,15 +76,13 @@ static AnimCurStateRec animCurState[MAX_DEVICES];
 
 static unsigned char empty[4];
 
-static CursorBits   animCursorBits = {
+CursorBits   animCursorBits = {
     empty, empty, 2, 1, 1, 0, 0, 1
 };
 
 static int AnimCurGeneration;
 static DevPrivateKey AnimCurScreenPrivateKey = &AnimCurScreenPrivateKey;
 
-#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)
 #define SetAnimCurScreen(s,p) dixSetPrivate(&(s)->devPrivates, AnimCurScreenPrivateKey, p)
@@ -286,10 +274,7 @@ AnimCurRealizeCursor (DeviceIntPtr pDev,
     Bool		ret;
     
     Unwrap (as, pScreen, RealizeCursor);
-    if (IsAnimCur(pCursor))
-	ret = TRUE;
-    else
-	ret = (*pScreen->RealizeCursor) (pDev, pScreen, pCursor);
+    ret = (*pScreen->RealizeCursor) (pDev, pScreen, pCursor);
     Wrap (as, pScreen, RealizeCursor, AnimCurRealizeCursor);
     return ret;
 }
@@ -303,6 +288,7 @@ AnimCurUnrealizeCursor (DeviceIntPtr pDev,
     Bool		ret;
     
     Unwrap (as, pScreen, UnrealizeCursor);
+    ret = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor);
     if (IsAnimCur(pCursor))
     {
         AnimCurPtr  ac = GetAnimCur(pCursor);
@@ -311,10 +297,7 @@ AnimCurUnrealizeCursor (DeviceIntPtr pDev,
 	if (pScreen->myNum == 0)
 	    for (i = 0; i < ac->nelt; i++)
 		FreeCursor (ac->elts[i].pCursor, 0);
-	ret = TRUE;
     }
-    else
-	ret = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor);
     Wrap (as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor);
     return ret;
 }
@@ -379,9 +362,11 @@ AnimCurInit (ScreenPtr pScreen)
 int
 AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor, ClientPtr client, XID cid)
 {
-    CursorPtr	pCursor;
-    int		rc, i;
-    AnimCurPtr	ac;
+    CursorPtr	 pCursor;
+    int		 rc, nscr, i;
+    AnimCurPtr	 ac;
+    ScreenPtr 	 pscr;
+    DeviceIntPtr pDev;
 
     for (i = 0; i < screenInfo.numScreens; i++)
 	if (!GetAnimCurScreenIfSet (screenInfo.screens[i]))
@@ -433,7 +418,54 @@ AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *pp
 	ac->elts[i].pCursor = cursors[i];
 	ac->elts[i].delay = deltas[i];
     }
-    
+
+    /*
+     * 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];
+        for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
+        {
+            if (DevHasCursor(pDev))
+            {
+                if (!( *pscr->RealizeCursor)(pDev, pscr, pCursor))
+                {
+                    /* 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, pCursor);
+                        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, pCursor);
+                            pDevIt = pDevIt->next;
+                        }
+                        ( *pscr->UnrealizeCursor)(pDev, pscr, pCursor);
+                    }
+                    dixFreePrivates(pCursor->devPrivates);
+		    xfree(pCursor);
+                    return BadAlloc;
+                }
+            }
+        }
+    }
     *ppCursor = pCursor;
     return Success;
 }
diff --git a/render/glyph.c b/render/glyph.c
index de01970..e5bd1ca 100644
--- a/render/glyph.c
+++ b/render/glyph.c
@@ -422,6 +422,8 @@ AllocateGlyph (xGlyphInfo *gi, int fdepth)
 
     for (i = 0; i < screenInfo.numScreens; i++)
     {
+	*GetGlyphPrivatesForScreen (glyph, screenInfo.screens[i]) = NULL;
+
 	ps = GetPictureScreenIfSet (screenInfo.screens[i]);
 
 	if (ps)
diff --git a/render/picturestr.h b/render/picturestr.h
index acd15c7..34632dc 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -26,6 +26,7 @@
 
 #include "scrnintstr.h"
 #include "glyphstr.h"
+#include "cursorstr.h"
 #include "resource.h"
 #include "privates.h"
 
@@ -620,6 +621,22 @@ PictureGradientColor (PictGradientStopPtr stop1,
 
 void RenderExtensionInit (void);
 
+
+typedef struct _AnimCurElt {
+    CursorPtr	pCursor;    /* cursor to show */
+    CARD32	delay;	    /* in ms */
+} AnimCurElt;
+
+typedef struct _AnimCur {
+    int		nelt;	    /* number of elements in the elts array */
+    AnimCurElt	*elts;	    /* actually allocated right after the structure */
+} AnimCurRec, *AnimCurPtr;
+
+extern CursorBits animCursorBits;
+
+#define IsAnimCur(c)	    ((c) && ((c)->bits == &animCursorBits))
+#define GetAnimCur(c)	    ((AnimCurPtr) ((c) + 1))
+
 Bool
 AnimCurInit (ScreenPtr pScreen);
 
diff --git a/render/render.c b/render/render.c
index 538697b..5a2e1d0 100644
--- a/render/render.c
+++ b/render/render.c
@@ -2736,6 +2736,8 @@ PanoramiXRenderCreatePicture (ClientPtr client)
     else
 	newPict->u.pict.root = FALSE;
 
+    newPict->u.pict.sourcePict = FALSE;
+
     for(j = 1; j < PanoramiXNumScreens; j++)
 	newPict->info[j].id = FakeClientID(client->index);
     
@@ -2766,10 +2768,18 @@ PanoramiXRenderChangePicture (ClientPtr client)
     VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
 		       RenderErrBase + BadPicture);
     
-    FOR_NSCREENS_BACKWARD(j) {
-        stuff->picture = pict->info[j].id;
-        result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client);
-        if(result != Success) break;
+    if (pict->u.pict.sourcePict)
+    {
+	stuff->picture = pict->info[0].id;
+	result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client);
+    }
+    else
+    {
+	FOR_NSCREENS_BACKWARD(j) {
+	    stuff->picture = pict->info[j].id;
+	    result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client);
+	    if(result != Success) break;
+	}
     }
 
     return (result);
@@ -2807,11 +2817,19 @@ PanoramiXRenderSetPictureTransform (ClientPtr client)
     
     VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
 		       RenderErrBase + BadPicture);
-    
-    FOR_NSCREENS_BACKWARD(j) {
-        stuff->picture = pict->info[j].id;
-        result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client);
-        if(result != Success) break;
+
+    if (pict->u.pict.sourcePict)
+    {
+	stuff->picture = pict->info[0].id;
+	result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client);
+    }
+    else
+    {
+	FOR_NSCREENS_BACKWARD(j) {
+	    stuff->picture = pict->info[j].id;
+	    result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client);
+	    if(result != Success) break;
+	}
     }
 
     return (result);
@@ -2830,9 +2848,9 @@ PanoramiXRenderSetPictureFilter (ClientPtr client)
 		       RenderErrBase + BadPicture);
     
     FOR_NSCREENS_BACKWARD(j) {
-        stuff->picture = pict->info[j].id;
-        result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client);
-        if(result != Success) break;
+	stuff->picture = pict->info[j].id;
+	result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client);
+	if(result != Success) break;
     }
 
     return (result);
@@ -2853,10 +2871,18 @@ PanoramiXRenderFreePicture (ClientPtr client)
 		       RenderErrBase + BadPicture);
     
 
-    FOR_NSCREENS_BACKWARD(j) {
-	stuff->picture = pict->info[j].id;
+    if (pict->u.pict.sourcePict)
+    {
+	stuff->picture = pict->info[0].id;
 	result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client);
-	if(result != Success) break;
+    }
+    else
+    {
+	FOR_NSCREENS_BACKWARD(j) {
+	    stuff->picture = pict->info[j].id;
+	    result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client);
+	    if(result != Success) break;
+	}
     }
 
     /* Since ProcRenderFreePicture is using FreeResource, it will free
@@ -3268,6 +3294,114 @@ PanoramiXRenderAddTraps (ClientPtr client)
     return result;
 }
 
+static int
+PanoramiXRenderCreateSolidFill (ClientPtr client)
+{
+    REQUEST(xRenderCreateSolidFillReq);
+    PanoramiXRes    *newPict;
+    int		    result = Success, j;
+
+    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
+    if (!(newPict = (PanoramiXRes *) xalloc (sizeof (PanoramiXRes))))
+	return BadAlloc;
+
+    newPict->type = XRT_PICTURE;
+    for (j = 0; j < PanoramiXNumScreens; j++)
+	newPict->info[j].id = stuff->pid;
+
+    newPict->u.pict.root       = FALSE;
+    newPict->u.pict.sourcePict = TRUE;
+
+    result = (*PanoramiXSaveRenderVector[X_RenderCreateSolidFill]) (client);
+    if (result == Success)
+	AddResource (newPict->info[0].id, XRT_PICTURE, newPict);
+    else
+	xfree (newPict);
+
+    return result;
+}
+
+static int
+PanoramiXRenderCreateLinearGradient (ClientPtr client)
+{
+    REQUEST(xRenderCreateLinearGradientReq);
+    PanoramiXRes    *newPict;
+    int		    result = Success, j;
+
+    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
+    if (!(newPict = (PanoramiXRes *) xalloc (sizeof (PanoramiXRes))))
+	return BadAlloc;
+
+    newPict->type = XRT_PICTURE;
+    for (j = 0; j < PanoramiXNumScreens; j++)
+	newPict->info[j].id = stuff->pid;
+
+    newPict->u.pict.root       = FALSE;
+    newPict->u.pict.sourcePict = TRUE;
+
+    result = (*PanoramiXSaveRenderVector[X_RenderCreateLinearGradient]) (client);
+    if (result == Success)
+	AddResource (newPict->info[0].id, XRT_PICTURE, newPict);
+    else
+	xfree (newPict);
+
+    return result;
+}
+
+static int
+PanoramiXRenderCreateRadialGradient (ClientPtr client)
+{
+    REQUEST(xRenderCreateRadialGradientReq);
+    PanoramiXRes    *newPict;
+    int		    result = Success, j;
+
+    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
+    if (!(newPict = (PanoramiXRes *) xalloc (sizeof (PanoramiXRes))))
+	return BadAlloc;
+
+    newPict->type = XRT_PICTURE;
+    for (j = 0; j < PanoramiXNumScreens; j++)
+	newPict->info[j].id = stuff->pid;
+
+    newPict->u.pict.root       = FALSE;
+    newPict->u.pict.sourcePict = TRUE;
+
+    result = (*PanoramiXSaveRenderVector[X_RenderCreateRadialGradient]) (client);
+    if (result == Success)
+	AddResource (newPict->info[0].id, XRT_PICTURE, newPict);
+    else
+	xfree (newPict);
+
+    return result;
+}
+
+static int
+PanoramiXRenderCreateConicalGradient (ClientPtr client)
+{
+    REQUEST(xRenderCreateConicalGradientReq);
+    PanoramiXRes    *newPict;
+    int		    result = Success, j;
+
+    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
+    if (!(newPict = (PanoramiXRes *) xalloc (sizeof (PanoramiXRes))))
+	return BadAlloc;
+
+    newPict->type = XRT_PICTURE;
+    for (j = 0; j < PanoramiXNumScreens; j++)
+	newPict->info[j].id = stuff->pid;
+
+    newPict->u.pict.root       = FALSE;
+    newPict->u.pict.sourcePict = TRUE;
+
+    result = (*PanoramiXSaveRenderVector[X_RenderCreateConicalGradient]) (client);
+    if (result == Success)
+	AddResource (newPict->info[0].id, XRT_PICTURE, newPict);
+    else
+	xfree (newPict);
+
+    return result;
+}
+
 void
 PanoramiXRenderInit (void)
 {
@@ -3296,6 +3430,10 @@ PanoramiXRenderInit (void)
     ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip;
     ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan;
     ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps;
+    ProcRenderVector[X_RenderCreateSolidFill] = PanoramiXRenderCreateSolidFill;
+    ProcRenderVector[X_RenderCreateLinearGradient] = PanoramiXRenderCreateLinearGradient;
+    ProcRenderVector[X_RenderCreateRadialGradient] = PanoramiXRenderCreateRadialGradient;
+    ProcRenderVector[X_RenderCreateConicalGradient] = PanoramiXRenderCreateConicalGradient;
 }
 
 void
diff --git a/xfixes/region.c b/xfixes/region.c
old mode 100644
new mode 100755
index cac24b5..3a90530
--- a/xfixes/region.c
+++ b/xfixes/region.c
@@ -864,3 +864,84 @@ SProcXFixesExpandRegion (ClientPtr client)
     return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
 }
 
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+
+#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\
+    pPicture = SecurityLookupIDByType(client, pid, XRT_PICTURE, mode);\
+    if (!pPicture) { \
+	client->errorValue = pid; \
+	return err; \
+    } \
+}
+
+extern unsigned long	XRT_PICTURE;
+
+extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr);
+
+int
+PanoramiXFixesSetGCClipRegion (ClientPtr client)
+{
+    REQUEST(xXFixesSetGCClipRegionReq);
+    int		    result = Success, j;
+    PanoramiXRes    *gc;
+    REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
+
+    if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->gc, XRT_GC, DixReadAccess)))
+	return BadGC;
+
+    FOR_NSCREENS_BACKWARD(j) {
+        stuff->gc = gc->info[j].id;
+        result = (*PanoramiXSaveXFixesVector[X_XFixesSetGCClipRegion]) (client);
+        if(result != Success) break;
+    }
+
+    return (result);
+}
+
+int
+PanoramiXFixesSetWindowShapeRegion (ClientPtr client)
+{
+    int		    result = Success, j;
+    PanoramiXRes    *win;
+    REQUEST(xXFixesSetWindowShapeRegionReq);
+
+    REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
+
+    if(!(win = (PanoramiXRes *)SecurityLookupIDByType(
+	     client, stuff->dest, XRT_WINDOW, DixWriteAccess)))
+	return BadWindow;
+
+    FOR_NSCREENS_FORWARD(j) {
+	stuff->dest = win->info[j].id;
+	result = (*PanoramiXSaveXFixesVector[X_XFixesSetWindowShapeRegion]) (client);
+        if(result != Success) break;
+    }
+
+    return (result);
+}
+
+int
+PanoramiXFixesSetPictureClipRegion (ClientPtr client)
+{
+    REQUEST(xXFixesSetPictureClipRegionReq);
+    int		    result = Success, j;
+    PanoramiXRes    *pict;
+
+    REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
+
+    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
+		       RenderErrBase + BadPicture);
+
+    FOR_NSCREENS_BACKWARD(j) {
+        stuff->picture = pict->info[j].id;
+	result = (*PanoramiXSaveXFixesVector[X_XFixesSetPictureClipRegion]) (client);
+        if(result != Success) break;
+    }
+
+    return (result);
+}
+
+#endif
diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c
index 0db4989..858208f 100755
--- a/xfixes/xfixes.c
+++ b/xfixes/xfixes.c
@@ -259,3 +259,33 @@ XFixesExtensionInit(void)
 	    (EventSwapPtr) SXFixesCursorNotifyEvent;
     }
 }
+
+#ifdef PANORAMIX
+
+int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr);
+
+void
+PanoramiXFixesInit (void)
+{
+    int i;
+
+    for (i = 0; i < XFixesNumberRequests; i++)
+	PanoramiXSaveXFixesVector[i] = ProcXFixesVector[i];
+    /*
+     * Stuff in Xinerama aware request processing hooks
+     */
+    ProcXFixesVector[X_XFixesSetGCClipRegion] = PanoramiXFixesSetGCClipRegion;
+    ProcXFixesVector[X_XFixesSetWindowShapeRegion] = PanoramiXFixesSetWindowShapeRegion;
+    ProcXFixesVector[X_XFixesSetPictureClipRegion] = PanoramiXFixesSetPictureClipRegion;
+}
+
+void
+PanoramiXFixesReset (void)
+{
+    int i;
+
+    for (i = 0; i < XFixesNumberRequests; i++)
+	ProcXFixesVector[i] = PanoramiXSaveXFixesVector[i];
+}
+
+#endif
diff --git a/xfixes/xfixesint.h b/xfixes/xfixesint.h
index 33a3205..4a4e783 100755
--- a/xfixes/xfixesint.h
+++ b/xfixes/xfixesint.h
@@ -255,6 +255,17 @@ ProcXFixesExpandRegion (ClientPtr client);
 int
 SProcXFixesExpandRegion (ClientPtr client);
 
+#ifdef PANORAMIX
+int
+PanoramiXFixesSetGCClipRegion (ClientPtr client);
+
+int
+PanoramiXFixesSetWindowShapeRegion (ClientPtr client);
+
+int
+PanoramiXFixesSetPictureClipRegion (ClientPtr client);
+#endif
+
 /* Cursor Visibility (Version 4) */
 
 int 
@@ -269,4 +280,9 @@ ProcXFixesShowCursor (ClientPtr client);
 int 
 SProcXFixesShowCursor (ClientPtr client);
 
+#ifdef PANORAMIX
+void PanoramiXFixesInit (void);
+void PanoramiXFixesReset (void);
+#endif
+
 #endif /* _XFIXESINT_H_ */
openSUSE Build Service is sponsored by