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 (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 = RegionNumRects (bounding); 120 boundBox = RegionRects (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 (RegionContainsRect(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 RegionEmpty(universe); 256 (*miSetRedirectBorderClipProc) (pParent, universe); 257 } 258 RegionCopy(universe, &pParent->borderSize); 259 } 260#endif 261 262 oldVis = pParent->visibility; 263 switch (RegionContainsRect(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 (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 RegionTranslate(&pChild->borderClip, 324 dx, dy); 325 RegionTranslate(&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 RegionNull(&pChild->valdata->after.borderExposed); 335 if (HasParentRelativeBorder(pChild)) 336 { 337 RegionSubtract(&pChild->valdata->after.borderExposed, 338 &pChild->borderClip, 339 &pChild->winSize); 340 } 341 RegionNull(&pChild->valdata->after.exposed); 342 } 343 if (pChild->firstChild) 344 { 345 pChild = pChild->firstChild; 346 continue; 347 } 348 } 349 while (!pChild->nextSib && (pChild != pParent)) 350 pChild = pChild->parent; 351 if (pChild == pParent) 352 break; 353 pChild = pChild->nextSib; 354 } 355 return; 356 } 357 /* fall through */ 358 default: 359 /* 360 * To calculate exposures correctly, we have to translate the old 361 * borderClip and clipList regions to the window's new location so there 362 * is a correspondence between pieces of the new and old clipping regions. 363 */ 364 if (dx || dy) 365 { 366 /* 367 * We translate the old clipList because that will be exposed or copied 368 * if gravity is right. 369 */ 370 RegionTranslate(&pParent->borderClip, dx, dy); 371 RegionTranslate(&pParent->clipList, dx, dy); 372 } 373 break; 374 case VTBroken: 375 RegionEmpty(&pParent->borderClip); 376 RegionEmpty(&pParent->clipList); 377 break; 378 } 379 380 borderVisible = pParent->valdata->before.borderVisible; 381 resized = pParent->valdata->before.resized; 382 RegionNull(&pParent->valdata->after.borderExposed); 383 RegionNull(&pParent->valdata->after.exposed); 384 385 /* 386 * Since the borderClip must not be clipped by the children, we do 387 * the border exposure first... 388 * 389 * 'universe' is the window's borderClip. To figure the exposures, remove 390 * the area that used to be exposed from the new. 391 * This leaves a region of pieces that weren't exposed before. 392 */ 393 394 if (HasBorder (pParent)) 395 { 396 if (borderVisible) 397 { 398 /* 399 * when the border changes shape, the old visible portions 400 * of the border will be saved by DIX in borderVisible -- 401 * use that region and destroy it 402 */ 403 RegionSubtract(exposed, universe, borderVisible); 404 RegionDestroy(borderVisible); 405 } 406 else 407 { 408 RegionSubtract(exposed, universe, &pParent->borderClip); 409 } 410 if (HasParentRelativeBorder(pParent) && (dx || dy)) 411 RegionSubtract(&pParent->valdata->after.borderExposed, 412 universe, 413 &pParent->winSize); 414 else 415 RegionSubtract(&pParent->valdata->after.borderExposed, 416 exposed, &pParent->winSize); 417 418 RegionCopy(&pParent->borderClip, universe); 419 420 /* 421 * To get the right clipList for the parent, and to make doubly sure 422 * that no child overlaps the parent's border, we remove the parent's 423 * border from the universe before proceeding. 424 */ 425 426 RegionIntersect(universe, universe, &pParent->winSize); 427 } 428 else 429 RegionCopy(&pParent->borderClip, universe); 430 431 if ((pChild = pParent->firstChild) && pParent->mapped) 432 { 433 RegionNull(&childUniverse); 434 RegionNull(&childUnion); 435 if ((pChild->drawable.y < pParent->lastChild->drawable.y) || 436 ((pChild->drawable.y == pParent->lastChild->drawable.y) && 437 (pChild->drawable.x < pParent->lastChild->drawable.x))) 438 { 439 for (; pChild; pChild = pChild->nextSib) 440 { 441 if (pChild->viewable && !TreatAsTransparent(pChild)) 442 RegionAppend(&childUnion, &pChild->borderSize); 443 } 444 } 445 else 446 { 447 for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) 448 { 449 if (pChild->viewable && !TreatAsTransparent(pChild)) 450 RegionAppend(&childUnion, &pChild->borderSize); 451 } 452 } 453 RegionValidate(&childUnion, &overlap); 454 455 for (pChild = pParent->firstChild; 456 pChild; 457 pChild = pChild->nextSib) 458 { 459 if (pChild->viewable) { 460 /* 461 * If the child is viewable, we want to remove its extents 462 * from the current universe, but we only re-clip it if 463 * it's been marked. 464 */ 465 if (pChild->valdata) { 466 /* 467 * Figure out the new universe from the child's 468 * perspective and recurse. 469 */ 470 RegionIntersect(&childUniverse, 471 universe, 472 &pChild->borderSize); 473 miComputeClips (pChild, pScreen, &childUniverse, kind, 474 exposed); 475 } 476 /* 477 * Once the child has been processed, we remove its extents 478 * from the current universe, thus denying its space to any 479 * other sibling. 480 */ 481 if (overlap && !TreatAsTransparent (pChild)) 482 RegionSubtract(universe, universe, 483 &pChild->borderSize); 484 } 485 } 486 if (!overlap) 487 RegionSubtract(universe, universe, &childUnion); 488 RegionUninit(&childUnion); 489 RegionUninit(&childUniverse); 490 } /* if any children */ 491 492 /* 493 * 'universe' now contains the new clipList for the parent window. 494 * 495 * To figure the exposure of the window we subtract the old clip from the 496 * new, just as for the border. 497 */ 498 499 if (oldVis == VisibilityFullyObscured || 500 oldVis == VisibilityNotViewable) 501 { 502 RegionCopy(&pParent->valdata->after.exposed, universe); 503 } 504 else if (newVis != VisibilityFullyObscured && 505 newVis != VisibilityNotViewable) 506 { 507 RegionSubtract(&pParent->valdata->after.exposed, 508 universe, &pParent->clipList); 509 } 510 511 /* HACK ALERT - copying contents of regions, instead of regions */ 512 { 513 RegionRec tmp; 514 515 tmp = pParent->clipList; 516 pParent->clipList = *universe; 517 *universe = tmp; 518 } 519 520#ifdef NOTDEF 521 RegionCopy(&pParent->clipList, universe); 522#endif 523 524 pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; 525 526 if (pScreen->ClipNotify) 527 (* pScreen->ClipNotify) (pParent, dx, dy); 528} 529 530static void 531miTreeObscured( 532 WindowPtr pParent ) 533{ 534 WindowPtr pChild; 535 int oldVis; 536 537 pChild = pParent; 538 while (1) 539 { 540 if (pChild->viewable) 541 { 542 oldVis = pChild->visibility; 543 if (oldVis != (pChild->visibility = VisibilityFullyObscured) && 544 ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask)) 545 SendVisibilityNotify(pChild); 546 if (pChild->firstChild) 547 { 548 pChild = pChild->firstChild; 549 continue; 550 } 551 } 552 while (!pChild->nextSib && (pChild != pParent)) 553 pChild = pChild->parent; 554 if (pChild == pParent) 555 break; 556 pChild = pChild->nextSib; 557 } 558} 559 560/* 561 *----------------------------------------------------------------------- 562 * miValidateTree -- 563 * Recomputes the clip list for pParent and all its inferiors. 564 * 565 * Results: 566 * Always returns 1. 567 * 568 * Side Effects: 569 * The clipList, borderClip, exposed, and borderExposed regions for 570 * each marked window are altered. 571 * 572 * Notes: 573 * This routine assumes that all affected windows have been marked 574 * (valdata created) and their winSize and borderSize regions 575 * adjusted to correspond to their new positions. The borderClip and 576 * clipList regions should not have been touched. 577 * 578 * The top-most level is treated differently from all lower levels 579 * because pParent is unchanged. For the top level, we merge the 580 * regions taken up by the marked children back into the clipList 581 * for pParent, thus forming a region from which the marked children 582 * can claim their areas. For lower levels, where the old clipList 583 * and borderClip are invalid, we can't do this and have to do the 584 * extra operations done in miComputeClips, but this is much faster 585 * e.g. when only one child has moved... 586 * 587 *----------------------------------------------------------------------- 588 */ 589/*ARGSUSED*/ 590int 591miValidateTree ( 592 WindowPtr pParent, /* Parent to validate */ 593 WindowPtr pChild, /* First child of pParent that was 594 * affected */ 595 VTKind kind /* What kind of configuration caused call */ 596 ) 597{ 598 RegionRec totalClip; /* Total clipping region available to 599 * the marked children. pParent's clipList 600 * merged with the borderClips of all 601 * the marked children. */ 602 RegionRec childClip; /* The new borderClip for the current 603 * child */ 604 RegionRec childUnion; /* the space covered by borderSize for 605 * all marked children */ 606 RegionRec exposed; /* For intermediate calculations */ 607 ScreenPtr pScreen; 608 WindowPtr pWin; 609 Bool overlap; 610 int viewvals; 611 Bool forward; 612 613 pScreen = pParent->drawable.pScreen; 614 if (pChild == NullWindow) 615 pChild = pParent->firstChild; 616 617 RegionNull(&childClip); 618 RegionNull(&exposed); 619 620 /* 621 * compute the area of the parent window occupied 622 * by the marked children + the parent itself. This 623 * is the area which can be divied up among the marked 624 * children in their new configuration. 625 */ 626 RegionNull(&totalClip); 627 viewvals = 0; 628 if (RegionBroken(&pParent->clipList) && 629 !RegionBroken(&pParent->borderClip)) 630 { 631 kind = VTBroken; 632 /* 633 * When rebuilding clip lists after out of memory, 634 * assume everything is busted. 635 */ 636 forward = TRUE; 637 RegionCopy(&totalClip, &pParent->borderClip); 638 RegionIntersect(&totalClip, &totalClip, &pParent->winSize); 639 640 for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib) 641 { 642 if (pWin->viewable && !TreatAsTransparent (pWin)) 643 RegionSubtract(&totalClip, &totalClip, &pWin->borderSize); 644 } 645 for (pWin = pChild; pWin; pWin = pWin->nextSib) 646 if (pWin->valdata && pWin->viewable) 647 viewvals++; 648 649 RegionEmpty(&pParent->clipList); 650 } 651 else 652 { 653 if ((pChild->drawable.y < pParent->lastChild->drawable.y) || 654 ((pChild->drawable.y == pParent->lastChild->drawable.y) && 655 (pChild->drawable.x < pParent->lastChild->drawable.x))) 656 { 657 forward = TRUE; 658 for (pWin = pChild; pWin; pWin = pWin->nextSib) 659 { 660 if (pWin->valdata) 661 { 662 RegionPtr pBorderClip = &pWin->borderClip; 663#ifdef COMPOSITE 664 if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc) 665 pBorderClip = (*miGetRedirectBorderClipProc)(pWin); 666#endif 667 RegionAppend(&totalClip, pBorderClip ); 668 if (pWin->viewable) 669 viewvals++; 670 } 671 } 672 } 673 else 674 { 675 forward = FALSE; 676 pWin = pParent->lastChild; 677 while (1) 678 { 679 if (pWin->valdata) 680 { 681 RegionPtr pBorderClip = &pWin->borderClip; 682#ifdef COMPOSITE 683 if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc) 684 pBorderClip = (*miGetRedirectBorderClipProc)(pWin); 685#endif 686 RegionAppend(&totalClip, pBorderClip ); 687 if (pWin->viewable) 688 viewvals++; 689 } 690 if (pWin == pChild) 691 break; 692 pWin = pWin->prevSib; 693 } 694 } 695 RegionValidate(&totalClip, &overlap); 696 } 697 698 /* 699 * Now go through the children of the root and figure their new 700 * borderClips from the totalClip, passing that off to miComputeClips 701 * to handle recursively. Once that's done, we remove the child 702 * from the totalClip to clip any siblings below it. 703 */ 704 705 overlap = TRUE; 706 if (kind != VTStack) 707 { 708 RegionUnion(&totalClip, &totalClip, &pParent->clipList); 709 if (viewvals > 1) 710 { 711 /* 712 * precompute childUnion to discover whether any of them 713 * overlap. This seems redundant, but performance studies 714 * have demonstrated that the cost of this loop is 715 * lower than the cost of multiple Subtracts in the 716 * loop below. 717 */ 718 RegionNull(&childUnion); 719 if (forward) 720 { 721 for (pWin = pChild; pWin; pWin = pWin->nextSib) 722 if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin)) 723 RegionAppend(&childUnion, 724 &pWin->borderSize); 725 } 726 else 727 { 728 pWin = pParent->lastChild; 729 while (1) 730 { 731 if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin)) 732 RegionAppend(&childUnion, 733 &pWin->borderSize); 734 if (pWin == pChild) 735 break; 736 pWin = pWin->prevSib; 737 } 738 } 739 RegionValidate(&childUnion, &overlap); 740 if (overlap) 741 RegionUninit(&childUnion); 742 } 743 } 744 745 for (pWin = pChild; 746 pWin != NullWindow; 747 pWin = pWin->nextSib) 748 { 749 if (pWin->viewable) { 750 if (pWin->valdata) { 751 RegionIntersect(&childClip, 752 &totalClip, 753 &pWin->borderSize); 754 miComputeClips (pWin, pScreen, &childClip, kind, &exposed); 755 if (overlap && !TreatAsTransparent (pWin)) 756 { 757 RegionSubtract(&totalClip, 758 &totalClip, 759 &pWin->borderSize); 760 } 761 } else if (pWin->visibility == VisibilityNotViewable) { 762 miTreeObscured(pWin); 763 } 764 } else { 765 if (pWin->valdata) { 766 RegionEmpty(&pWin->clipList); 767 if (pScreen->ClipNotify) 768 (* pScreen->ClipNotify) (pWin, 0, 0); 769 RegionEmpty(&pWin->borderClip); 770 pWin->valdata = NULL; 771 } 772 } 773 } 774 775 RegionUninit(&childClip); 776 if (!overlap) 777 { 778 RegionSubtract(&totalClip, &totalClip, &childUnion); 779 RegionUninit(&childUnion); 780 } 781 782 RegionNull(&pParent->valdata->after.exposed); 783 RegionNull(&pParent->valdata->after.borderExposed); 784 785 /* 786 * each case below is responsible for updating the 787 * clipList and serial number for the parent window 788 */ 789 790 switch (kind) { 791 case VTStack: 792 break; 793 default: 794 /* 795 * totalClip contains the new clipList for the parent. Figure out 796 * exposures and obscures as per miComputeClips and reset the parent's 797 * clipList. 798 */ 799 RegionSubtract(&pParent->valdata->after.exposed, 800 &totalClip, &pParent->clipList); 801 /* fall through */ 802 case VTMap: 803 RegionCopy(&pParent->clipList, &totalClip); 804 pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; 805 break; 806 } 807 808 RegionUninit(&totalClip); 809 RegionUninit(&exposed); 810 if (pScreen->ClipNotify) 811 (*pScreen->ClipNotify) (pParent, 0, 0); 812 return 1; 813} 814