#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <stddef.h>
#include <X11/X.h>
#include "scrnintstr.h"
#include "validate.h"
#include "windowstr.h"
#include "mi.h"
#include "regionstr.h"
#include "mivalidate.h"
#include "globals.h"
int RootlessShapedWindowIn (ScreenPtr pScreen, RegionPtr universe,
RegionPtr bounding, BoxPtr rect, int x, int y);
int RootlessMiValidateTree (WindowPtr pRoot, WindowPtr pChild, VTKind kind);
#ifdef SHAPE
int
RootlessShapedWindowIn (ScreenPtr pScreen, RegionPtr universe,
RegionPtr bounding, BoxPtr rect, int x, int 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
RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen,
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 (RootlessShapedWindowIn (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);
RootlessComputeClips (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
RootlessTreeObscured(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
RootlessMiValidateTree (WindowPtr pRoot,
WindowPtr pChild,
VTKind kind )
{
RegionRec childClip;
RegionRec exposed;
register ScreenPtr pScreen;
register WindowPtr pWin;
pScreen = pRoot->drawable.pScreen;
if (pChild == NullWindow)
pChild = pRoot->firstChild;
REGION_NULL(pScreen, &childClip);
REGION_NULL(pScreen, &exposed);
if (REGION_BROKEN (pScreen, &pRoot->clipList) &&
!REGION_BROKEN (pScreen, &pRoot->borderClip))
{
kind = VTBroken;
REGION_EMPTY (pScreen, &pRoot->clipList);
ErrorF("ValidateTree: BUSTED!\n");
}
for (pWin = pChild;
pWin != NullWindow;
pWin = pWin->nextSib)
{
if (pWin->viewable) {
if (pWin->valdata) {
REGION_COPY( pScreen, &childClip, &pWin->borderSize);
RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
} else if (pWin->visibility == VisibilityNotViewable) {
RootlessTreeObscured(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);
REGION_NULL(pScreen, &pRoot->valdata->after.exposed);
REGION_NULL(pScreen, &pRoot->valdata->after.borderExposed);
return 1;
}