1706f2543Smrg/*
2706f2543Smrg * Calculate window clip lists for rootless mode
3706f2543Smrg *
4706f2543Smrg * This file is very closely based on mivaltree.c.
5706f2543Smrg */
6706f2543Smrg
7706f2543Smrg/*
8706f2543Smrg * mivaltree.c --
9706f2543Smrg *	Functions for recalculating window clip lists. Main function
10706f2543Smrg *	is miValidateTree.
11706f2543Smrg *
12706f2543Smrg
13706f2543SmrgCopyright 1987, 1988, 1989, 1998  The Open Group
14706f2543Smrg
15706f2543SmrgAll Rights Reserved.
16706f2543Smrg
17706f2543SmrgThe above copyright notice and this permission notice shall be included in
18706f2543Smrgall copies or substantial portions of the Software.
19706f2543Smrg
20706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
23706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26706f2543Smrg
27706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
28706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
29706f2543Smrgin this Software without prior written authorization from The Open Group.
30706f2543Smrg
31706f2543Smrg *
32706f2543Smrg * Copyright 1987, 1988, 1989 by
33706f2543Smrg * Digital Equipment Corporation, Maynard, Massachusetts,
34706f2543Smrg *
35706f2543Smrg *                         All Rights Reserved
36706f2543Smrg *
37706f2543Smrg * Permission to use, copy, modify, and distribute this software and its
38706f2543Smrg * documentation for any purpose and without fee is hereby granted,
39706f2543Smrg * provided that the above copyright notice appear in all copies and that
40706f2543Smrg * both that copyright notice and this permission notice appear in
41706f2543Smrg * supporting documentation, and that the name of Digital not be
42706f2543Smrg * used in advertising or publicity pertaining to distribution of the
43706f2543Smrg * software without specific, written prior permission.
44706f2543Smrg *
45706f2543Smrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
46706f2543Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
47706f2543Smrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
48706f2543Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
49706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
50706f2543Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51706f2543Smrg * SOFTWARE.
52706f2543Smrg *
53706f2543Smrg ******************************************************************/
54706f2543Smrg
55706f2543Smrg/* The panoramix components contained the following notice */
56706f2543Smrg/*****************************************************************
57706f2543Smrg
58706f2543SmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
59706f2543Smrg
60706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
61706f2543Smrgof this software and associated documentation files (the "Software"), to deal
62706f2543Smrgin the Software without restriction, including without limitation the rights
63706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
64706f2543Smrgcopies of the Software.
65706f2543Smrg
66706f2543SmrgThe above copyright notice and this permission notice shall be included in
67706f2543Smrgall copies or substantial portions of the Software.
68706f2543Smrg
69706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
72706f2543SmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
73706f2543SmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
74706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
75706f2543SmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
76706f2543Smrg
77706f2543SmrgExcept as contained in this notice, the name of Digital Equipment Corporation
78706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use or other
79706f2543Smrgdealings in this Software without prior written authorization from Digital
80706f2543SmrgEquipment Corporation.
81706f2543Smrg
82706f2543Smrg******************************************************************/
83706f2543Smrg /*
84706f2543Smrg  * Aug '86: Susan Angebranndt -- original code
85706f2543Smrg  * July '87: Adam de Boor -- substantially modified and commented
86706f2543Smrg  * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
87706f2543Smrg  *             In particular, much improved code for window mapping and
88706f2543Smrg  *             circulating.
89706f2543Smrg  *		Bob Scheifler -- avoid miComputeClips for unmapped windows,
90706f2543Smrg  *				 valdata changes
91706f2543Smrg  */
92706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
93706f2543Smrg#include <dix-config.h>
94706f2543Smrg#endif
95706f2543Smrg
96706f2543Smrg#include <stddef.h> /* For NULL */
97706f2543Smrg#include    <X11/X.h>
98706f2543Smrg#include    "scrnintstr.h"
99706f2543Smrg#include    "validate.h"
100706f2543Smrg#include    "windowstr.h"
101706f2543Smrg#include    "mi.h"
102706f2543Smrg#include    "regionstr.h"
103706f2543Smrg#include    "mivalidate.h"
104706f2543Smrg
105706f2543Smrg#include    "globals.h"
106706f2543Smrg
107706f2543Smrgint RootlessMiValidateTree (WindowPtr pRoot, WindowPtr pChild, VTKind kind);
108706f2543Smrg
109706f2543Smrg/*
110706f2543Smrg * Compute the visibility of a shaped window
111706f2543Smrg */
112706f2543Smrgstatic int
113706f2543SmrgRootlessShapedWindowIn (RegionPtr universe,
114706f2543Smrg			RegionPtr bounding, BoxPtr rect, int x, int y)
115706f2543Smrg{
116706f2543Smrg    BoxRec  box;
117706f2543Smrg    register BoxPtr  boundBox;
118706f2543Smrg    int	    nbox;
119706f2543Smrg    Bool    someIn, someOut;
120706f2543Smrg    register int t, x1, y1, x2, y2;
121706f2543Smrg
122706f2543Smrg    nbox = RegionNumRects (bounding);
123706f2543Smrg    boundBox = RegionRects (bounding);
124706f2543Smrg    someIn = someOut = FALSE;
125706f2543Smrg    x1 = rect->x1;
126706f2543Smrg    y1 = rect->y1;
127706f2543Smrg    x2 = rect->x2;
128706f2543Smrg    y2 = rect->y2;
129706f2543Smrg    while (nbox--)
130706f2543Smrg    {
131706f2543Smrg	if ((t = boundBox->x1 + x) < x1)
132706f2543Smrg	    t = x1;
133706f2543Smrg	box.x1 = t;
134706f2543Smrg	if ((t = boundBox->y1 + y) < y1)
135706f2543Smrg	    t = y1;
136706f2543Smrg	box.y1 = t;
137706f2543Smrg	if ((t = boundBox->x2 + x) > x2)
138706f2543Smrg	    t = x2;
139706f2543Smrg	box.x2 = t;
140706f2543Smrg	if ((t = boundBox->y2 + y) > y2)
141706f2543Smrg	    t = y2;
142706f2543Smrg	box.y2 = t;
143706f2543Smrg	if (box.x1 > box.x2)
144706f2543Smrg	    box.x2 = box.x1;
145706f2543Smrg	if (box.y1 > box.y2)
146706f2543Smrg	    box.y2 = box.y1;
147706f2543Smrg	switch (RegionContainsRect(universe, &box))
148706f2543Smrg	{
149706f2543Smrg	case rgnIN:
150706f2543Smrg	    if (someOut)
151706f2543Smrg		return rgnPART;
152706f2543Smrg	    someIn = TRUE;
153706f2543Smrg	    break;
154706f2543Smrg	case rgnOUT:
155706f2543Smrg	    if (someIn)
156706f2543Smrg		return rgnPART;
157706f2543Smrg	    someOut = TRUE;
158706f2543Smrg	    break;
159706f2543Smrg	default:
160706f2543Smrg	    return rgnPART;
161706f2543Smrg	}
162706f2543Smrg	boundBox++;
163706f2543Smrg    }
164706f2543Smrg    if (someIn)
165706f2543Smrg	return rgnIN;
166706f2543Smrg    return rgnOUT;
167706f2543Smrg}
168706f2543Smrg
169706f2543Smrg#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
170706f2543Smrg				    HasBorder(w) && \
171706f2543Smrg				    (w)->backgroundState == ParentRelative)
172706f2543Smrg
173706f2543Smrg
174706f2543Smrg/*
175706f2543Smrg *-----------------------------------------------------------------------
176706f2543Smrg * RootlessComputeClips --
177706f2543Smrg *	Recompute the clipList, borderClip, exposed and borderExposed
178706f2543Smrg *	regions for pParent and its children. Only viewable windows are
179706f2543Smrg *	taken into account.
180706f2543Smrg *
181706f2543Smrg * Results:
182706f2543Smrg *	None.
183706f2543Smrg *
184706f2543Smrg * Side Effects:
185706f2543Smrg *	clipList, borderClip, exposed and borderExposed are altered.
186706f2543Smrg *	A VisibilityNotify event may be generated on the parent window.
187706f2543Smrg *
188706f2543Smrg *-----------------------------------------------------------------------
189706f2543Smrg */
190706f2543Smrgstatic void
191706f2543SmrgRootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen,
192706f2543Smrg		      RegionPtr universe, VTKind kind, RegionPtr exposed)
193706f2543Smrg{
194706f2543Smrg    int			dx,
195706f2543Smrg			dy;
196706f2543Smrg    RegionRec		childUniverse;
197706f2543Smrg    register WindowPtr	pChild;
198706f2543Smrg    int     	  	oldVis, newVis;
199706f2543Smrg    BoxRec		borderSize;
200706f2543Smrg    RegionRec		childUnion;
201706f2543Smrg    Bool		overlap;
202706f2543Smrg    RegionPtr		borderVisible;
203706f2543Smrg    Bool		resized;
204706f2543Smrg    /*
205706f2543Smrg     * Figure out the new visibility of this window.
206706f2543Smrg     * The extent of the universe should be the same as the extent of
207706f2543Smrg     * the borderSize region. If the window is unobscured, this rectangle
208706f2543Smrg     * will be completely inside the universe (the universe will cover it
209706f2543Smrg     * completely). If the window is completely obscured, none of the
210706f2543Smrg     * universe will cover the rectangle.
211706f2543Smrg     */
212706f2543Smrg    borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
213706f2543Smrg    borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
214706f2543Smrg    dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
215706f2543Smrg    if (dx > 32767)
216706f2543Smrg	dx = 32767;
217706f2543Smrg    borderSize.x2 = dx;
218706f2543Smrg    dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
219706f2543Smrg    if (dy > 32767)
220706f2543Smrg	dy = 32767;
221706f2543Smrg    borderSize.y2 = dy;
222706f2543Smrg
223706f2543Smrg    oldVis = pParent->visibility;
224706f2543Smrg    switch (RegionContainsRect(universe, &borderSize))
225706f2543Smrg    {
226706f2543Smrg    case rgnIN:
227706f2543Smrg	    newVis = VisibilityUnobscured;
228706f2543Smrg	    break;
229706f2543Smrg	case rgnPART:
230706f2543Smrg	    newVis = VisibilityPartiallyObscured;
231706f2543Smrg	    {
232706f2543Smrg		RegionPtr   pBounding;
233706f2543Smrg
234706f2543Smrg		if ((pBounding = wBoundingShape (pParent)))
235706f2543Smrg		{
236706f2543Smrg		    switch (RootlessShapedWindowIn (universe,
237706f2543Smrg						    pBounding, &borderSize,
238706f2543Smrg						    pParent->drawable.x,
239706f2543Smrg						    pParent->drawable.y))
240706f2543Smrg		    {
241706f2543Smrg		    case rgnIN:
242706f2543Smrg			newVis = VisibilityUnobscured;
243706f2543Smrg			break;
244706f2543Smrg		    case rgnOUT:
245706f2543Smrg			newVis = VisibilityFullyObscured;
246706f2543Smrg			break;
247706f2543Smrg		    }
248706f2543Smrg		}
249706f2543Smrg	    }
250706f2543Smrg	    break;
251706f2543Smrg	default:
252706f2543Smrg	    newVis = VisibilityFullyObscured;
253706f2543Smrg	    break;
254706f2543Smrg    }
255706f2543Smrg
256706f2543Smrg    pParent->visibility = newVis;
257706f2543Smrg    if (oldVis != newVis &&
258706f2543Smrg	((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
259706f2543Smrg	SendVisibilityNotify(pParent);
260706f2543Smrg
261706f2543Smrg    dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
262706f2543Smrg    dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
263706f2543Smrg
264706f2543Smrg    /*
265706f2543Smrg     * avoid computations when dealing with simple operations
266706f2543Smrg     */
267706f2543Smrg
268706f2543Smrg    switch (kind) {
269706f2543Smrg    case VTMap:
270706f2543Smrg    case VTStack:
271706f2543Smrg    case VTUnmap:
272706f2543Smrg	break;
273706f2543Smrg    case VTMove:
274706f2543Smrg	if ((oldVis == newVis) &&
275706f2543Smrg	    ((oldVis == VisibilityFullyObscured) ||
276706f2543Smrg	     (oldVis == VisibilityUnobscured)))
277706f2543Smrg	{
278706f2543Smrg	    pChild = pParent;
279706f2543Smrg	    while (1)
280706f2543Smrg	    {
281706f2543Smrg		if (pChild->viewable)
282706f2543Smrg		{
283706f2543Smrg		    if (pChild->visibility != VisibilityFullyObscured)
284706f2543Smrg		    {
285706f2543Smrg			RegionTranslate(&pChild->borderClip,
286706f2543Smrg						      dx, dy);
287706f2543Smrg			RegionTranslate(&pChild->clipList,
288706f2543Smrg						      dx, dy);
289706f2543Smrg			pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
290706f2543Smrg			if (pScreen->ClipNotify)
291706f2543Smrg			    (* pScreen->ClipNotify) (pChild, dx, dy);
292706f2543Smrg
293706f2543Smrg		    }
294706f2543Smrg		    if (pChild->valdata)
295706f2543Smrg		    {
296706f2543Smrg			RegionNull(&pChild->valdata->after.borderExposed);
297706f2543Smrg			if (HasParentRelativeBorder(pChild))
298706f2543Smrg			  {
299706f2543Smrg			    RegionSubtract(&pChild->valdata->after.borderExposed,
300706f2543Smrg					   &pChild->borderClip,
301706f2543Smrg					   &pChild->winSize);
302706f2543Smrg			}
303706f2543Smrg			RegionNull(&pChild->valdata->after.exposed);
304706f2543Smrg		    }
305706f2543Smrg		    if (pChild->firstChild)
306706f2543Smrg		    {
307706f2543Smrg			pChild = pChild->firstChild;
308706f2543Smrg			continue;
309706f2543Smrg		    }
310706f2543Smrg		}
311706f2543Smrg		while (!pChild->nextSib && (pChild != pParent))
312706f2543Smrg		    pChild = pChild->parent;
313706f2543Smrg		if (pChild == pParent)
314706f2543Smrg		    break;
315706f2543Smrg		pChild = pChild->nextSib;
316706f2543Smrg	    }
317706f2543Smrg	    return;
318706f2543Smrg	}
319706f2543Smrg	/* fall through */
320706f2543Smrg    default:
321706f2543Smrg    	/*
322706f2543Smrg     	 * To calculate exposures correctly, we have to translate the old
323706f2543Smrg     	 * borderClip and clipList regions to the window's new location so there
324706f2543Smrg     	 * is a correspondence between pieces of the new and old clipping regions.
325706f2543Smrg     	 */
326706f2543Smrg    	if (dx || dy)
327706f2543Smrg    	{
328706f2543Smrg	    /*
329706f2543Smrg	     * We translate the old clipList because that will be exposed or copied
330706f2543Smrg	     * if gravity is right.
331706f2543Smrg	     */
332706f2543Smrg	    RegionTranslate(&pParent->borderClip, dx, dy);
333706f2543Smrg	    RegionTranslate(&pParent->clipList, dx, dy);
334706f2543Smrg    	}
335706f2543Smrg	break;
336706f2543Smrg    case VTBroken:
337706f2543Smrg	RegionEmpty(&pParent->borderClip);
338706f2543Smrg	RegionEmpty(&pParent->clipList);
339706f2543Smrg	break;
340706f2543Smrg    }
341706f2543Smrg
342706f2543Smrg    borderVisible = pParent->valdata->before.borderVisible;
343706f2543Smrg    resized = pParent->valdata->before.resized;
344706f2543Smrg    RegionNull(&pParent->valdata->after.borderExposed);
345706f2543Smrg    RegionNull(&pParent->valdata->after.exposed);
346706f2543Smrg
347706f2543Smrg    /*
348706f2543Smrg     * Since the borderClip must not be clipped by the children, we do
349706f2543Smrg     * the border exposure first...
350706f2543Smrg     *
351706f2543Smrg     * 'universe' is the window's borderClip. To figure the exposures, remove
352706f2543Smrg     * the area that used to be exposed from the new.
353706f2543Smrg     * This leaves a region of pieces that weren't exposed before.
354706f2543Smrg     */
355706f2543Smrg
356706f2543Smrg    if (HasBorder (pParent))
357706f2543Smrg    {
358706f2543Smrg    	if (borderVisible)
359706f2543Smrg    	{
360706f2543Smrg	    /*
361706f2543Smrg	     * when the border changes shape, the old visible portions
362706f2543Smrg	     * of the border will be saved by DIX in borderVisible --
363706f2543Smrg	     * use that region and destroy it
364706f2543Smrg	     */
365706f2543Smrg	    RegionSubtract(exposed, universe, borderVisible);
366706f2543Smrg	    RegionDestroy(borderVisible);
367706f2543Smrg    	}
368706f2543Smrg    	else
369706f2543Smrg    	{
370706f2543Smrg	    RegionSubtract(exposed, universe, &pParent->borderClip);
371706f2543Smrg    	}
372706f2543Smrg	if (HasParentRelativeBorder(pParent) && (dx || dy)) {
373706f2543Smrg	    RegionSubtract(&pParent->valdata->after.borderExposed,
374706f2543Smrg				  universe,
375706f2543Smrg				  &pParent->winSize);
376706f2543Smrg	} else {
377706f2543Smrg	    RegionSubtract(&pParent->valdata->after.borderExposed,
378706f2543Smrg			       exposed, &pParent->winSize);
379706f2543Smrg	}
380706f2543Smrg
381706f2543Smrg	RegionCopy(&pParent->borderClip, universe);
382706f2543Smrg
383706f2543Smrg    	/*
384706f2543Smrg     	 * To get the right clipList for the parent, and to make doubly sure
385706f2543Smrg     	 * that no child overlaps the parent's border, we remove the parent's
386706f2543Smrg     	 * border from the universe before proceeding.
387706f2543Smrg     	 */
388706f2543Smrg
389706f2543Smrg	RegionIntersect(universe, universe, &pParent->winSize);
390706f2543Smrg    }
391706f2543Smrg    else
392706f2543Smrg	RegionCopy(&pParent->borderClip, universe);
393706f2543Smrg
394706f2543Smrg    if ((pChild = pParent->firstChild) && pParent->mapped)
395706f2543Smrg    {
396706f2543Smrg	RegionNull(&childUniverse);
397706f2543Smrg	RegionNull(&childUnion);
398706f2543Smrg	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
399706f2543Smrg	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
400706f2543Smrg	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
401706f2543Smrg	{
402706f2543Smrg	    for (; pChild; pChild = pChild->nextSib)
403706f2543Smrg	    {
404706f2543Smrg		if (pChild->viewable)
405706f2543Smrg		    RegionAppend(&childUnion, &pChild->borderSize);
406706f2543Smrg	    }
407706f2543Smrg	}
408706f2543Smrg	else
409706f2543Smrg	{
410706f2543Smrg	    for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
411706f2543Smrg	    {
412706f2543Smrg		if (pChild->viewable)
413706f2543Smrg		    RegionAppend(&childUnion, &pChild->borderSize);
414706f2543Smrg	    }
415706f2543Smrg	}
416706f2543Smrg	RegionValidate(&childUnion, &overlap);
417706f2543Smrg
418706f2543Smrg	for (pChild = pParent->firstChild;
419706f2543Smrg	     pChild;
420706f2543Smrg	     pChild = pChild->nextSib)
421706f2543Smrg 	{
422706f2543Smrg	    if (pChild->viewable) {
423706f2543Smrg		/*
424706f2543Smrg		 * If the child is viewable, we want to remove its extents
425706f2543Smrg		 * from the current universe, but we only re-clip it if
426706f2543Smrg		 * it's been marked.
427706f2543Smrg		 */
428706f2543Smrg		if (pChild->valdata) {
429706f2543Smrg		    /*
430706f2543Smrg		     * Figure out the new universe from the child's
431706f2543Smrg		     * perspective and recurse.
432706f2543Smrg		     */
433706f2543Smrg		    RegionIntersect(&childUniverse,
434706f2543Smrg					    universe,
435706f2543Smrg					    &pChild->borderSize);
436706f2543Smrg		    RootlessComputeClips (pChild, pScreen, &childUniverse,
437706f2543Smrg					  kind, exposed);
438706f2543Smrg		}
439706f2543Smrg		/*
440706f2543Smrg		 * Once the child has been processed, we remove its extents
441706f2543Smrg		 * from the current universe, thus denying its space to any
442706f2543Smrg		 * other sibling.
443706f2543Smrg		 */
444706f2543Smrg		if (overlap)
445706f2543Smrg		    RegionSubtract(universe, universe,
446706f2543Smrg					  &pChild->borderSize);
447706f2543Smrg	    }
448706f2543Smrg	}
449706f2543Smrg	if (!overlap)
450706f2543Smrg	    RegionSubtract(universe, universe, &childUnion);
451706f2543Smrg	RegionUninit(&childUnion);
452706f2543Smrg	RegionUninit(&childUniverse);
453706f2543Smrg    } /* if any children */
454706f2543Smrg
455706f2543Smrg    /*
456706f2543Smrg     * 'universe' now contains the new clipList for the parent window.
457706f2543Smrg     *
458706f2543Smrg     * To figure the exposure of the window we subtract the old clip from the
459706f2543Smrg     * new, just as for the border.
460706f2543Smrg     */
461706f2543Smrg
462706f2543Smrg    if (oldVis == VisibilityFullyObscured ||
463706f2543Smrg	oldVis == VisibilityNotViewable)
464706f2543Smrg    {
465706f2543Smrg	RegionCopy(&pParent->valdata->after.exposed, universe);
466706f2543Smrg    }
467706f2543Smrg    else if (newVis != VisibilityFullyObscured &&
468706f2543Smrg	     newVis != VisibilityNotViewable)
469706f2543Smrg    {
470706f2543Smrg	RegionSubtract(&pParent->valdata->after.exposed,
471706f2543Smrg			       universe, &pParent->clipList);
472706f2543Smrg    }
473706f2543Smrg
474706f2543Smrg    /* HACK ALERT - copying contents of regions, instead of regions */
475706f2543Smrg    {
476706f2543Smrg	RegionRec   tmp;
477706f2543Smrg
478706f2543Smrg	tmp = pParent->clipList;
479706f2543Smrg	pParent->clipList = *universe;
480706f2543Smrg	*universe = tmp;
481706f2543Smrg    }
482706f2543Smrg
483706f2543Smrg#ifdef NOTDEF
484706f2543Smrg    RegionCopy(&pParent->clipList, universe);
485706f2543Smrg#endif
486706f2543Smrg
487706f2543Smrg    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
488706f2543Smrg
489706f2543Smrg    if (pScreen->ClipNotify)
490706f2543Smrg	(* pScreen->ClipNotify) (pParent, dx, dy);
491706f2543Smrg}
492706f2543Smrg
493706f2543Smrgstatic void
494706f2543SmrgRootlessTreeObscured(WindowPtr pParent)
495706f2543Smrg{
496706f2543Smrg    register WindowPtr pChild;
497706f2543Smrg    register int    oldVis;
498706f2543Smrg
499706f2543Smrg    pChild = pParent;
500706f2543Smrg    while (1)
501706f2543Smrg    {
502706f2543Smrg	if (pChild->viewable)
503706f2543Smrg	{
504706f2543Smrg	    oldVis = pChild->visibility;
505706f2543Smrg	    if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
506706f2543Smrg		((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
507706f2543Smrg		SendVisibilityNotify(pChild);
508706f2543Smrg	    if (pChild->firstChild)
509706f2543Smrg	    {
510706f2543Smrg		pChild = pChild->firstChild;
511706f2543Smrg		continue;
512706f2543Smrg	    }
513706f2543Smrg	}
514706f2543Smrg	while (!pChild->nextSib && (pChild != pParent))
515706f2543Smrg	    pChild = pChild->parent;
516706f2543Smrg	if (pChild == pParent)
517706f2543Smrg	    break;
518706f2543Smrg	pChild = pChild->nextSib;
519706f2543Smrg    }
520706f2543Smrg}
521706f2543Smrg
522706f2543Smrg/*
523706f2543Smrg *-----------------------------------------------------------------------
524706f2543Smrg * RootlessMiValidateTree --
525706f2543Smrg *	Recomputes the clip list for pParent and all its inferiors.
526706f2543Smrg *
527706f2543Smrg * Results:
528706f2543Smrg *	Always returns 1.
529706f2543Smrg *
530706f2543Smrg * Side Effects:
531706f2543Smrg *	The clipList, borderClip, exposed, and borderExposed regions for
532706f2543Smrg *	each marked window are altered.
533706f2543Smrg *
534706f2543Smrg * Notes:
535706f2543Smrg *	This routine assumes that all affected windows have been marked
536706f2543Smrg *	(valdata created) and their winSize and borderSize regions
537706f2543Smrg *	adjusted to correspond to their new positions. The borderClip and
538706f2543Smrg *	clipList regions should not have been touched.
539706f2543Smrg *
540706f2543Smrg *	The top-most level is treated differently from all lower levels
541706f2543Smrg *	because pParent is unchanged. For the top level, we merge the
542706f2543Smrg *	regions taken up by the marked children back into the clipList
543706f2543Smrg *	for pParent, thus forming a region from which the marked children
544706f2543Smrg *	can claim their areas. For lower levels, where the old clipList
545706f2543Smrg *	and borderClip are invalid, we can't do this and have to do the
546706f2543Smrg *	extra operations done in miComputeClips, but this is much faster
547706f2543Smrg *	e.g. when only one child has moved...
548706f2543Smrg *
549706f2543Smrg *-----------------------------------------------------------------------
550706f2543Smrg */
551706f2543Smrg/*
552706f2543Smrg   Quartz version: used for validate from root in rootless mode.
553706f2543Smrg   We need to make sure top-level windows don't clip each other,
554706f2543Smrg   and that top-level windows aren't clipped to the root window.
555706f2543Smrg*/
556706f2543Smrg/*ARGSUSED*/
557706f2543Smrg// fixme this is ugly
558706f2543Smrg// Xprint/ValTree.c doesn't work, but maybe that method can?
559706f2543Smrgint
560706f2543SmrgRootlessMiValidateTree (WindowPtr pRoot, /* Parent to validate */
561706f2543Smrg			WindowPtr pChild, /* First child of pRoot that was
562706f2543Smrg					   * affected */
563706f2543Smrg			VTKind kind /* What kind of configuration caused call */)
564706f2543Smrg{
565706f2543Smrg    RegionRec	  	childClip;  /* The new borderClip for the current
566706f2543Smrg				     * child */
567706f2543Smrg    RegionRec		exposed;    /* For intermediate calculations */
568706f2543Smrg    register ScreenPtr	pScreen;
569706f2543Smrg    register WindowPtr	pWin;
570706f2543Smrg
571706f2543Smrg    pScreen = pRoot->drawable.pScreen;
572706f2543Smrg    if (pChild == NullWindow)
573706f2543Smrg	pChild = pRoot->firstChild;
574706f2543Smrg
575706f2543Smrg    RegionNull(&childClip);
576706f2543Smrg    RegionNull(&exposed);
577706f2543Smrg
578706f2543Smrg    if (RegionBroken(&pRoot->clipList) &&
579706f2543Smrg	!RegionBroken(&pRoot->borderClip))
580706f2543Smrg    {
581706f2543Smrg        // fixme this might not work, but hopefully doesn't happen anyway.
582706f2543Smrg        kind = VTBroken;
583706f2543Smrg        RegionEmpty(&pRoot->clipList);
584706f2543Smrg        ErrorF("ValidateTree: BUSTED!\n");
585706f2543Smrg    }
586706f2543Smrg
587706f2543Smrg    /*
588706f2543Smrg     * Recursively compute the clips for all children of the root.
589706f2543Smrg     * They don't clip against each other or the root itself, so
590706f2543Smrg     * childClip is always reset to that child's size.
591706f2543Smrg     */
592706f2543Smrg
593706f2543Smrg    for (pWin = pChild;
594706f2543Smrg	 pWin != NullWindow;
595706f2543Smrg	 pWin = pWin->nextSib)
596706f2543Smrg    {
597706f2543Smrg        if (pWin->viewable) {
598706f2543Smrg            if (pWin->valdata) {
599706f2543Smrg                RegionCopy(&childClip, &pWin->borderSize);
600706f2543Smrg                RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
601706f2543Smrg            } else if (pWin->visibility == VisibilityNotViewable) {
602706f2543Smrg                RootlessTreeObscured(pWin);
603706f2543Smrg            }
604706f2543Smrg        } else {
605706f2543Smrg            if (pWin->valdata) {
606706f2543Smrg                RegionEmpty(&pWin->clipList);
607706f2543Smrg                if (pScreen->ClipNotify)
608706f2543Smrg                    (* pScreen->ClipNotify) (pWin, 0, 0);
609706f2543Smrg                RegionEmpty(&pWin->borderClip);
610706f2543Smrg                pWin->valdata = NULL;
611706f2543Smrg            }
612706f2543Smrg        }
613706f2543Smrg    }
614706f2543Smrg
615706f2543Smrg    RegionUninit(&childClip);
616706f2543Smrg
617706f2543Smrg    /* The root is never clipped by its children, so nothing on the root
618706f2543Smrg       is ever exposed by moving or mapping its children. */
619706f2543Smrg    RegionNull(&pRoot->valdata->after.exposed);
620706f2543Smrg    RegionNull(&pRoot->valdata->after.borderExposed);
621706f2543Smrg
622706f2543Smrg    return 1;
623706f2543Smrg}
624