home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / ddx / mi / mivaltree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-10  |  19.4 KB  |  690 lines

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