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], ®ion, &box, 1);
+ (*pScreen->WindowExposures) (pChild0, ®ion, NullRegion);
+ REGION_UNINIT (screenInfo.screens[0], ®ion);
+ }
+
+ 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, ®, &dst, 0);
+
+ if (pGC->pCompositeClip)
+ {
+ REGION_TRANSLATE (pGC->pScreen, pGC->pCompositeClip,
+ -pDraw->x, -pDraw->y);
+ REGION_INTERSECT (pGC->pScreen, ®, ®, pGC->pCompositeClip);
+ REGION_TRANSLATE (pGC->pScreen, pGC->pCompositeClip,
+ pDraw->x, pDraw->y);
+ }
+
+ nBox = REGION_NUM_RECTS (®);
+ pBox = REGION_RECTS (®);
+
+ 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, ®);
+
+ 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_ */