#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#define NEED_EVENTS
#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
_X_EXPORT RegionPtr
miHandleExposures(pSrcDrawable, pDstDrawable,
pGC, srcx, srcy, width, height, dstx, dsty, plane)
DrawablePtr pSrcDrawable;
DrawablePtr pDstDrawable;
GCPtr pGC;
int srcx, srcy;
int width, height;
int dstx, dsty;
unsigned long plane;
{
ScreenPtr pscr;
RegionPtr prgnSrcClip;
RegionRec rgnSrcRec;
RegionPtr prgnDstClip;
RegionRec rgnDstRec;
BoxRec srcBox;
RegionRec rgnExposed;
WindowPtr pSrcWin;
BoxRec expBox;
Bool extents;
pGC->pScreen = pscr = pGC->pScreen;
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 ((RECT_IN_REGION(pscr, prgnSrcClip, &TsrcBox)) == rgnIN)
{
REGION_DESTROY(pscr, prgnSrcClip);
return NULL;
}
}
else
{
if ((RECT_IN_REGION(pscr, &pSrcWin->clipList, &TsrcBox)) == rgnIN)
return NULL;
prgnSrcClip = &rgnSrcRec;
REGION_NULL(pscr, prgnSrcClip);
REGION_COPY(pscr, prgnSrcClip, &pSrcWin->clipList);
}
REGION_TRANSLATE(pscr, 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;
REGION_INIT(pscr, prgnSrcClip, &box, 1);
pSrcWin = (WindowPtr)NULL;
}
if (pDstDrawable == pSrcDrawable)
{
prgnDstClip = prgnSrcClip;
}
else if (pDstDrawable->type != DRAWABLE_PIXMAP)
{
if (pGC->subWindowMode == IncludeInferiors)
{
prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
}
else
{
prgnDstClip = &rgnDstRec;
REGION_NULL(pscr, prgnDstClip);
REGION_COPY(pscr, prgnDstClip,
&((WindowPtr)pDstDrawable)->clipList);
}
REGION_TRANSLATE(pscr, prgnDstClip,
-pDstDrawable->x, -pDstDrawable->y);
}
else
{
BoxRec box;
box.x1 = 0;
box.y1 = 0;
box.x2 = pDstDrawable->width;
box.y2 = pDstDrawable->height;
prgnDstClip = &rgnDstRec;
REGION_INIT(pscr, prgnDstClip, &box, 1);
}
REGION_INIT(pscr, &rgnExposed, &srcBox, 1);
REGION_SUBTRACT(pscr, &rgnExposed, &rgnExposed, prgnSrcClip);
if (pSrcWin && pSrcWin->backStorage)
{
(* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable,
pDstDrawable,
pGC,
&rgnExposed,
srcx, srcy,
dstx, dsty,
plane);
}
REGION_TRANSLATE(pscr, &rgnExposed, dstx-srcx, dsty-srcy);
REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, prgnDstClip);
extents = pGC->graphicsExposures &&
(REGION_NUM_RECTS(&rgnExposed) > RECTLIMIT) &&
(pDstDrawable->type != DRAWABLE_PIXMAP);
#ifdef SHAPE
if (pSrcWin)
{
RegionPtr region;
if (!(region = wClipShape (pSrcWin)))
region = wBoundingShape (pSrcWin);
if (extents && pSrcWin && region &&
(RECT_IN_REGION(pscr, region, &srcBox) != rgnIN))
extents = FALSE;
}
#endif
if (extents)
{
WindowPtr pWin = (WindowPtr)pDstDrawable;
expBox = *REGION_EXTENTS(pscr, &rgnExposed);
REGION_RESET(pscr, &rgnExposed, &expBox);
if (pWin->backStorage)
(void) (* pWin->drawable.pScreen->ClearBackingStore)(
pWin,
expBox.x1,
expBox.y1,
expBox.x2 - expBox.x1,
expBox.y2 - expBox.y1,
FALSE);
}
if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
(((WindowPtr)pDstDrawable)->backgroundState != None))
{
WindowPtr pWin = (WindowPtr)pDstDrawable;
REGION_TRANSLATE(pscr, &rgnExposed,
pDstDrawable->x, pDstDrawable->y);
if (extents)
{
REGION_INTERSECT(pscr, &rgnExposed, &rgnExposed, &pWin->clipList);
}
(*pWin->drawable.pScreen->PaintWindowBackground)(
(WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
if (extents)
{
REGION_RESET(pscr, &rgnExposed, &expBox);
}
else
REGION_TRANSLATE(pscr, &rgnExposed,
-pDstDrawable->x, -pDstDrawable->y);
}
if (prgnDstClip == &rgnDstRec)
{
REGION_UNINIT(pscr, prgnDstClip);
}
else if (prgnDstClip != prgnSrcClip)
{
REGION_DESTROY(pscr, prgnDstClip);
}
if (prgnSrcClip == &rgnSrcRec)
{
REGION_UNINIT(pscr, prgnSrcClip);
}
else
{
REGION_DESTROY(pscr, prgnSrcClip);
}
if (pGC->graphicsExposures)
{
RegionPtr exposed = REGION_CREATE(pscr, NullBox, 0);
*exposed = rgnExposed;
return exposed;
}
else
{
REGION_UNINIT(pscr, &rgnExposed);
return NULL;
}
}
_X_EXPORT void
miSendGraphicsExpose (client, pRgn, drawable, major, minor)
ClientPtr client;
RegionPtr pRgn;
XID drawable;
int major;
int minor;
{
if (pRgn && !REGION_NIL(pRgn))
{
xEvent *pEvent;
xEvent *pe;
BoxPtr pBox;
int i;
int numRects;
numRects = REGION_NUM_RECTS(pRgn);
pBox = REGION_RECTS(pRgn);
if(!(pEvent = (xEvent *)ALLOCATE_LOCAL(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, pEvent, numRects,
(Mask)0, NoEventMask, NullGrab);
DEALLOCATE_LOCAL(pEvent);
}
else
{
xEvent event;
event.u.u.type = NoExpose;
event.u.noExposure.drawable = drawable;
event.u.noExposure.majorEvent = major;
event.u.noExposure.minorEvent = minor;
TryClientEvents(client, &event, 1,
(Mask)0, NoEventMask, NullGrab);
}
}
void
miSendExposures(pWin, pRgn, dx, dy)
WindowPtr pWin;
RegionPtr pRgn;
int dx, dy;
{
BoxPtr pBox;
int numRects;
xEvent *pEvent, *pe;
int i;
pBox = REGION_RECTS(pRgn);
numRects = REGION_NUM_RECTS(pRgn);
if(!(pEvent = (xEvent *) ALLOCATE_LOCAL(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 = panoramiXdataPtr[scrnum].x;
y = panoramiXdataPtr[scrnum].y;
pWin = WindowTable[0];
realWin = pWin->drawable.id;
} else if (scrnum) {
PanoramiXRes *win;
win = PanoramiXFindIDByScrnum(XRT_WINDOW,
pWin->drawable.id, scrnum);
if(!win) {
DEALLOCATE_LOCAL(pEvent);
return;
}
realWin = win->info[0].id;
pWin = LookupIDByType(realWin, RT_WINDOW);
}
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);
DEALLOCATE_LOCAL(pEvent);
}
_X_EXPORT void
miWindowExposures(pWin, prgn, other_exposed)
WindowPtr pWin;
RegionPtr prgn, other_exposed;
{
RegionPtr exposures = prgn;
if (pWin->backStorage && prgn)
exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn);
if ((prgn && !REGION_NIL(prgn)) ||
(exposures && !REGION_NIL(exposures)) || other_exposed)
{
RegionRec expRec;
int clientInterested;
clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
if (other_exposed)
{
if (exposures)
{
REGION_UNION(pWin->drawable.pScreen, other_exposed,
exposures,
other_exposed);
if (exposures != prgn)
REGION_DESTROY(pWin->drawable.pScreen, exposures);
}
exposures = other_exposed;
}
if (clientInterested && exposures && (REGION_NUM_RECTS(exposures) > RECTLIMIT))
{
BoxRec box;
box = *REGION_EXTENTS( pWin->drawable.pScreen, exposures);
if (exposures == prgn) {
exposures = &expRec;
REGION_INIT( pWin->drawable.pScreen, exposures, &box, 1);
REGION_RESET( pWin->drawable.pScreen, prgn, &box);
} else {
REGION_RESET( pWin->drawable.pScreen, exposures, &box);
REGION_UNION( pWin->drawable.pScreen, prgn, prgn, exposures);
}
REGION_INTERSECT( pWin->drawable.pScreen, prgn, prgn, &pWin->clipList);
if (pWin->backStorage)
(void) (* pWin->drawable.pScreen->ClearBackingStore)(
pWin,
box.x1 - pWin->drawable.x,
box.y1 - pWin->drawable.y,
box.x2 - box.x1,
box.y2 - box.y1,
FALSE);
}
if (prgn && !REGION_NIL(prgn))
(*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND);
if (clientInterested && exposures && !REGION_NIL(exposures))
miSendExposures(pWin, exposures,
pWin->drawable.x, pWin->drawable.y);
if (exposures == &expRec)
{
REGION_UNINIT( pWin->drawable.pScreen, exposures);
}
else if (exposures && exposures != prgn && exposures != other_exposed)
REGION_DESTROY( pWin->drawable.pScreen, exposures);
if (prgn)
REGION_EMPTY( pWin->drawable.pScreen, prgn);
}
else if (exposures && exposures != prgn)
REGION_DESTROY( pWin->drawable.pScreen, exposures);
}
static RESTYPE ResType = 0;
static int numGCs = 0;
static GCPtr screenContext[MAXSCREENS];
static int
tossGC (
pointer value,
XID id)
{
GCPtr pGC = (GCPtr)value;
screenContext[pGC->pScreen->myNum] = (GCPtr)NULL;
FreeGC (pGC, id);
numGCs--;
if (!numGCs)
ResType = 0;
return 0;
}
_X_EXPORT void
miPaintWindow(pWin, prgn, what)
WindowPtr pWin;
RegionPtr prgn;
int what;
{
int status;
Bool usingScratchGC = FALSE;
WindowPtr pRoot;
#define FUNCTION 0
#define FOREGROUND 1
#define TILE 2
#define FILLSTYLE 3
#define ABSX 4
#define ABSY 5
#define CLIPMASK 6
#define SUBWINDOW 7
#define COUNT_BITS 8
ChangeGCVal gcval[7];
ChangeGCVal newValues [COUNT_BITS];
BITS32 gcmask, index, mask;
RegionRec prgnWin;
DDXPointRec oldCorner;
BoxRec box;
WindowPtr pBgWin;
GCPtr pGC;
int i;
BoxPtr pbox;
ScreenPtr pScreen = pWin->drawable.pScreen;
xRectangle *prect;
int numRects;
gcmask = 0;
if (what == PW_BACKGROUND)
{
switch (pWin->backgroundState) {
case None:
return;
case ParentRelative:
(*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what);
return;
case BackgroundPixel:
newValues[FOREGROUND].val = pWin->background.pixel;
newValues[FILLSTYLE].val = FillSolid;
gcmask |= GCForeground | GCFillStyle;
break;
case BackgroundPixmap:
newValues[TILE].ptr = (pointer)pWin->background.pixmap;
newValues[FILLSTYLE].val = FillTiled;
gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
break;
}
}
else
{
if (pWin->borderIsPixel)
{
newValues[FOREGROUND].val = pWin->border.pixel;
newValues[FILLSTYLE].val = FillSolid;
gcmask |= GCForeground | GCFillStyle;
}
else
{
newValues[TILE].ptr = (pointer)pWin->border.pixmap;
newValues[FILLSTYLE].val = FillTiled;
gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
}
}
prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) *
sizeof(xRectangle));
if (!prect)
return;
newValues[FUNCTION].val = GXcopy;
gcmask |= GCFunction | GCClipMask;
i = pScreen->myNum;
pRoot = WindowTable[i];
pBgWin = pWin;
if (what == PW_BORDER)
{
while (pBgWin->backgroundState == ParentRelative)
pBgWin = pBgWin->parent;
}
if ((pWin->drawable.depth != pRoot->drawable.depth) ||
(pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel))
{
usingScratchGC = TRUE;
pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
if (!pGC)
{
DEALLOCATE_LOCAL(prect);
return;
}
if (what == PW_BORDER)
{
prgnWin = pWin->clipList;
oldCorner.x = pWin->drawable.x;
oldCorner.y = pWin->drawable.y;
pWin->drawable.x = pWin->drawable.y = 0;
box.x1 = 0;
box.y1 = 0;
box.x2 = pScreen->width;
box.y2 = pScreen->height;
REGION_INIT(pScreen, &pWin->clipList, &box, 1);
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
newValues[ABSX].val = pBgWin->drawable.x;
newValues[ABSY].val = pBgWin->drawable.y;
}
else
{
newValues[ABSX].val = 0;
newValues[ABSY].val = 0;
}
} else {
if (screenContext[i] == (GCPtr)NULL)
{
if (!ResType && !(ResType = CreateNewResourceType(tossGC)))
return;
screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0,
(XID *)NULL, &status);
if (!screenContext[i])
return;
numGCs++;
if (!AddResource(FakeClientID(0), ResType,
(pointer)screenContext[i]))
return;
}
pGC = screenContext[i];
newValues[SUBWINDOW].val = IncludeInferiors;
newValues[ABSX].val = pBgWin->drawable.x;
newValues[ABSY].val = pBgWin->drawable.y;
gcmask |= GCSubwindowMode;
pWin = pRoot;
}
if (pWin->backStorage)
(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
mask = gcmask;
gcmask = 0;
i = 0;
while (mask) {
index = lowbit (mask);
mask &= ~index;
switch (index) {
case GCFunction:
if (pGC->alu != newValues[FUNCTION].val) {
gcmask |= index;
gcval[i++].val = newValues[FUNCTION].val;
}
break;
case GCTileStipXOrigin:
if ( pGC->patOrg.x != newValues[ABSX].val) {
gcmask |= index;
gcval[i++].val = newValues[ABSX].val;
}
break;
case GCTileStipYOrigin:
if ( pGC->patOrg.y != newValues[ABSY].val) {
gcmask |= index;
gcval[i++].val = newValues[ABSY].val;
}
break;
case GCClipMask:
if ( pGC->clientClipType != CT_NONE) {
gcmask |= index;
gcval[i++].val = CT_NONE;
}
break;
case GCSubwindowMode:
if ( pGC->subWindowMode != newValues[SUBWINDOW].val) {
gcmask |= index;
gcval[i++].val = newValues[SUBWINDOW].val;
}
break;
case GCTile:
if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr)
{
gcmask |= index;
gcval[i++].ptr = newValues[TILE].ptr;
}
break;
case GCFillStyle:
if ( pGC->fillStyle != newValues[FILLSTYLE].val) {
gcmask |= index;
gcval[i++].val = newValues[FILLSTYLE].val;
}
break;
case GCForeground:
if ( pGC->fgPixel != newValues[FOREGROUND].val) {
gcmask |= index;
gcval[i++].val = newValues[FOREGROUND].val;
}
break;
}
}
if (gcmask)
dixChangeGC(NullClient, pGC, gcmask, NULL, gcval);
if (pWin->drawable.serialNumber != pGC->serialNumber)
ValidateGC((DrawablePtr)pWin, pGC);
numRects = REGION_NUM_RECTS(prgn);
pbox = REGION_RECTS(prgn);
for (i= numRects; --i >= 0; pbox++, prect++)
{
prect->x = pbox->x1 - pWin->drawable.x;
prect->y = pbox->y1 - pWin->drawable.y;
prect->width = pbox->x2 - pbox->x1;
prect->height = pbox->y2 - pbox->y1;
}
prect -= numRects;
(*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect);
DEALLOCATE_LOCAL(prect);
if (pWin->backStorage)
(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
if (usingScratchGC)
{
if (what == PW_BORDER)
{
REGION_UNINIT(pScreen, &pWin->clipList);
pWin->clipList = prgnWin;
pWin->drawable.x = oldCorner.x;
pWin->drawable.y = oldCorner.y;
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
FreeScratchGC(pGC);
}
}
_X_EXPORT void
miClearDrawable(pDraw, pGC)
DrawablePtr pDraw;
GCPtr pGC;
{
XID fg = pGC->fgPixel;
XID bg = pGC->bgPixel;
xRectangle rect;
rect.x = 0;
rect.y = 0;
rect.width = pDraw->width;
rect.height = pDraw->height;
DoChangeGC(pGC, GCForeground, &bg, 0);
ValidateGC(pDraw, pGC);
(*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
DoChangeGC(pGC, GCForeground, &fg, 0);
ValidateGC(pDraw, pGC);
}