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