mivaltree.c revision 4642e01f
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
1104642e01fSmrgmiShapedWindowIn (ScreenPtr pScreen, 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
11905b261ecSmrg    nbox = REGION_NUM_RECTS (bounding);
12005b261ecSmrg    boundBox = REGION_RECTS (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;
14405b261ecSmrg	switch (RECT_IN_REGION(pScreen, 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))
2554642e01fSmrg		REGION_EMPTY (pScreen, universe);
25605b261ecSmrg	    (*miSetRedirectBorderClipProc) (pParent, universe);
2574642e01fSmrg	}
25805b261ecSmrg	REGION_COPY(pScreen, universe, &pParent->borderSize);
25905b261ecSmrg    }
26005b261ecSmrg#endif
26105b261ecSmrg
26205b261ecSmrg    oldVis = pParent->visibility;
26305b261ecSmrg    switch (RECT_IN_REGION( pScreen, 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		{
27505b261ecSmrg		    switch (miShapedWindowIn (pScreen, 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		    {
32305b261ecSmrg			REGION_TRANSLATE( pScreen, &pChild->borderClip,
32405b261ecSmrg						      dx, dy);
32505b261ecSmrg			REGION_TRANSLATE( pScreen, &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		    {
33405b261ecSmrg			REGION_NULL(pScreen,
33505b261ecSmrg				    &pChild->valdata->after.borderExposed);
33605b261ecSmrg			if (HasParentRelativeBorder(pChild))
33705b261ecSmrg			{
33805b261ecSmrg			    REGION_SUBTRACT(pScreen,
33905b261ecSmrg					 &pChild->valdata->after.borderExposed,
34005b261ecSmrg					 &pChild->borderClip,
34105b261ecSmrg					 &pChild->winSize);
34205b261ecSmrg			}
34305b261ecSmrg			REGION_NULL(pScreen, &pChild->valdata->after.exposed);
34405b261ecSmrg		    }
34505b261ecSmrg		    if (pChild->firstChild)
34605b261ecSmrg		    {
34705b261ecSmrg			pChild = pChild->firstChild;
34805b261ecSmrg			continue;
34905b261ecSmrg		    }
35005b261ecSmrg		}
35105b261ecSmrg		while (!pChild->nextSib && (pChild != pParent))
35205b261ecSmrg		    pChild = pChild->parent;
35305b261ecSmrg		if (pChild == pParent)
35405b261ecSmrg		    break;
35505b261ecSmrg		pChild = pChild->nextSib;
35605b261ecSmrg	    }
35705b261ecSmrg	    return;
35805b261ecSmrg	}
35905b261ecSmrg	/* fall through */
36005b261ecSmrg    default:
36105b261ecSmrg    	/*
36205b261ecSmrg     	 * To calculate exposures correctly, we have to translate the old
36305b261ecSmrg     	 * borderClip and clipList regions to the window's new location so there
36405b261ecSmrg     	 * is a correspondence between pieces of the new and old clipping regions.
36505b261ecSmrg     	 */
36605b261ecSmrg    	if (dx || dy)
36705b261ecSmrg    	{
36805b261ecSmrg	    /*
36905b261ecSmrg	     * We translate the old clipList because that will be exposed or copied
37005b261ecSmrg	     * if gravity is right.
37105b261ecSmrg	     */
37205b261ecSmrg	    REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy);
37305b261ecSmrg	    REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy);
37405b261ecSmrg    	}
37505b261ecSmrg	break;
37605b261ecSmrg    case VTBroken:
37705b261ecSmrg	REGION_EMPTY (pScreen, &pParent->borderClip);
37805b261ecSmrg	REGION_EMPTY (pScreen, &pParent->clipList);
37905b261ecSmrg	break;
38005b261ecSmrg    }
38105b261ecSmrg
38205b261ecSmrg    borderVisible = pParent->valdata->before.borderVisible;
38305b261ecSmrg    resized = pParent->valdata->before.resized;
38405b261ecSmrg    REGION_NULL(pScreen, &pParent->valdata->after.borderExposed);
38505b261ecSmrg    REGION_NULL(pScreen, &pParent->valdata->after.exposed);
38605b261ecSmrg
38705b261ecSmrg    /*
38805b261ecSmrg     * Since the borderClip must not be clipped by the children, we do
38905b261ecSmrg     * the border exposure first...
39005b261ecSmrg     *
39105b261ecSmrg     * 'universe' is the window's borderClip. To figure the exposures, remove
39205b261ecSmrg     * the area that used to be exposed from the new.
39305b261ecSmrg     * This leaves a region of pieces that weren't exposed before.
39405b261ecSmrg     */
39505b261ecSmrg
39605b261ecSmrg    if (HasBorder (pParent))
39705b261ecSmrg    {
39805b261ecSmrg    	if (borderVisible)
39905b261ecSmrg    	{
40005b261ecSmrg	    /*
40105b261ecSmrg	     * when the border changes shape, the old visible portions
40205b261ecSmrg	     * of the border will be saved by DIX in borderVisible --
40305b261ecSmrg	     * use that region and destroy it
40405b261ecSmrg	     */
40505b261ecSmrg	    REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
40605b261ecSmrg	    REGION_DESTROY( pScreen, borderVisible);
40705b261ecSmrg    	}
40805b261ecSmrg    	else
40905b261ecSmrg    	{
41005b261ecSmrg	    REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip);
41105b261ecSmrg    	}
41205b261ecSmrg	if (HasParentRelativeBorder(pParent) && (dx || dy))
41305b261ecSmrg	    REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
41405b261ecSmrg				  universe,
41505b261ecSmrg				  &pParent->winSize);
41605b261ecSmrg	else
41705b261ecSmrg	    REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
41805b261ecSmrg			       exposed, &pParent->winSize);
41905b261ecSmrg
42005b261ecSmrg    	REGION_COPY( pScreen, &pParent->borderClip, universe);
42105b261ecSmrg
42205b261ecSmrg    	/*
42305b261ecSmrg     	 * To get the right clipList for the parent, and to make doubly sure
42405b261ecSmrg     	 * that no child overlaps the parent's border, we remove the parent's
42505b261ecSmrg     	 * border from the universe before proceeding.
42605b261ecSmrg     	 */
42705b261ecSmrg
42805b261ecSmrg    	REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
42905b261ecSmrg    }
43005b261ecSmrg    else
43105b261ecSmrg    	REGION_COPY( pScreen, &pParent->borderClip, universe);
43205b261ecSmrg
43305b261ecSmrg    if ((pChild = pParent->firstChild) && pParent->mapped)
43405b261ecSmrg    {
43505b261ecSmrg	REGION_NULL(pScreen, &childUniverse);
43605b261ecSmrg	REGION_NULL(pScreen, &childUnion);
43705b261ecSmrg	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
43805b261ecSmrg	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
43905b261ecSmrg	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
44005b261ecSmrg	{
44105b261ecSmrg	    for (; pChild; pChild = pChild->nextSib)
44205b261ecSmrg	    {
44305b261ecSmrg		if (pChild->viewable && !TreatAsTransparent(pChild))
44405b261ecSmrg		    REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
44505b261ecSmrg	    }
44605b261ecSmrg	}
44705b261ecSmrg	else
44805b261ecSmrg	{
44905b261ecSmrg	    for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
45005b261ecSmrg	    {
45105b261ecSmrg		if (pChild->viewable && !TreatAsTransparent(pChild))
45205b261ecSmrg		    REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
45305b261ecSmrg	    }
45405b261ecSmrg	}
45505b261ecSmrg	REGION_VALIDATE( pScreen, &childUnion, &overlap);
45605b261ecSmrg
45705b261ecSmrg	for (pChild = pParent->firstChild;
45805b261ecSmrg	     pChild;
45905b261ecSmrg	     pChild = pChild->nextSib)
46005b261ecSmrg 	{
46105b261ecSmrg	    if (pChild->viewable) {
46205b261ecSmrg		/*
46305b261ecSmrg		 * If the child is viewable, we want to remove its extents
46405b261ecSmrg		 * from the current universe, but we only re-clip it if
46505b261ecSmrg		 * it's been marked.
46605b261ecSmrg		 */
46705b261ecSmrg		if (pChild->valdata) {
46805b261ecSmrg		    /*
46905b261ecSmrg		     * Figure out the new universe from the child's
47005b261ecSmrg		     * perspective and recurse.
47105b261ecSmrg		     */
47205b261ecSmrg		    REGION_INTERSECT( pScreen, &childUniverse,
47305b261ecSmrg					    universe,
47405b261ecSmrg					    &pChild->borderSize);
47505b261ecSmrg		    miComputeClips (pChild, pScreen, &childUniverse, kind,
47605b261ecSmrg				    exposed);
47705b261ecSmrg		}
47805b261ecSmrg		/*
47905b261ecSmrg		 * Once the child has been processed, we remove its extents
48005b261ecSmrg		 * from the current universe, thus denying its space to any
48105b261ecSmrg		 * other sibling.
48205b261ecSmrg		 */
48305b261ecSmrg		if (overlap && !TreatAsTransparent (pChild))
48405b261ecSmrg		    REGION_SUBTRACT( pScreen, universe, universe,
48505b261ecSmrg					  &pChild->borderSize);
48605b261ecSmrg	    }
48705b261ecSmrg	}
48805b261ecSmrg	if (!overlap)
48905b261ecSmrg	    REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
49005b261ecSmrg	REGION_UNINIT( pScreen, &childUnion);
49105b261ecSmrg	REGION_UNINIT( pScreen, &childUniverse);
49205b261ecSmrg    } /* if any children */
49305b261ecSmrg
49405b261ecSmrg    /*
49505b261ecSmrg     * 'universe' now contains the new clipList for the parent window.
49605b261ecSmrg     *
49705b261ecSmrg     * To figure the exposure of the window we subtract the old clip from the
49805b261ecSmrg     * new, just as for the border.
49905b261ecSmrg     */
50005b261ecSmrg
50105b261ecSmrg    if (oldVis == VisibilityFullyObscured ||
50205b261ecSmrg	oldVis == VisibilityNotViewable)
50305b261ecSmrg    {
50405b261ecSmrg	REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe);
50505b261ecSmrg    }
50605b261ecSmrg    else if (newVis != VisibilityFullyObscured &&
50705b261ecSmrg	     newVis != VisibilityNotViewable)
50805b261ecSmrg    {
50905b261ecSmrg    	REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
51005b261ecSmrg			       universe, &pParent->clipList);
51105b261ecSmrg    }
51205b261ecSmrg
51305b261ecSmrg    /* HACK ALERT - copying contents of regions, instead of regions */
51405b261ecSmrg    {
51505b261ecSmrg	RegionRec   tmp;
51605b261ecSmrg
51705b261ecSmrg	tmp = pParent->clipList;
51805b261ecSmrg	pParent->clipList = *universe;
51905b261ecSmrg	*universe = tmp;
52005b261ecSmrg    }
52105b261ecSmrg
52205b261ecSmrg#ifdef NOTDEF
52305b261ecSmrg    REGION_COPY( pScreen, &pParent->clipList, universe);
52405b261ecSmrg#endif
52505b261ecSmrg
52605b261ecSmrg    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
52705b261ecSmrg
52805b261ecSmrg    if (pScreen->ClipNotify)
52905b261ecSmrg	(* pScreen->ClipNotify) (pParent, dx, dy);
53005b261ecSmrg}
53105b261ecSmrg
53205b261ecSmrgstatic void
53305b261ecSmrgmiTreeObscured(
53405b261ecSmrg    WindowPtr pParent )
53505b261ecSmrg{
53605b261ecSmrg    WindowPtr 	pChild;
53705b261ecSmrg    int    	oldVis;
53805b261ecSmrg
53905b261ecSmrg    pChild = pParent;
54005b261ecSmrg    while (1)
54105b261ecSmrg    {
54205b261ecSmrg	if (pChild->viewable)
54305b261ecSmrg	{
54405b261ecSmrg	    oldVis = pChild->visibility;
54505b261ecSmrg	    if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
54605b261ecSmrg		((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
54705b261ecSmrg		SendVisibilityNotify(pChild);
54805b261ecSmrg	    if (pChild->firstChild)
54905b261ecSmrg	    {
55005b261ecSmrg		pChild = pChild->firstChild;
55105b261ecSmrg		continue;
55205b261ecSmrg	    }
55305b261ecSmrg	}
55405b261ecSmrg	while (!pChild->nextSib && (pChild != pParent))
55505b261ecSmrg	    pChild = pChild->parent;
55605b261ecSmrg	if (pChild == pParent)
55705b261ecSmrg	    break;
55805b261ecSmrg	pChild = pChild->nextSib;
55905b261ecSmrg    }
56005b261ecSmrg}
56105b261ecSmrg
56205b261ecSmrg/*
56305b261ecSmrg *-----------------------------------------------------------------------
56405b261ecSmrg * miValidateTree --
56505b261ecSmrg *	Recomputes the clip list for pParent and all its inferiors.
56605b261ecSmrg *
56705b261ecSmrg * Results:
56805b261ecSmrg *	Always returns 1.
56905b261ecSmrg *
57005b261ecSmrg * Side Effects:
57105b261ecSmrg *	The clipList, borderClip, exposed, and borderExposed regions for
57205b261ecSmrg *	each marked window are altered.
57305b261ecSmrg *
57405b261ecSmrg * Notes:
57505b261ecSmrg *	This routine assumes that all affected windows have been marked
57605b261ecSmrg *	(valdata created) and their winSize and borderSize regions
57705b261ecSmrg *	adjusted to correspond to their new positions. The borderClip and
57805b261ecSmrg *	clipList regions should not have been touched.
57905b261ecSmrg *
58005b261ecSmrg *	The top-most level is treated differently from all lower levels
58105b261ecSmrg *	because pParent is unchanged. For the top level, we merge the
58205b261ecSmrg *	regions taken up by the marked children back into the clipList
58305b261ecSmrg *	for pParent, thus forming a region from which the marked children
58405b261ecSmrg *	can claim their areas. For lower levels, where the old clipList
58505b261ecSmrg *	and borderClip are invalid, we can't do this and have to do the
58605b261ecSmrg *	extra operations done in miComputeClips, but this is much faster
58705b261ecSmrg *	e.g. when only one child has moved...
58805b261ecSmrg *
58905b261ecSmrg *-----------------------------------------------------------------------
59005b261ecSmrg */
59105b261ecSmrg/*ARGSUSED*/
59205b261ecSmrgint
5934642e01fSmrgmiValidateTree (
5944642e01fSmrg    WindowPtr		pParent,    /* Parent to validate */
5954642e01fSmrg    WindowPtr		pChild,     /* First child of pParent that was
59605b261ecSmrg				     * affected */
5974642e01fSmrg    VTKind		kind        /* What kind of configuration caused call */
5984642e01fSmrg    )
59905b261ecSmrg{
60005b261ecSmrg    RegionRec	  	totalClip;  /* Total clipping region available to
60105b261ecSmrg				     * the marked children. pParent's clipList
60205b261ecSmrg				     * merged with the borderClips of all
60305b261ecSmrg				     * the marked children. */
60405b261ecSmrg    RegionRec	  	childClip;  /* The new borderClip for the current
60505b261ecSmrg				     * child */
60605b261ecSmrg    RegionRec		childUnion; /* the space covered by borderSize for
60705b261ecSmrg				     * all marked children */
60805b261ecSmrg    RegionRec		exposed;    /* For intermediate calculations */
60905b261ecSmrg    ScreenPtr		pScreen;
61005b261ecSmrg    WindowPtr		pWin;
61105b261ecSmrg    Bool		overlap;
61205b261ecSmrg    int			viewvals;
61305b261ecSmrg    Bool		forward;
61405b261ecSmrg
61505b261ecSmrg    pScreen = pParent->drawable.pScreen;
61605b261ecSmrg    if (pChild == NullWindow)
61705b261ecSmrg	pChild = pParent->firstChild;
61805b261ecSmrg
61905b261ecSmrg    REGION_NULL(pScreen, &childClip);
62005b261ecSmrg    REGION_NULL(pScreen, &exposed);
62105b261ecSmrg
62205b261ecSmrg    /*
62305b261ecSmrg     * compute the area of the parent window occupied
62405b261ecSmrg     * by the marked children + the parent itself.  This
62505b261ecSmrg     * is the area which can be divied up among the marked
62605b261ecSmrg     * children in their new configuration.
62705b261ecSmrg     */
62805b261ecSmrg    REGION_NULL(pScreen, &totalClip);
62905b261ecSmrg    viewvals = 0;
63005b261ecSmrg    if (REGION_BROKEN (pScreen, &pParent->clipList) &&
63105b261ecSmrg	!REGION_BROKEN (pScreen, &pParent->borderClip))
63205b261ecSmrg    {
63305b261ecSmrg	kind = VTBroken;
63405b261ecSmrg	/*
63505b261ecSmrg	 * When rebuilding clip lists after out of memory,
63605b261ecSmrg	 * assume everything is busted.
63705b261ecSmrg	 */
63805b261ecSmrg	forward = TRUE;
63905b261ecSmrg	REGION_COPY (pScreen, &totalClip, &pParent->borderClip);
64005b261ecSmrg	REGION_INTERSECT (pScreen, &totalClip, &totalClip, &pParent->winSize);
64105b261ecSmrg
64205b261ecSmrg	for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib)
64305b261ecSmrg	{
64405b261ecSmrg	    if (pWin->viewable && !TreatAsTransparent (pWin))
64505b261ecSmrg		REGION_SUBTRACT (pScreen, &totalClip, &totalClip, &pWin->borderSize);
64605b261ecSmrg	}
64705b261ecSmrg	for (pWin = pChild; pWin; pWin = pWin->nextSib)
64805b261ecSmrg	    if (pWin->valdata && pWin->viewable)
64905b261ecSmrg		viewvals++;
65005b261ecSmrg
65105b261ecSmrg	REGION_EMPTY (pScreen, &pParent->clipList);
65205b261ecSmrg    }
65305b261ecSmrg    else
65405b261ecSmrg    {
65505b261ecSmrg	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
65605b261ecSmrg	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
65705b261ecSmrg	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
65805b261ecSmrg	{
65905b261ecSmrg	    forward = TRUE;
66005b261ecSmrg	    for (pWin = pChild; pWin; pWin = pWin->nextSib)
66105b261ecSmrg	    {
66205b261ecSmrg		if (pWin->valdata)
66305b261ecSmrg		{
66405b261ecSmrg		    RegionPtr	pBorderClip = &pWin->borderClip;
66505b261ecSmrg#ifdef COMPOSITE
66605b261ecSmrg		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
66705b261ecSmrg			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
66805b261ecSmrg#endif
66905b261ecSmrg		    REGION_APPEND( pScreen, &totalClip, pBorderClip );
67005b261ecSmrg		    if (pWin->viewable)
67105b261ecSmrg			viewvals++;
67205b261ecSmrg		}
67305b261ecSmrg	    }
67405b261ecSmrg	}
67505b261ecSmrg	else
67605b261ecSmrg	{
67705b261ecSmrg	    forward = FALSE;
67805b261ecSmrg	    pWin = pParent->lastChild;
67905b261ecSmrg	    while (1)
68005b261ecSmrg	    {
68105b261ecSmrg		if (pWin->valdata)
68205b261ecSmrg		{
68305b261ecSmrg		    RegionPtr	pBorderClip = &pWin->borderClip;
68405b261ecSmrg#ifdef COMPOSITE
68505b261ecSmrg		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
68605b261ecSmrg			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
68705b261ecSmrg#endif
68805b261ecSmrg		    REGION_APPEND( pScreen, &totalClip, pBorderClip );
68905b261ecSmrg		    if (pWin->viewable)
69005b261ecSmrg			viewvals++;
69105b261ecSmrg		}
69205b261ecSmrg		if (pWin == pChild)
69305b261ecSmrg		    break;
69405b261ecSmrg		pWin = pWin->prevSib;
69505b261ecSmrg	    }
69605b261ecSmrg	}
69705b261ecSmrg	REGION_VALIDATE( pScreen, &totalClip, &overlap);
69805b261ecSmrg    }
69905b261ecSmrg
70005b261ecSmrg    /*
70105b261ecSmrg     * Now go through the children of the root and figure their new
70205b261ecSmrg     * borderClips from the totalClip, passing that off to miComputeClips
70305b261ecSmrg     * to handle recursively. Once that's done, we remove the child
70405b261ecSmrg     * from the totalClip to clip any siblings below it.
70505b261ecSmrg     */
70605b261ecSmrg
70705b261ecSmrg    overlap = TRUE;
70805b261ecSmrg    if (kind != VTStack)
70905b261ecSmrg    {
71005b261ecSmrg	REGION_UNION( pScreen, &totalClip, &totalClip, &pParent->clipList);
71105b261ecSmrg	if (viewvals > 1)
71205b261ecSmrg	{
71305b261ecSmrg	    /*
71405b261ecSmrg	     * precompute childUnion to discover whether any of them
71505b261ecSmrg	     * overlap.  This seems redundant, but performance studies
71605b261ecSmrg	     * have demonstrated that the cost of this loop is
71705b261ecSmrg	     * lower than the cost of multiple Subtracts in the
71805b261ecSmrg	     * loop below.
71905b261ecSmrg	     */
72005b261ecSmrg	    REGION_NULL(pScreen, &childUnion);
72105b261ecSmrg	    if (forward)
72205b261ecSmrg	    {
72305b261ecSmrg		for (pWin = pChild; pWin; pWin = pWin->nextSib)
72405b261ecSmrg		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
72505b261ecSmrg			REGION_APPEND( pScreen, &childUnion,
72605b261ecSmrg						   &pWin->borderSize);
72705b261ecSmrg	    }
72805b261ecSmrg	    else
72905b261ecSmrg	    {
73005b261ecSmrg		pWin = pParent->lastChild;
73105b261ecSmrg		while (1)
73205b261ecSmrg		{
73305b261ecSmrg		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
73405b261ecSmrg			REGION_APPEND( pScreen, &childUnion,
73505b261ecSmrg						   &pWin->borderSize);
73605b261ecSmrg		    if (pWin == pChild)
73705b261ecSmrg			break;
73805b261ecSmrg		    pWin = pWin->prevSib;
73905b261ecSmrg		}
74005b261ecSmrg	    }
74105b261ecSmrg	    REGION_VALIDATE(pScreen, &childUnion, &overlap);
74205b261ecSmrg	    if (overlap)
74305b261ecSmrg		REGION_UNINIT(pScreen, &childUnion);
74405b261ecSmrg	}
74505b261ecSmrg    }
74605b261ecSmrg
74705b261ecSmrg    for (pWin = pChild;
74805b261ecSmrg	 pWin != NullWindow;
74905b261ecSmrg	 pWin = pWin->nextSib)
75005b261ecSmrg    {
75105b261ecSmrg	if (pWin->viewable) {
75205b261ecSmrg	    if (pWin->valdata) {
75305b261ecSmrg		REGION_INTERSECT( pScreen, &childClip,
75405b261ecSmrg					&totalClip,
75505b261ecSmrg 					&pWin->borderSize);
75605b261ecSmrg		miComputeClips (pWin, pScreen, &childClip, kind, &exposed);
75705b261ecSmrg		if (overlap && !TreatAsTransparent (pWin))
75805b261ecSmrg		{
75905b261ecSmrg		    REGION_SUBTRACT( pScreen, &totalClip,
76005b261ecSmrg				       	   &totalClip,
76105b261ecSmrg				       	   &pWin->borderSize);
76205b261ecSmrg		}
76305b261ecSmrg	    } else if (pWin->visibility == VisibilityNotViewable) {
76405b261ecSmrg		miTreeObscured(pWin);
76505b261ecSmrg	    }
76605b261ecSmrg	} else {
76705b261ecSmrg	    if (pWin->valdata) {
76805b261ecSmrg		REGION_EMPTY( pScreen, &pWin->clipList);
76905b261ecSmrg		if (pScreen->ClipNotify)
77005b261ecSmrg		    (* pScreen->ClipNotify) (pWin, 0, 0);
77105b261ecSmrg		REGION_EMPTY( pScreen, &pWin->borderClip);
77205b261ecSmrg		pWin->valdata = (ValidatePtr)NULL;
77305b261ecSmrg	    }
77405b261ecSmrg	}
77505b261ecSmrg    }
77605b261ecSmrg
77705b261ecSmrg    REGION_UNINIT( pScreen, &childClip);
77805b261ecSmrg    if (!overlap)
77905b261ecSmrg    {
78005b261ecSmrg	REGION_SUBTRACT(pScreen, &totalClip, &totalClip, &childUnion);
78105b261ecSmrg	REGION_UNINIT(pScreen, &childUnion);
78205b261ecSmrg    }
78305b261ecSmrg
78405b261ecSmrg    REGION_NULL(pScreen, &pParent->valdata->after.exposed);
78505b261ecSmrg    REGION_NULL(pScreen, &pParent->valdata->after.borderExposed);
78605b261ecSmrg
78705b261ecSmrg    /*
78805b261ecSmrg     * each case below is responsible for updating the
78905b261ecSmrg     * clipList and serial number for the parent window
79005b261ecSmrg     */
79105b261ecSmrg
79205b261ecSmrg    switch (kind) {
79305b261ecSmrg    case VTStack:
79405b261ecSmrg	break;
79505b261ecSmrg    default:
79605b261ecSmrg	/*
79705b261ecSmrg	 * totalClip contains the new clipList for the parent. Figure out
79805b261ecSmrg	 * exposures and obscures as per miComputeClips and reset the parent's
79905b261ecSmrg	 * clipList.
80005b261ecSmrg	 */
80105b261ecSmrg	REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
80205b261ecSmrg			       &totalClip, &pParent->clipList);
80305b261ecSmrg	/* fall through */
80405b261ecSmrg    case VTMap:
80505b261ecSmrg	REGION_COPY( pScreen, &pParent->clipList, &totalClip);
80605b261ecSmrg	pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
80705b261ecSmrg	break;
80805b261ecSmrg    }
80905b261ecSmrg
81005b261ecSmrg    REGION_UNINIT( pScreen, &totalClip);
81105b261ecSmrg    REGION_UNINIT( pScreen, &exposed);
81205b261ecSmrg    if (pScreen->ClipNotify)
81305b261ecSmrg	(*pScreen->ClipNotify) (pParent, 0, 0);
81405b261ecSmrg    return (1);
81505b261ecSmrg}
816