mivaltree.c revision 35c4bbdf
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 *
3035c4bbdfSmrg * Copyright 1987, 1988, 1989 by
3105b261ecSmrg * Digital Equipment Corporation, Maynard, Massachusetts,
3235c4bbdfSmrg *
3305b261ecSmrg *                         All Rights Reserved
3435c4bbdfSmrg *
3535c4bbdfSmrg * Permission to use, copy, modify, and distribute this software and its
3635c4bbdfSmrg * documentation for any purpose and without fee is hereby granted,
3705b261ecSmrg * provided that the above copyright notice appear in all copies and that
3835c4bbdfSmrg * 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
4135c4bbdfSmrg * software without specific, written prior permission.
4235c4bbdfSmrg *
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.
5035c4bbdfSmrg *
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
8235c4bbdfSmrg /*
8305b261ecSmrg  * Aug '86: Susan Angebranndt -- original code
8405b261ecSmrg  * July '87: Adam de Boor -- substantially modified and commented
8505b261ecSmrg  * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
8605b261ecSmrg  *             In particular, much improved code for window mapping and
8705b261ecSmrg  *             circulating.
8835c4bbdfSmrg  *             Bob Scheifler -- avoid miComputeClips for unmapped windows,
8935c4bbdfSmrg  *                              valdata changes
9005b261ecSmrg  */
9105b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
9205b261ecSmrg#include <dix-config.h>
9305b261ecSmrg#endif
9405b261ecSmrg
9505b261ecSmrg#include    <X11/X.h>
9605b261ecSmrg#include    "scrnintstr.h"
9705b261ecSmrg#include    "validate.h"
9805b261ecSmrg#include    "windowstr.h"
9905b261ecSmrg#include    "mi.h"
10005b261ecSmrg#include    "regionstr.h"
10105b261ecSmrg#include    "mivalidate.h"
10205b261ecSmrg#include    "globals.h"
10335c4bbdfSmrg#ifdef COMPOSITE
10435c4bbdfSmrg#include    "compint.h"
10535c4bbdfSmrg#endif
10605b261ecSmrg
10705b261ecSmrg/*
10805b261ecSmrg * Compute the visibility of a shaped window
10905b261ecSmrg */
1104642e01fSmrgint
11135c4bbdfSmrgmiShapedWindowIn(RegionPtr universe, RegionPtr bounding,
11235c4bbdfSmrg                 BoxPtr rect, int x, int y)
11305b261ecSmrg{
11435c4bbdfSmrg    BoxRec box;
11535c4bbdfSmrg    BoxPtr boundBox;
11635c4bbdfSmrg    int nbox;
11735c4bbdfSmrg    Bool someIn, someOut;
11835c4bbdfSmrg    int t, x1, y1, x2, y2;
11935c4bbdfSmrg
12035c4bbdfSmrg    nbox = RegionNumRects(bounding);
12135c4bbdfSmrg    boundBox = RegionRects(bounding);
12205b261ecSmrg    someIn = someOut = FALSE;
12305b261ecSmrg    x1 = rect->x1;
12405b261ecSmrg    y1 = rect->y1;
12505b261ecSmrg    x2 = rect->x2;
12605b261ecSmrg    y2 = rect->y2;
12735c4bbdfSmrg    while (nbox--) {
12835c4bbdfSmrg        if ((t = boundBox->x1 + x) < x1)
12935c4bbdfSmrg            t = x1;
13035c4bbdfSmrg        box.x1 = t;
13135c4bbdfSmrg        if ((t = boundBox->y1 + y) < y1)
13235c4bbdfSmrg            t = y1;
13335c4bbdfSmrg        box.y1 = t;
13435c4bbdfSmrg        if ((t = boundBox->x2 + x) > x2)
13535c4bbdfSmrg            t = x2;
13635c4bbdfSmrg        box.x2 = t;
13735c4bbdfSmrg        if ((t = boundBox->y2 + y) > y2)
13835c4bbdfSmrg            t = y2;
13935c4bbdfSmrg        box.y2 = t;
14035c4bbdfSmrg        if (box.x1 > box.x2)
14135c4bbdfSmrg            box.x2 = box.x1;
14235c4bbdfSmrg        if (box.y1 > box.y2)
14335c4bbdfSmrg            box.y2 = box.y1;
14435c4bbdfSmrg        switch (RegionContainsRect(universe, &box)) {
14535c4bbdfSmrg        case rgnIN:
14635c4bbdfSmrg            if (someOut)
14735c4bbdfSmrg                return rgnPART;
14835c4bbdfSmrg            someIn = TRUE;
14935c4bbdfSmrg            break;
15035c4bbdfSmrg        case rgnOUT:
15135c4bbdfSmrg            if (someIn)
15235c4bbdfSmrg                return rgnPART;
15335c4bbdfSmrg            someOut = TRUE;
15435c4bbdfSmrg            break;
15535c4bbdfSmrg        default:
15635c4bbdfSmrg            return rgnPART;
15735c4bbdfSmrg        }
15835c4bbdfSmrg        boundBox++;
15905b261ecSmrg    }
16005b261ecSmrg    if (someIn)
16135c4bbdfSmrg        return rgnIN;
16205b261ecSmrg    return rgnOUT;
16305b261ecSmrg}
16405b261ecSmrg
16505b261ecSmrg/*
16605b261ecSmrg * Manual redirected windows are treated as transparent; they do not obscure
16705b261ecSmrg * siblings or parent windows
16805b261ecSmrg */
16905b261ecSmrg
17005b261ecSmrg#ifdef COMPOSITE
17105b261ecSmrg#define TreatAsTransparent(w)	((w)->redirectDraw == RedirectDrawManual)
17205b261ecSmrg#else
17305b261ecSmrg#define TreatAsTransparent(w)	FALSE
17405b261ecSmrg#endif
17505b261ecSmrg
17605b261ecSmrg#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
17705b261ecSmrg				    HasBorder(w) && \
17805b261ecSmrg				    (w)->backgroundState == ParentRelative)
17905b261ecSmrg
18005b261ecSmrg/*
18105b261ecSmrg *-----------------------------------------------------------------------
18205b261ecSmrg * miComputeClips --
18305b261ecSmrg *	Recompute the clipList, borderClip, exposed and borderExposed
18405b261ecSmrg *	regions for pParent and its children. Only viewable windows are
18505b261ecSmrg *	taken into account.
18605b261ecSmrg *
18705b261ecSmrg * Results:
18805b261ecSmrg *	None.
18905b261ecSmrg *
19005b261ecSmrg * Side Effects:
19105b261ecSmrg *	clipList, borderClip, exposed and borderExposed are altered.
19205b261ecSmrg *	A VisibilityNotify event may be generated on the parent window.
19305b261ecSmrg *
19405b261ecSmrg *-----------------------------------------------------------------------
19505b261ecSmrg */
19605b261ecSmrgstatic void
19735c4bbdfSmrgmiComputeClips(WindowPtr pParent,
19835c4bbdfSmrg               ScreenPtr pScreen,
19935c4bbdfSmrg               RegionPtr universe, VTKind kind, RegionPtr exposed)
20035c4bbdfSmrg{                               /* for intermediate calculations */
20135c4bbdfSmrg    int dx, dy;
20235c4bbdfSmrg    RegionRec childUniverse;
20335c4bbdfSmrg    WindowPtr pChild;
20435c4bbdfSmrg    int oldVis, newVis;
20535c4bbdfSmrg    BoxRec borderSize;
20635c4bbdfSmrg    RegionRec childUnion;
20735c4bbdfSmrg    Bool overlap;
20835c4bbdfSmrg    RegionPtr borderVisible;
20935c4bbdfSmrg
21005b261ecSmrg    /*
21105b261ecSmrg     * Figure out the new visibility of this window.
21205b261ecSmrg     * The extent of the universe should be the same as the extent of
21305b261ecSmrg     * the borderSize region. If the window is unobscured, this rectangle
21405b261ecSmrg     * will be completely inside the universe (the universe will cover it
21505b261ecSmrg     * completely). If the window is completely obscured, none of the
21605b261ecSmrg     * universe will cover the rectangle.
21705b261ecSmrg     */
21805b261ecSmrg    borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
21905b261ecSmrg    borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
22035c4bbdfSmrg    dx = (int) pParent->drawable.x + (int) pParent->drawable.width +
22135c4bbdfSmrg        wBorderWidth(pParent);
22205b261ecSmrg    if (dx > 32767)
22335c4bbdfSmrg        dx = 32767;
22405b261ecSmrg    borderSize.x2 = dx;
22535c4bbdfSmrg    dy = (int) pParent->drawable.y + (int) pParent->drawable.height +
22635c4bbdfSmrg        wBorderWidth(pParent);
22705b261ecSmrg    if (dy > 32767)
22835c4bbdfSmrg        dy = 32767;
22905b261ecSmrg    borderSize.y2 = dy;
23005b261ecSmrg
23105b261ecSmrg#ifdef COMPOSITE
23205b261ecSmrg    /*
23305b261ecSmrg     * In redirected drawing case, reset universe to borderSize
23405b261ecSmrg     */
23535c4bbdfSmrg    if (pParent->redirectDraw != RedirectDrawNone) {
23635c4bbdfSmrg        if (TreatAsTransparent(pParent))
23735c4bbdfSmrg            RegionEmpty(universe);
23835c4bbdfSmrg        compSetRedirectBorderClip (pParent, universe);
23935c4bbdfSmrg        RegionCopy(universe, &pParent->borderSize);
24005b261ecSmrg    }
24105b261ecSmrg#endif
24205b261ecSmrg
24305b261ecSmrg    oldVis = pParent->visibility;
24435c4bbdfSmrg    switch (RegionContainsRect(universe, &borderSize)) {
24535c4bbdfSmrg    case rgnIN:
24635c4bbdfSmrg        newVis = VisibilityUnobscured;
24735c4bbdfSmrg        break;
24835c4bbdfSmrg    case rgnPART:
24935c4bbdfSmrg        newVis = VisibilityPartiallyObscured;
25035c4bbdfSmrg        {
25135c4bbdfSmrg            RegionPtr pBounding;
25235c4bbdfSmrg
25335c4bbdfSmrg            if ((pBounding = wBoundingShape(pParent))) {
25435c4bbdfSmrg                switch (miShapedWindowIn(universe, pBounding,
25535c4bbdfSmrg                                         &borderSize,
25635c4bbdfSmrg                                         pParent->drawable.x,
25735c4bbdfSmrg                                         pParent->drawable.y)) {
25835c4bbdfSmrg                case rgnIN:
25935c4bbdfSmrg                    newVis = VisibilityUnobscured;
26035c4bbdfSmrg                    break;
26135c4bbdfSmrg                case rgnOUT:
26235c4bbdfSmrg                    newVis = VisibilityFullyObscured;
26335c4bbdfSmrg                    break;
26435c4bbdfSmrg                }
26535c4bbdfSmrg            }
26635c4bbdfSmrg        }
26735c4bbdfSmrg        break;
26835c4bbdfSmrg    default:
26935c4bbdfSmrg        newVis = VisibilityFullyObscured;
27035c4bbdfSmrg        break;
27105b261ecSmrg    }
27205b261ecSmrg    pParent->visibility = newVis;
27305b261ecSmrg    if (oldVis != newVis &&
27435c4bbdfSmrg        ((pParent->
27535c4bbdfSmrg          eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
27635c4bbdfSmrg        SendVisibilityNotify(pParent);
27705b261ecSmrg
27805b261ecSmrg    dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
27905b261ecSmrg    dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
28005b261ecSmrg
28105b261ecSmrg    /*
28205b261ecSmrg     * avoid computations when dealing with simple operations
28305b261ecSmrg     */
28405b261ecSmrg
28505b261ecSmrg    switch (kind) {
28605b261ecSmrg    case VTMap:
28705b261ecSmrg    case VTStack:
28805b261ecSmrg    case VTUnmap:
28935c4bbdfSmrg        break;
29005b261ecSmrg    case VTMove:
29135c4bbdfSmrg        if ((oldVis == newVis) &&
29235c4bbdfSmrg            ((oldVis == VisibilityFullyObscured) ||
29335c4bbdfSmrg             (oldVis == VisibilityUnobscured))) {
29435c4bbdfSmrg            pChild = pParent;
29535c4bbdfSmrg            while (1) {
29635c4bbdfSmrg                if (pChild->viewable) {
29735c4bbdfSmrg                    if (pChild->visibility != VisibilityFullyObscured) {
29835c4bbdfSmrg                        RegionTranslate(&pChild->borderClip, dx, dy);
29935c4bbdfSmrg                        RegionTranslate(&pChild->clipList, dx, dy);
30035c4bbdfSmrg                        pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
30135c4bbdfSmrg                        if (pScreen->ClipNotify)
30235c4bbdfSmrg                            (*pScreen->ClipNotify) (pChild, dx, dy);
30335c4bbdfSmrg
30435c4bbdfSmrg                    }
30535c4bbdfSmrg                    if (pChild->valdata) {
30635c4bbdfSmrg                        RegionNull(&pChild->valdata->after.borderExposed);
30735c4bbdfSmrg                        if (HasParentRelativeBorder(pChild)) {
30835c4bbdfSmrg                            RegionSubtract(&pChild->valdata->after.
30935c4bbdfSmrg                                           borderExposed, &pChild->borderClip,
31035c4bbdfSmrg                                           &pChild->winSize);
31135c4bbdfSmrg                        }
31235c4bbdfSmrg                        RegionNull(&pChild->valdata->after.exposed);
31335c4bbdfSmrg                    }
31435c4bbdfSmrg                    if (pChild->firstChild) {
31535c4bbdfSmrg                        pChild = pChild->firstChild;
31635c4bbdfSmrg                        continue;
31735c4bbdfSmrg                    }
31835c4bbdfSmrg                }
31935c4bbdfSmrg                while (!pChild->nextSib && (pChild != pParent))
32035c4bbdfSmrg                    pChild = pChild->parent;
32135c4bbdfSmrg                if (pChild == pParent)
32235c4bbdfSmrg                    break;
32335c4bbdfSmrg                pChild = pChild->nextSib;
32435c4bbdfSmrg            }
32535c4bbdfSmrg            return;
32635c4bbdfSmrg        }
32735c4bbdfSmrg        /* fall through */
32805b261ecSmrg    default:
32935c4bbdfSmrg        /*
33035c4bbdfSmrg         * To calculate exposures correctly, we have to translate the old
33135c4bbdfSmrg         * borderClip and clipList regions to the window's new location so there
33235c4bbdfSmrg         * is a correspondence between pieces of the new and old clipping regions.
33335c4bbdfSmrg         */
33435c4bbdfSmrg        if (dx || dy) {
33535c4bbdfSmrg            /*
33635c4bbdfSmrg             * We translate the old clipList because that will be exposed or copied
33735c4bbdfSmrg             * if gravity is right.
33835c4bbdfSmrg             */
33935c4bbdfSmrg            RegionTranslate(&pParent->borderClip, dx, dy);
34035c4bbdfSmrg            RegionTranslate(&pParent->clipList, dx, dy);
34135c4bbdfSmrg        }
34235c4bbdfSmrg        break;
34305b261ecSmrg    case VTBroken:
34435c4bbdfSmrg        RegionEmpty(&pParent->borderClip);
34535c4bbdfSmrg        RegionEmpty(&pParent->clipList);
34635c4bbdfSmrg        break;
34705b261ecSmrg    }
34805b261ecSmrg
34905b261ecSmrg    borderVisible = pParent->valdata->before.borderVisible;
3506747b715Smrg    RegionNull(&pParent->valdata->after.borderExposed);
3516747b715Smrg    RegionNull(&pParent->valdata->after.exposed);
35205b261ecSmrg
35305b261ecSmrg    /*
35405b261ecSmrg     * Since the borderClip must not be clipped by the children, we do
35505b261ecSmrg     * the border exposure first...
35605b261ecSmrg     *
35705b261ecSmrg     * 'universe' is the window's borderClip. To figure the exposures, remove
35805b261ecSmrg     * the area that used to be exposed from the new.
35905b261ecSmrg     * This leaves a region of pieces that weren't exposed before.
36005b261ecSmrg     */
36105b261ecSmrg
36235c4bbdfSmrg    if (HasBorder(pParent)) {
36335c4bbdfSmrg        if (borderVisible) {
36435c4bbdfSmrg            /*
36535c4bbdfSmrg             * when the border changes shape, the old visible portions
36635c4bbdfSmrg             * of the border will be saved by DIX in borderVisible --
36735c4bbdfSmrg             * use that region and destroy it
36835c4bbdfSmrg             */
36935c4bbdfSmrg            RegionSubtract(exposed, universe, borderVisible);
37035c4bbdfSmrg            RegionDestroy(borderVisible);
37135c4bbdfSmrg        }
37235c4bbdfSmrg        else {
37335c4bbdfSmrg            RegionSubtract(exposed, universe, &pParent->borderClip);
37435c4bbdfSmrg        }
37535c4bbdfSmrg        if (HasParentRelativeBorder(pParent) && (dx || dy))
37635c4bbdfSmrg            RegionSubtract(&pParent->valdata->after.borderExposed,
37735c4bbdfSmrg                           universe, &pParent->winSize);
37835c4bbdfSmrg        else
37935c4bbdfSmrg            RegionSubtract(&pParent->valdata->after.borderExposed,
38035c4bbdfSmrg                           exposed, &pParent->winSize);
38135c4bbdfSmrg
38235c4bbdfSmrg        RegionCopy(&pParent->borderClip, universe);
38335c4bbdfSmrg
38435c4bbdfSmrg        /*
38535c4bbdfSmrg         * To get the right clipList for the parent, and to make doubly sure
38635c4bbdfSmrg         * that no child overlaps the parent's border, we remove the parent's
38735c4bbdfSmrg         * border from the universe before proceeding.
38835c4bbdfSmrg         */
38935c4bbdfSmrg
39035c4bbdfSmrg        RegionIntersect(universe, universe, &pParent->winSize);
39105b261ecSmrg    }
39205b261ecSmrg    else
39335c4bbdfSmrg        RegionCopy(&pParent->borderClip, universe);
39435c4bbdfSmrg
39535c4bbdfSmrg    if ((pChild = pParent->firstChild) && pParent->mapped) {
39635c4bbdfSmrg        RegionNull(&childUniverse);
39735c4bbdfSmrg        RegionNull(&childUnion);
39835c4bbdfSmrg        if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
39935c4bbdfSmrg            ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
40035c4bbdfSmrg             (pChild->drawable.x < pParent->lastChild->drawable.x))) {
40135c4bbdfSmrg            for (; pChild; pChild = pChild->nextSib) {
40235c4bbdfSmrg                if (pChild->viewable && !TreatAsTransparent(pChild))
40335c4bbdfSmrg                    RegionAppend(&childUnion, &pChild->borderSize);
40435c4bbdfSmrg            }
40535c4bbdfSmrg        }
40635c4bbdfSmrg        else {
40735c4bbdfSmrg            for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) {
40835c4bbdfSmrg                if (pChild->viewable && !TreatAsTransparent(pChild))
40935c4bbdfSmrg                    RegionAppend(&childUnion, &pChild->borderSize);
41035c4bbdfSmrg            }
41135c4bbdfSmrg        }
41235c4bbdfSmrg        RegionValidate(&childUnion, &overlap);
41335c4bbdfSmrg
41435c4bbdfSmrg        for (pChild = pParent->firstChild; pChild; pChild = pChild->nextSib) {
41535c4bbdfSmrg            if (pChild->viewable) {
41635c4bbdfSmrg                /*
41735c4bbdfSmrg                 * If the child is viewable, we want to remove its extents
41835c4bbdfSmrg                 * from the current universe, but we only re-clip it if
41935c4bbdfSmrg                 * it's been marked.
42035c4bbdfSmrg                 */
42135c4bbdfSmrg                if (pChild->valdata) {
42235c4bbdfSmrg                    /*
42335c4bbdfSmrg                     * Figure out the new universe from the child's
42435c4bbdfSmrg                     * perspective and recurse.
42535c4bbdfSmrg                     */
42635c4bbdfSmrg                    RegionIntersect(&childUniverse,
42735c4bbdfSmrg                                    universe, &pChild->borderSize);
42835c4bbdfSmrg                    miComputeClips(pChild, pScreen, &childUniverse, kind,
42935c4bbdfSmrg                                   exposed);
43035c4bbdfSmrg                }
43135c4bbdfSmrg                /*
43235c4bbdfSmrg                 * Once the child has been processed, we remove its extents
43335c4bbdfSmrg                 * from the current universe, thus denying its space to any
43435c4bbdfSmrg                 * other sibling.
43535c4bbdfSmrg                 */
43635c4bbdfSmrg                if (overlap && !TreatAsTransparent(pChild))
43735c4bbdfSmrg                    RegionSubtract(universe, universe, &pChild->borderSize);
43835c4bbdfSmrg            }
43935c4bbdfSmrg        }
44035c4bbdfSmrg        if (!overlap)
44135c4bbdfSmrg            RegionSubtract(universe, universe, &childUnion);
44235c4bbdfSmrg        RegionUninit(&childUnion);
44335c4bbdfSmrg        RegionUninit(&childUniverse);
44435c4bbdfSmrg    }                           /* if any children */
44505b261ecSmrg
44605b261ecSmrg    /*
44705b261ecSmrg     * 'universe' now contains the new clipList for the parent window.
44805b261ecSmrg     *
44905b261ecSmrg     * To figure the exposure of the window we subtract the old clip from the
45005b261ecSmrg     * new, just as for the border.
45105b261ecSmrg     */
45205b261ecSmrg
45335c4bbdfSmrg    if (oldVis == VisibilityFullyObscured || oldVis == VisibilityNotViewable) {
45435c4bbdfSmrg        RegionCopy(&pParent->valdata->after.exposed, universe);
45505b261ecSmrg    }
45605b261ecSmrg    else if (newVis != VisibilityFullyObscured &&
45735c4bbdfSmrg             newVis != VisibilityNotViewable) {
45835c4bbdfSmrg        RegionSubtract(&pParent->valdata->after.exposed,
45935c4bbdfSmrg                       universe, &pParent->clipList);
46005b261ecSmrg    }
46105b261ecSmrg
46205b261ecSmrg    /* HACK ALERT - copying contents of regions, instead of regions */
46305b261ecSmrg    {
46435c4bbdfSmrg        RegionRec tmp;
46505b261ecSmrg
46635c4bbdfSmrg        tmp = pParent->clipList;
46735c4bbdfSmrg        pParent->clipList = *universe;
46835c4bbdfSmrg        *universe = tmp;
46905b261ecSmrg    }
47005b261ecSmrg
47105b261ecSmrg#ifdef NOTDEF
4726747b715Smrg    RegionCopy(&pParent->clipList, universe);
47305b261ecSmrg#endif
47405b261ecSmrg
47505b261ecSmrg    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
47605b261ecSmrg
47705b261ecSmrg    if (pScreen->ClipNotify)
47835c4bbdfSmrg        (*pScreen->ClipNotify) (pParent, dx, dy);
47905b261ecSmrg}
48005b261ecSmrg
48105b261ecSmrgstatic void
48235c4bbdfSmrgmiTreeObscured(WindowPtr pParent)
48305b261ecSmrg{
48435c4bbdfSmrg    WindowPtr pChild;
48535c4bbdfSmrg    int oldVis;
48605b261ecSmrg
48705b261ecSmrg    pChild = pParent;
48835c4bbdfSmrg    while (1) {
48935c4bbdfSmrg        if (pChild->viewable) {
49035c4bbdfSmrg            oldVis = pChild->visibility;
49135c4bbdfSmrg            if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
49235c4bbdfSmrg                ((pChild->
49335c4bbdfSmrg                  eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
49435c4bbdfSmrg                SendVisibilityNotify(pChild);
49535c4bbdfSmrg            if (pChild->firstChild) {
49635c4bbdfSmrg                pChild = pChild->firstChild;
49735c4bbdfSmrg                continue;
49835c4bbdfSmrg            }
49935c4bbdfSmrg        }
50035c4bbdfSmrg        while (!pChild->nextSib && (pChild != pParent))
50135c4bbdfSmrg            pChild = pChild->parent;
50235c4bbdfSmrg        if (pChild == pParent)
50335c4bbdfSmrg            break;
50435c4bbdfSmrg        pChild = pChild->nextSib;
50505b261ecSmrg    }
50605b261ecSmrg}
50705b261ecSmrg
50835c4bbdfSmrgstatic RegionPtr
50935c4bbdfSmrggetBorderClip(WindowPtr pWin)
51035c4bbdfSmrg{
51135c4bbdfSmrg#ifdef COMPOSITE
51235c4bbdfSmrg    if (pWin->redirectDraw != RedirectDrawNone)
51335c4bbdfSmrg        return compGetRedirectBorderClip(pWin);
51435c4bbdfSmrg    else
51535c4bbdfSmrg#endif
51635c4bbdfSmrg        return &pWin->borderClip;
51735c4bbdfSmrg}
51835c4bbdfSmrg
51905b261ecSmrg/*
52005b261ecSmrg *-----------------------------------------------------------------------
52105b261ecSmrg * miValidateTree --
52205b261ecSmrg *	Recomputes the clip list for pParent and all its inferiors.
52305b261ecSmrg *
52405b261ecSmrg * Results:
52505b261ecSmrg *	Always returns 1.
52605b261ecSmrg *
52705b261ecSmrg * Side Effects:
52805b261ecSmrg *	The clipList, borderClip, exposed, and borderExposed regions for
52905b261ecSmrg *	each marked window are altered.
53005b261ecSmrg *
53105b261ecSmrg * Notes:
53205b261ecSmrg *	This routine assumes that all affected windows have been marked
53305b261ecSmrg *	(valdata created) and their winSize and borderSize regions
53405b261ecSmrg *	adjusted to correspond to their new positions. The borderClip and
53505b261ecSmrg *	clipList regions should not have been touched.
53605b261ecSmrg *
53705b261ecSmrg *	The top-most level is treated differently from all lower levels
53805b261ecSmrg *	because pParent is unchanged. For the top level, we merge the
53905b261ecSmrg *	regions taken up by the marked children back into the clipList
54005b261ecSmrg *	for pParent, thus forming a region from which the marked children
54105b261ecSmrg *	can claim their areas. For lower levels, where the old clipList
54205b261ecSmrg *	and borderClip are invalid, we can't do this and have to do the
54305b261ecSmrg *	extra operations done in miComputeClips, but this is much faster
54405b261ecSmrg *	e.g. when only one child has moved...
54505b261ecSmrg *
54605b261ecSmrg *-----------------------------------------------------------------------
54705b261ecSmrg */
54835c4bbdfSmrg /*ARGSUSED*/ int
54935c4bbdfSmrgmiValidateTree(WindowPtr pParent,       /* Parent to validate */
55035c4bbdfSmrg               WindowPtr pChild,        /* First child of pParent that was
55135c4bbdfSmrg                                         * affected */
55235c4bbdfSmrg               VTKind kind      /* What kind of configuration caused call */
5534642e01fSmrg    )
55405b261ecSmrg{
55535c4bbdfSmrg    RegionRec totalClip;        /* Total clipping region available to
55635c4bbdfSmrg                                 * the marked children. pParent's clipList
55735c4bbdfSmrg                                 * merged with the borderClips of all
55835c4bbdfSmrg                                 * the marked children. */
55935c4bbdfSmrg    RegionRec childClip;        /* The new borderClip for the current
56035c4bbdfSmrg                                 * child */
56135c4bbdfSmrg    RegionRec childUnion;       /* the space covered by borderSize for
56235c4bbdfSmrg                                 * all marked children */
56335c4bbdfSmrg    RegionRec exposed;          /* For intermediate calculations */
56435c4bbdfSmrg    ScreenPtr pScreen;
56535c4bbdfSmrg    WindowPtr pWin;
56635c4bbdfSmrg    Bool overlap;
56735c4bbdfSmrg    int viewvals;
56835c4bbdfSmrg    Bool forward;
56905b261ecSmrg
57005b261ecSmrg    pScreen = pParent->drawable.pScreen;
57105b261ecSmrg    if (pChild == NullWindow)
57235c4bbdfSmrg        pChild = pParent->firstChild;
57305b261ecSmrg
5746747b715Smrg    RegionNull(&childClip);
5756747b715Smrg    RegionNull(&exposed);
57605b261ecSmrg
57705b261ecSmrg    /*
57805b261ecSmrg     * compute the area of the parent window occupied
57905b261ecSmrg     * by the marked children + the parent itself.  This
58005b261ecSmrg     * is the area which can be divied up among the marked
58105b261ecSmrg     * children in their new configuration.
58205b261ecSmrg     */
5836747b715Smrg    RegionNull(&totalClip);
58405b261ecSmrg    viewvals = 0;
58535c4bbdfSmrg    if (RegionBroken(&pParent->clipList) && !RegionBroken(&pParent->borderClip)) {
58635c4bbdfSmrg        kind = VTBroken;
58735c4bbdfSmrg        /*
58835c4bbdfSmrg         * When rebuilding clip lists after out of memory,
58935c4bbdfSmrg         * assume everything is busted.
59035c4bbdfSmrg         */
59135c4bbdfSmrg        forward = TRUE;
59235c4bbdfSmrg        RegionCopy(&totalClip, &pParent->borderClip);
59335c4bbdfSmrg        RegionIntersect(&totalClip, &totalClip, &pParent->winSize);
59435c4bbdfSmrg
59535c4bbdfSmrg        for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib) {
59635c4bbdfSmrg            if (pWin->viewable && !TreatAsTransparent(pWin))
59735c4bbdfSmrg                RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
59835c4bbdfSmrg        }
59935c4bbdfSmrg        for (pWin = pChild; pWin; pWin = pWin->nextSib)
60035c4bbdfSmrg            if (pWin->valdata && pWin->viewable)
60135c4bbdfSmrg                viewvals++;
60235c4bbdfSmrg
60335c4bbdfSmrg        RegionEmpty(&pParent->clipList);
60405b261ecSmrg    }
60535c4bbdfSmrg    else {
60635c4bbdfSmrg        if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
60735c4bbdfSmrg            ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
60835c4bbdfSmrg             (pChild->drawable.x < pParent->lastChild->drawable.x))) {
60935c4bbdfSmrg            forward = TRUE;
61035c4bbdfSmrg            for (pWin = pChild; pWin; pWin = pWin->nextSib) {
61135c4bbdfSmrg                if (pWin->valdata) {
61235c4bbdfSmrg                    RegionAppend(&totalClip, getBorderClip(pWin));
61335c4bbdfSmrg                    if (pWin->viewable)
61435c4bbdfSmrg                        viewvals++;
61535c4bbdfSmrg                }
61635c4bbdfSmrg            }
61735c4bbdfSmrg        }
61835c4bbdfSmrg        else {
61935c4bbdfSmrg            forward = FALSE;
62035c4bbdfSmrg            pWin = pParent->lastChild;
62135c4bbdfSmrg            while (1) {
62235c4bbdfSmrg                if (pWin->valdata) {
62335c4bbdfSmrg                    RegionAppend(&totalClip, getBorderClip(pWin));
62435c4bbdfSmrg                    if (pWin->viewable)
62535c4bbdfSmrg                        viewvals++;
62635c4bbdfSmrg                }
62735c4bbdfSmrg                if (pWin == pChild)
62835c4bbdfSmrg                    break;
62935c4bbdfSmrg                pWin = pWin->prevSib;
63035c4bbdfSmrg            }
63135c4bbdfSmrg        }
63235c4bbdfSmrg        RegionValidate(&totalClip, &overlap);
63305b261ecSmrg    }
63405b261ecSmrg
63505b261ecSmrg    /*
63605b261ecSmrg     * Now go through the children of the root and figure their new
63705b261ecSmrg     * borderClips from the totalClip, passing that off to miComputeClips
63805b261ecSmrg     * to handle recursively. Once that's done, we remove the child
63905b261ecSmrg     * from the totalClip to clip any siblings below it.
64005b261ecSmrg     */
64105b261ecSmrg
64205b261ecSmrg    overlap = TRUE;
64335c4bbdfSmrg    if (kind != VTStack) {
64435c4bbdfSmrg        RegionUnion(&totalClip, &totalClip, &pParent->clipList);
64535c4bbdfSmrg        if (viewvals > 1) {
64635c4bbdfSmrg            /*
64735c4bbdfSmrg             * precompute childUnion to discover whether any of them
64835c4bbdfSmrg             * overlap.  This seems redundant, but performance studies
64935c4bbdfSmrg             * have demonstrated that the cost of this loop is
65035c4bbdfSmrg             * lower than the cost of multiple Subtracts in the
65135c4bbdfSmrg             * loop below.
65235c4bbdfSmrg             */
65335c4bbdfSmrg            RegionNull(&childUnion);
65435c4bbdfSmrg            if (forward) {
65535c4bbdfSmrg                for (pWin = pChild; pWin; pWin = pWin->nextSib)
65635c4bbdfSmrg                    if (pWin->valdata && pWin->viewable &&
65735c4bbdfSmrg                        !TreatAsTransparent(pWin))
65835c4bbdfSmrg                        RegionAppend(&childUnion, &pWin->borderSize);
65935c4bbdfSmrg            }
66035c4bbdfSmrg            else {
66135c4bbdfSmrg                pWin = pParent->lastChild;
66235c4bbdfSmrg                while (1) {
66335c4bbdfSmrg                    if (pWin->valdata && pWin->viewable &&
66435c4bbdfSmrg                        !TreatAsTransparent(pWin))
66535c4bbdfSmrg                        RegionAppend(&childUnion, &pWin->borderSize);
66635c4bbdfSmrg                    if (pWin == pChild)
66735c4bbdfSmrg                        break;
66835c4bbdfSmrg                    pWin = pWin->prevSib;
66935c4bbdfSmrg                }
67035c4bbdfSmrg            }
67135c4bbdfSmrg            RegionValidate(&childUnion, &overlap);
67235c4bbdfSmrg            if (overlap)
67335c4bbdfSmrg                RegionUninit(&childUnion);
67435c4bbdfSmrg        }
67505b261ecSmrg    }
67605b261ecSmrg
67735c4bbdfSmrg    for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) {
67835c4bbdfSmrg        if (pWin->viewable) {
67935c4bbdfSmrg            if (pWin->valdata) {
68035c4bbdfSmrg                RegionIntersect(&childClip, &totalClip, &pWin->borderSize);
68135c4bbdfSmrg                miComputeClips(pWin, pScreen, &childClip, kind, &exposed);
68235c4bbdfSmrg                if (overlap && !TreatAsTransparent(pWin)) {
68335c4bbdfSmrg                    RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
68435c4bbdfSmrg                }
68535c4bbdfSmrg            }
68635c4bbdfSmrg            else if (pWin->visibility == VisibilityNotViewable) {
68735c4bbdfSmrg                miTreeObscured(pWin);
68835c4bbdfSmrg            }
68935c4bbdfSmrg        }
69035c4bbdfSmrg        else {
69135c4bbdfSmrg            if (pWin->valdata) {
69235c4bbdfSmrg                RegionEmpty(&pWin->clipList);
69335c4bbdfSmrg                if (pScreen->ClipNotify)
69435c4bbdfSmrg                    (*pScreen->ClipNotify) (pWin, 0, 0);
69535c4bbdfSmrg                RegionEmpty(&pWin->borderClip);
69635c4bbdfSmrg                pWin->valdata = NULL;
69735c4bbdfSmrg            }
69835c4bbdfSmrg        }
69905b261ecSmrg    }
70005b261ecSmrg
7016747b715Smrg    RegionUninit(&childClip);
70235c4bbdfSmrg    if (!overlap) {
70335c4bbdfSmrg        RegionSubtract(&totalClip, &totalClip, &childUnion);
70435c4bbdfSmrg        RegionUninit(&childUnion);
70505b261ecSmrg    }
70605b261ecSmrg
7076747b715Smrg    RegionNull(&pParent->valdata->after.exposed);
7086747b715Smrg    RegionNull(&pParent->valdata->after.borderExposed);
70905b261ecSmrg
71005b261ecSmrg    /*
71105b261ecSmrg     * each case below is responsible for updating the
71205b261ecSmrg     * clipList and serial number for the parent window
71305b261ecSmrg     */
71405b261ecSmrg
71505b261ecSmrg    switch (kind) {
71605b261ecSmrg    case VTStack:
71735c4bbdfSmrg        break;
71805b261ecSmrg    default:
71935c4bbdfSmrg        /*
72035c4bbdfSmrg         * totalClip contains the new clipList for the parent. Figure out
72135c4bbdfSmrg         * exposures and obscures as per miComputeClips and reset the parent's
72235c4bbdfSmrg         * clipList.
72335c4bbdfSmrg         */
72435c4bbdfSmrg        RegionSubtract(&pParent->valdata->after.exposed,
72535c4bbdfSmrg                       &totalClip, &pParent->clipList);
72635c4bbdfSmrg        /* fall through */
72705b261ecSmrg    case VTMap:
72835c4bbdfSmrg        RegionCopy(&pParent->clipList, &totalClip);
72935c4bbdfSmrg        pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
73035c4bbdfSmrg        break;
73105b261ecSmrg    }
73205b261ecSmrg
7336747b715Smrg    RegionUninit(&totalClip);
7346747b715Smrg    RegionUninit(&exposed);
73505b261ecSmrg    if (pScreen->ClipNotify)
73635c4bbdfSmrg        (*pScreen->ClipNotify) (pParent, 0, 0);
7376747b715Smrg    return 1;
73805b261ecSmrg}
739