#include "X.h"
#include "scrnintstr.h"
#include "validate.h"
#include "windowstr.h"
#include "mi.h"
#include "regionstr.h"
#include "mivalidate.h"
#include "globals.h"
#ifdef SHAPE
int
miShapedWindowIn (pScreen, universe, bounding, rect, x, y)
ScreenPtr pScreen;
RegionPtr universe, bounding;
BoxPtr rect;
register int x, y;
{
BoxRec box;
register BoxPtr boundBox;
int nbox;
Bool someIn, someOut;
register int t, x1, y1, x2, y2;
nbox = REGION_NUM_RECTS (bounding);
boundBox = REGION_RECTS (bounding);
someIn = someOut = FALSE;
x1 = rect->x1;
y1 = rect->y1;
x2 = rect->x2;
y2 = rect->y2;
while (nbox--)
{
if ((t = boundBox->x1 + x) < x1)
t = x1;
box.x1 = t;
if ((t = boundBox->y1 + y) < y1)
t = y1;
box.y1 = t;
if ((t = boundBox->x2 + x) > x2)
t = x2;
box.x2 = t;
if ((t = boundBox->y2 + y) > y2)
t = y2;
box.y2 = t;
if (box.x1 > box.x2)
box.x2 = box.x1;
if (box.y1 > box.y2)
box.y2 = box.y1;
switch (RECT_IN_REGION(pScreen, universe, &box))
{
case rgnIN:
if (someOut)
return rgnPART;
someIn = TRUE;
break;
case rgnOUT:
if (someIn)
return rgnPART;
someOut = TRUE;
break;
default:
return rgnPART;
}
boundBox++;
}
if (someIn)
return rgnIN;
return rgnOUT;
}
#endif
#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
HasBorder(w) && \
(w)->backgroundState == ParentRelative)
static void
miComputeClips (
register WindowPtr pParent,
register ScreenPtr pScreen,
register RegionPtr universe,
VTKind kind,
RegionPtr exposed )
{
int dx,
dy;
RegionRec childUniverse;
register WindowPtr pChild;
int oldVis, newVis;
BoxRec borderSize;
RegionRec childUnion;
Bool overlap;
RegionPtr borderVisible;
Bool resized;
borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
if (dx > 32767)
dx = 32767;
borderSize.x2 = dx;
dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
if (dy > 32767)
dy = 32767;
borderSize.y2 = dy;
oldVis = pParent->visibility;
switch (RECT_IN_REGION( pScreen, universe, &borderSize))
{
case rgnIN:
newVis = VisibilityUnobscured;
break;
case rgnPART:
newVis = VisibilityPartiallyObscured;
#ifdef SHAPE
{
RegionPtr pBounding;
if ((pBounding = wBoundingShape (pParent)))
{
switch (miShapedWindowIn (pScreen, universe, pBounding,
&borderSize,
pParent->drawable.x,
pParent->drawable.y))
{
case rgnIN:
newVis = VisibilityUnobscured;
break;
case rgnOUT:
newVis = VisibilityFullyObscured;
break;
}
}
}
#endif
break;
default:
newVis = VisibilityFullyObscured;
break;
}
pParent->visibility = newVis;
if (oldVis != newVis &&
((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
SendVisibilityNotify(pParent);
dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
switch (kind) {
case VTMap:
case VTStack:
case VTUnmap:
break;
case VTMove:
if ((oldVis == newVis) &&
((oldVis == VisibilityFullyObscured) ||
(oldVis == VisibilityUnobscured)))
{
pChild = pParent;
while (1)
{
if (pChild->viewable)
{
if (pChild->visibility != VisibilityFullyObscured)
{
REGION_TRANSLATE( pScreen, &pChild->borderClip,
dx, dy);
REGION_TRANSLATE( pScreen, &pChild->clipList,
dx, dy);
pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pChild, dx, dy);
}
if (pChild->valdata)
{
REGION_NULL(pScreen,
&pChild->valdata->after.borderExposed);
if (HasParentRelativeBorder(pChild))
{
REGION_SUBTRACT(pScreen,
&pChild->valdata->after.borderExposed,
&pChild->borderClip,
&pChild->winSize);
}
REGION_NULL(pScreen, &pChild->valdata->after.exposed);
}
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
}
while (!pChild->nextSib && (pChild != pParent))
pChild = pChild->parent;
if (pChild == pParent)
break;
pChild = pChild->nextSib;
}
return;
}
default:
if (dx || dy)
{
REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy);
REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy);
}
break;
case VTBroken:
REGION_EMPTY (pScreen, &pParent->borderClip);
REGION_EMPTY (pScreen, &pParent->clipList);
break;
}
borderVisible = pParent->valdata->before.borderVisible;
resized = pParent->valdata->before.resized;
REGION_NULL(pScreen, &pParent->valdata->after.borderExposed);
REGION_NULL(pScreen, &pParent->valdata->after.exposed);
if (HasBorder (pParent))
{
if (borderVisible)
{
REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
REGION_DESTROY( pScreen, borderVisible);
}
else
{
REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip);
}
if (HasParentRelativeBorder(pParent) && (dx || dy))
REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
universe,
&pParent->winSize);
else
REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
exposed, &pParent->winSize);
REGION_COPY( pScreen, &pParent->borderClip, universe);
REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
}
else
REGION_COPY( pScreen, &pParent->borderClip, universe);
if ((pChild = pParent->firstChild) && pParent->mapped)
{
REGION_NULL(pScreen, &childUniverse);
REGION_NULL(pScreen, &childUnion);
if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
((pChild->drawable.y == pParent->lastChild->drawable.y) &&
(pChild->drawable.x < pParent->lastChild->drawable.x)))
{
for (; pChild; pChild = pChild->nextSib)
{
if (pChild->viewable)
REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
}
}
else
{
for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
{
if (pChild->viewable)
REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
}
}
REGION_VALIDATE( pScreen, &childUnion, &overlap);
for (pChild = pParent->firstChild;
pChild;
pChild = pChild->nextSib)
{
if (pChild->viewable) {
if (pChild->valdata) {
REGION_INTERSECT( pScreen, &childUniverse,
universe,
&pChild->borderSize);
miComputeClips (pChild, pScreen, &childUniverse, kind,
exposed);
}
if (overlap)
REGION_SUBTRACT( pScreen, universe, universe,
&pChild->borderSize);
}
}
if (!overlap)
REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
REGION_UNINIT( pScreen, &childUnion);
REGION_UNINIT( pScreen, &childUniverse);
}
if (oldVis == VisibilityFullyObscured ||
oldVis == VisibilityNotViewable)
{
REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe);
}
else if (newVis != VisibilityFullyObscured &&
newVis != VisibilityNotViewable)
{
REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
universe, &pParent->clipList);
}
if (pParent->backStorage && !resized)
{
REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe);
(* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
}
{
RegionRec tmp;
tmp = pParent->clipList;
pParent->clipList = *universe;
*universe = tmp;
}
#ifdef NOTDEF
REGION_COPY( pScreen, &pParent->clipList, universe);
#endif
pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pParent, dx, dy);
}
static void
miTreeObscured(
register WindowPtr pParent )
{
register WindowPtr pChild;
register int oldVis;
pChild = pParent;
while (1)
{
if (pChild->viewable)
{
oldVis = pChild->visibility;
if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
SendVisibilityNotify(pChild);
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
}
while (!pChild->nextSib && (pChild != pParent))
pChild = pChild->parent;
if (pChild == pParent)
break;
pChild = pChild->nextSib;
}
}
int
miValidateTree (pParent, pChild, kind)
WindowPtr pParent;
WindowPtr pChild;
VTKind kind;
{
RegionRec totalClip;
RegionRec childClip;
RegionRec childUnion;
RegionRec exposed;
register ScreenPtr pScreen;
register WindowPtr pWin;
Bool overlap;
int viewvals;
Bool forward;
pScreen = pParent->drawable.pScreen;
if (pChild == NullWindow)
pChild = pParent->firstChild;
REGION_NULL(pScreen, &childClip);
REGION_NULL(pScreen, &exposed);
REGION_NULL(pScreen, &totalClip);
viewvals = 0;
if (REGION_BROKEN (pScreen, &pParent->clipList) &&
!REGION_BROKEN (pScreen, &pParent->borderClip))
{
kind = VTBroken;
forward = TRUE;
REGION_COPY (pScreen, &totalClip, &pParent->borderClip);
REGION_INTERSECT (pScreen, &totalClip, &totalClip, &pParent->winSize);
for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib)
{
if (pWin->viewable)
REGION_SUBTRACT (pScreen, &totalClip, &totalClip, &pWin->borderSize);
}
for (pWin = pChild; pWin; pWin = pWin->nextSib)
if (pWin->valdata && pWin->viewable)
viewvals++;
REGION_EMPTY (pScreen, &pParent->clipList);
}
else
{
if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
((pChild->drawable.y == pParent->lastChild->drawable.y) &&
(pChild->drawable.x < pParent->lastChild->drawable.x)))
{
forward = TRUE;
for (pWin = pChild; pWin; pWin = pWin->nextSib)
{
if (pWin->valdata)
{
REGION_APPEND( pScreen, &totalClip, &pWin->borderClip);
if (pWin->viewable)
viewvals++;
}
}
}
else
{
forward = FALSE;
pWin = pParent->lastChild;
while (1)
{
if (pWin->valdata)
{
REGION_APPEND( pScreen, &totalClip, &pWin->borderClip);
if (pWin->viewable)
viewvals++;
}
if (pWin == pChild)
break;
pWin = pWin->prevSib;
}
}
REGION_VALIDATE( pScreen, &totalClip, &overlap);
}
overlap = TRUE;
if (kind != VTStack)
{
REGION_UNION( pScreen, &totalClip, &totalClip, &pParent->clipList);
if (viewvals > 1)
{
REGION_NULL(pScreen, &childUnion);
if (forward)
{
for (pWin = pChild; pWin; pWin = pWin->nextSib)
if (pWin->valdata && pWin->viewable)
REGION_APPEND( pScreen, &childUnion,
&pWin->borderSize);
}
else
{
pWin = pParent->lastChild;
while (1)
{
if (pWin->valdata && pWin->viewable)
REGION_APPEND( pScreen, &childUnion,
&pWin->borderSize);
if (pWin == pChild)
break;
pWin = pWin->prevSib;
}
}
REGION_VALIDATE(pScreen, &childUnion, &overlap);
if (overlap)
REGION_UNINIT(pScreen, &childUnion);
}
}
for (pWin = pChild;
pWin != NullWindow;
pWin = pWin->nextSib)
{
if (pWin->viewable) {
if (pWin->valdata) {
REGION_INTERSECT( pScreen, &childClip,
&totalClip,
&pWin->borderSize);
miComputeClips (pWin, pScreen, &childClip, kind, &exposed);
if (overlap)
{
REGION_SUBTRACT( pScreen, &totalClip,
&totalClip,
&pWin->borderSize);
}
} else if (pWin->visibility == VisibilityNotViewable) {
miTreeObscured(pWin);
}
} else {
if (pWin->valdata) {
REGION_EMPTY( pScreen, &pWin->clipList);
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pWin, 0, 0);
REGION_EMPTY( pScreen, &pWin->borderClip);
pWin->valdata = (ValidatePtr)NULL;
}
}
}
REGION_UNINIT( pScreen, &childClip);
if (!overlap)
{
REGION_SUBTRACT(pScreen, &totalClip, &totalClip, &childUnion);
REGION_UNINIT(pScreen, &childUnion);
}
REGION_NULL(pScreen, &pParent->valdata->after.exposed);
REGION_NULL(pScreen, &pParent->valdata->after.borderExposed);
switch (kind) {
case VTStack:
break;
default:
REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
&totalClip, &pParent->clipList);
case VTMap:
if (pParent->backStorage) {
REGION_SUBTRACT( pScreen, &exposed, &pParent->clipList, &totalClip);
(* pScreen->SaveDoomedAreas)(pParent, &exposed, 0, 0);
}
REGION_COPY( pScreen, &pParent->clipList, &totalClip);
pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
break;
}
REGION_UNINIT( pScreen, &totalClip);
REGION_UNINIT( pScreen, &exposed);
if (pScreen->ClipNotify)
(*pScreen->ClipNotify) (pParent, 0, 0);
return (1);
}