diff options
-rw-r--r-- | Xext/panoramiXprocs.c | 70 |
1 files changed, 60 insertions, 10 deletions
diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c index 18f3ac715..f31b1e054 100644 --- a/Xext/panoramiXprocs.c +++ b/Xext/panoramiXprocs.c @@ -1050,7 +1050,7 @@ PanoramiXClearToBackground(ClientPtr client) int PanoramiXCopyArea(ClientPtr client) { - int j, result, srcx, srcy, dstx, dsty; + int j, result, srcx, srcy, dstx, dsty, width, height; PanoramiXRes *gc, *src, *dst; Bool srcIsRoot = FALSE; Bool dstIsRoot = FALSE; @@ -1091,6 +1091,8 @@ PanoramiXCopyArea(ClientPtr client) srcy = stuff->srcY; dstx = stuff->dstX; dsty = stuff->dstY; + width = stuff->width; + height = stuff->height; if ((dst->type == XRT_PIXMAP) && (src->type == XRT_WINDOW)) { DrawablePtr drawables[MAXSCREENS]; DrawablePtr pDst; @@ -1105,13 +1107,12 @@ PanoramiXCopyArea(ClientPtr client) return rc; } - pitch = PixmapBytePad(stuff->width, drawables[0]->depth); - if (!(data = calloc(stuff->height, pitch))) + pitch = PixmapBytePad(width, drawables[0]->depth); + if (!(data = calloc(height, pitch))) return BadAlloc; - XineramaGetImageData(drawables, srcx, srcy, - stuff->width, stuff->height, ZPixmap, ~0, data, - pitch, srcIsRoot); + XineramaGetImageData(drawables, srcx, srcy, width, height, ZPixmap, ~0, + data, pitch, srcIsRoot); FOR_NSCREENS_BACKWARD(j) { stuff->gc = gc->info[j].id; @@ -1123,14 +1124,63 @@ PanoramiXCopyArea(ClientPtr client) } (*pGC->ops->PutImage) (pDst, pGC, pDst->depth, dstx, dsty, - stuff->width, stuff->height, - 0, ZPixmap, data); - + width, height, 0, ZPixmap, data); if (dstShared) break; } - free(data); + + if (pGC->graphicsExposures) { + RegionRec rgn; + int dx, dy; + BoxRec sourceBox; + + dx = drawables[0]->x; + dy = drawables[0]->y; + if (srcIsRoot) { + dx += screenInfo.screens[0]->x; + dy += screenInfo.screens[0]->y; + } + + sourceBox.x1 = min(srcx + dx, 0); + sourceBox.y1 = min(srcy + dy, 0); + sourceBox.x2 = max(sourceBox.x1 + width, 32767); + sourceBox.y2 = max(sourceBox.y1 + height, 32767); + + RegionInit(&rgn, &sourceBox, 1); + + /* subtract the (screen-space) clips of the source drawables */ + FOR_NSCREENS(j) { + ScreenPtr screen = screenInfo.screens[j]; + RegionPtr sd; + + if (pGC->subWindowMode == IncludeInferiors) + sd = NotClippedByChildren((WindowPtr)drawables[j]); + else + sd = &((WindowPtr)drawables[j])->clipList; + + if (srcIsRoot) + RegionTranslate(&rgn, -screen->x, -screen->y); + + RegionSubtract(&rgn, &rgn, sd); + + if (srcIsRoot) + RegionTranslate(&rgn, screen->x, screen->y); + + if (pGC->subWindowMode == IncludeInferiors) + RegionDestroy(sd); + } + + /* -dx/-dy to get back to dest-relative, plus request offsets */ + RegionTranslate(&rgn, -dx + dstx, -dy + dsty); + + /* intersect with gc clip; just one screen is fine because pixmap */ + RegionIntersect(&rgn, &rgn, pGC->pCompositeClip); + + /* and expose */ + SendGraphicsExpose(client, &rgn, dst->info[0].id, X_CopyArea, 0); + RegionUninit(&rgn); + } } else { DrawablePtr pDst = NULL, pSrc = NULL; |