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