1706f2543Smrg/* 2706f2543Smrg * mivaltree.c -- 3706f2543Smrg * Functions for recalculating window clip lists. Main function 4706f2543Smrg * is miValidateTree. 5706f2543Smrg * 6706f2543Smrg 7706f2543SmrgCopyright 1987, 1988, 1989, 1998 The Open Group 8706f2543Smrg 9706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 10706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 11706f2543Smrgthe above copyright notice appear in all copies and that both that 12706f2543Smrgcopyright notice and this permission notice appear in supporting 13706f2543Smrgdocumentation. 14706f2543Smrg 15706f2543SmrgThe above copyright notice and this permission notice shall be included in 16706f2543Smrgall copies or substantial portions of the Software. 17706f2543Smrg 18706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24706f2543Smrg 25706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be 26706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings 27706f2543Smrgin this Software without prior written authorization from The Open Group. 28706f2543Smrg 29706f2543Smrg * 30706f2543Smrg * Copyright 1987, 1988, 1989 by 31706f2543Smrg * Digital Equipment Corporation, Maynard, Massachusetts, 32706f2543Smrg * 33706f2543Smrg * All Rights Reserved 34706f2543Smrg * 35706f2543Smrg * Permission to use, copy, modify, and distribute this software and its 36706f2543Smrg * documentation for any purpose and without fee is hereby granted, 37706f2543Smrg * provided that the above copyright notice appear in all copies and that 38706f2543Smrg * both that copyright notice and this permission notice appear in 39706f2543Smrg * supporting documentation, and that the name of Digital not be 40706f2543Smrg * used in advertising or publicity pertaining to distribution of the 41706f2543Smrg * software without specific, written prior permission. 42706f2543Smrg * 43706f2543Smrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 44706f2543Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 45706f2543Smrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 46706f2543Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 47706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 48706f2543Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 49706f2543Smrg * SOFTWARE. 50706f2543Smrg * 51706f2543Smrg ******************************************************************/ 52706f2543Smrg 53706f2543Smrg/* The panoramix components contained the following notice */ 54706f2543Smrg/***************************************************************** 55706f2543Smrg 56706f2543SmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 57706f2543Smrg 58706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy 59706f2543Smrgof this software and associated documentation files (the "Software"), to deal 60706f2543Smrgin the Software without restriction, including without limitation the rights 61706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 62706f2543Smrgcopies of the Software. 63706f2543Smrg 64706f2543SmrgThe above copyright notice and this permission notice shall be included in 65706f2543Smrgall copies or substantial portions of the Software. 66706f2543Smrg 67706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 68706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 69706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 70706f2543SmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 71706f2543SmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 72706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 73706f2543SmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 74706f2543Smrg 75706f2543SmrgExcept as contained in this notice, the name of Digital Equipment Corporation 76706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use or other 77706f2543Smrgdealings in this Software without prior written authorization from Digital 78706f2543SmrgEquipment Corporation. 79706f2543Smrg 80706f2543Smrg******************************************************************/ 81706f2543Smrg 82706f2543Smrg 83706f2543Smrg /* 84706f2543Smrg * Aug '86: Susan Angebranndt -- original code 85706f2543Smrg * July '87: Adam de Boor -- substantially modified and commented 86706f2543Smrg * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible. 87706f2543Smrg * In particular, much improved code for window mapping and 88706f2543Smrg * circulating. 89706f2543Smrg * Bob Scheifler -- avoid miComputeClips for unmapped windows, 90706f2543Smrg * valdata changes 91706f2543Smrg */ 92706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 93706f2543Smrg#include <dix-config.h> 94706f2543Smrg#endif 95706f2543Smrg 96706f2543Smrg#include <X11/X.h> 97706f2543Smrg#include "scrnintstr.h" 98706f2543Smrg#include "validate.h" 99706f2543Smrg#include "windowstr.h" 100706f2543Smrg#include "mi.h" 101706f2543Smrg#include "regionstr.h" 102706f2543Smrg#include "mivalidate.h" 103706f2543Smrg 104706f2543Smrg#include "globals.h" 105706f2543Smrg 106706f2543Smrg/* 107706f2543Smrg * Compute the visibility of a shaped window 108706f2543Smrg */ 109706f2543Smrgint 110706f2543SmrgmiShapedWindowIn (RegionPtr universe, RegionPtr bounding, 111706f2543Smrg BoxPtr rect, int x, int y) 112706f2543Smrg{ 113706f2543Smrg BoxRec box; 114706f2543Smrg BoxPtr boundBox; 115706f2543Smrg int nbox; 116706f2543Smrg Bool someIn, someOut; 117706f2543Smrg int t, x1, y1, x2, y2; 118706f2543Smrg 119706f2543Smrg nbox = RegionNumRects (bounding); 120706f2543Smrg boundBox = RegionRects (bounding); 121706f2543Smrg someIn = someOut = FALSE; 122706f2543Smrg x1 = rect->x1; 123706f2543Smrg y1 = rect->y1; 124706f2543Smrg x2 = rect->x2; 125706f2543Smrg y2 = rect->y2; 126706f2543Smrg while (nbox--) 127706f2543Smrg { 128706f2543Smrg if ((t = boundBox->x1 + x) < x1) 129706f2543Smrg t = x1; 130706f2543Smrg box.x1 = t; 131706f2543Smrg if ((t = boundBox->y1 + y) < y1) 132706f2543Smrg t = y1; 133706f2543Smrg box.y1 = t; 134706f2543Smrg if ((t = boundBox->x2 + x) > x2) 135706f2543Smrg t = x2; 136706f2543Smrg box.x2 = t; 137706f2543Smrg if ((t = boundBox->y2 + y) > y2) 138706f2543Smrg t = y2; 139706f2543Smrg box.y2 = t; 140706f2543Smrg if (box.x1 > box.x2) 141706f2543Smrg box.x2 = box.x1; 142706f2543Smrg if (box.y1 > box.y2) 143706f2543Smrg box.y2 = box.y1; 144706f2543Smrg switch (RegionContainsRect(universe, &box)) 145706f2543Smrg { 146706f2543Smrg case rgnIN: 147706f2543Smrg if (someOut) 148706f2543Smrg return rgnPART; 149706f2543Smrg someIn = TRUE; 150706f2543Smrg break; 151706f2543Smrg case rgnOUT: 152706f2543Smrg if (someIn) 153706f2543Smrg return rgnPART; 154706f2543Smrg someOut = TRUE; 155706f2543Smrg break; 156706f2543Smrg default: 157706f2543Smrg return rgnPART; 158706f2543Smrg } 159706f2543Smrg boundBox++; 160706f2543Smrg } 161706f2543Smrg if (someIn) 162706f2543Smrg return rgnIN; 163706f2543Smrg return rgnOUT; 164706f2543Smrg} 165706f2543Smrg 166706f2543Smrgstatic GetRedirectBorderClipProcPtr miGetRedirectBorderClipProc; 167706f2543Smrgstatic SetRedirectBorderClipProcPtr miSetRedirectBorderClipProc; 168706f2543Smrg 169706f2543Smrgvoid 170706f2543SmrgmiRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip, 171706f2543Smrg GetRedirectBorderClipProcPtr getBorderClip) 172706f2543Smrg{ 173706f2543Smrg miSetRedirectBorderClipProc = setBorderClip; 174706f2543Smrg miGetRedirectBorderClipProc = getBorderClip; 175706f2543Smrg} 176706f2543Smrg 177706f2543Smrg/* 178706f2543Smrg * Manual redirected windows are treated as transparent; they do not obscure 179706f2543Smrg * siblings or parent windows 180706f2543Smrg */ 181706f2543Smrg 182706f2543Smrg#ifdef COMPOSITE 183706f2543Smrg#define TreatAsTransparent(w) ((w)->redirectDraw == RedirectDrawManual) 184706f2543Smrg#else 185706f2543Smrg#define TreatAsTransparent(w) FALSE 186706f2543Smrg#endif 187706f2543Smrg 188706f2543Smrg#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \ 189706f2543Smrg HasBorder(w) && \ 190706f2543Smrg (w)->backgroundState == ParentRelative) 191706f2543Smrg 192706f2543Smrg 193706f2543Smrg/* 194706f2543Smrg *----------------------------------------------------------------------- 195706f2543Smrg * miComputeClips -- 196706f2543Smrg * Recompute the clipList, borderClip, exposed and borderExposed 197706f2543Smrg * regions for pParent and its children. Only viewable windows are 198706f2543Smrg * taken into account. 199706f2543Smrg * 200706f2543Smrg * Results: 201706f2543Smrg * None. 202706f2543Smrg * 203706f2543Smrg * Side Effects: 204706f2543Smrg * clipList, borderClip, exposed and borderExposed are altered. 205706f2543Smrg * A VisibilityNotify event may be generated on the parent window. 206706f2543Smrg * 207706f2543Smrg *----------------------------------------------------------------------- 208706f2543Smrg */ 209706f2543Smrgstatic void 210706f2543SmrgmiComputeClips ( 211706f2543Smrg WindowPtr pParent, 212706f2543Smrg ScreenPtr pScreen, 213706f2543Smrg RegionPtr universe, 214706f2543Smrg VTKind kind, 215706f2543Smrg RegionPtr exposed ) /* for intermediate calculations */ 216706f2543Smrg{ 217706f2543Smrg int dx, 218706f2543Smrg dy; 219706f2543Smrg RegionRec childUniverse; 220706f2543Smrg WindowPtr pChild; 221706f2543Smrg int oldVis, newVis; 222706f2543Smrg BoxRec borderSize; 223706f2543Smrg RegionRec childUnion; 224706f2543Smrg Bool overlap; 225706f2543Smrg RegionPtr borderVisible; 226706f2543Smrg Bool resized; 227706f2543Smrg /* 228706f2543Smrg * Figure out the new visibility of this window. 229706f2543Smrg * The extent of the universe should be the same as the extent of 230706f2543Smrg * the borderSize region. If the window is unobscured, this rectangle 231706f2543Smrg * will be completely inside the universe (the universe will cover it 232706f2543Smrg * completely). If the window is completely obscured, none of the 233706f2543Smrg * universe will cover the rectangle. 234706f2543Smrg */ 235706f2543Smrg borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent); 236706f2543Smrg borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent); 237706f2543Smrg dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent); 238706f2543Smrg if (dx > 32767) 239706f2543Smrg dx = 32767; 240706f2543Smrg borderSize.x2 = dx; 241706f2543Smrg dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent); 242706f2543Smrg if (dy > 32767) 243706f2543Smrg dy = 32767; 244706f2543Smrg borderSize.y2 = dy; 245706f2543Smrg 246706f2543Smrg#ifdef COMPOSITE 247706f2543Smrg /* 248706f2543Smrg * In redirected drawing case, reset universe to borderSize 249706f2543Smrg */ 250706f2543Smrg if (pParent->redirectDraw != RedirectDrawNone) 251706f2543Smrg { 252706f2543Smrg if (miSetRedirectBorderClipProc) 253706f2543Smrg { 254706f2543Smrg if (TreatAsTransparent (pParent)) 255706f2543Smrg RegionEmpty(universe); 256706f2543Smrg (*miSetRedirectBorderClipProc) (pParent, universe); 257706f2543Smrg } 258706f2543Smrg RegionCopy(universe, &pParent->borderSize); 259706f2543Smrg } 260706f2543Smrg#endif 261706f2543Smrg 262706f2543Smrg oldVis = pParent->visibility; 263706f2543Smrg switch (RegionContainsRect(universe, &borderSize)) 264706f2543Smrg { 265706f2543Smrg case rgnIN: 266706f2543Smrg newVis = VisibilityUnobscured; 267706f2543Smrg break; 268706f2543Smrg case rgnPART: 269706f2543Smrg newVis = VisibilityPartiallyObscured; 270706f2543Smrg { 271706f2543Smrg RegionPtr pBounding; 272706f2543Smrg 273706f2543Smrg if ((pBounding = wBoundingShape (pParent))) 274706f2543Smrg { 275706f2543Smrg switch (miShapedWindowIn (universe, pBounding, 276706f2543Smrg &borderSize, 277706f2543Smrg pParent->drawable.x, 278706f2543Smrg pParent->drawable.y)) 279706f2543Smrg { 280706f2543Smrg case rgnIN: 281706f2543Smrg newVis = VisibilityUnobscured; 282706f2543Smrg break; 283706f2543Smrg case rgnOUT: 284706f2543Smrg newVis = VisibilityFullyObscured; 285706f2543Smrg break; 286706f2543Smrg } 287706f2543Smrg } 288706f2543Smrg } 289706f2543Smrg break; 290706f2543Smrg default: 291706f2543Smrg newVis = VisibilityFullyObscured; 292706f2543Smrg break; 293706f2543Smrg } 294706f2543Smrg pParent->visibility = newVis; 295706f2543Smrg if (oldVis != newVis && 296706f2543Smrg ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask)) 297706f2543Smrg SendVisibilityNotify(pParent); 298706f2543Smrg 299706f2543Smrg dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x; 300706f2543Smrg dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y; 301706f2543Smrg 302706f2543Smrg /* 303706f2543Smrg * avoid computations when dealing with simple operations 304706f2543Smrg */ 305706f2543Smrg 306706f2543Smrg switch (kind) { 307706f2543Smrg case VTMap: 308706f2543Smrg case VTStack: 309706f2543Smrg case VTUnmap: 310706f2543Smrg break; 311706f2543Smrg case VTMove: 312706f2543Smrg if ((oldVis == newVis) && 313706f2543Smrg ((oldVis == VisibilityFullyObscured) || 314706f2543Smrg (oldVis == VisibilityUnobscured))) 315706f2543Smrg { 316706f2543Smrg pChild = pParent; 317706f2543Smrg while (1) 318706f2543Smrg { 319706f2543Smrg if (pChild->viewable) 320706f2543Smrg { 321706f2543Smrg if (pChild->visibility != VisibilityFullyObscured) 322706f2543Smrg { 323706f2543Smrg RegionTranslate(&pChild->borderClip, 324706f2543Smrg dx, dy); 325706f2543Smrg RegionTranslate(&pChild->clipList, 326706f2543Smrg dx, dy); 327706f2543Smrg pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; 328706f2543Smrg if (pScreen->ClipNotify) 329706f2543Smrg (* pScreen->ClipNotify) (pChild, dx, dy); 330706f2543Smrg 331706f2543Smrg } 332706f2543Smrg if (pChild->valdata) 333706f2543Smrg { 334706f2543Smrg RegionNull(&pChild->valdata->after.borderExposed); 335706f2543Smrg if (HasParentRelativeBorder(pChild)) 336706f2543Smrg { 337706f2543Smrg RegionSubtract(&pChild->valdata->after.borderExposed, 338706f2543Smrg &pChild->borderClip, 339706f2543Smrg &pChild->winSize); 340706f2543Smrg } 341706f2543Smrg RegionNull(&pChild->valdata->after.exposed); 342706f2543Smrg } 343706f2543Smrg if (pChild->firstChild) 344706f2543Smrg { 345706f2543Smrg pChild = pChild->firstChild; 346706f2543Smrg continue; 347706f2543Smrg } 348706f2543Smrg } 349706f2543Smrg while (!pChild->nextSib && (pChild != pParent)) 350706f2543Smrg pChild = pChild->parent; 351706f2543Smrg if (pChild == pParent) 352706f2543Smrg break; 353706f2543Smrg pChild = pChild->nextSib; 354706f2543Smrg } 355706f2543Smrg return; 356706f2543Smrg } 357706f2543Smrg /* fall through */ 358706f2543Smrg default: 359706f2543Smrg /* 360706f2543Smrg * To calculate exposures correctly, we have to translate the old 361706f2543Smrg * borderClip and clipList regions to the window's new location so there 362706f2543Smrg * is a correspondence between pieces of the new and old clipping regions. 363706f2543Smrg */ 364706f2543Smrg if (dx || dy) 365706f2543Smrg { 366706f2543Smrg /* 367706f2543Smrg * We translate the old clipList because that will be exposed or copied 368706f2543Smrg * if gravity is right. 369706f2543Smrg */ 370706f2543Smrg RegionTranslate(&pParent->borderClip, dx, dy); 371706f2543Smrg RegionTranslate(&pParent->clipList, dx, dy); 372706f2543Smrg } 373706f2543Smrg break; 374706f2543Smrg case VTBroken: 375706f2543Smrg RegionEmpty(&pParent->borderClip); 376706f2543Smrg RegionEmpty(&pParent->clipList); 377706f2543Smrg break; 378706f2543Smrg } 379706f2543Smrg 380706f2543Smrg borderVisible = pParent->valdata->before.borderVisible; 381706f2543Smrg resized = pParent->valdata->before.resized; 382706f2543Smrg RegionNull(&pParent->valdata->after.borderExposed); 383706f2543Smrg RegionNull(&pParent->valdata->after.exposed); 384706f2543Smrg 385706f2543Smrg /* 386706f2543Smrg * Since the borderClip must not be clipped by the children, we do 387706f2543Smrg * the border exposure first... 388706f2543Smrg * 389706f2543Smrg * 'universe' is the window's borderClip. To figure the exposures, remove 390706f2543Smrg * the area that used to be exposed from the new. 391706f2543Smrg * This leaves a region of pieces that weren't exposed before. 392706f2543Smrg */ 393706f2543Smrg 394706f2543Smrg if (HasBorder (pParent)) 395706f2543Smrg { 396706f2543Smrg if (borderVisible) 397706f2543Smrg { 398706f2543Smrg /* 399706f2543Smrg * when the border changes shape, the old visible portions 400706f2543Smrg * of the border will be saved by DIX in borderVisible -- 401706f2543Smrg * use that region and destroy it 402706f2543Smrg */ 403706f2543Smrg RegionSubtract(exposed, universe, borderVisible); 404706f2543Smrg RegionDestroy(borderVisible); 405706f2543Smrg } 406706f2543Smrg else 407706f2543Smrg { 408706f2543Smrg RegionSubtract(exposed, universe, &pParent->borderClip); 409706f2543Smrg } 410706f2543Smrg if (HasParentRelativeBorder(pParent) && (dx || dy)) 411706f2543Smrg RegionSubtract(&pParent->valdata->after.borderExposed, 412706f2543Smrg universe, 413706f2543Smrg &pParent->winSize); 414706f2543Smrg else 415706f2543Smrg RegionSubtract(&pParent->valdata->after.borderExposed, 416706f2543Smrg exposed, &pParent->winSize); 417706f2543Smrg 418706f2543Smrg RegionCopy(&pParent->borderClip, universe); 419706f2543Smrg 420706f2543Smrg /* 421706f2543Smrg * To get the right clipList for the parent, and to make doubly sure 422706f2543Smrg * that no child overlaps the parent's border, we remove the parent's 423706f2543Smrg * border from the universe before proceeding. 424706f2543Smrg */ 425706f2543Smrg 426706f2543Smrg RegionIntersect(universe, universe, &pParent->winSize); 427706f2543Smrg } 428706f2543Smrg else 429706f2543Smrg RegionCopy(&pParent->borderClip, universe); 430706f2543Smrg 431706f2543Smrg if ((pChild = pParent->firstChild) && pParent->mapped) 432706f2543Smrg { 433706f2543Smrg RegionNull(&childUniverse); 434706f2543Smrg RegionNull(&childUnion); 435706f2543Smrg if ((pChild->drawable.y < pParent->lastChild->drawable.y) || 436706f2543Smrg ((pChild->drawable.y == pParent->lastChild->drawable.y) && 437706f2543Smrg (pChild->drawable.x < pParent->lastChild->drawable.x))) 438706f2543Smrg { 439706f2543Smrg for (; pChild; pChild = pChild->nextSib) 440706f2543Smrg { 441706f2543Smrg if (pChild->viewable && !TreatAsTransparent(pChild)) 442706f2543Smrg RegionAppend(&childUnion, &pChild->borderSize); 443706f2543Smrg } 444706f2543Smrg } 445706f2543Smrg else 446706f2543Smrg { 447706f2543Smrg for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) 448706f2543Smrg { 449706f2543Smrg if (pChild->viewable && !TreatAsTransparent(pChild)) 450706f2543Smrg RegionAppend(&childUnion, &pChild->borderSize); 451706f2543Smrg } 452706f2543Smrg } 453706f2543Smrg RegionValidate(&childUnion, &overlap); 454706f2543Smrg 455706f2543Smrg for (pChild = pParent->firstChild; 456706f2543Smrg pChild; 457706f2543Smrg pChild = pChild->nextSib) 458706f2543Smrg { 459706f2543Smrg if (pChild->viewable) { 460706f2543Smrg /* 461706f2543Smrg * If the child is viewable, we want to remove its extents 462706f2543Smrg * from the current universe, but we only re-clip it if 463706f2543Smrg * it's been marked. 464706f2543Smrg */ 465706f2543Smrg if (pChild->valdata) { 466706f2543Smrg /* 467706f2543Smrg * Figure out the new universe from the child's 468706f2543Smrg * perspective and recurse. 469706f2543Smrg */ 470706f2543Smrg RegionIntersect(&childUniverse, 471706f2543Smrg universe, 472706f2543Smrg &pChild->borderSize); 473706f2543Smrg miComputeClips (pChild, pScreen, &childUniverse, kind, 474706f2543Smrg exposed); 475706f2543Smrg } 476706f2543Smrg /* 477706f2543Smrg * Once the child has been processed, we remove its extents 478706f2543Smrg * from the current universe, thus denying its space to any 479706f2543Smrg * other sibling. 480706f2543Smrg */ 481706f2543Smrg if (overlap && !TreatAsTransparent (pChild)) 482706f2543Smrg RegionSubtract(universe, universe, 483706f2543Smrg &pChild->borderSize); 484706f2543Smrg } 485706f2543Smrg } 486706f2543Smrg if (!overlap) 487706f2543Smrg RegionSubtract(universe, universe, &childUnion); 488706f2543Smrg RegionUninit(&childUnion); 489706f2543Smrg RegionUninit(&childUniverse); 490706f2543Smrg } /* if any children */ 491706f2543Smrg 492706f2543Smrg /* 493706f2543Smrg * 'universe' now contains the new clipList for the parent window. 494706f2543Smrg * 495706f2543Smrg * To figure the exposure of the window we subtract the old clip from the 496706f2543Smrg * new, just as for the border. 497706f2543Smrg */ 498706f2543Smrg 499706f2543Smrg if (oldVis == VisibilityFullyObscured || 500706f2543Smrg oldVis == VisibilityNotViewable) 501706f2543Smrg { 502706f2543Smrg RegionCopy(&pParent->valdata->after.exposed, universe); 503706f2543Smrg } 504706f2543Smrg else if (newVis != VisibilityFullyObscured && 505706f2543Smrg newVis != VisibilityNotViewable) 506706f2543Smrg { 507706f2543Smrg RegionSubtract(&pParent->valdata->after.exposed, 508706f2543Smrg universe, &pParent->clipList); 509706f2543Smrg } 510706f2543Smrg 511706f2543Smrg /* HACK ALERT - copying contents of regions, instead of regions */ 512706f2543Smrg { 513706f2543Smrg RegionRec tmp; 514706f2543Smrg 515706f2543Smrg tmp = pParent->clipList; 516706f2543Smrg pParent->clipList = *universe; 517706f2543Smrg *universe = tmp; 518706f2543Smrg } 519706f2543Smrg 520706f2543Smrg#ifdef NOTDEF 521706f2543Smrg RegionCopy(&pParent->clipList, universe); 522706f2543Smrg#endif 523706f2543Smrg 524706f2543Smrg pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; 525706f2543Smrg 526706f2543Smrg if (pScreen->ClipNotify) 527706f2543Smrg (* pScreen->ClipNotify) (pParent, dx, dy); 528706f2543Smrg} 529706f2543Smrg 530706f2543Smrgstatic void 531706f2543SmrgmiTreeObscured( 532706f2543Smrg WindowPtr pParent ) 533706f2543Smrg{ 534706f2543Smrg WindowPtr pChild; 535706f2543Smrg int oldVis; 536706f2543Smrg 537706f2543Smrg pChild = pParent; 538706f2543Smrg while (1) 539706f2543Smrg { 540706f2543Smrg if (pChild->viewable) 541706f2543Smrg { 542706f2543Smrg oldVis = pChild->visibility; 543706f2543Smrg if (oldVis != (pChild->visibility = VisibilityFullyObscured) && 544706f2543Smrg ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask)) 545706f2543Smrg SendVisibilityNotify(pChild); 546706f2543Smrg if (pChild->firstChild) 547706f2543Smrg { 548706f2543Smrg pChild = pChild->firstChild; 549706f2543Smrg continue; 550706f2543Smrg } 551706f2543Smrg } 552706f2543Smrg while (!pChild->nextSib && (pChild != pParent)) 553706f2543Smrg pChild = pChild->parent; 554706f2543Smrg if (pChild == pParent) 555706f2543Smrg break; 556706f2543Smrg pChild = pChild->nextSib; 557706f2543Smrg } 558706f2543Smrg} 559706f2543Smrg 560706f2543Smrg/* 561706f2543Smrg *----------------------------------------------------------------------- 562706f2543Smrg * miValidateTree -- 563706f2543Smrg * Recomputes the clip list for pParent and all its inferiors. 564706f2543Smrg * 565706f2543Smrg * Results: 566706f2543Smrg * Always returns 1. 567706f2543Smrg * 568706f2543Smrg * Side Effects: 569706f2543Smrg * The clipList, borderClip, exposed, and borderExposed regions for 570706f2543Smrg * each marked window are altered. 571706f2543Smrg * 572706f2543Smrg * Notes: 573706f2543Smrg * This routine assumes that all affected windows have been marked 574706f2543Smrg * (valdata created) and their winSize and borderSize regions 575706f2543Smrg * adjusted to correspond to their new positions. The borderClip and 576706f2543Smrg * clipList regions should not have been touched. 577706f2543Smrg * 578706f2543Smrg * The top-most level is treated differently from all lower levels 579706f2543Smrg * because pParent is unchanged. For the top level, we merge the 580706f2543Smrg * regions taken up by the marked children back into the clipList 581706f2543Smrg * for pParent, thus forming a region from which the marked children 582706f2543Smrg * can claim their areas. For lower levels, where the old clipList 583706f2543Smrg * and borderClip are invalid, we can't do this and have to do the 584706f2543Smrg * extra operations done in miComputeClips, but this is much faster 585706f2543Smrg * e.g. when only one child has moved... 586706f2543Smrg * 587706f2543Smrg *----------------------------------------------------------------------- 588706f2543Smrg */ 589706f2543Smrg/*ARGSUSED*/ 590706f2543Smrgint 591706f2543SmrgmiValidateTree ( 592706f2543Smrg WindowPtr pParent, /* Parent to validate */ 593706f2543Smrg WindowPtr pChild, /* First child of pParent that was 594706f2543Smrg * affected */ 595706f2543Smrg VTKind kind /* What kind of configuration caused call */ 596706f2543Smrg ) 597706f2543Smrg{ 598706f2543Smrg RegionRec totalClip; /* Total clipping region available to 599706f2543Smrg * the marked children. pParent's clipList 600706f2543Smrg * merged with the borderClips of all 601706f2543Smrg * the marked children. */ 602706f2543Smrg RegionRec childClip; /* The new borderClip for the current 603706f2543Smrg * child */ 604706f2543Smrg RegionRec childUnion; /* the space covered by borderSize for 605706f2543Smrg * all marked children */ 606706f2543Smrg RegionRec exposed; /* For intermediate calculations */ 607706f2543Smrg ScreenPtr pScreen; 608706f2543Smrg WindowPtr pWin; 609706f2543Smrg Bool overlap; 610706f2543Smrg int viewvals; 611706f2543Smrg Bool forward; 612706f2543Smrg 613706f2543Smrg pScreen = pParent->drawable.pScreen; 614706f2543Smrg if (pChild == NullWindow) 615706f2543Smrg pChild = pParent->firstChild; 616706f2543Smrg 617706f2543Smrg RegionNull(&childClip); 618706f2543Smrg RegionNull(&exposed); 619706f2543Smrg 620706f2543Smrg /* 621706f2543Smrg * compute the area of the parent window occupied 622706f2543Smrg * by the marked children + the parent itself. This 623706f2543Smrg * is the area which can be divied up among the marked 624706f2543Smrg * children in their new configuration. 625706f2543Smrg */ 626706f2543Smrg RegionNull(&totalClip); 627706f2543Smrg viewvals = 0; 628706f2543Smrg if (RegionBroken(&pParent->clipList) && 629706f2543Smrg !RegionBroken(&pParent->borderClip)) 630706f2543Smrg { 631706f2543Smrg kind = VTBroken; 632706f2543Smrg /* 633706f2543Smrg * When rebuilding clip lists after out of memory, 634706f2543Smrg * assume everything is busted. 635706f2543Smrg */ 636706f2543Smrg forward = TRUE; 637706f2543Smrg RegionCopy(&totalClip, &pParent->borderClip); 638706f2543Smrg RegionIntersect(&totalClip, &totalClip, &pParent->winSize); 639706f2543Smrg 640706f2543Smrg for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib) 641706f2543Smrg { 642706f2543Smrg if (pWin->viewable && !TreatAsTransparent (pWin)) 643706f2543Smrg RegionSubtract(&totalClip, &totalClip, &pWin->borderSize); 644706f2543Smrg } 645706f2543Smrg for (pWin = pChild; pWin; pWin = pWin->nextSib) 646706f2543Smrg if (pWin->valdata && pWin->viewable) 647706f2543Smrg viewvals++; 648706f2543Smrg 649706f2543Smrg RegionEmpty(&pParent->clipList); 650706f2543Smrg } 651706f2543Smrg else 652706f2543Smrg { 653706f2543Smrg if ((pChild->drawable.y < pParent->lastChild->drawable.y) || 654706f2543Smrg ((pChild->drawable.y == pParent->lastChild->drawable.y) && 655706f2543Smrg (pChild->drawable.x < pParent->lastChild->drawable.x))) 656706f2543Smrg { 657706f2543Smrg forward = TRUE; 658706f2543Smrg for (pWin = pChild; pWin; pWin = pWin->nextSib) 659706f2543Smrg { 660706f2543Smrg if (pWin->valdata) 661706f2543Smrg { 662706f2543Smrg RegionPtr pBorderClip = &pWin->borderClip; 663706f2543Smrg#ifdef COMPOSITE 664706f2543Smrg if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc) 665706f2543Smrg pBorderClip = (*miGetRedirectBorderClipProc)(pWin); 666706f2543Smrg#endif 667706f2543Smrg RegionAppend(&totalClip, pBorderClip ); 668706f2543Smrg if (pWin->viewable) 669706f2543Smrg viewvals++; 670706f2543Smrg } 671706f2543Smrg } 672706f2543Smrg } 673706f2543Smrg else 674706f2543Smrg { 675706f2543Smrg forward = FALSE; 676706f2543Smrg pWin = pParent->lastChild; 677706f2543Smrg while (1) 678706f2543Smrg { 679706f2543Smrg if (pWin->valdata) 680706f2543Smrg { 681706f2543Smrg RegionPtr pBorderClip = &pWin->borderClip; 682706f2543Smrg#ifdef COMPOSITE 683706f2543Smrg if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc) 684706f2543Smrg pBorderClip = (*miGetRedirectBorderClipProc)(pWin); 685706f2543Smrg#endif 686706f2543Smrg RegionAppend(&totalClip, pBorderClip ); 687706f2543Smrg if (pWin->viewable) 688706f2543Smrg viewvals++; 689706f2543Smrg } 690706f2543Smrg if (pWin == pChild) 691706f2543Smrg break; 692706f2543Smrg pWin = pWin->prevSib; 693706f2543Smrg } 694706f2543Smrg } 695706f2543Smrg RegionValidate(&totalClip, &overlap); 696706f2543Smrg } 697706f2543Smrg 698706f2543Smrg /* 699706f2543Smrg * Now go through the children of the root and figure their new 700706f2543Smrg * borderClips from the totalClip, passing that off to miComputeClips 701706f2543Smrg * to handle recursively. Once that's done, we remove the child 702706f2543Smrg * from the totalClip to clip any siblings below it. 703706f2543Smrg */ 704706f2543Smrg 705706f2543Smrg overlap = TRUE; 706706f2543Smrg if (kind != VTStack) 707706f2543Smrg { 708706f2543Smrg RegionUnion(&totalClip, &totalClip, &pParent->clipList); 709706f2543Smrg if (viewvals > 1) 710706f2543Smrg { 711706f2543Smrg /* 712706f2543Smrg * precompute childUnion to discover whether any of them 713706f2543Smrg * overlap. This seems redundant, but performance studies 714706f2543Smrg * have demonstrated that the cost of this loop is 715706f2543Smrg * lower than the cost of multiple Subtracts in the 716706f2543Smrg * loop below. 717706f2543Smrg */ 718706f2543Smrg RegionNull(&childUnion); 719706f2543Smrg if (forward) 720706f2543Smrg { 721706f2543Smrg for (pWin = pChild; pWin; pWin = pWin->nextSib) 722706f2543Smrg if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin)) 723706f2543Smrg RegionAppend(&childUnion, 724706f2543Smrg &pWin->borderSize); 725706f2543Smrg } 726706f2543Smrg else 727706f2543Smrg { 728706f2543Smrg pWin = pParent->lastChild; 729706f2543Smrg while (1) 730706f2543Smrg { 731706f2543Smrg if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin)) 732706f2543Smrg RegionAppend(&childUnion, 733706f2543Smrg &pWin->borderSize); 734706f2543Smrg if (pWin == pChild) 735706f2543Smrg break; 736706f2543Smrg pWin = pWin->prevSib; 737706f2543Smrg } 738706f2543Smrg } 739706f2543Smrg RegionValidate(&childUnion, &overlap); 740706f2543Smrg if (overlap) 741706f2543Smrg RegionUninit(&childUnion); 742706f2543Smrg } 743706f2543Smrg } 744706f2543Smrg 745706f2543Smrg for (pWin = pChild; 746706f2543Smrg pWin != NullWindow; 747706f2543Smrg pWin = pWin->nextSib) 748706f2543Smrg { 749706f2543Smrg if (pWin->viewable) { 750706f2543Smrg if (pWin->valdata) { 751706f2543Smrg RegionIntersect(&childClip, 752706f2543Smrg &totalClip, 753706f2543Smrg &pWin->borderSize); 754706f2543Smrg miComputeClips (pWin, pScreen, &childClip, kind, &exposed); 755706f2543Smrg if (overlap && !TreatAsTransparent (pWin)) 756706f2543Smrg { 757706f2543Smrg RegionSubtract(&totalClip, 758706f2543Smrg &totalClip, 759706f2543Smrg &pWin->borderSize); 760706f2543Smrg } 761706f2543Smrg } else if (pWin->visibility == VisibilityNotViewable) { 762706f2543Smrg miTreeObscured(pWin); 763706f2543Smrg } 764706f2543Smrg } else { 765706f2543Smrg if (pWin->valdata) { 766706f2543Smrg RegionEmpty(&pWin->clipList); 767706f2543Smrg if (pScreen->ClipNotify) 768706f2543Smrg (* pScreen->ClipNotify) (pWin, 0, 0); 769706f2543Smrg RegionEmpty(&pWin->borderClip); 770706f2543Smrg pWin->valdata = NULL; 771706f2543Smrg } 772706f2543Smrg } 773706f2543Smrg } 774706f2543Smrg 775706f2543Smrg RegionUninit(&childClip); 776706f2543Smrg if (!overlap) 777706f2543Smrg { 778706f2543Smrg RegionSubtract(&totalClip, &totalClip, &childUnion); 779706f2543Smrg RegionUninit(&childUnion); 780706f2543Smrg } 781706f2543Smrg 782706f2543Smrg RegionNull(&pParent->valdata->after.exposed); 783706f2543Smrg RegionNull(&pParent->valdata->after.borderExposed); 784706f2543Smrg 785706f2543Smrg /* 786706f2543Smrg * each case below is responsible for updating the 787706f2543Smrg * clipList and serial number for the parent window 788706f2543Smrg */ 789706f2543Smrg 790706f2543Smrg switch (kind) { 791706f2543Smrg case VTStack: 792706f2543Smrg break; 793706f2543Smrg default: 794706f2543Smrg /* 795706f2543Smrg * totalClip contains the new clipList for the parent. Figure out 796706f2543Smrg * exposures and obscures as per miComputeClips and reset the parent's 797706f2543Smrg * clipList. 798706f2543Smrg */ 799706f2543Smrg RegionSubtract(&pParent->valdata->after.exposed, 800706f2543Smrg &totalClip, &pParent->clipList); 801706f2543Smrg /* fall through */ 802706f2543Smrg case VTMap: 803706f2543Smrg RegionCopy(&pParent->clipList, &totalClip); 804706f2543Smrg pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; 805706f2543Smrg break; 806706f2543Smrg } 807706f2543Smrg 808706f2543Smrg RegionUninit(&totalClip); 809706f2543Smrg RegionUninit(&exposed); 810706f2543Smrg if (pScreen->ClipNotify) 811706f2543Smrg (*pScreen->ClipNotify) (pParent, 0, 0); 812706f2543Smrg return 1; 813706f2543Smrg} 814