xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

mivaltree.c (26229B)


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