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