mivaltree.c revision 6747b715
105b261ecSmrg/*
205b261ecSmrg * mivaltree.c --
305b261ecSmrg *	Functions for recalculating window clip lists. Main function
405b261ecSmrg *	is miValidateTree.
505b261ecSmrg *
605b261ecSmrg
705b261ecSmrgCopyright 1987, 1988, 1989, 1998  The Open Group
805b261ecSmrg
905b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
1005b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
1105b261ecSmrgthe above copyright notice appear in all copies and that both that
1205b261ecSmrgcopyright notice and this permission notice appear in supporting
1305b261ecSmrgdocumentation.
1405b261ecSmrg
1505b261ecSmrgThe above copyright notice and this permission notice shall be included in
1605b261ecSmrgall copies or substantial portions of the Software.
1705b261ecSmrg
1805b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1905b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2005b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2105b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2205b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2305b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2405b261ecSmrg
2505b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2605b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2705b261ecSmrgin this Software without prior written authorization from The Open Group.
2805b261ecSmrg
2905b261ecSmrg *
3005b261ecSmrg * Copyright 1987, 1988, 1989 by
3105b261ecSmrg * Digital Equipment Corporation, Maynard, Massachusetts,
3205b261ecSmrg *
3305b261ecSmrg *                         All Rights Reserved
3405b261ecSmrg *
3505b261ecSmrg * Permission to use, copy, modify, and distribute this software and its
3605b261ecSmrg * documentation for any purpose and without fee is hereby granted,
3705b261ecSmrg * provided that the above copyright notice appear in all copies and that
3805b261ecSmrg * both that copyright notice and this permission notice appear in
3905b261ecSmrg * supporting documentation, and that the name of Digital not be
4005b261ecSmrg * used in advertising or publicity pertaining to distribution of the
4105b261ecSmrg * software without specific, written prior permission.
4205b261ecSmrg *
4305b261ecSmrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
4405b261ecSmrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4505b261ecSmrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4605b261ecSmrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4705b261ecSmrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4805b261ecSmrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4905b261ecSmrg * SOFTWARE.
5005b261ecSmrg *
5105b261ecSmrg ******************************************************************/
5205b261ecSmrg
5305b261ecSmrg/* The panoramix components contained the following notice */
5405b261ecSmrg/*****************************************************************
5505b261ecSmrg
5605b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
5705b261ecSmrg
5805b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5905b261ecSmrgof this software and associated documentation files (the "Software"), to deal
6005b261ecSmrgin the Software without restriction, including without limitation the rights
6105b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6205b261ecSmrgcopies of the Software.
6305b261ecSmrg
6405b261ecSmrgThe above copyright notice and this permission notice shall be included in
6505b261ecSmrgall copies or substantial portions of the Software.
6605b261ecSmrg
6705b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6805b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6905b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
7005b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
7105b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
7205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
7305b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7405b261ecSmrg
7505b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
7605b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
7705b261ecSmrgdealings in this Software without prior written authorization from Digital
7805b261ecSmrgEquipment Corporation.
7905b261ecSmrg
8005b261ecSmrg******************************************************************/
8105b261ecSmrg
8205b261ecSmrg
8305b261ecSmrg /*
8405b261ecSmrg  * Aug '86: Susan Angebranndt -- original code
8505b261ecSmrg  * July '87: Adam de Boor -- substantially modified and commented
8605b261ecSmrg  * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
8705b261ecSmrg  *             In particular, much improved code for window mapping and
8805b261ecSmrg  *             circulating.
8905b261ecSmrg  *		Bob Scheifler -- avoid miComputeClips for unmapped windows,
9005b261ecSmrg  *				 valdata changes
9105b261ecSmrg  */
9205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
9305b261ecSmrg#include <dix-config.h>
9405b261ecSmrg#endif
9505b261ecSmrg
9605b261ecSmrg#include    <X11/X.h>
9705b261ecSmrg#include    "scrnintstr.h"
9805b261ecSmrg#include    "validate.h"
9905b261ecSmrg#include    "windowstr.h"
10005b261ecSmrg#include    "mi.h"
10105b261ecSmrg#include    "regionstr.h"
10205b261ecSmrg#include    "mivalidate.h"
10305b261ecSmrg
10405b261ecSmrg#include    "globals.h"
10505b261ecSmrg
10605b261ecSmrg/*
10705b261ecSmrg * Compute the visibility of a shaped window
10805b261ecSmrg */
1094642e01fSmrgint
1106747b715SmrgmiShapedWindowIn (RegionPtr universe, RegionPtr bounding,
1114642e01fSmrg                  BoxPtr rect, int x, int y)
11205b261ecSmrg{
11305b261ecSmrg    BoxRec  	box;
11405b261ecSmrg    BoxPtr	boundBox;
11505b261ecSmrg    int		nbox;
11605b261ecSmrg    Bool	someIn, someOut;
11705b261ecSmrg    int 	t, x1, y1, x2, y2;
11805b261ecSmrg
1196747b715Smrg    nbox = RegionNumRects (bounding);
1206747b715Smrg    boundBox = RegionRects (bounding);
12105b261ecSmrg    someIn = someOut = FALSE;
12205b261ecSmrg    x1 = rect->x1;
12305b261ecSmrg    y1 = rect->y1;
12405b261ecSmrg    x2 = rect->x2;
12505b261ecSmrg    y2 = rect->y2;
12605b261ecSmrg    while (nbox--)
12705b261ecSmrg    {
12805b261ecSmrg	if ((t = boundBox->x1 + x) < x1)
12905b261ecSmrg	    t = x1;
13005b261ecSmrg	box.x1 = t;
13105b261ecSmrg	if ((t = boundBox->y1 + y) < y1)
13205b261ecSmrg	    t = y1;
13305b261ecSmrg	box.y1 = t;
13405b261ecSmrg	if ((t = boundBox->x2 + x) > x2)
13505b261ecSmrg	    t = x2;
13605b261ecSmrg	box.x2 = t;
13705b261ecSmrg	if ((t = boundBox->y2 + y) > y2)
13805b261ecSmrg	    t = y2;
13905b261ecSmrg	box.y2 = t;
14005b261ecSmrg	if (box.x1 > box.x2)
14105b261ecSmrg	    box.x2 = box.x1;
14205b261ecSmrg	if (box.y1 > box.y2)
14305b261ecSmrg	    box.y2 = box.y1;
1446747b715Smrg	switch (RegionContainsRect(universe, &box))
14505b261ecSmrg	{
14605b261ecSmrg	case rgnIN:
14705b261ecSmrg	    if (someOut)
14805b261ecSmrg		return rgnPART;
14905b261ecSmrg	    someIn = TRUE;
15005b261ecSmrg	    break;
15105b261ecSmrg	case rgnOUT:
15205b261ecSmrg	    if (someIn)
15305b261ecSmrg		return rgnPART;
15405b261ecSmrg	    someOut = TRUE;
15505b261ecSmrg	    break;
15605b261ecSmrg	default:
15705b261ecSmrg	    return rgnPART;
15805b261ecSmrg	}
15905b261ecSmrg	boundBox++;
16005b261ecSmrg    }
16105b261ecSmrg    if (someIn)
16205b261ecSmrg	return rgnIN;
16305b261ecSmrg    return rgnOUT;
16405b261ecSmrg}
16505b261ecSmrg
16605b261ecSmrgstatic GetRedirectBorderClipProcPtr	miGetRedirectBorderClipProc;
16705b261ecSmrgstatic SetRedirectBorderClipProcPtr	miSetRedirectBorderClipProc;
16805b261ecSmrg
16905b261ecSmrgvoid
17005b261ecSmrgmiRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip,
17105b261ecSmrg				  GetRedirectBorderClipProcPtr getBorderClip)
17205b261ecSmrg{
17305b261ecSmrg    miSetRedirectBorderClipProc = setBorderClip;
17405b261ecSmrg    miGetRedirectBorderClipProc = getBorderClip;
17505b261ecSmrg}
17605b261ecSmrg
17705b261ecSmrg/*
17805b261ecSmrg * Manual redirected windows are treated as transparent; they do not obscure
17905b261ecSmrg * siblings or parent windows
18005b261ecSmrg */
18105b261ecSmrg
18205b261ecSmrg#ifdef COMPOSITE
18305b261ecSmrg#define TreatAsTransparent(w)	((w)->redirectDraw == RedirectDrawManual)
18405b261ecSmrg#else
18505b261ecSmrg#define TreatAsTransparent(w)	FALSE
18605b261ecSmrg#endif
18705b261ecSmrg
18805b261ecSmrg#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
18905b261ecSmrg				    HasBorder(w) && \
19005b261ecSmrg				    (w)->backgroundState == ParentRelative)
19105b261ecSmrg
19205b261ecSmrg
19305b261ecSmrg/*
19405b261ecSmrg *-----------------------------------------------------------------------
19505b261ecSmrg * miComputeClips --
19605b261ecSmrg *	Recompute the clipList, borderClip, exposed and borderExposed
19705b261ecSmrg *	regions for pParent and its children. Only viewable windows are
19805b261ecSmrg *	taken into account.
19905b261ecSmrg *
20005b261ecSmrg * Results:
20105b261ecSmrg *	None.
20205b261ecSmrg *
20305b261ecSmrg * Side Effects:
20405b261ecSmrg *	clipList, borderClip, exposed and borderExposed are altered.
20505b261ecSmrg *	A VisibilityNotify event may be generated on the parent window.
20605b261ecSmrg *
20705b261ecSmrg *-----------------------------------------------------------------------
20805b261ecSmrg */
20905b261ecSmrgstatic void
21005b261ecSmrgmiComputeClips (
21105b261ecSmrg    WindowPtr	pParent,
21205b261ecSmrg    ScreenPtr	pScreen,
21305b261ecSmrg    RegionPtr	universe,
21405b261ecSmrg    VTKind		kind,
21505b261ecSmrg    RegionPtr		exposed ) /* for intermediate calculations */
21605b261ecSmrg{
21705b261ecSmrg    int			dx,
21805b261ecSmrg			dy;
21905b261ecSmrg    RegionRec		childUniverse;
22005b261ecSmrg    WindowPtr		pChild;
22105b261ecSmrg    int     	  	oldVis, newVis;
22205b261ecSmrg    BoxRec		borderSize;
22305b261ecSmrg    RegionRec		childUnion;
22405b261ecSmrg    Bool		overlap;
22505b261ecSmrg    RegionPtr		borderVisible;
22605b261ecSmrg    Bool		resized;
22705b261ecSmrg    /*
22805b261ecSmrg     * Figure out the new visibility of this window.
22905b261ecSmrg     * The extent of the universe should be the same as the extent of
23005b261ecSmrg     * the borderSize region. If the window is unobscured, this rectangle
23105b261ecSmrg     * will be completely inside the universe (the universe will cover it
23205b261ecSmrg     * completely). If the window is completely obscured, none of the
23305b261ecSmrg     * universe will cover the rectangle.
23405b261ecSmrg     */
23505b261ecSmrg    borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
23605b261ecSmrg    borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
23705b261ecSmrg    dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
23805b261ecSmrg    if (dx > 32767)
23905b261ecSmrg	dx = 32767;
24005b261ecSmrg    borderSize.x2 = dx;
24105b261ecSmrg    dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
24205b261ecSmrg    if (dy > 32767)
24305b261ecSmrg	dy = 32767;
24405b261ecSmrg    borderSize.y2 = dy;
24505b261ecSmrg
24605b261ecSmrg#ifdef COMPOSITE
24705b261ecSmrg    /*
24805b261ecSmrg     * In redirected drawing case, reset universe to borderSize
24905b261ecSmrg     */
25005b261ecSmrg    if (pParent->redirectDraw != RedirectDrawNone)
25105b261ecSmrg    {
25205b261ecSmrg	if (miSetRedirectBorderClipProc)
2534642e01fSmrg	{
2544642e01fSmrg	    if (TreatAsTransparent (pParent))
2556747b715Smrg		RegionEmpty(universe);
25605b261ecSmrg	    (*miSetRedirectBorderClipProc) (pParent, universe);
2574642e01fSmrg	}
2586747b715Smrg	RegionCopy(universe, &pParent->borderSize);
25905b261ecSmrg    }
26005b261ecSmrg#endif
26105b261ecSmrg
26205b261ecSmrg    oldVis = pParent->visibility;
2636747b715Smrg    switch (RegionContainsRect(universe, &borderSize))
26405b261ecSmrg    {
26505b261ecSmrg	case rgnIN:
26605b261ecSmrg	    newVis = VisibilityUnobscured;
26705b261ecSmrg	    break;
26805b261ecSmrg	case rgnPART:
26905b261ecSmrg	    newVis = VisibilityPartiallyObscured;
27005b261ecSmrg	    {
27105b261ecSmrg		RegionPtr   pBounding;
27205b261ecSmrg
27305b261ecSmrg		if ((pBounding = wBoundingShape (pParent)))
27405b261ecSmrg		{
2756747b715Smrg		    switch (miShapedWindowIn (universe, pBounding,
27605b261ecSmrg					      &borderSize,
27705b261ecSmrg					      pParent->drawable.x,
27805b261ecSmrg 					      pParent->drawable.y))
27905b261ecSmrg		    {
28005b261ecSmrg		    case rgnIN:
28105b261ecSmrg			newVis = VisibilityUnobscured;
28205b261ecSmrg			break;
28305b261ecSmrg		    case rgnOUT:
28405b261ecSmrg			newVis = VisibilityFullyObscured;
28505b261ecSmrg			break;
28605b261ecSmrg		    }
28705b261ecSmrg		}
28805b261ecSmrg	    }
28905b261ecSmrg	    break;
29005b261ecSmrg	default:
29105b261ecSmrg	    newVis = VisibilityFullyObscured;
29205b261ecSmrg	    break;
29305b261ecSmrg    }
29405b261ecSmrg    pParent->visibility = newVis;
29505b261ecSmrg    if (oldVis != newVis &&
29605b261ecSmrg	((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
29705b261ecSmrg	SendVisibilityNotify(pParent);
29805b261ecSmrg
29905b261ecSmrg    dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
30005b261ecSmrg    dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
30105b261ecSmrg
30205b261ecSmrg    /*
30305b261ecSmrg     * avoid computations when dealing with simple operations
30405b261ecSmrg     */
30505b261ecSmrg
30605b261ecSmrg    switch (kind) {
30705b261ecSmrg    case VTMap:
30805b261ecSmrg    case VTStack:
30905b261ecSmrg    case VTUnmap:
31005b261ecSmrg	break;
31105b261ecSmrg    case VTMove:
31205b261ecSmrg	if ((oldVis == newVis) &&
31305b261ecSmrg	    ((oldVis == VisibilityFullyObscured) ||
31405b261ecSmrg	     (oldVis == VisibilityUnobscured)))
31505b261ecSmrg	{
31605b261ecSmrg	    pChild = pParent;
31705b261ecSmrg	    while (1)
31805b261ecSmrg	    {
31905b261ecSmrg		if (pChild->viewable)
32005b261ecSmrg		{
32105b261ecSmrg		    if (pChild->visibility != VisibilityFullyObscured)
32205b261ecSmrg		    {
3236747b715Smrg			RegionTranslate(&pChild->borderClip,
32405b261ecSmrg						      dx, dy);
3256747b715Smrg			RegionTranslate(&pChild->clipList,
32605b261ecSmrg						      dx, dy);
32705b261ecSmrg			pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
32805b261ecSmrg			if (pScreen->ClipNotify)
32905b261ecSmrg			    (* pScreen->ClipNotify) (pChild, dx, dy);
33005b261ecSmrg
33105b261ecSmrg		    }
33205b261ecSmrg		    if (pChild->valdata)
33305b261ecSmrg		    {
3346747b715Smrg			RegionNull(&pChild->valdata->after.borderExposed);
33505b261ecSmrg			if (HasParentRelativeBorder(pChild))
33605b261ecSmrg			{
3376747b715Smrg			    RegionSubtract(&pChild->valdata->after.borderExposed,
3386747b715Smrg					   &pChild->borderClip,
3396747b715Smrg					   &pChild->winSize);
34005b261ecSmrg			}
3416747b715Smrg			RegionNull(&pChild->valdata->after.exposed);
34205b261ecSmrg		    }
34305b261ecSmrg		    if (pChild->firstChild)
34405b261ecSmrg		    {
34505b261ecSmrg			pChild = pChild->firstChild;
34605b261ecSmrg			continue;
34705b261ecSmrg		    }
34805b261ecSmrg		}
34905b261ecSmrg		while (!pChild->nextSib && (pChild != pParent))
35005b261ecSmrg		    pChild = pChild->parent;
35105b261ecSmrg		if (pChild == pParent)
35205b261ecSmrg		    break;
35305b261ecSmrg		pChild = pChild->nextSib;
35405b261ecSmrg	    }
35505b261ecSmrg	    return;
35605b261ecSmrg	}
35705b261ecSmrg	/* fall through */
35805b261ecSmrg    default:
35905b261ecSmrg    	/*
36005b261ecSmrg     	 * To calculate exposures correctly, we have to translate the old
36105b261ecSmrg     	 * borderClip and clipList regions to the window's new location so there
36205b261ecSmrg     	 * is a correspondence between pieces of the new and old clipping regions.
36305b261ecSmrg     	 */
36405b261ecSmrg    	if (dx || dy)
36505b261ecSmrg    	{
36605b261ecSmrg	    /*
36705b261ecSmrg	     * We translate the old clipList because that will be exposed or copied
36805b261ecSmrg	     * if gravity is right.
36905b261ecSmrg	     */
3706747b715Smrg	    RegionTranslate(&pParent->borderClip, dx, dy);
3716747b715Smrg	    RegionTranslate(&pParent->clipList, dx, dy);
37205b261ecSmrg    	}
37305b261ecSmrg	break;
37405b261ecSmrg    case VTBroken:
3756747b715Smrg	RegionEmpty(&pParent->borderClip);
3766747b715Smrg	RegionEmpty(&pParent->clipList);
37705b261ecSmrg	break;
37805b261ecSmrg    }
37905b261ecSmrg
38005b261ecSmrg    borderVisible = pParent->valdata->before.borderVisible;
38105b261ecSmrg    resized = pParent->valdata->before.resized;
3826747b715Smrg    RegionNull(&pParent->valdata->after.borderExposed);
3836747b715Smrg    RegionNull(&pParent->valdata->after.exposed);
38405b261ecSmrg
38505b261ecSmrg    /*
38605b261ecSmrg     * Since the borderClip must not be clipped by the children, we do
38705b261ecSmrg     * the border exposure first...
38805b261ecSmrg     *
38905b261ecSmrg     * 'universe' is the window's borderClip. To figure the exposures, remove
39005b261ecSmrg     * the area that used to be exposed from the new.
39105b261ecSmrg     * This leaves a region of pieces that weren't exposed before.
39205b261ecSmrg     */
39305b261ecSmrg
39405b261ecSmrg    if (HasBorder (pParent))
39505b261ecSmrg    {
39605b261ecSmrg    	if (borderVisible)
39705b261ecSmrg    	{
39805b261ecSmrg	    /*
39905b261ecSmrg	     * when the border changes shape, the old visible portions
40005b261ecSmrg	     * of the border will be saved by DIX in borderVisible --
40105b261ecSmrg	     * use that region and destroy it
40205b261ecSmrg	     */
4036747b715Smrg	    RegionSubtract(exposed, universe, borderVisible);
4046747b715Smrg	    RegionDestroy(borderVisible);
40505b261ecSmrg    	}
40605b261ecSmrg    	else
40705b261ecSmrg    	{
4086747b715Smrg	    RegionSubtract(exposed, universe, &pParent->borderClip);
40905b261ecSmrg    	}
41005b261ecSmrg	if (HasParentRelativeBorder(pParent) && (dx || dy))
4116747b715Smrg	    RegionSubtract(&pParent->valdata->after.borderExposed,
41205b261ecSmrg				  universe,
41305b261ecSmrg				  &pParent->winSize);
41405b261ecSmrg	else
4156747b715Smrg	    RegionSubtract(&pParent->valdata->after.borderExposed,
41605b261ecSmrg			       exposed, &pParent->winSize);
41705b261ecSmrg
4186747b715Smrg	RegionCopy(&pParent->borderClip, universe);
41905b261ecSmrg
42005b261ecSmrg    	/*
42105b261ecSmrg     	 * To get the right clipList for the parent, and to make doubly sure
42205b261ecSmrg     	 * that no child overlaps the parent's border, we remove the parent's
42305b261ecSmrg     	 * border from the universe before proceeding.
42405b261ecSmrg     	 */
42505b261ecSmrg
4266747b715Smrg	RegionIntersect(universe, universe, &pParent->winSize);
42705b261ecSmrg    }
42805b261ecSmrg    else
4296747b715Smrg	RegionCopy(&pParent->borderClip, universe);
43005b261ecSmrg
43105b261ecSmrg    if ((pChild = pParent->firstChild) && pParent->mapped)
43205b261ecSmrg    {
4336747b715Smrg	RegionNull(&childUniverse);
4346747b715Smrg	RegionNull(&childUnion);
43505b261ecSmrg	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
43605b261ecSmrg	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
43705b261ecSmrg	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
43805b261ecSmrg	{
43905b261ecSmrg	    for (; pChild; pChild = pChild->nextSib)
44005b261ecSmrg	    {
44105b261ecSmrg		if (pChild->viewable && !TreatAsTransparent(pChild))
4426747b715Smrg		    RegionAppend(&childUnion, &pChild->borderSize);
44305b261ecSmrg	    }
44405b261ecSmrg	}
44505b261ecSmrg	else
44605b261ecSmrg	{
44705b261ecSmrg	    for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
44805b261ecSmrg	    {
44905b261ecSmrg		if (pChild->viewable && !TreatAsTransparent(pChild))
4506747b715Smrg		    RegionAppend(&childUnion, &pChild->borderSize);
45105b261ecSmrg	    }
45205b261ecSmrg	}
4536747b715Smrg	RegionValidate(&childUnion, &overlap);
45405b261ecSmrg
45505b261ecSmrg	for (pChild = pParent->firstChild;
45605b261ecSmrg	     pChild;
45705b261ecSmrg	     pChild = pChild->nextSib)
45805b261ecSmrg 	{
45905b261ecSmrg	    if (pChild->viewable) {
46005b261ecSmrg		/*
46105b261ecSmrg		 * If the child is viewable, we want to remove its extents
46205b261ecSmrg		 * from the current universe, but we only re-clip it if
46305b261ecSmrg		 * it's been marked.
46405b261ecSmrg		 */
46505b261ecSmrg		if (pChild->valdata) {
46605b261ecSmrg		    /*
46705b261ecSmrg		     * Figure out the new universe from the child's
46805b261ecSmrg		     * perspective and recurse.
46905b261ecSmrg		     */
4706747b715Smrg		    RegionIntersect(&childUniverse,
47105b261ecSmrg					    universe,
47205b261ecSmrg					    &pChild->borderSize);
47305b261ecSmrg		    miComputeClips (pChild, pScreen, &childUniverse, kind,
47405b261ecSmrg				    exposed);
47505b261ecSmrg		}
47605b261ecSmrg		/*
47705b261ecSmrg		 * Once the child has been processed, we remove its extents
47805b261ecSmrg		 * from the current universe, thus denying its space to any
47905b261ecSmrg		 * other sibling.
48005b261ecSmrg		 */
48105b261ecSmrg		if (overlap && !TreatAsTransparent (pChild))
4826747b715Smrg		    RegionSubtract(universe, universe,
48305b261ecSmrg					  &pChild->borderSize);
48405b261ecSmrg	    }
48505b261ecSmrg	}
48605b261ecSmrg	if (!overlap)
4876747b715Smrg	    RegionSubtract(universe, universe, &childUnion);
4886747b715Smrg	RegionUninit(&childUnion);
4896747b715Smrg	RegionUninit(&childUniverse);
49005b261ecSmrg    } /* if any children */
49105b261ecSmrg
49205b261ecSmrg    /*
49305b261ecSmrg     * 'universe' now contains the new clipList for the parent window.
49405b261ecSmrg     *
49505b261ecSmrg     * To figure the exposure of the window we subtract the old clip from the
49605b261ecSmrg     * new, just as for the border.
49705b261ecSmrg     */
49805b261ecSmrg
49905b261ecSmrg    if (oldVis == VisibilityFullyObscured ||
50005b261ecSmrg	oldVis == VisibilityNotViewable)
50105b261ecSmrg    {
5026747b715Smrg	RegionCopy(&pParent->valdata->after.exposed, universe);
50305b261ecSmrg    }
50405b261ecSmrg    else if (newVis != VisibilityFullyObscured &&
50505b261ecSmrg	     newVis != VisibilityNotViewable)
50605b261ecSmrg    {
5076747b715Smrg	RegionSubtract(&pParent->valdata->after.exposed,
50805b261ecSmrg			       universe, &pParent->clipList);
50905b261ecSmrg    }
51005b261ecSmrg
51105b261ecSmrg    /* HACK ALERT - copying contents of regions, instead of regions */
51205b261ecSmrg    {
51305b261ecSmrg	RegionRec   tmp;
51405b261ecSmrg
51505b261ecSmrg	tmp = pParent->clipList;
51605b261ecSmrg	pParent->clipList = *universe;
51705b261ecSmrg	*universe = tmp;
51805b261ecSmrg    }
51905b261ecSmrg
52005b261ecSmrg#ifdef NOTDEF
5216747b715Smrg    RegionCopy(&pParent->clipList, universe);
52205b261ecSmrg#endif
52305b261ecSmrg
52405b261ecSmrg    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
52505b261ecSmrg
52605b261ecSmrg    if (pScreen->ClipNotify)
52705b261ecSmrg	(* pScreen->ClipNotify) (pParent, dx, dy);
52805b261ecSmrg}
52905b261ecSmrg
53005b261ecSmrgstatic void
53105b261ecSmrgmiTreeObscured(
53205b261ecSmrg    WindowPtr pParent )
53305b261ecSmrg{
53405b261ecSmrg    WindowPtr 	pChild;
53505b261ecSmrg    int    	oldVis;
53605b261ecSmrg
53705b261ecSmrg    pChild = pParent;
53805b261ecSmrg    while (1)
53905b261ecSmrg    {
54005b261ecSmrg	if (pChild->viewable)
54105b261ecSmrg	{
54205b261ecSmrg	    oldVis = pChild->visibility;
54305b261ecSmrg	    if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
54405b261ecSmrg		((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
54505b261ecSmrg		SendVisibilityNotify(pChild);
54605b261ecSmrg	    if (pChild->firstChild)
54705b261ecSmrg	    {
54805b261ecSmrg		pChild = pChild->firstChild;
54905b261ecSmrg		continue;
55005b261ecSmrg	    }
55105b261ecSmrg	}
55205b261ecSmrg	while (!pChild->nextSib && (pChild != pParent))
55305b261ecSmrg	    pChild = pChild->parent;
55405b261ecSmrg	if (pChild == pParent)
55505b261ecSmrg	    break;
55605b261ecSmrg	pChild = pChild->nextSib;
55705b261ecSmrg    }
55805b261ecSmrg}
55905b261ecSmrg
56005b261ecSmrg/*
56105b261ecSmrg *-----------------------------------------------------------------------
56205b261ecSmrg * miValidateTree --
56305b261ecSmrg *	Recomputes the clip list for pParent and all its inferiors.
56405b261ecSmrg *
56505b261ecSmrg * Results:
56605b261ecSmrg *	Always returns 1.
56705b261ecSmrg *
56805b261ecSmrg * Side Effects:
56905b261ecSmrg *	The clipList, borderClip, exposed, and borderExposed regions for
57005b261ecSmrg *	each marked window are altered.
57105b261ecSmrg *
57205b261ecSmrg * Notes:
57305b261ecSmrg *	This routine assumes that all affected windows have been marked
57405b261ecSmrg *	(valdata created) and their winSize and borderSize regions
57505b261ecSmrg *	adjusted to correspond to their new positions. The borderClip and
57605b261ecSmrg *	clipList regions should not have been touched.
57705b261ecSmrg *
57805b261ecSmrg *	The top-most level is treated differently from all lower levels
57905b261ecSmrg *	because pParent is unchanged. For the top level, we merge the
58005b261ecSmrg *	regions taken up by the marked children back into the clipList
58105b261ecSmrg *	for pParent, thus forming a region from which the marked children
58205b261ecSmrg *	can claim their areas. For lower levels, where the old clipList
58305b261ecSmrg *	and borderClip are invalid, we can't do this and have to do the
58405b261ecSmrg *	extra operations done in miComputeClips, but this is much faster
58505b261ecSmrg *	e.g. when only one child has moved...
58605b261ecSmrg *
58705b261ecSmrg *-----------------------------------------------------------------------
58805b261ecSmrg */
58905b261ecSmrg/*ARGSUSED*/
59005b261ecSmrgint
5914642e01fSmrgmiValidateTree (
5924642e01fSmrg    WindowPtr		pParent,    /* Parent to validate */
5934642e01fSmrg    WindowPtr		pChild,     /* First child of pParent that was
59405b261ecSmrg				     * affected */
5954642e01fSmrg    VTKind		kind        /* What kind of configuration caused call */
5964642e01fSmrg    )
59705b261ecSmrg{
59805b261ecSmrg    RegionRec	  	totalClip;  /* Total clipping region available to
59905b261ecSmrg				     * the marked children. pParent's clipList
60005b261ecSmrg				     * merged with the borderClips of all
60105b261ecSmrg				     * the marked children. */
60205b261ecSmrg    RegionRec	  	childClip;  /* The new borderClip for the current
60305b261ecSmrg				     * child */
60405b261ecSmrg    RegionRec		childUnion; /* the space covered by borderSize for
60505b261ecSmrg				     * all marked children */
60605b261ecSmrg    RegionRec		exposed;    /* For intermediate calculations */
60705b261ecSmrg    ScreenPtr		pScreen;
60805b261ecSmrg    WindowPtr		pWin;
60905b261ecSmrg    Bool		overlap;
61005b261ecSmrg    int			viewvals;
61105b261ecSmrg    Bool		forward;
61205b261ecSmrg
61305b261ecSmrg    pScreen = pParent->drawable.pScreen;
61405b261ecSmrg    if (pChild == NullWindow)
61505b261ecSmrg	pChild = pParent->firstChild;
61605b261ecSmrg
6176747b715Smrg    RegionNull(&childClip);
6186747b715Smrg    RegionNull(&exposed);
61905b261ecSmrg
62005b261ecSmrg    /*
62105b261ecSmrg     * compute the area of the parent window occupied
62205b261ecSmrg     * by the marked children + the parent itself.  This
62305b261ecSmrg     * is the area which can be divied up among the marked
62405b261ecSmrg     * children in their new configuration.
62505b261ecSmrg     */
6266747b715Smrg    RegionNull(&totalClip);
62705b261ecSmrg    viewvals = 0;
6286747b715Smrg    if (RegionBroken(&pParent->clipList) &&
6296747b715Smrg	!RegionBroken(&pParent->borderClip))
63005b261ecSmrg    {
63105b261ecSmrg	kind = VTBroken;
63205b261ecSmrg	/*
63305b261ecSmrg	 * When rebuilding clip lists after out of memory,
63405b261ecSmrg	 * assume everything is busted.
63505b261ecSmrg	 */
63605b261ecSmrg	forward = TRUE;
6376747b715Smrg	RegionCopy(&totalClip, &pParent->borderClip);
6386747b715Smrg	RegionIntersect(&totalClip, &totalClip, &pParent->winSize);
63905b261ecSmrg
64005b261ecSmrg	for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib)
64105b261ecSmrg	{
64205b261ecSmrg	    if (pWin->viewable && !TreatAsTransparent (pWin))
6436747b715Smrg		RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
64405b261ecSmrg	}
64505b261ecSmrg	for (pWin = pChild; pWin; pWin = pWin->nextSib)
64605b261ecSmrg	    if (pWin->valdata && pWin->viewable)
64705b261ecSmrg		viewvals++;
64805b261ecSmrg
6496747b715Smrg	RegionEmpty(&pParent->clipList);
65005b261ecSmrg    }
65105b261ecSmrg    else
65205b261ecSmrg    {
65305b261ecSmrg	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
65405b261ecSmrg	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
65505b261ecSmrg	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
65605b261ecSmrg	{
65705b261ecSmrg	    forward = TRUE;
65805b261ecSmrg	    for (pWin = pChild; pWin; pWin = pWin->nextSib)
65905b261ecSmrg	    {
66005b261ecSmrg		if (pWin->valdata)
66105b261ecSmrg		{
66205b261ecSmrg		    RegionPtr	pBorderClip = &pWin->borderClip;
66305b261ecSmrg#ifdef COMPOSITE
66405b261ecSmrg		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
66505b261ecSmrg			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
66605b261ecSmrg#endif
6676747b715Smrg		    RegionAppend(&totalClip, pBorderClip );
66805b261ecSmrg		    if (pWin->viewable)
66905b261ecSmrg			viewvals++;
67005b261ecSmrg		}
67105b261ecSmrg	    }
67205b261ecSmrg	}
67305b261ecSmrg	else
67405b261ecSmrg	{
67505b261ecSmrg	    forward = FALSE;
67605b261ecSmrg	    pWin = pParent->lastChild;
67705b261ecSmrg	    while (1)
67805b261ecSmrg	    {
67905b261ecSmrg		if (pWin->valdata)
68005b261ecSmrg		{
68105b261ecSmrg		    RegionPtr	pBorderClip = &pWin->borderClip;
68205b261ecSmrg#ifdef COMPOSITE
68305b261ecSmrg		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
68405b261ecSmrg			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
68505b261ecSmrg#endif
6866747b715Smrg		    RegionAppend(&totalClip, pBorderClip );
68705b261ecSmrg		    if (pWin->viewable)
68805b261ecSmrg			viewvals++;
68905b261ecSmrg		}
69005b261ecSmrg		if (pWin == pChild)
69105b261ecSmrg		    break;
69205b261ecSmrg		pWin = pWin->prevSib;
69305b261ecSmrg	    }
69405b261ecSmrg	}
6956747b715Smrg	RegionValidate(&totalClip, &overlap);
69605b261ecSmrg    }
69705b261ecSmrg
69805b261ecSmrg    /*
69905b261ecSmrg     * Now go through the children of the root and figure their new
70005b261ecSmrg     * borderClips from the totalClip, passing that off to miComputeClips
70105b261ecSmrg     * to handle recursively. Once that's done, we remove the child
70205b261ecSmrg     * from the totalClip to clip any siblings below it.
70305b261ecSmrg     */
70405b261ecSmrg
70505b261ecSmrg    overlap = TRUE;
70605b261ecSmrg    if (kind != VTStack)
70705b261ecSmrg    {
7086747b715Smrg	RegionUnion(&totalClip, &totalClip, &pParent->clipList);
70905b261ecSmrg	if (viewvals > 1)
71005b261ecSmrg	{
71105b261ecSmrg	    /*
71205b261ecSmrg	     * precompute childUnion to discover whether any of them
71305b261ecSmrg	     * overlap.  This seems redundant, but performance studies
71405b261ecSmrg	     * have demonstrated that the cost of this loop is
71505b261ecSmrg	     * lower than the cost of multiple Subtracts in the
71605b261ecSmrg	     * loop below.
71705b261ecSmrg	     */
7186747b715Smrg	    RegionNull(&childUnion);
71905b261ecSmrg	    if (forward)
72005b261ecSmrg	    {
72105b261ecSmrg		for (pWin = pChild; pWin; pWin = pWin->nextSib)
72205b261ecSmrg		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
7236747b715Smrg			RegionAppend(&childUnion,
72405b261ecSmrg						   &pWin->borderSize);
72505b261ecSmrg	    }
72605b261ecSmrg	    else
72705b261ecSmrg	    {
72805b261ecSmrg		pWin = pParent->lastChild;
72905b261ecSmrg		while (1)
73005b261ecSmrg		{
73105b261ecSmrg		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
7326747b715Smrg			RegionAppend(&childUnion,
73305b261ecSmrg						   &pWin->borderSize);
73405b261ecSmrg		    if (pWin == pChild)
73505b261ecSmrg			break;
73605b261ecSmrg		    pWin = pWin->prevSib;
73705b261ecSmrg		}
73805b261ecSmrg	    }
7396747b715Smrg	    RegionValidate(&childUnion, &overlap);
74005b261ecSmrg	    if (overlap)
7416747b715Smrg		RegionUninit(&childUnion);
74205b261ecSmrg	}
74305b261ecSmrg    }
74405b261ecSmrg
74505b261ecSmrg    for (pWin = pChild;
74605b261ecSmrg	 pWin != NullWindow;
74705b261ecSmrg	 pWin = pWin->nextSib)
74805b261ecSmrg    {
74905b261ecSmrg	if (pWin->viewable) {
75005b261ecSmrg	    if (pWin->valdata) {
7516747b715Smrg		RegionIntersect(&childClip,
75205b261ecSmrg					&totalClip,
75305b261ecSmrg 					&pWin->borderSize);
75405b261ecSmrg		miComputeClips (pWin, pScreen, &childClip, kind, &exposed);
75505b261ecSmrg		if (overlap && !TreatAsTransparent (pWin))
75605b261ecSmrg		{
7576747b715Smrg		    RegionSubtract(&totalClip,
75805b261ecSmrg				       	   &totalClip,
75905b261ecSmrg				       	   &pWin->borderSize);
76005b261ecSmrg		}
76105b261ecSmrg	    } else if (pWin->visibility == VisibilityNotViewable) {
76205b261ecSmrg		miTreeObscured(pWin);
76305b261ecSmrg	    }
76405b261ecSmrg	} else {
76505b261ecSmrg	    if (pWin->valdata) {
7666747b715Smrg		RegionEmpty(&pWin->clipList);
76705b261ecSmrg		if (pScreen->ClipNotify)
76805b261ecSmrg		    (* pScreen->ClipNotify) (pWin, 0, 0);
7696747b715Smrg		RegionEmpty(&pWin->borderClip);
7706747b715Smrg		pWin->valdata = NULL;
77105b261ecSmrg	    }
77205b261ecSmrg	}
77305b261ecSmrg    }
77405b261ecSmrg
7756747b715Smrg    RegionUninit(&childClip);
77605b261ecSmrg    if (!overlap)
77705b261ecSmrg    {
7786747b715Smrg	RegionSubtract(&totalClip, &totalClip, &childUnion);
7796747b715Smrg	RegionUninit(&childUnion);
78005b261ecSmrg    }
78105b261ecSmrg
7826747b715Smrg    RegionNull(&pParent->valdata->after.exposed);
7836747b715Smrg    RegionNull(&pParent->valdata->after.borderExposed);
78405b261ecSmrg
78505b261ecSmrg    /*
78605b261ecSmrg     * each case below is responsible for updating the
78705b261ecSmrg     * clipList and serial number for the parent window
78805b261ecSmrg     */
78905b261ecSmrg
79005b261ecSmrg    switch (kind) {
79105b261ecSmrg    case VTStack:
79205b261ecSmrg	break;
79305b261ecSmrg    default:
79405b261ecSmrg	/*
79505b261ecSmrg	 * totalClip contains the new clipList for the parent. Figure out
79605b261ecSmrg	 * exposures and obscures as per miComputeClips and reset the parent's
79705b261ecSmrg	 * clipList.
79805b261ecSmrg	 */
7996747b715Smrg	RegionSubtract(&pParent->valdata->after.exposed,
80005b261ecSmrg			       &totalClip, &pParent->clipList);
80105b261ecSmrg	/* fall through */
80205b261ecSmrg    case VTMap:
8036747b715Smrg	RegionCopy(&pParent->clipList, &totalClip);
80405b261ecSmrg	pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
80505b261ecSmrg	break;
80605b261ecSmrg    }
80705b261ecSmrg
8086747b715Smrg    RegionUninit(&totalClip);
8096747b715Smrg    RegionUninit(&exposed);
81005b261ecSmrg    if (pScreen->ClipNotify)
81105b261ecSmrg	(*pScreen->ClipNotify) (pParent, 0, 0);
8126747b715Smrg    return 1;
81305b261ecSmrg}
814