mivaltree.c revision 4642e01f
1/* 2 * mivaltree.c -- 3 * Functions for recalculating window clip lists. Main function 4 * is miValidateTree. 5 * 6 7Copyright 1987, 1988, 1989, 1998 The Open Group 8 9Permission to use, copy, modify, distribute, and sell this software and its 10documentation for any purpose is hereby granted without fee, provided that 11the above copyright notice appear in all copies and that both that 12copyright notice and this permission notice appear in supporting 13documentation. 14 15The above copyright notice and this permission notice shall be included in 16all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of The Open Group shall not be 26used in advertising or otherwise to promote the sale, use or other dealings 27in this Software without prior written authorization from The Open Group. 28 29 * 30 * Copyright 1987, 1988, 1989 by 31 * Digital Equipment Corporation, Maynard, Massachusetts, 32 * 33 * All Rights Reserved 34 * 35 * Permission to use, copy, modify, and distribute this software and its 36 * documentation for any purpose and without fee is hereby granted, 37 * provided that the above copyright notice appear in all copies and that 38 * both that copyright notice and this permission notice appear in 39 * supporting documentation, and that the name of Digital not be 40 * used in advertising or publicity pertaining to distribution of the 41 * software without specific, written prior permission. 42 * 43 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 44 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 45 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 46 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 47 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 48 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 49 * SOFTWARE. 50 * 51 ******************************************************************/ 52 53/* The panoramix components contained the following notice */ 54/***************************************************************** 55 56Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 57 58Permission is hereby granted, free of charge, to any person obtaining a copy 59of this software and associated documentation files (the "Software"), to deal 60in the Software without restriction, including without limitation the rights 61to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 62copies of the Software. 63 64The above copyright notice and this permission notice shall be included in 65all copies or substantial portions of the Software. 66 67THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 68IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 69FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 70DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 71BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 72WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 73IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 74 75Except as contained in this notice, the name of Digital Equipment Corporation 76shall not be used in advertising or otherwise to promote the sale, use or other 77dealings in this Software without prior written authorization from Digital 78Equipment Corporation. 79 80******************************************************************/ 81 82 83 /* 84 * Aug '86: Susan Angebranndt -- original code 85 * July '87: Adam de Boor -- substantially modified and commented 86 * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible. 87 * In particular, much improved code for window mapping and 88 * circulating. 89 * Bob Scheifler -- avoid miComputeClips for unmapped windows, 90 * valdata changes 91 */ 92#ifdef HAVE_DIX_CONFIG_H 93#include <dix-config.h> 94#endif 95 96#include <X11/X.h> 97#include "scrnintstr.h" 98#include "validate.h" 99#include "windowstr.h" 100#include "mi.h" 101#include "regionstr.h" 102#include "mivalidate.h" 103 104#include "globals.h" 105 106/* 107 * Compute the visibility of a shaped window 108 */ 109int 110miShapedWindowIn (ScreenPtr pScreen, RegionPtr universe, RegionPtr bounding, 111 BoxPtr rect, int x, int y) 112{ 113 BoxRec box; 114 BoxPtr boundBox; 115 int nbox; 116 Bool someIn, someOut; 117 int t, x1, y1, x2, y2; 118 119 nbox = REGION_NUM_RECTS (bounding); 120 boundBox = REGION_RECTS (bounding); 121 someIn = someOut = FALSE; 122 x1 = rect->x1; 123 y1 = rect->y1; 124 x2 = rect->x2; 125 y2 = rect->y2; 126 while (nbox--) 127 { 128 if ((t = boundBox->x1 + x) < x1) 129 t = x1; 130 box.x1 = t; 131 if ((t = boundBox->y1 + y) < y1) 132 t = y1; 133 box.y1 = t; 134 if ((t = boundBox->x2 + x) > x2) 135 t = x2; 136 box.x2 = t; 137 if ((t = boundBox->y2 + y) > y2) 138 t = y2; 139 box.y2 = t; 140 if (box.x1 > box.x2) 141 box.x2 = box.x1; 142 if (box.y1 > box.y2) 143 box.y2 = box.y1; 144 switch (RECT_IN_REGION(pScreen, universe, &box)) 145 { 146 case rgnIN: 147 if (someOut) 148 return rgnPART; 149 someIn = TRUE; 150 break; 151 case rgnOUT: 152 if (someIn) 153 return rgnPART; 154 someOut = TRUE; 155 break; 156 default: 157 return rgnPART; 158 } 159 boundBox++; 160 } 161 if (someIn) 162 return rgnIN; 163 return rgnOUT; 164} 165 166static GetRedirectBorderClipProcPtr miGetRedirectBorderClipProc; 167static SetRedirectBorderClipProcPtr miSetRedirectBorderClipProc; 168 169void 170miRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip, 171 GetRedirectBorderClipProcPtr getBorderClip) 172{ 173 miSetRedirectBorderClipProc = setBorderClip; 174 miGetRedirectBorderClipProc = getBorderClip; 175} 176 177/* 178 * Manual redirected windows are treated as transparent; they do not obscure 179 * siblings or parent windows 180 */ 181 182#ifdef COMPOSITE 183#define TreatAsTransparent(w) ((w)->redirectDraw == RedirectDrawManual) 184#else 185#define TreatAsTransparent(w) FALSE 186#endif 187 188#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \ 189 HasBorder(w) && \ 190 (w)->backgroundState == ParentRelative) 191 192 193/* 194 *----------------------------------------------------------------------- 195 * miComputeClips -- 196 * Recompute the clipList, borderClip, exposed and borderExposed 197 * regions for pParent and its children. Only viewable windows are 198 * taken into account. 199 * 200 * Results: 201 * None. 202 * 203 * Side Effects: 204 * clipList, borderClip, exposed and borderExposed are altered. 205 * A VisibilityNotify event may be generated on the parent window. 206 * 207 *----------------------------------------------------------------------- 208 */ 209static void 210miComputeClips ( 211 WindowPtr pParent, 212 ScreenPtr pScreen, 213 RegionPtr universe, 214 VTKind kind, 215 RegionPtr exposed ) /* for intermediate calculations */ 216{ 217 int dx, 218 dy; 219 RegionRec childUniverse; 220 WindowPtr pChild; 221 int oldVis, newVis; 222 BoxRec borderSize; 223 RegionRec childUnion; 224 Bool overlap; 225 RegionPtr borderVisible; 226 Bool resized; 227 /* 228 * Figure out the new visibility of this window. 229 * The extent of the universe should be the same as the extent of 230 * the borderSize region. If the window is unobscured, this rectangle 231 * will be completely inside the universe (the universe will cover it 232 * completely). If the window is completely obscured, none of the 233 * universe will cover the rectangle. 234 */ 235 borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent); 236 borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent); 237 dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent); 238 if (dx > 32767) 239 dx = 32767; 240 borderSize.x2 = dx; 241 dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent); 242 if (dy > 32767) 243 dy = 32767; 244 borderSize.y2 = dy; 245 246#ifdef COMPOSITE 247 /* 248 * In redirected drawing case, reset universe to borderSize 249 */ 250 if (pParent->redirectDraw != RedirectDrawNone) 251 { 252 if (miSetRedirectBorderClipProc) 253 { 254 if (TreatAsTransparent (pParent)) 255 REGION_EMPTY (pScreen, universe); 256 (*miSetRedirectBorderClipProc) (pParent, universe); 257 } 258 REGION_COPY(pScreen, universe, &pParent->borderSize); 259 } 260#endif 261 262 oldVis = pParent->visibility; 263 switch (RECT_IN_REGION( pScreen, universe, &borderSize)) 264 { 265 case rgnIN: 266 newVis = VisibilityUnobscured; 267 break; 268 case rgnPART: 269 newVis = VisibilityPartiallyObscured; 270 { 271 RegionPtr pBounding; 272 273 if ((pBounding = wBoundingShape (pParent))) 274 { 275 switch (miShapedWindowIn (pScreen, universe, pBounding, 276 &borderSize, 277 pParent->drawable.x, 278 pParent->drawable.y)) 279 { 280 case rgnIN: 281 newVis = VisibilityUnobscured; 282 break; 283 case rgnOUT: 284 newVis = VisibilityFullyObscured; 285 break; 286 } 287 } 288 } 289 break; 290 default: 291 newVis = VisibilityFullyObscured; 292 break; 293 } 294 pParent->visibility = newVis; 295 if (oldVis != newVis && 296 ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask)) 297 SendVisibilityNotify(pParent); 298 299 dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x; 300 dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y; 301 302 /* 303 * avoid computations when dealing with simple operations 304 */ 305 306 switch (kind) { 307 case VTMap: 308 case VTStack: 309 case VTUnmap: 310 break; 311 case VTMove: 312 if ((oldVis == newVis) && 313 ((oldVis == VisibilityFullyObscured) || 314 (oldVis == VisibilityUnobscured))) 315 { 316 pChild = pParent; 317 while (1) 318 { 319 if (pChild->viewable) 320 { 321 if (pChild->visibility != VisibilityFullyObscured) 322 { 323 REGION_TRANSLATE( pScreen, &pChild->borderClip, 324 dx, dy); 325 REGION_TRANSLATE( pScreen, &pChild->clipList, 326 dx, dy); 327 pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; 328 if (pScreen->ClipNotify) 329 (* pScreen->ClipNotify) (pChild, dx, dy); 330 331 } 332 if (pChild->valdata) 333 { 334 REGION_NULL(pScreen, 335 &pChild->valdata->after.borderExposed); 336 if (HasParentRelativeBorder(pChild)) 337 { 338 REGION_SUBTRACT(pScreen, 339 &pChild->valdata->after.borderExposed, 340 &pChild->borderClip, 341 &pChild->winSize); 342 } 343 REGION_NULL(pScreen, &pChild->valdata->after.exposed); 344 } 345 if (pChild->firstChild) 346 { 347 pChild = pChild->firstChild; 348 continue; 349 } 350 } 351 while (!pChild->nextSib && (pChild != pParent)) 352 pChild = pChild->parent; 353 if (pChild == pParent) 354 break; 355 pChild = pChild->nextSib; 356 } 357 return; 358 } 359 /* fall through */ 360 default: 361 /* 362 * To calculate exposures correctly, we have to translate the old 363 * borderClip and clipList regions to the window's new location so there 364 * is a correspondence between pieces of the new and old clipping regions. 365 */ 366 if (dx || dy) 367 { 368 /* 369 * We translate the old clipList because that will be exposed or copied 370 * if gravity is right. 371 */ 372 REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy); 373 REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy); 374 } 375 break; 376 case VTBroken: 377 REGION_EMPTY (pScreen, &pParent->borderClip); 378 REGION_EMPTY (pScreen, &pParent->clipList); 379 break; 380 } 381 382 borderVisible = pParent->valdata->before.borderVisible; 383 resized = pParent->valdata->before.resized; 384 REGION_NULL(pScreen, &pParent->valdata->after.borderExposed); 385 REGION_NULL(pScreen, &pParent->valdata->after.exposed); 386 387 /* 388 * Since the borderClip must not be clipped by the children, we do 389 * the border exposure first... 390 * 391 * 'universe' is the window's borderClip. To figure the exposures, remove 392 * the area that used to be exposed from the new. 393 * This leaves a region of pieces that weren't exposed before. 394 */ 395 396 if (HasBorder (pParent)) 397 { 398 if (borderVisible) 399 { 400 /* 401 * when the border changes shape, the old visible portions 402 * of the border will be saved by DIX in borderVisible -- 403 * use that region and destroy it 404 */ 405 REGION_SUBTRACT( pScreen, exposed, universe, borderVisible); 406 REGION_DESTROY( pScreen, borderVisible); 407 } 408 else 409 { 410 REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip); 411 } 412 if (HasParentRelativeBorder(pParent) && (dx || dy)) 413 REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, 414 universe, 415 &pParent->winSize); 416 else 417 REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed, 418 exposed, &pParent->winSize); 419 420 REGION_COPY( pScreen, &pParent->borderClip, universe); 421 422 /* 423 * To get the right clipList for the parent, and to make doubly sure 424 * that no child overlaps the parent's border, we remove the parent's 425 * border from the universe before proceeding. 426 */ 427 428 REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize); 429 } 430 else 431 REGION_COPY( pScreen, &pParent->borderClip, universe); 432 433 if ((pChild = pParent->firstChild) && pParent->mapped) 434 { 435 REGION_NULL(pScreen, &childUniverse); 436 REGION_NULL(pScreen, &childUnion); 437 if ((pChild->drawable.y < pParent->lastChild->drawable.y) || 438 ((pChild->drawable.y == pParent->lastChild->drawable.y) && 439 (pChild->drawable.x < pParent->lastChild->drawable.x))) 440 { 441 for (; pChild; pChild = pChild->nextSib) 442 { 443 if (pChild->viewable && !TreatAsTransparent(pChild)) 444 REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); 445 } 446 } 447 else 448 { 449 for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) 450 { 451 if (pChild->viewable && !TreatAsTransparent(pChild)) 452 REGION_APPEND( pScreen, &childUnion, &pChild->borderSize); 453 } 454 } 455 REGION_VALIDATE( pScreen, &childUnion, &overlap); 456 457 for (pChild = pParent->firstChild; 458 pChild; 459 pChild = pChild->nextSib) 460 { 461 if (pChild->viewable) { 462 /* 463 * If the child is viewable, we want to remove its extents 464 * from the current universe, but we only re-clip it if 465 * it's been marked. 466 */ 467 if (pChild->valdata) { 468 /* 469 * Figure out the new universe from the child's 470 * perspective and recurse. 471 */ 472 REGION_INTERSECT( pScreen, &childUniverse, 473 universe, 474 &pChild->borderSize); 475 miComputeClips (pChild, pScreen, &childUniverse, kind, 476 exposed); 477 } 478 /* 479 * Once the child has been processed, we remove its extents 480 * from the current universe, thus denying its space to any 481 * other sibling. 482 */ 483 if (overlap && !TreatAsTransparent (pChild)) 484 REGION_SUBTRACT( pScreen, universe, universe, 485 &pChild->borderSize); 486 } 487 } 488 if (!overlap) 489 REGION_SUBTRACT( pScreen, universe, universe, &childUnion); 490 REGION_UNINIT( pScreen, &childUnion); 491 REGION_UNINIT( pScreen, &childUniverse); 492 } /* if any children */ 493 494 /* 495 * 'universe' now contains the new clipList for the parent window. 496 * 497 * To figure the exposure of the window we subtract the old clip from the 498 * new, just as for the border. 499 */ 500 501 if (oldVis == VisibilityFullyObscured || 502 oldVis == VisibilityNotViewable) 503 { 504 REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe); 505 } 506 else if (newVis != VisibilityFullyObscured && 507 newVis != VisibilityNotViewable) 508 { 509 REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed, 510 universe, &pParent->clipList); 511 } 512 513 /* HACK ALERT - copying contents of regions, instead of regions */ 514 { 515 RegionRec tmp; 516 517 tmp = pParent->clipList; 518 pParent->clipList = *universe; 519 *universe = tmp; 520 } 521 522#ifdef NOTDEF 523 REGION_COPY( pScreen, &pParent->clipList, universe); 524#endif 525 526 pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; 527 528 if (pScreen->ClipNotify) 529 (* pScreen->ClipNotify) (pParent, dx, dy); 530} 531 532static void 533miTreeObscured( 534 WindowPtr pParent ) 535{ 536 WindowPtr pChild; 537 int oldVis; 538 539 pChild = pParent; 540 while (1) 541 { 542 if (pChild->viewable) 543 { 544 oldVis = pChild->visibility; 545 if (oldVis != (pChild->visibility = VisibilityFullyObscured) && 546 ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask)) 547 SendVisibilityNotify(pChild); 548 if (pChild->firstChild) 549 { 550 pChild = pChild->firstChild; 551 continue; 552 } 553 } 554 while (!pChild->nextSib && (pChild != pParent)) 555 pChild = pChild->parent; 556 if (pChild == pParent) 557 break; 558 pChild = pChild->nextSib; 559 } 560} 561 562/* 563 *----------------------------------------------------------------------- 564 * miValidateTree -- 565 * Recomputes the clip list for pParent and all its inferiors. 566 * 567 * Results: 568 * Always returns 1. 569 * 570 * Side Effects: 571 * The clipList, borderClip, exposed, and borderExposed regions for 572 * each marked window are altered. 573 * 574 * Notes: 575 * This routine assumes that all affected windows have been marked 576 * (valdata created) and their winSize and borderSize regions 577 * adjusted to correspond to their new positions. The borderClip and 578 * clipList regions should not have been touched. 579 * 580 * The top-most level is treated differently from all lower levels 581 * because pParent is unchanged. For the top level, we merge the 582 * regions taken up by the marked children back into the clipList 583 * for pParent, thus forming a region from which the marked children 584 * can claim their areas. For lower levels, where the old clipList 585 * and borderClip are invalid, we can't do this and have to do the 586 * extra operations done in miComputeClips, but this is much faster 587 * e.g. when only one child has moved... 588 * 589 *----------------------------------------------------------------------- 590 */ 591/*ARGSUSED*/ 592int 593miValidateTree ( 594 WindowPtr pParent, /* Parent to validate */ 595 WindowPtr pChild, /* First child of pParent that was 596 * affected */ 597 VTKind kind /* What kind of configuration caused call */ 598 ) 599{ 600 RegionRec totalClip; /* Total clipping region available to 601 * the marked children. pParent's clipList 602 * merged with the borderClips of all 603 * the marked children. */ 604 RegionRec childClip; /* The new borderClip for the current 605 * child */ 606 RegionRec childUnion; /* the space covered by borderSize for 607 * all marked children */ 608 RegionRec exposed; /* For intermediate calculations */ 609 ScreenPtr pScreen; 610 WindowPtr pWin; 611 Bool overlap; 612 int viewvals; 613 Bool forward; 614 615 pScreen = pParent->drawable.pScreen; 616 if (pChild == NullWindow) 617 pChild = pParent->firstChild; 618 619 REGION_NULL(pScreen, &childClip); 620 REGION_NULL(pScreen, &exposed); 621 622 /* 623 * compute the area of the parent window occupied 624 * by the marked children + the parent itself. This 625 * is the area which can be divied up among the marked 626 * children in their new configuration. 627 */ 628 REGION_NULL(pScreen, &totalClip); 629 viewvals = 0; 630 if (REGION_BROKEN (pScreen, &pParent->clipList) && 631 !REGION_BROKEN (pScreen, &pParent->borderClip)) 632 { 633 kind = VTBroken; 634 /* 635 * When rebuilding clip lists after out of memory, 636 * assume everything is busted. 637 */ 638 forward = TRUE; 639 REGION_COPY (pScreen, &totalClip, &pParent->borderClip); 640 REGION_INTERSECT (pScreen, &totalClip, &totalClip, &pParent->winSize); 641 642 for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib) 643 { 644 if (pWin->viewable && !TreatAsTransparent (pWin)) 645 REGION_SUBTRACT (pScreen, &totalClip, &totalClip, &pWin->borderSize); 646 } 647 for (pWin = pChild; pWin; pWin = pWin->nextSib) 648 if (pWin->valdata && pWin->viewable) 649 viewvals++; 650 651 REGION_EMPTY (pScreen, &pParent->clipList); 652 } 653 else 654 { 655 if ((pChild->drawable.y < pParent->lastChild->drawable.y) || 656 ((pChild->drawable.y == pParent->lastChild->drawable.y) && 657 (pChild->drawable.x < pParent->lastChild->drawable.x))) 658 { 659 forward = TRUE; 660 for (pWin = pChild; pWin; pWin = pWin->nextSib) 661 { 662 if (pWin->valdata) 663 { 664 RegionPtr pBorderClip = &pWin->borderClip; 665#ifdef COMPOSITE 666 if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc) 667 pBorderClip = (*miGetRedirectBorderClipProc)(pWin); 668#endif 669 REGION_APPEND( pScreen, &totalClip, pBorderClip ); 670 if (pWin->viewable) 671 viewvals++; 672 } 673 } 674 } 675 else 676 { 677 forward = FALSE; 678 pWin = pParent->lastChild; 679 while (1) 680 { 681 if (pWin->valdata) 682 { 683 RegionPtr pBorderClip = &pWin->borderClip; 684#ifdef COMPOSITE 685 if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc) 686 pBorderClip = (*miGetRedirectBorderClipProc)(pWin); 687#endif 688 REGION_APPEND( pScreen, &totalClip, pBorderClip ); 689 if (pWin->viewable) 690 viewvals++; 691 } 692 if (pWin == pChild) 693 break; 694 pWin = pWin->prevSib; 695 } 696 } 697 REGION_VALIDATE( pScreen, &totalClip, &overlap); 698 } 699 700 /* 701 * Now go through the children of the root and figure their new 702 * borderClips from the totalClip, passing that off to miComputeClips 703 * to handle recursively. Once that's done, we remove the child 704 * from the totalClip to clip any siblings below it. 705 */ 706 707 overlap = TRUE; 708 if (kind != VTStack) 709 { 710 REGION_UNION( pScreen, &totalClip, &totalClip, &pParent->clipList); 711 if (viewvals > 1) 712 { 713 /* 714 * precompute childUnion to discover whether any of them 715 * overlap. This seems redundant, but performance studies 716 * have demonstrated that the cost of this loop is 717 * lower than the cost of multiple Subtracts in the 718 * loop below. 719 */ 720 REGION_NULL(pScreen, &childUnion); 721 if (forward) 722 { 723 for (pWin = pChild; pWin; pWin = pWin->nextSib) 724 if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin)) 725 REGION_APPEND( pScreen, &childUnion, 726 &pWin->borderSize); 727 } 728 else 729 { 730 pWin = pParent->lastChild; 731 while (1) 732 { 733 if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin)) 734 REGION_APPEND( pScreen, &childUnion, 735 &pWin->borderSize); 736 if (pWin == pChild) 737 break; 738 pWin = pWin->prevSib; 739 } 740 } 741 REGION_VALIDATE(pScreen, &childUnion, &overlap); 742 if (overlap) 743 REGION_UNINIT(pScreen, &childUnion); 744 } 745 } 746 747 for (pWin = pChild; 748 pWin != NullWindow; 749 pWin = pWin->nextSib) 750 { 751 if (pWin->viewable) { 752 if (pWin->valdata) { 753 REGION_INTERSECT( pScreen, &childClip, 754 &totalClip, 755 &pWin->borderSize); 756 miComputeClips (pWin, pScreen, &childClip, kind, &exposed); 757 if (overlap && !TreatAsTransparent (pWin)) 758 { 759 REGION_SUBTRACT( pScreen, &totalClip, 760 &totalClip, 761 &pWin->borderSize); 762 } 763 } else if (pWin->visibility == VisibilityNotViewable) { 764 miTreeObscured(pWin); 765 } 766 } else { 767 if (pWin->valdata) { 768 REGION_EMPTY( pScreen, &pWin->clipList); 769 if (pScreen->ClipNotify) 770 (* pScreen->ClipNotify) (pWin, 0, 0); 771 REGION_EMPTY( pScreen, &pWin->borderClip); 772 pWin->valdata = (ValidatePtr)NULL; 773 } 774 } 775 } 776 777 REGION_UNINIT( pScreen, &childClip); 778 if (!overlap) 779 { 780 REGION_SUBTRACT(pScreen, &totalClip, &totalClip, &childUnion); 781 REGION_UNINIT(pScreen, &childUnion); 782 } 783 784 REGION_NULL(pScreen, &pParent->valdata->after.exposed); 785 REGION_NULL(pScreen, &pParent->valdata->after.borderExposed); 786 787 /* 788 * each case below is responsible for updating the 789 * clipList and serial number for the parent window 790 */ 791 792 switch (kind) { 793 case VTStack: 794 break; 795 default: 796 /* 797 * totalClip contains the new clipList for the parent. Figure out 798 * exposures and obscures as per miComputeClips and reset the parent's 799 * clipList. 800 */ 801 REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed, 802 &totalClip, &pParent->clipList); 803 /* fall through */ 804 case VTMap: 805 REGION_COPY( pScreen, &pParent->clipList, &totalClip); 806 pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; 807 break; 808 } 809 810 REGION_UNINIT( pScreen, &totalClip); 811 REGION_UNINIT( pScreen, &exposed); 812 if (pScreen->ClipNotify) 813 (*pScreen->ClipNotify) (pParent, 0, 0); 814 return (1); 815} 816