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