#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include <X11/Xprotostr.h>
#include "misc.h"
#include "regionstr.h"
#include "scrnintstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmap.h"
#include "input.h"
#include "dixstruct.h"
#include "mi.h"
#include <X11/Xmd.h>
#include "globals.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
#ifndef RECTLIMIT
#define RECTLIMIT 25
#endif
RegionPtr
miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
GCPtr pGC, int srcx, int srcy, int width, int height,
int dstx, int dsty, unsigned long plane)
{
RegionPtr prgnSrcClip;
RegionRec rgnSrcRec;
RegionPtr prgnDstClip;
RegionRec rgnDstRec;
BoxRec srcBox;
RegionRec rgnExposed;
WindowPtr pSrcWin;
BoxRec expBox;
Bool extents;
if (!pGC->graphicsExposures &&
(pDstDrawable->type == DRAWABLE_PIXMAP) &&
((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
(((WindowPtr)pSrcDrawable)->backStorage == NULL)))
return NULL;
srcBox.x1 = srcx;
srcBox.y1 = srcy;
srcBox.x2 = srcx+width;
srcBox.y2 = srcy+height;
if (pSrcDrawable->type != DRAWABLE_PIXMAP)
{
BoxRec TsrcBox;
TsrcBox.x1 = srcx + pSrcDrawable->x;
TsrcBox.y1 = srcy + pSrcDrawable->y;
TsrcBox.x2 = TsrcBox.x1 + width;
TsrcBox.y2 = TsrcBox.y1 + height;
pSrcWin = (WindowPtr) pSrcDrawable;
if (pGC->subWindowMode == IncludeInferiors)
{
prgnSrcClip = NotClippedByChildren (pSrcWin);
if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN)
{
RegionDestroy(prgnSrcClip);
return NULL;
}
}
else
{
if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
return NULL;
prgnSrcClip = &rgnSrcRec;
RegionNull(prgnSrcClip);
RegionCopy(prgnSrcClip, &pSrcWin->clipList);
}
RegionTranslate(prgnSrcClip,
-pSrcDrawable->x, -pSrcDrawable->y);
}
else
{
BoxRec box;
if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
(srcBox.x2 <= pSrcDrawable->width) &&
(srcBox.y2 <= pSrcDrawable->height))
return NULL;
box.x1 = 0;
box.y1 = 0;
box.x2 = pSrcDrawable->width;
box.y2 = pSrcDrawable->height;
prgnSrcClip = &rgnSrcRec;
RegionInit(prgnSrcClip, &box, 1);
pSrcWin = NULL;
}
if (pDstDrawable == pSrcDrawable)
{
prgnDstClip = prgnSrcClip;
}
else if (pDstDrawable->type != DRAWABLE_PIXMAP)
{
if (pGC->subWindowMode == IncludeInferiors)
{
prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
}
else
{
prgnDstClip = &rgnDstRec;
RegionNull(prgnDstClip);
RegionCopy(prgnDstClip,
&((WindowPtr)pDstDrawable)->clipList);
}
RegionTranslate(prgnDstClip,
-pDstDrawable->x, -pDstDrawable->y);
}
else
{
BoxRec box;
box.x1 = 0;
box.y1 = 0;
box.x2 = pDstDrawable->width;
box.y2 = pDstDrawable->height;
prgnDstClip = &rgnDstRec;
RegionInit(prgnDstClip, &box, 1);
}
RegionInit(&rgnExposed, &srcBox, 1);
RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
RegionTranslate(&rgnExposed, dstx-srcx, dsty-srcy);
RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
if (pGC->clientClipType == CT_REGION)
RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);
extents = pGC->graphicsExposures &&
(RegionNumRects(&rgnExposed) > RECTLIMIT) &&
(pDstDrawable->type != DRAWABLE_PIXMAP);
if (pSrcWin)
{
RegionPtr region;
if (!(region = wClipShape (pSrcWin)))
region = wBoundingShape (pSrcWin);
if (extents && pSrcWin && region &&
(RegionContainsRect(region, &srcBox) != rgnIN))
extents = FALSE;
}
if (extents)
{
expBox = *RegionExtents(&rgnExposed);
RegionReset(&rgnExposed, &expBox);
}
if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
(((WindowPtr)pDstDrawable)->backgroundState != None))
{
WindowPtr pWin = (WindowPtr)pDstDrawable;
RegionTranslate(&rgnExposed,
pDstDrawable->x, pDstDrawable->y);
if (extents)
{
RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
}
miPaintWindow((WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
if (extents)
{
RegionReset(&rgnExposed, &expBox);
}
else
RegionTranslate(&rgnExposed,
-pDstDrawable->x, -pDstDrawable->y);
}
if (prgnDstClip == &rgnDstRec)
{
RegionUninit(prgnDstClip);
}
else if (prgnDstClip != prgnSrcClip)
{
RegionDestroy(prgnDstClip);
}
if (prgnSrcClip == &rgnSrcRec)
{
RegionUninit(prgnSrcClip);
}
else
{
RegionDestroy(prgnSrcClip);
}
if (pGC->graphicsExposures)
{
RegionPtr exposed = RegionCreate(NullBox, 0);
*exposed = rgnExposed;
return exposed;
}
else
{
RegionUninit(&rgnExposed);
return NULL;
}
}
void
miSendGraphicsExpose (ClientPtr client, RegionPtr pRgn, XID drawable,
int major, int minor)
{
if (pRgn && !RegionNil(pRgn))
{
xEvent *pEvent;
xEvent *pe;
BoxPtr pBox;
int i;
int numRects;
numRects = RegionNumRects(pRgn);
pBox = RegionRects(pRgn);
if(!(pEvent = malloc(numRects * sizeof(xEvent))))
return;
pe = pEvent;
for (i=1; i<=numRects; i++, pe++, pBox++)
{
pe->u.u.type = GraphicsExpose;
pe->u.graphicsExposure.drawable = drawable;
pe->u.graphicsExposure.x = pBox->x1;
pe->u.graphicsExposure.y = pBox->y1;
pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
pe->u.graphicsExposure.count = numRects - i;
pe->u.graphicsExposure.majorEvent = major;
pe->u.graphicsExposure.minorEvent = minor;
}
TryClientEvents(client, NULL, pEvent, numRects,
(Mask)0, NoEventMask, NullGrab);
free(pEvent);
}
else
{
xEvent event;
memset(&event, 0, sizeof(xEvent));
event.u.u.type = NoExpose;
event.u.noExposure.drawable = drawable;
event.u.noExposure.majorEvent = major;
event.u.noExposure.minorEvent = minor;
WriteEventsToClient(client, 1, &event);
}
}
void
miSendExposures( WindowPtr pWin, RegionPtr pRgn, int dx, int dy)
{
BoxPtr pBox;
int numRects;
xEvent *pEvent, *pe;
int i;
pBox = RegionRects(pRgn);
numRects = RegionNumRects(pRgn);
if(!(pEvent = calloc(1, numRects * sizeof(xEvent))))
return;
for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
{
pe->u.u.type = Expose;
pe->u.expose.window = pWin->drawable.id;
pe->u.expose.x = pBox->x1 - dx;
pe->u.expose.y = pBox->y1 - dy;
pe->u.expose.width = pBox->x2 - pBox->x1;
pe->u.expose.height = pBox->y2 - pBox->y1;
pe->u.expose.count = i;
}
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
int scrnum = pWin->drawable.pScreen->myNum;
int x = 0, y = 0;
XID realWin = 0;
if(!pWin->parent) {
x = screenInfo.screens[scrnum]->x;
y = screenInfo.screens[scrnum]->y;
pWin = screenInfo.screens[0]->root;
realWin = pWin->drawable.id;
} else if (scrnum) {
PanoramiXRes *win;
win = PanoramiXFindIDByScrnum(XRT_WINDOW,
pWin->drawable.id, scrnum);
if(!win) {
free(pEvent);
return;
}
realWin = win->info[0].id;
dixLookupWindow(&pWin, realWin, serverClient, DixSendAccess);
}
if(x || y || scrnum)
for (i = 0; i < numRects; i++) {
pEvent[i].u.expose.window = realWin;
pEvent[i].u.expose.x += x;
pEvent[i].u.expose.y += y;
}
}
#endif
DeliverEvents(pWin, pEvent, numRects, NullWindow);
free(pEvent);
}
void
miWindowExposures( WindowPtr pWin, RegionPtr prgn, RegionPtr other_exposed)
{
RegionPtr exposures = prgn;
if ((prgn && !RegionNil(prgn)) ||
(exposures && !RegionNil(exposures)) || other_exposed)
{
RegionRec expRec;
int clientInterested;
clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
if (other_exposed)
{
if (exposures)
{
RegionUnion(other_exposed,
exposures,
other_exposed);
if (exposures != prgn)
RegionDestroy(exposures);
}
exposures = other_exposed;
}
if (clientInterested && exposures && (RegionNumRects(exposures) > RECTLIMIT))
{
BoxRec box;
box = *RegionExtents(exposures);
if (exposures == prgn) {
exposures = &expRec;
RegionInit(exposures, &box, 1);
RegionReset(prgn, &box);
} else {
RegionReset(exposures, &box);
RegionUnion(prgn, prgn, exposures);
}
RegionIntersect(prgn, prgn, &pWin->clipList);
}
if (prgn && !RegionNil(prgn))
miPaintWindow(pWin, prgn, PW_BACKGROUND);
if (clientInterested && exposures && !RegionNil(exposures))
miSendExposures(pWin, exposures,
pWin->drawable.x, pWin->drawable.y);
if (exposures == &expRec)
{
RegionUninit(exposures);
}
else if (exposures && exposures != prgn && exposures != other_exposed)
RegionDestroy(exposures);
if (prgn)
RegionEmpty(prgn);
}
else if (exposures && exposures != prgn)
RegionDestroy(exposures);
}
#ifdef ROOTLESS
void RootlessSetPixmapOfAncestors(WindowPtr pWin);
void RootlessStartDrawing(WindowPtr pWin);
void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
Bool IsFramedWindow(WindowPtr pWin);
#include "../fb/fb.h"
#endif
void
miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
ChangeGCVal gcval[6];
BITS32 gcmask;
GCPtr pGC;
int i;
BoxPtr pbox;
xRectangle *prect;
int numRects;
int draw_x_off, draw_y_off;
int tile_x_off, tile_y_off;
PixUnion fill;
Bool solid = TRUE;
DrawablePtr drawable = &pWin->drawable;
#ifdef XQUARTZ_CLIP_DEBUG
ErrorF("START %d BS %d (pR = %ld)\n", what, pWin->backgroundState, ParentRelative);
ErrorF(" Rgn: %d %d %d %d\n", prgn->extents.x1, prgn->extents.y1,
prgn->extents.x2 - prgn->extents.x1,
prgn->extents.y2 - prgn->extents.y1);
ErrorF(" Win: %d %d (%d %d) %d %d\n", pWin->origin.x, pWin->origin.y,
pWin->winSize.extents.x1, pWin->winSize.extents.y1,
pWin->winSize.extents.x2 - pWin->winSize.extents.x1,
pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
ErrorF(" Draw: %d %d %d %d\n", pWin->drawable.x, pWin->drawable.y,
pWin->drawable.width, pWin->drawable.height);
#endif
#ifdef ROOTLESS
if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
return;
#endif
if (what == PW_BACKGROUND)
{
#ifdef ROOTLESS
if(IsFramedWindow(pWin)) {
RootlessStartDrawing(pWin);
RootlessDamageRegion(pWin, prgn);
if(pWin->backgroundState == ParentRelative) {
RootlessSetPixmapOfAncestors(pWin);
}
}
#endif
while (pWin->backgroundState == ParentRelative)
pWin = pWin->parent;
draw_x_off = drawable->x;
draw_y_off = drawable->y;
tile_x_off = pWin->drawable.x - draw_x_off;
tile_y_off = pWin->drawable.y - draw_y_off;
fill = pWin->background;
switch (pWin->backgroundState) {
case None:
return;
case BackgroundPixmap:
solid = FALSE;
break;
}
}
else
{
PixmapPtr pixmap;
#ifdef ROOTLESS
if(IsFramedWindow(pWin)) {
RootlessStartDrawing(pWin);
RootlessDamageRegion(pWin, prgn);
if(!pWin->borderIsPixel &&
pWin->backgroundState == ParentRelative) {
RootlessSetPixmapOfAncestors(pWin);
}
}
#endif
tile_x_off = drawable->x;
tile_y_off = drawable->y;
if (!pScreen->GetWindowPixmap)
return;
pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
drawable = &pixmap->drawable;
#ifdef XQUARTZ_CLIP_DEBUG
ErrorF(" Draw: %d %d %d %d\n",
drawable->x, drawable->y, drawable->width, drawable->height);
#endif
#ifdef COMPOSITE
draw_x_off = pixmap->screen_x;
draw_y_off = pixmap->screen_y;
tile_x_off -= draw_x_off;
tile_y_off -= draw_y_off;
#else
draw_x_off = 0;
draw_y_off = 0;
#endif
fill = pWin->border;
solid = pWin->borderIsPixel;
}
gcval[0].val = GXcopy;
gcmask = GCFunction;
#ifdef ROOTLESS_SAFEALPHA
#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
#endif
if (solid)
{
#ifdef ROOTLESS_SAFEALPHA
gcval[1].val = fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
#else
gcval[1].val = fill.pixel;
#endif
gcval[2].val = FillSolid;
gcmask |= GCForeground | GCFillStyle;
}
else
{
int c=1;
#ifdef ROOTLESS_SAFEALPHA
gcval[c++].val = ((CARD32)-1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel);
gcmask |= GCPlaneMask;
#endif
gcval[c++].val = FillTiled;
gcval[c++].ptr = (pointer)fill.pixmap;
gcval[c++].val = tile_x_off;
gcval[c++].val = tile_y_off;
gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
}
prect = malloc(RegionNumRects(prgn) * sizeof(xRectangle));
if (!prect)
return;
pGC = GetScratchGC(drawable->depth, drawable->pScreen);
if (!pGC)
{
free(prect);
return;
}
ChangeGC (NullClient, pGC, gcmask, gcval);
ValidateGC (drawable, pGC);
#ifdef XQUARTZ_CLIP_DEBUG
ErrorF(" GC: %d %d %d %d\n",
pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);
#endif
#ifdef XQUARTZ
if(what == PW_BORDER) {
#if 0
if(solid) {
#if 1
fbFillRegionSolid(&pWin->drawable,
prgn,
0,
fbReplicatePixel(fill.pixel,
pWin->drawable.bitsPerPixel));
#else
fbFillRegionSolid(drawable,
prgn,
0,
fbReplicatePixel(fill.pixel,
drawable->bitsPerPixel));
#endif
return;
}
#endif
pGC->pCompositeClip->extents.x1 += prgn->extents.x1;
pGC->pCompositeClip->extents.y1 += prgn->extents.y1;
pGC->pCompositeClip->extents.x2 += prgn->extents.x1;
pGC->pCompositeClip->extents.y2 += prgn->extents.y1;
if(pGC->pCompositeClip->extents.x2 > drawable->pScreen->width)
pGC->pCompositeClip->extents.x2 = drawable->pScreen->width;
if(pGC->pCompositeClip->extents.y2 > drawable->pScreen->height)
pGC->pCompositeClip->extents.y2 = drawable->pScreen->height;
}
#endif
#ifdef XQUARTZ_CLIP_DEBUG
ErrorF(" GC: %d %d %d %d\n",
pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);
#endif
numRects = RegionNumRects(prgn);
pbox = RegionRects(prgn);
for (i= numRects; --i >= 0; pbox++, prect++)
{
prect->x = pbox->x1 - draw_x_off;
prect->y = pbox->y1 - draw_y_off;
prect->width = pbox->x2 - pbox->x1;
prect->height = pbox->y2 - pbox->y1;
}
prect -= numRects;
(*pGC->ops->PolyFillRect)(drawable, pGC, numRects, prect);
free(prect);
FreeScratchGC(pGC);
}
void
miClearDrawable(DrawablePtr pDraw, GCPtr pGC)
{
ChangeGCVal fg, bg;
xRectangle rect;
fg.val = pGC->fgPixel;
bg.val = pGC->bgPixel;
rect.x = 0;
rect.y = 0;
rect.width = pDraw->width;
rect.height = pDraw->height;
ChangeGC(NullClient, pGC, GCForeground, &bg);
ValidateGC(pDraw, pGC);
(*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
ChangeGC(NullClient, pGC, GCForeground, &fg);
ValidateGC(pDraw, pGC);
}