Imported Upstream version 1.15.1
[deb_xorg-server.git] / mi / mivaltree.c
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
103 #include "globals.h"
104
105 /*
106 * Compute the visibility of a shaped window
107 */
108 int
109 miShapedWindowIn(RegionPtr universe, RegionPtr bounding,
110 BoxPtr rect, int x, int y)
111 {
112 BoxRec box;
113 BoxPtr boundBox;
114 int nbox;
115 Bool someIn, someOut;
116 int t, x1, y1, x2, y2;
117
118 nbox = RegionNumRects(bounding);
119 boundBox = RegionRects(bounding);
120 someIn = someOut = FALSE;
121 x1 = rect->x1;
122 y1 = rect->y1;
123 x2 = rect->x2;
124 y2 = rect->y2;
125 while (nbox--) {
126 if ((t = boundBox->x1 + x) < x1)
127 t = x1;
128 box.x1 = t;
129 if ((t = boundBox->y1 + y) < y1)
130 t = y1;
131 box.y1 = t;
132 if ((t = boundBox->x2 + x) > x2)
133 t = x2;
134 box.x2 = t;
135 if ((t = boundBox->y2 + y) > y2)
136 t = y2;
137 box.y2 = t;
138 if (box.x1 > box.x2)
139 box.x2 = box.x1;
140 if (box.y1 > box.y2)
141 box.y2 = box.y1;
142 switch (RegionContainsRect(universe, &box)) {
143 case rgnIN:
144 if (someOut)
145 return rgnPART;
146 someIn = TRUE;
147 break;
148 case rgnOUT:
149 if (someIn)
150 return rgnPART;
151 someOut = TRUE;
152 break;
153 default:
154 return rgnPART;
155 }
156 boundBox++;
157 }
158 if (someIn)
159 return rgnIN;
160 return rgnOUT;
161 }
162
163 static GetRedirectBorderClipProcPtr miGetRedirectBorderClipProc;
164 static SetRedirectBorderClipProcPtr miSetRedirectBorderClipProc;
165
166 void
167 miRegisterRedirectBorderClipProc(SetRedirectBorderClipProcPtr setBorderClip,
168 GetRedirectBorderClipProcPtr getBorderClip)
169 {
170 miSetRedirectBorderClipProc = setBorderClip;
171 miGetRedirectBorderClipProc = getBorderClip;
172 }
173
174 /*
175 * Manual redirected windows are treated as transparent; they do not obscure
176 * siblings or parent windows
177 */
178
179 #ifdef COMPOSITE
180 #define TreatAsTransparent(w) ((w)->redirectDraw == RedirectDrawManual)
181 #else
182 #define TreatAsTransparent(w) FALSE
183 #endif
184
185 #define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
186 HasBorder(w) && \
187 (w)->backgroundState == ParentRelative)
188
189 /*
190 *-----------------------------------------------------------------------
191 * miComputeClips --
192 * Recompute the clipList, borderClip, exposed and borderExposed
193 * regions for pParent and its children. Only viewable windows are
194 * taken into account.
195 *
196 * Results:
197 * None.
198 *
199 * Side Effects:
200 * clipList, borderClip, exposed and borderExposed are altered.
201 * A VisibilityNotify event may be generated on the parent window.
202 *
203 *-----------------------------------------------------------------------
204 */
205 static void
206 miComputeClips(WindowPtr pParent,
207 ScreenPtr pScreen,
208 RegionPtr universe, VTKind kind, RegionPtr exposed)
209 { /* for intermediate calculations */
210 int dx, dy;
211 RegionRec childUniverse;
212 WindowPtr pChild;
213 int oldVis, newVis;
214 BoxRec borderSize;
215 RegionRec childUnion;
216 Bool overlap;
217 RegionPtr borderVisible;
218
219 /*
220 * Figure out the new visibility of this window.
221 * The extent of the universe should be the same as the extent of
222 * the borderSize region. If the window is unobscured, this rectangle
223 * will be completely inside the universe (the universe will cover it
224 * completely). If the window is completely obscured, none of the
225 * universe will cover the rectangle.
226 */
227 borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
228 borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
229 dx = (int) pParent->drawable.x + (int) pParent->drawable.width +
230 wBorderWidth(pParent);
231 if (dx > 32767)
232 dx = 32767;
233 borderSize.x2 = dx;
234 dy = (int) pParent->drawable.y + (int) pParent->drawable.height +
235 wBorderWidth(pParent);
236 if (dy > 32767)
237 dy = 32767;
238 borderSize.y2 = dy;
239
240 #ifdef COMPOSITE
241 /*
242 * In redirected drawing case, reset universe to borderSize
243 */
244 if (pParent->redirectDraw != RedirectDrawNone) {
245 if (miSetRedirectBorderClipProc) {
246 if (TreatAsTransparent(pParent))
247 RegionEmpty(universe);
248 (*miSetRedirectBorderClipProc) (pParent, universe);
249 }
250 RegionCopy(universe, &pParent->borderSize);
251 }
252 #endif
253
254 oldVis = pParent->visibility;
255 switch (RegionContainsRect(universe, &borderSize)) {
256 case rgnIN:
257 newVis = VisibilityUnobscured;
258 break;
259 case rgnPART:
260 newVis = VisibilityPartiallyObscured;
261 {
262 RegionPtr pBounding;
263
264 if ((pBounding = wBoundingShape(pParent))) {
265 switch (miShapedWindowIn(universe, pBounding,
266 &borderSize,
267 pParent->drawable.x,
268 pParent->drawable.y)) {
269 case rgnIN:
270 newVis = VisibilityUnobscured;
271 break;
272 case rgnOUT:
273 newVis = VisibilityFullyObscured;
274 break;
275 }
276 }
277 }
278 break;
279 default:
280 newVis = VisibilityFullyObscured;
281 break;
282 }
283 pParent->visibility = newVis;
284 if (oldVis != newVis &&
285 ((pParent->
286 eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
287 SendVisibilityNotify(pParent);
288
289 dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
290 dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
291
292 /*
293 * avoid computations when dealing with simple operations
294 */
295
296 switch (kind) {
297 case VTMap:
298 case VTStack:
299 case VTUnmap:
300 break;
301 case VTMove:
302 if ((oldVis == newVis) &&
303 ((oldVis == VisibilityFullyObscured) ||
304 (oldVis == VisibilityUnobscured))) {
305 pChild = pParent;
306 while (1) {
307 if (pChild->viewable) {
308 if (pChild->visibility != VisibilityFullyObscured) {
309 RegionTranslate(&pChild->borderClip, dx, dy);
310 RegionTranslate(&pChild->clipList, dx, dy);
311 pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
312 if (pScreen->ClipNotify)
313 (*pScreen->ClipNotify) (pChild, dx, dy);
314
315 }
316 if (pChild->valdata) {
317 RegionNull(&pChild->valdata->after.borderExposed);
318 if (HasParentRelativeBorder(pChild)) {
319 RegionSubtract(&pChild->valdata->after.
320 borderExposed, &pChild->borderClip,
321 &pChild->winSize);
322 }
323 RegionNull(&pChild->valdata->after.exposed);
324 }
325 if (pChild->firstChild) {
326 pChild = pChild->firstChild;
327 continue;
328 }
329 }
330 while (!pChild->nextSib && (pChild != pParent))
331 pChild = pChild->parent;
332 if (pChild == pParent)
333 break;
334 pChild = pChild->nextSib;
335 }
336 return;
337 }
338 /* fall through */
339 default:
340 /*
341 * To calculate exposures correctly, we have to translate the old
342 * borderClip and clipList regions to the window's new location so there
343 * is a correspondence between pieces of the new and old clipping regions.
344 */
345 if (dx || dy) {
346 /*
347 * We translate the old clipList because that will be exposed or copied
348 * if gravity is right.
349 */
350 RegionTranslate(&pParent->borderClip, dx, dy);
351 RegionTranslate(&pParent->clipList, dx, dy);
352 }
353 break;
354 case VTBroken:
355 RegionEmpty(&pParent->borderClip);
356 RegionEmpty(&pParent->clipList);
357 break;
358 }
359
360 borderVisible = pParent->valdata->before.borderVisible;
361 RegionNull(&pParent->valdata->after.borderExposed);
362 RegionNull(&pParent->valdata->after.exposed);
363
364 /*
365 * Since the borderClip must not be clipped by the children, we do
366 * the border exposure first...
367 *
368 * 'universe' is the window's borderClip. To figure the exposures, remove
369 * the area that used to be exposed from the new.
370 * This leaves a region of pieces that weren't exposed before.
371 */
372
373 if (HasBorder(pParent)) {
374 if (borderVisible) {
375 /*
376 * when the border changes shape, the old visible portions
377 * of the border will be saved by DIX in borderVisible --
378 * use that region and destroy it
379 */
380 RegionSubtract(exposed, universe, borderVisible);
381 RegionDestroy(borderVisible);
382 }
383 else {
384 RegionSubtract(exposed, universe, &pParent->borderClip);
385 }
386 if (HasParentRelativeBorder(pParent) && (dx || dy))
387 RegionSubtract(&pParent->valdata->after.borderExposed,
388 universe, &pParent->winSize);
389 else
390 RegionSubtract(&pParent->valdata->after.borderExposed,
391 exposed, &pParent->winSize);
392
393 RegionCopy(&pParent->borderClip, universe);
394
395 /*
396 * To get the right clipList for the parent, and to make doubly sure
397 * that no child overlaps the parent's border, we remove the parent's
398 * border from the universe before proceeding.
399 */
400
401 RegionIntersect(universe, universe, &pParent->winSize);
402 }
403 else
404 RegionCopy(&pParent->borderClip, universe);
405
406 if ((pChild = pParent->firstChild) && pParent->mapped) {
407 RegionNull(&childUniverse);
408 RegionNull(&childUnion);
409 if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
410 ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
411 (pChild->drawable.x < pParent->lastChild->drawable.x))) {
412 for (; pChild; pChild = pChild->nextSib) {
413 if (pChild->viewable && !TreatAsTransparent(pChild))
414 RegionAppend(&childUnion, &pChild->borderSize);
415 }
416 }
417 else {
418 for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) {
419 if (pChild->viewable && !TreatAsTransparent(pChild))
420 RegionAppend(&childUnion, &pChild->borderSize);
421 }
422 }
423 RegionValidate(&childUnion, &overlap);
424
425 for (pChild = pParent->firstChild; pChild; pChild = pChild->nextSib) {
426 if (pChild->viewable) {
427 /*
428 * If the child is viewable, we want to remove its extents
429 * from the current universe, but we only re-clip it if
430 * it's been marked.
431 */
432 if (pChild->valdata) {
433 /*
434 * Figure out the new universe from the child's
435 * perspective and recurse.
436 */
437 RegionIntersect(&childUniverse,
438 universe, &pChild->borderSize);
439 miComputeClips(pChild, pScreen, &childUniverse, kind,
440 exposed);
441 }
442 /*
443 * Once the child has been processed, we remove its extents
444 * from the current universe, thus denying its space to any
445 * other sibling.
446 */
447 if (overlap && !TreatAsTransparent(pChild))
448 RegionSubtract(universe, universe, &pChild->borderSize);
449 }
450 }
451 if (!overlap)
452 RegionSubtract(universe, universe, &childUnion);
453 RegionUninit(&childUnion);
454 RegionUninit(&childUniverse);
455 } /* if any children */
456
457 /*
458 * 'universe' now contains the new clipList for the parent window.
459 *
460 * To figure the exposure of the window we subtract the old clip from the
461 * new, just as for the border.
462 */
463
464 if (oldVis == VisibilityFullyObscured || oldVis == VisibilityNotViewable) {
465 RegionCopy(&pParent->valdata->after.exposed, universe);
466 }
467 else if (newVis != VisibilityFullyObscured &&
468 newVis != VisibilityNotViewable) {
469 RegionSubtract(&pParent->valdata->after.exposed,
470 universe, &pParent->clipList);
471 }
472
473 /* HACK ALERT - copying contents of regions, instead of regions */
474 {
475 RegionRec tmp;
476
477 tmp = pParent->clipList;
478 pParent->clipList = *universe;
479 *universe = tmp;
480 }
481
482 #ifdef NOTDEF
483 RegionCopy(&pParent->clipList, universe);
484 #endif
485
486 pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
487
488 if (pScreen->ClipNotify)
489 (*pScreen->ClipNotify) (pParent, dx, dy);
490 }
491
492 static void
493 miTreeObscured(WindowPtr pParent)
494 {
495 WindowPtr pChild;
496 int oldVis;
497
498 pChild = pParent;
499 while (1) {
500 if (pChild->viewable) {
501 oldVis = pChild->visibility;
502 if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
503 ((pChild->
504 eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
505 SendVisibilityNotify(pChild);
506 if (pChild->firstChild) {
507 pChild = pChild->firstChild;
508 continue;
509 }
510 }
511 while (!pChild->nextSib && (pChild != pParent))
512 pChild = pChild->parent;
513 if (pChild == pParent)
514 break;
515 pChild = pChild->nextSib;
516 }
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 RegionPtr pBorderClip = &pWin->borderClip;
613
614 #ifdef COMPOSITE
615 if (pWin->redirectDraw != RedirectDrawNone &&
616 miGetRedirectBorderClipProc)
617 pBorderClip = (*miGetRedirectBorderClipProc) (pWin);
618 #endif
619 RegionAppend(&totalClip, pBorderClip);
620 if (pWin->viewable)
621 viewvals++;
622 }
623 }
624 }
625 else {
626 forward = FALSE;
627 pWin = pParent->lastChild;
628 while (1) {
629 if (pWin->valdata) {
630 RegionPtr pBorderClip = &pWin->borderClip;
631
632 #ifdef COMPOSITE
633 if (pWin->redirectDraw != RedirectDrawNone &&
634 miGetRedirectBorderClipProc)
635 pBorderClip = (*miGetRedirectBorderClipProc) (pWin);
636 #endif
637 RegionAppend(&totalClip, pBorderClip);
638 if (pWin->viewable)
639 viewvals++;
640 }
641 if (pWin == pChild)
642 break;
643 pWin = pWin->prevSib;
644 }
645 }
646 RegionValidate(&totalClip, &overlap);
647 }
648
649 /*
650 * Now go through the children of the root and figure their new
651 * borderClips from the totalClip, passing that off to miComputeClips
652 * to handle recursively. Once that's done, we remove the child
653 * from the totalClip to clip any siblings below it.
654 */
655
656 overlap = TRUE;
657 if (kind != VTStack) {
658 RegionUnion(&totalClip, &totalClip, &pParent->clipList);
659 if (viewvals > 1) {
660 /*
661 * precompute childUnion to discover whether any of them
662 * overlap. This seems redundant, but performance studies
663 * have demonstrated that the cost of this loop is
664 * lower than the cost of multiple Subtracts in the
665 * loop below.
666 */
667 RegionNull(&childUnion);
668 if (forward) {
669 for (pWin = pChild; pWin; pWin = pWin->nextSib)
670 if (pWin->valdata && pWin->viewable &&
671 !TreatAsTransparent(pWin))
672 RegionAppend(&childUnion, &pWin->borderSize);
673 }
674 else {
675 pWin = pParent->lastChild;
676 while (1) {
677 if (pWin->valdata && pWin->viewable &&
678 !TreatAsTransparent(pWin))
679 RegionAppend(&childUnion, &pWin->borderSize);
680 if (pWin == pChild)
681 break;
682 pWin = pWin->prevSib;
683 }
684 }
685 RegionValidate(&childUnion, &overlap);
686 if (overlap)
687 RegionUninit(&childUnion);
688 }
689 }
690
691 for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) {
692 if (pWin->viewable) {
693 if (pWin->valdata) {
694 RegionIntersect(&childClip, &totalClip, &pWin->borderSize);
695 miComputeClips(pWin, pScreen, &childClip, kind, &exposed);
696 if (overlap && !TreatAsTransparent(pWin)) {
697 RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
698 }
699 }
700 else if (pWin->visibility == VisibilityNotViewable) {
701 miTreeObscured(pWin);
702 }
703 }
704 else {
705 if (pWin->valdata) {
706 RegionEmpty(&pWin->clipList);
707 if (pScreen->ClipNotify)
708 (*pScreen->ClipNotify) (pWin, 0, 0);
709 RegionEmpty(&pWin->borderClip);
710 pWin->valdata = NULL;
711 }
712 }
713 }
714
715 RegionUninit(&childClip);
716 if (!overlap) {
717 RegionSubtract(&totalClip, &totalClip, &childUnion);
718 RegionUninit(&childUnion);
719 }
720
721 RegionNull(&pParent->valdata->after.exposed);
722 RegionNull(&pParent->valdata->after.borderExposed);
723
724 /*
725 * each case below is responsible for updating the
726 * clipList and serial number for the parent window
727 */
728
729 switch (kind) {
730 case VTStack:
731 break;
732 default:
733 /*
734 * totalClip contains the new clipList for the parent. Figure out
735 * exposures and obscures as per miComputeClips and reset the parent's
736 * clipList.
737 */
738 RegionSubtract(&pParent->valdata->after.exposed,
739 &totalClip, &pParent->clipList);
740 /* fall through */
741 case VTMap:
742 RegionCopy(&pParent->clipList, &totalClip);
743 pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
744 break;
745 }
746
747 RegionUninit(&totalClip);
748 RegionUninit(&exposed);
749 if (pScreen->ClipNotify)
750 (*pScreen->ClipNotify) (pParent, 0, 0);
751 return 1;
752 }