1706f2543Smrg/*
2706f2543Smrg * mivaltree.c --
3706f2543Smrg *	Functions for recalculating window clip lists. Main function
4706f2543Smrg *	is miValidateTree.
5706f2543Smrg *
6706f2543Smrg
7706f2543SmrgCopyright 1987, 1988, 1989, 1998  The Open Group
8706f2543Smrg
9706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
10706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
11706f2543Smrgthe above copyright notice appear in all copies and that both that
12706f2543Smrgcopyright notice and this permission notice appear in supporting
13706f2543Smrgdocumentation.
14706f2543Smrg
15706f2543SmrgThe above copyright notice and this permission notice shall be included in
16706f2543Smrgall copies or substantial portions of the Software.
17706f2543Smrg
18706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24706f2543Smrg
25706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
26706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
27706f2543Smrgin this Software without prior written authorization from The Open Group.
28706f2543Smrg
29706f2543Smrg *
30706f2543Smrg * Copyright 1987, 1988, 1989 by
31706f2543Smrg * Digital Equipment Corporation, Maynard, Massachusetts,
32706f2543Smrg *
33706f2543Smrg *                         All Rights Reserved
34706f2543Smrg *
35706f2543Smrg * Permission to use, copy, modify, and distribute this software and its
36706f2543Smrg * documentation for any purpose and without fee is hereby granted,
37706f2543Smrg * provided that the above copyright notice appear in all copies and that
38706f2543Smrg * both that copyright notice and this permission notice appear in
39706f2543Smrg * supporting documentation, and that the name of Digital not be
40706f2543Smrg * used in advertising or publicity pertaining to distribution of the
41706f2543Smrg * software without specific, written prior permission.
42706f2543Smrg *
43706f2543Smrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
44706f2543Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
45706f2543Smrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
46706f2543Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
47706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
48706f2543Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49706f2543Smrg * SOFTWARE.
50706f2543Smrg *
51706f2543Smrg ******************************************************************/
52706f2543Smrg
53706f2543Smrg/* The panoramix components contained the following notice */
54706f2543Smrg/*****************************************************************
55706f2543Smrg
56706f2543SmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
57706f2543Smrg
58706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
59706f2543Smrgof this software and associated documentation files (the "Software"), to deal
60706f2543Smrgin the Software without restriction, including without limitation the rights
61706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62706f2543Smrgcopies of the Software.
63706f2543Smrg
64706f2543SmrgThe above copyright notice and this permission notice shall be included in
65706f2543Smrgall copies or substantial portions of the Software.
66706f2543Smrg
67706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
69706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
70706f2543SmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
71706f2543SmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
72706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
73706f2543SmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
74706f2543Smrg
75706f2543SmrgExcept as contained in this notice, the name of Digital Equipment Corporation
76706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use or other
77706f2543Smrgdealings in this Software without prior written authorization from Digital
78706f2543SmrgEquipment Corporation.
79706f2543Smrg
80706f2543Smrg******************************************************************/
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    <X11/X.h>
97706f2543Smrg#include    "scrnintstr.h"
98706f2543Smrg#include    "validate.h"
99706f2543Smrg#include    "windowstr.h"
100706f2543Smrg#include    "mi.h"
101706f2543Smrg#include    "regionstr.h"
102706f2543Smrg#include    "mivalidate.h"
103706f2543Smrg
104706f2543Smrg#include    "globals.h"
105706f2543Smrg
106706f2543Smrg/*
107706f2543Smrg * Compute the visibility of a shaped window
108706f2543Smrg */
109706f2543Smrgint
110706f2543SmrgmiShapedWindowIn (RegionPtr universe, RegionPtr bounding,
111706f2543Smrg                  BoxPtr rect, int x, int y)
112706f2543Smrg{
113706f2543Smrg    BoxRec  	box;
114706f2543Smrg    BoxPtr	boundBox;
115706f2543Smrg    int		nbox;
116706f2543Smrg    Bool	someIn, someOut;
117706f2543Smrg    int 	t, x1, y1, x2, y2;
118706f2543Smrg
119706f2543Smrg    nbox = RegionNumRects (bounding);
120706f2543Smrg    boundBox = RegionRects (bounding);
121706f2543Smrg    someIn = someOut = FALSE;
122706f2543Smrg    x1 = rect->x1;
123706f2543Smrg    y1 = rect->y1;
124706f2543Smrg    x2 = rect->x2;
125706f2543Smrg    y2 = rect->y2;
126706f2543Smrg    while (nbox--)
127706f2543Smrg    {
128706f2543Smrg	if ((t = boundBox->x1 + x) < x1)
129706f2543Smrg	    t = x1;
130706f2543Smrg	box.x1 = t;
131706f2543Smrg	if ((t = boundBox->y1 + y) < y1)
132706f2543Smrg	    t = y1;
133706f2543Smrg	box.y1 = t;
134706f2543Smrg	if ((t = boundBox->x2 + x) > x2)
135706f2543Smrg	    t = x2;
136706f2543Smrg	box.x2 = t;
137706f2543Smrg	if ((t = boundBox->y2 + y) > y2)
138706f2543Smrg	    t = y2;
139706f2543Smrg	box.y2 = t;
140706f2543Smrg	if (box.x1 > box.x2)
141706f2543Smrg	    box.x2 = box.x1;
142706f2543Smrg	if (box.y1 > box.y2)
143706f2543Smrg	    box.y2 = box.y1;
144706f2543Smrg	switch (RegionContainsRect(universe, &box))
145706f2543Smrg	{
146706f2543Smrg	case rgnIN:
147706f2543Smrg	    if (someOut)
148706f2543Smrg		return rgnPART;
149706f2543Smrg	    someIn = TRUE;
150706f2543Smrg	    break;
151706f2543Smrg	case rgnOUT:
152706f2543Smrg	    if (someIn)
153706f2543Smrg		return rgnPART;
154706f2543Smrg	    someOut = TRUE;
155706f2543Smrg	    break;
156706f2543Smrg	default:
157706f2543Smrg	    return rgnPART;
158706f2543Smrg	}
159706f2543Smrg	boundBox++;
160706f2543Smrg    }
161706f2543Smrg    if (someIn)
162706f2543Smrg	return rgnIN;
163706f2543Smrg    return rgnOUT;
164706f2543Smrg}
165706f2543Smrg
166706f2543Smrgstatic GetRedirectBorderClipProcPtr	miGetRedirectBorderClipProc;
167706f2543Smrgstatic SetRedirectBorderClipProcPtr	miSetRedirectBorderClipProc;
168706f2543Smrg
169706f2543Smrgvoid
170706f2543SmrgmiRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip,
171706f2543Smrg				  GetRedirectBorderClipProcPtr getBorderClip)
172706f2543Smrg{
173706f2543Smrg    miSetRedirectBorderClipProc = setBorderClip;
174706f2543Smrg    miGetRedirectBorderClipProc = getBorderClip;
175706f2543Smrg}
176706f2543Smrg
177706f2543Smrg/*
178706f2543Smrg * Manual redirected windows are treated as transparent; they do not obscure
179706f2543Smrg * siblings or parent windows
180706f2543Smrg */
181706f2543Smrg
182706f2543Smrg#ifdef COMPOSITE
183706f2543Smrg#define TreatAsTransparent(w)	((w)->redirectDraw == RedirectDrawManual)
184706f2543Smrg#else
185706f2543Smrg#define TreatAsTransparent(w)	FALSE
186706f2543Smrg#endif
187706f2543Smrg
188706f2543Smrg#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
189706f2543Smrg				    HasBorder(w) && \
190706f2543Smrg				    (w)->backgroundState == ParentRelative)
191706f2543Smrg
192706f2543Smrg
193706f2543Smrg/*
194706f2543Smrg *-----------------------------------------------------------------------
195706f2543Smrg * miComputeClips --
196706f2543Smrg *	Recompute the clipList, borderClip, exposed and borderExposed
197706f2543Smrg *	regions for pParent and its children. Only viewable windows are
198706f2543Smrg *	taken into account.
199706f2543Smrg *
200706f2543Smrg * Results:
201706f2543Smrg *	None.
202706f2543Smrg *
203706f2543Smrg * Side Effects:
204706f2543Smrg *	clipList, borderClip, exposed and borderExposed are altered.
205706f2543Smrg *	A VisibilityNotify event may be generated on the parent window.
206706f2543Smrg *
207706f2543Smrg *-----------------------------------------------------------------------
208706f2543Smrg */
209706f2543Smrgstatic void
210706f2543SmrgmiComputeClips (
211706f2543Smrg    WindowPtr	pParent,
212706f2543Smrg    ScreenPtr	pScreen,
213706f2543Smrg    RegionPtr	universe,
214706f2543Smrg    VTKind		kind,
215706f2543Smrg    RegionPtr		exposed ) /* for intermediate calculations */
216706f2543Smrg{
217706f2543Smrg    int			dx,
218706f2543Smrg			dy;
219706f2543Smrg    RegionRec		childUniverse;
220706f2543Smrg    WindowPtr		pChild;
221706f2543Smrg    int     	  	oldVis, newVis;
222706f2543Smrg    BoxRec		borderSize;
223706f2543Smrg    RegionRec		childUnion;
224706f2543Smrg    Bool		overlap;
225706f2543Smrg    RegionPtr		borderVisible;
226706f2543Smrg    Bool		resized;
227706f2543Smrg    /*
228706f2543Smrg     * Figure out the new visibility of this window.
229706f2543Smrg     * The extent of the universe should be the same as the extent of
230706f2543Smrg     * the borderSize region. If the window is unobscured, this rectangle
231706f2543Smrg     * will be completely inside the universe (the universe will cover it
232706f2543Smrg     * completely). If the window is completely obscured, none of the
233706f2543Smrg     * universe will cover the rectangle.
234706f2543Smrg     */
235706f2543Smrg    borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
236706f2543Smrg    borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
237706f2543Smrg    dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
238706f2543Smrg    if (dx > 32767)
239706f2543Smrg	dx = 32767;
240706f2543Smrg    borderSize.x2 = dx;
241706f2543Smrg    dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
242706f2543Smrg    if (dy > 32767)
243706f2543Smrg	dy = 32767;
244706f2543Smrg    borderSize.y2 = dy;
245706f2543Smrg
246706f2543Smrg#ifdef COMPOSITE
247706f2543Smrg    /*
248706f2543Smrg     * In redirected drawing case, reset universe to borderSize
249706f2543Smrg     */
250706f2543Smrg    if (pParent->redirectDraw != RedirectDrawNone)
251706f2543Smrg    {
252706f2543Smrg	if (miSetRedirectBorderClipProc)
253706f2543Smrg	{
254706f2543Smrg	    if (TreatAsTransparent (pParent))
255706f2543Smrg		RegionEmpty(universe);
256706f2543Smrg	    (*miSetRedirectBorderClipProc) (pParent, universe);
257706f2543Smrg	}
258706f2543Smrg	RegionCopy(universe, &pParent->borderSize);
259706f2543Smrg    }
260706f2543Smrg#endif
261706f2543Smrg
262706f2543Smrg    oldVis = pParent->visibility;
263706f2543Smrg    switch (RegionContainsRect(universe, &borderSize))
264706f2543Smrg    {
265706f2543Smrg	case rgnIN:
266706f2543Smrg	    newVis = VisibilityUnobscured;
267706f2543Smrg	    break;
268706f2543Smrg	case rgnPART:
269706f2543Smrg	    newVis = VisibilityPartiallyObscured;
270706f2543Smrg	    {
271706f2543Smrg		RegionPtr   pBounding;
272706f2543Smrg
273706f2543Smrg		if ((pBounding = wBoundingShape (pParent)))
274706f2543Smrg		{
275706f2543Smrg		    switch (miShapedWindowIn (universe, pBounding,
276706f2543Smrg					      &borderSize,
277706f2543Smrg					      pParent->drawable.x,
278706f2543Smrg 					      pParent->drawable.y))
279706f2543Smrg		    {
280706f2543Smrg		    case rgnIN:
281706f2543Smrg			newVis = VisibilityUnobscured;
282706f2543Smrg			break;
283706f2543Smrg		    case rgnOUT:
284706f2543Smrg			newVis = VisibilityFullyObscured;
285706f2543Smrg			break;
286706f2543Smrg		    }
287706f2543Smrg		}
288706f2543Smrg	    }
289706f2543Smrg	    break;
290706f2543Smrg	default:
291706f2543Smrg	    newVis = VisibilityFullyObscured;
292706f2543Smrg	    break;
293706f2543Smrg    }
294706f2543Smrg    pParent->visibility = newVis;
295706f2543Smrg    if (oldVis != newVis &&
296706f2543Smrg	((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
297706f2543Smrg	SendVisibilityNotify(pParent);
298706f2543Smrg
299706f2543Smrg    dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
300706f2543Smrg    dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
301706f2543Smrg
302706f2543Smrg    /*
303706f2543Smrg     * avoid computations when dealing with simple operations
304706f2543Smrg     */
305706f2543Smrg
306706f2543Smrg    switch (kind) {
307706f2543Smrg    case VTMap:
308706f2543Smrg    case VTStack:
309706f2543Smrg    case VTUnmap:
310706f2543Smrg	break;
311706f2543Smrg    case VTMove:
312706f2543Smrg	if ((oldVis == newVis) &&
313706f2543Smrg	    ((oldVis == VisibilityFullyObscured) ||
314706f2543Smrg	     (oldVis == VisibilityUnobscured)))
315706f2543Smrg	{
316706f2543Smrg	    pChild = pParent;
317706f2543Smrg	    while (1)
318706f2543Smrg	    {
319706f2543Smrg		if (pChild->viewable)
320706f2543Smrg		{
321706f2543Smrg		    if (pChild->visibility != VisibilityFullyObscured)
322706f2543Smrg		    {
323706f2543Smrg			RegionTranslate(&pChild->borderClip,
324706f2543Smrg						      dx, dy);
325706f2543Smrg			RegionTranslate(&pChild->clipList,
326706f2543Smrg						      dx, dy);
327706f2543Smrg			pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
328706f2543Smrg			if (pScreen->ClipNotify)
329706f2543Smrg			    (* pScreen->ClipNotify) (pChild, dx, dy);
330706f2543Smrg
331706f2543Smrg		    }
332706f2543Smrg		    if (pChild->valdata)
333706f2543Smrg		    {
334706f2543Smrg			RegionNull(&pChild->valdata->after.borderExposed);
335706f2543Smrg			if (HasParentRelativeBorder(pChild))
336706f2543Smrg			{
337706f2543Smrg			    RegionSubtract(&pChild->valdata->after.borderExposed,
338706f2543Smrg					   &pChild->borderClip,
339706f2543Smrg					   &pChild->winSize);
340706f2543Smrg			}
341706f2543Smrg			RegionNull(&pChild->valdata->after.exposed);
342706f2543Smrg		    }
343706f2543Smrg		    if (pChild->firstChild)
344706f2543Smrg		    {
345706f2543Smrg			pChild = pChild->firstChild;
346706f2543Smrg			continue;
347706f2543Smrg		    }
348706f2543Smrg		}
349706f2543Smrg		while (!pChild->nextSib && (pChild != pParent))
350706f2543Smrg		    pChild = pChild->parent;
351706f2543Smrg		if (pChild == pParent)
352706f2543Smrg		    break;
353706f2543Smrg		pChild = pChild->nextSib;
354706f2543Smrg	    }
355706f2543Smrg	    return;
356706f2543Smrg	}
357706f2543Smrg	/* fall through */
358706f2543Smrg    default:
359706f2543Smrg    	/*
360706f2543Smrg     	 * To calculate exposures correctly, we have to translate the old
361706f2543Smrg     	 * borderClip and clipList regions to the window's new location so there
362706f2543Smrg     	 * is a correspondence between pieces of the new and old clipping regions.
363706f2543Smrg     	 */
364706f2543Smrg    	if (dx || dy)
365706f2543Smrg    	{
366706f2543Smrg	    /*
367706f2543Smrg	     * We translate the old clipList because that will be exposed or copied
368706f2543Smrg	     * if gravity is right.
369706f2543Smrg	     */
370706f2543Smrg	    RegionTranslate(&pParent->borderClip, dx, dy);
371706f2543Smrg	    RegionTranslate(&pParent->clipList, dx, dy);
372706f2543Smrg    	}
373706f2543Smrg	break;
374706f2543Smrg    case VTBroken:
375706f2543Smrg	RegionEmpty(&pParent->borderClip);
376706f2543Smrg	RegionEmpty(&pParent->clipList);
377706f2543Smrg	break;
378706f2543Smrg    }
379706f2543Smrg
380706f2543Smrg    borderVisible = pParent->valdata->before.borderVisible;
381706f2543Smrg    resized = pParent->valdata->before.resized;
382706f2543Smrg    RegionNull(&pParent->valdata->after.borderExposed);
383706f2543Smrg    RegionNull(&pParent->valdata->after.exposed);
384706f2543Smrg
385706f2543Smrg    /*
386706f2543Smrg     * Since the borderClip must not be clipped by the children, we do
387706f2543Smrg     * the border exposure first...
388706f2543Smrg     *
389706f2543Smrg     * 'universe' is the window's borderClip. To figure the exposures, remove
390706f2543Smrg     * the area that used to be exposed from the new.
391706f2543Smrg     * This leaves a region of pieces that weren't exposed before.
392706f2543Smrg     */
393706f2543Smrg
394706f2543Smrg    if (HasBorder (pParent))
395706f2543Smrg    {
396706f2543Smrg    	if (borderVisible)
397706f2543Smrg    	{
398706f2543Smrg	    /*
399706f2543Smrg	     * when the border changes shape, the old visible portions
400706f2543Smrg	     * of the border will be saved by DIX in borderVisible --
401706f2543Smrg	     * use that region and destroy it
402706f2543Smrg	     */
403706f2543Smrg	    RegionSubtract(exposed, universe, borderVisible);
404706f2543Smrg	    RegionDestroy(borderVisible);
405706f2543Smrg    	}
406706f2543Smrg    	else
407706f2543Smrg    	{
408706f2543Smrg	    RegionSubtract(exposed, universe, &pParent->borderClip);
409706f2543Smrg    	}
410706f2543Smrg	if (HasParentRelativeBorder(pParent) && (dx || dy))
411706f2543Smrg	    RegionSubtract(&pParent->valdata->after.borderExposed,
412706f2543Smrg				  universe,
413706f2543Smrg				  &pParent->winSize);
414706f2543Smrg	else
415706f2543Smrg	    RegionSubtract(&pParent->valdata->after.borderExposed,
416706f2543Smrg			       exposed, &pParent->winSize);
417706f2543Smrg
418706f2543Smrg	RegionCopy(&pParent->borderClip, universe);
419706f2543Smrg
420706f2543Smrg    	/*
421706f2543Smrg     	 * To get the right clipList for the parent, and to make doubly sure
422706f2543Smrg     	 * that no child overlaps the parent's border, we remove the parent's
423706f2543Smrg     	 * border from the universe before proceeding.
424706f2543Smrg     	 */
425706f2543Smrg
426706f2543Smrg	RegionIntersect(universe, universe, &pParent->winSize);
427706f2543Smrg    }
428706f2543Smrg    else
429706f2543Smrg	RegionCopy(&pParent->borderClip, universe);
430706f2543Smrg
431706f2543Smrg    if ((pChild = pParent->firstChild) && pParent->mapped)
432706f2543Smrg    {
433706f2543Smrg	RegionNull(&childUniverse);
434706f2543Smrg	RegionNull(&childUnion);
435706f2543Smrg	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
436706f2543Smrg	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
437706f2543Smrg	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
438706f2543Smrg	{
439706f2543Smrg	    for (; pChild; pChild = pChild->nextSib)
440706f2543Smrg	    {
441706f2543Smrg		if (pChild->viewable && !TreatAsTransparent(pChild))
442706f2543Smrg		    RegionAppend(&childUnion, &pChild->borderSize);
443706f2543Smrg	    }
444706f2543Smrg	}
445706f2543Smrg	else
446706f2543Smrg	{
447706f2543Smrg	    for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
448706f2543Smrg	    {
449706f2543Smrg		if (pChild->viewable && !TreatAsTransparent(pChild))
450706f2543Smrg		    RegionAppend(&childUnion, &pChild->borderSize);
451706f2543Smrg	    }
452706f2543Smrg	}
453706f2543Smrg	RegionValidate(&childUnion, &overlap);
454706f2543Smrg
455706f2543Smrg	for (pChild = pParent->firstChild;
456706f2543Smrg	     pChild;
457706f2543Smrg	     pChild = pChild->nextSib)
458706f2543Smrg 	{
459706f2543Smrg	    if (pChild->viewable) {
460706f2543Smrg		/*
461706f2543Smrg		 * If the child is viewable, we want to remove its extents
462706f2543Smrg		 * from the current universe, but we only re-clip it if
463706f2543Smrg		 * it's been marked.
464706f2543Smrg		 */
465706f2543Smrg		if (pChild->valdata) {
466706f2543Smrg		    /*
467706f2543Smrg		     * Figure out the new universe from the child's
468706f2543Smrg		     * perspective and recurse.
469706f2543Smrg		     */
470706f2543Smrg		    RegionIntersect(&childUniverse,
471706f2543Smrg					    universe,
472706f2543Smrg					    &pChild->borderSize);
473706f2543Smrg		    miComputeClips (pChild, pScreen, &childUniverse, kind,
474706f2543Smrg				    exposed);
475706f2543Smrg		}
476706f2543Smrg		/*
477706f2543Smrg		 * Once the child has been processed, we remove its extents
478706f2543Smrg		 * from the current universe, thus denying its space to any
479706f2543Smrg		 * other sibling.
480706f2543Smrg		 */
481706f2543Smrg		if (overlap && !TreatAsTransparent (pChild))
482706f2543Smrg		    RegionSubtract(universe, universe,
483706f2543Smrg					  &pChild->borderSize);
484706f2543Smrg	    }
485706f2543Smrg	}
486706f2543Smrg	if (!overlap)
487706f2543Smrg	    RegionSubtract(universe, universe, &childUnion);
488706f2543Smrg	RegionUninit(&childUnion);
489706f2543Smrg	RegionUninit(&childUniverse);
490706f2543Smrg    } /* if any children */
491706f2543Smrg
492706f2543Smrg    /*
493706f2543Smrg     * 'universe' now contains the new clipList for the parent window.
494706f2543Smrg     *
495706f2543Smrg     * To figure the exposure of the window we subtract the old clip from the
496706f2543Smrg     * new, just as for the border.
497706f2543Smrg     */
498706f2543Smrg
499706f2543Smrg    if (oldVis == VisibilityFullyObscured ||
500706f2543Smrg	oldVis == VisibilityNotViewable)
501706f2543Smrg    {
502706f2543Smrg	RegionCopy(&pParent->valdata->after.exposed, universe);
503706f2543Smrg    }
504706f2543Smrg    else if (newVis != VisibilityFullyObscured &&
505706f2543Smrg	     newVis != VisibilityNotViewable)
506706f2543Smrg    {
507706f2543Smrg	RegionSubtract(&pParent->valdata->after.exposed,
508706f2543Smrg			       universe, &pParent->clipList);
509706f2543Smrg    }
510706f2543Smrg
511706f2543Smrg    /* HACK ALERT - copying contents of regions, instead of regions */
512706f2543Smrg    {
513706f2543Smrg	RegionRec   tmp;
514706f2543Smrg
515706f2543Smrg	tmp = pParent->clipList;
516706f2543Smrg	pParent->clipList = *universe;
517706f2543Smrg	*universe = tmp;
518706f2543Smrg    }
519706f2543Smrg
520706f2543Smrg#ifdef NOTDEF
521706f2543Smrg    RegionCopy(&pParent->clipList, universe);
522706f2543Smrg#endif
523706f2543Smrg
524706f2543Smrg    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
525706f2543Smrg
526706f2543Smrg    if (pScreen->ClipNotify)
527706f2543Smrg	(* pScreen->ClipNotify) (pParent, dx, dy);
528706f2543Smrg}
529706f2543Smrg
530706f2543Smrgstatic void
531706f2543SmrgmiTreeObscured(
532706f2543Smrg    WindowPtr pParent )
533706f2543Smrg{
534706f2543Smrg    WindowPtr 	pChild;
535706f2543Smrg    int    	oldVis;
536706f2543Smrg
537706f2543Smrg    pChild = pParent;
538706f2543Smrg    while (1)
539706f2543Smrg    {
540706f2543Smrg	if (pChild->viewable)
541706f2543Smrg	{
542706f2543Smrg	    oldVis = pChild->visibility;
543706f2543Smrg	    if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
544706f2543Smrg		((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
545706f2543Smrg		SendVisibilityNotify(pChild);
546706f2543Smrg	    if (pChild->firstChild)
547706f2543Smrg	    {
548706f2543Smrg		pChild = pChild->firstChild;
549706f2543Smrg		continue;
550706f2543Smrg	    }
551706f2543Smrg	}
552706f2543Smrg	while (!pChild->nextSib && (pChild != pParent))
553706f2543Smrg	    pChild = pChild->parent;
554706f2543Smrg	if (pChild == pParent)
555706f2543Smrg	    break;
556706f2543Smrg	pChild = pChild->nextSib;
557706f2543Smrg    }
558706f2543Smrg}
559706f2543Smrg
560706f2543Smrg/*
561706f2543Smrg *-----------------------------------------------------------------------
562706f2543Smrg * miValidateTree --
563706f2543Smrg *	Recomputes the clip list for pParent and all its inferiors.
564706f2543Smrg *
565706f2543Smrg * Results:
566706f2543Smrg *	Always returns 1.
567706f2543Smrg *
568706f2543Smrg * Side Effects:
569706f2543Smrg *	The clipList, borderClip, exposed, and borderExposed regions for
570706f2543Smrg *	each marked window are altered.
571706f2543Smrg *
572706f2543Smrg * Notes:
573706f2543Smrg *	This routine assumes that all affected windows have been marked
574706f2543Smrg *	(valdata created) and their winSize and borderSize regions
575706f2543Smrg *	adjusted to correspond to their new positions. The borderClip and
576706f2543Smrg *	clipList regions should not have been touched.
577706f2543Smrg *
578706f2543Smrg *	The top-most level is treated differently from all lower levels
579706f2543Smrg *	because pParent is unchanged. For the top level, we merge the
580706f2543Smrg *	regions taken up by the marked children back into the clipList
581706f2543Smrg *	for pParent, thus forming a region from which the marked children
582706f2543Smrg *	can claim their areas. For lower levels, where the old clipList
583706f2543Smrg *	and borderClip are invalid, we can't do this and have to do the
584706f2543Smrg *	extra operations done in miComputeClips, but this is much faster
585706f2543Smrg *	e.g. when only one child has moved...
586706f2543Smrg *
587706f2543Smrg *-----------------------------------------------------------------------
588706f2543Smrg */
589706f2543Smrg/*ARGSUSED*/
590706f2543Smrgint
591706f2543SmrgmiValidateTree (
592706f2543Smrg    WindowPtr		pParent,    /* Parent to validate */
593706f2543Smrg    WindowPtr		pChild,     /* First child of pParent that was
594706f2543Smrg				     * affected */
595706f2543Smrg    VTKind		kind        /* What kind of configuration caused call */
596706f2543Smrg    )
597706f2543Smrg{
598706f2543Smrg    RegionRec	  	totalClip;  /* Total clipping region available to
599706f2543Smrg				     * the marked children. pParent's clipList
600706f2543Smrg				     * merged with the borderClips of all
601706f2543Smrg				     * the marked children. */
602706f2543Smrg    RegionRec	  	childClip;  /* The new borderClip for the current
603706f2543Smrg				     * child */
604706f2543Smrg    RegionRec		childUnion; /* the space covered by borderSize for
605706f2543Smrg				     * all marked children */
606706f2543Smrg    RegionRec		exposed;    /* For intermediate calculations */
607706f2543Smrg    ScreenPtr		pScreen;
608706f2543Smrg    WindowPtr		pWin;
609706f2543Smrg    Bool		overlap;
610706f2543Smrg    int			viewvals;
611706f2543Smrg    Bool		forward;
612706f2543Smrg
613706f2543Smrg    pScreen = pParent->drawable.pScreen;
614706f2543Smrg    if (pChild == NullWindow)
615706f2543Smrg	pChild = pParent->firstChild;
616706f2543Smrg
617706f2543Smrg    RegionNull(&childClip);
618706f2543Smrg    RegionNull(&exposed);
619706f2543Smrg
620706f2543Smrg    /*
621706f2543Smrg     * compute the area of the parent window occupied
622706f2543Smrg     * by the marked children + the parent itself.  This
623706f2543Smrg     * is the area which can be divied up among the marked
624706f2543Smrg     * children in their new configuration.
625706f2543Smrg     */
626706f2543Smrg    RegionNull(&totalClip);
627706f2543Smrg    viewvals = 0;
628706f2543Smrg    if (RegionBroken(&pParent->clipList) &&
629706f2543Smrg	!RegionBroken(&pParent->borderClip))
630706f2543Smrg    {
631706f2543Smrg	kind = VTBroken;
632706f2543Smrg	/*
633706f2543Smrg	 * When rebuilding clip lists after out of memory,
634706f2543Smrg	 * assume everything is busted.
635706f2543Smrg	 */
636706f2543Smrg	forward = TRUE;
637706f2543Smrg	RegionCopy(&totalClip, &pParent->borderClip);
638706f2543Smrg	RegionIntersect(&totalClip, &totalClip, &pParent->winSize);
639706f2543Smrg
640706f2543Smrg	for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib)
641706f2543Smrg	{
642706f2543Smrg	    if (pWin->viewable && !TreatAsTransparent (pWin))
643706f2543Smrg		RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
644706f2543Smrg	}
645706f2543Smrg	for (pWin = pChild; pWin; pWin = pWin->nextSib)
646706f2543Smrg	    if (pWin->valdata && pWin->viewable)
647706f2543Smrg		viewvals++;
648706f2543Smrg
649706f2543Smrg	RegionEmpty(&pParent->clipList);
650706f2543Smrg    }
651706f2543Smrg    else
652706f2543Smrg    {
653706f2543Smrg	if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
654706f2543Smrg	    ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
655706f2543Smrg	     (pChild->drawable.x < pParent->lastChild->drawable.x)))
656706f2543Smrg	{
657706f2543Smrg	    forward = TRUE;
658706f2543Smrg	    for (pWin = pChild; pWin; pWin = pWin->nextSib)
659706f2543Smrg	    {
660706f2543Smrg		if (pWin->valdata)
661706f2543Smrg		{
662706f2543Smrg		    RegionPtr	pBorderClip = &pWin->borderClip;
663706f2543Smrg#ifdef COMPOSITE
664706f2543Smrg		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
665706f2543Smrg			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
666706f2543Smrg#endif
667706f2543Smrg		    RegionAppend(&totalClip, pBorderClip );
668706f2543Smrg		    if (pWin->viewable)
669706f2543Smrg			viewvals++;
670706f2543Smrg		}
671706f2543Smrg	    }
672706f2543Smrg	}
673706f2543Smrg	else
674706f2543Smrg	{
675706f2543Smrg	    forward = FALSE;
676706f2543Smrg	    pWin = pParent->lastChild;
677706f2543Smrg	    while (1)
678706f2543Smrg	    {
679706f2543Smrg		if (pWin->valdata)
680706f2543Smrg		{
681706f2543Smrg		    RegionPtr	pBorderClip = &pWin->borderClip;
682706f2543Smrg#ifdef COMPOSITE
683706f2543Smrg		    if (pWin->redirectDraw != RedirectDrawNone && miGetRedirectBorderClipProc)
684706f2543Smrg			pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
685706f2543Smrg#endif
686706f2543Smrg		    RegionAppend(&totalClip, pBorderClip );
687706f2543Smrg		    if (pWin->viewable)
688706f2543Smrg			viewvals++;
689706f2543Smrg		}
690706f2543Smrg		if (pWin == pChild)
691706f2543Smrg		    break;
692706f2543Smrg		pWin = pWin->prevSib;
693706f2543Smrg	    }
694706f2543Smrg	}
695706f2543Smrg	RegionValidate(&totalClip, &overlap);
696706f2543Smrg    }
697706f2543Smrg
698706f2543Smrg    /*
699706f2543Smrg     * Now go through the children of the root and figure their new
700706f2543Smrg     * borderClips from the totalClip, passing that off to miComputeClips
701706f2543Smrg     * to handle recursively. Once that's done, we remove the child
702706f2543Smrg     * from the totalClip to clip any siblings below it.
703706f2543Smrg     */
704706f2543Smrg
705706f2543Smrg    overlap = TRUE;
706706f2543Smrg    if (kind != VTStack)
707706f2543Smrg    {
708706f2543Smrg	RegionUnion(&totalClip, &totalClip, &pParent->clipList);
709706f2543Smrg	if (viewvals > 1)
710706f2543Smrg	{
711706f2543Smrg	    /*
712706f2543Smrg	     * precompute childUnion to discover whether any of them
713706f2543Smrg	     * overlap.  This seems redundant, but performance studies
714706f2543Smrg	     * have demonstrated that the cost of this loop is
715706f2543Smrg	     * lower than the cost of multiple Subtracts in the
716706f2543Smrg	     * loop below.
717706f2543Smrg	     */
718706f2543Smrg	    RegionNull(&childUnion);
719706f2543Smrg	    if (forward)
720706f2543Smrg	    {
721706f2543Smrg		for (pWin = pChild; pWin; pWin = pWin->nextSib)
722706f2543Smrg		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
723706f2543Smrg			RegionAppend(&childUnion,
724706f2543Smrg						   &pWin->borderSize);
725706f2543Smrg	    }
726706f2543Smrg	    else
727706f2543Smrg	    {
728706f2543Smrg		pWin = pParent->lastChild;
729706f2543Smrg		while (1)
730706f2543Smrg		{
731706f2543Smrg		    if (pWin->valdata && pWin->viewable && !TreatAsTransparent (pWin))
732706f2543Smrg			RegionAppend(&childUnion,
733706f2543Smrg						   &pWin->borderSize);
734706f2543Smrg		    if (pWin == pChild)
735706f2543Smrg			break;
736706f2543Smrg		    pWin = pWin->prevSib;
737706f2543Smrg		}
738706f2543Smrg	    }
739706f2543Smrg	    RegionValidate(&childUnion, &overlap);
740706f2543Smrg	    if (overlap)
741706f2543Smrg		RegionUninit(&childUnion);
742706f2543Smrg	}
743706f2543Smrg    }
744706f2543Smrg
745706f2543Smrg    for (pWin = pChild;
746706f2543Smrg	 pWin != NullWindow;
747706f2543Smrg	 pWin = pWin->nextSib)
748706f2543Smrg    {
749706f2543Smrg	if (pWin->viewable) {
750706f2543Smrg	    if (pWin->valdata) {
751706f2543Smrg		RegionIntersect(&childClip,
752706f2543Smrg					&totalClip,
753706f2543Smrg 					&pWin->borderSize);
754706f2543Smrg		miComputeClips (pWin, pScreen, &childClip, kind, &exposed);
755706f2543Smrg		if (overlap && !TreatAsTransparent (pWin))
756706f2543Smrg		{
757706f2543Smrg		    RegionSubtract(&totalClip,
758706f2543Smrg				       	   &totalClip,
759706f2543Smrg				       	   &pWin->borderSize);
760706f2543Smrg		}
761706f2543Smrg	    } else if (pWin->visibility == VisibilityNotViewable) {
762706f2543Smrg		miTreeObscured(pWin);
763706f2543Smrg	    }
764706f2543Smrg	} else {
765706f2543Smrg	    if (pWin->valdata) {
766706f2543Smrg		RegionEmpty(&pWin->clipList);
767706f2543Smrg		if (pScreen->ClipNotify)
768706f2543Smrg		    (* pScreen->ClipNotify) (pWin, 0, 0);
769706f2543Smrg		RegionEmpty(&pWin->borderClip);
770706f2543Smrg		pWin->valdata = NULL;
771706f2543Smrg	    }
772706f2543Smrg	}
773706f2543Smrg    }
774706f2543Smrg
775706f2543Smrg    RegionUninit(&childClip);
776706f2543Smrg    if (!overlap)
777706f2543Smrg    {
778706f2543Smrg	RegionSubtract(&totalClip, &totalClip, &childUnion);
779706f2543Smrg	RegionUninit(&childUnion);
780706f2543Smrg    }
781706f2543Smrg
782706f2543Smrg    RegionNull(&pParent->valdata->after.exposed);
783706f2543Smrg    RegionNull(&pParent->valdata->after.borderExposed);
784706f2543Smrg
785706f2543Smrg    /*
786706f2543Smrg     * each case below is responsible for updating the
787706f2543Smrg     * clipList and serial number for the parent window
788706f2543Smrg     */
789706f2543Smrg
790706f2543Smrg    switch (kind) {
791706f2543Smrg    case VTStack:
792706f2543Smrg	break;
793706f2543Smrg    default:
794706f2543Smrg	/*
795706f2543Smrg	 * totalClip contains the new clipList for the parent. Figure out
796706f2543Smrg	 * exposures and obscures as per miComputeClips and reset the parent's
797706f2543Smrg	 * clipList.
798706f2543Smrg	 */
799706f2543Smrg	RegionSubtract(&pParent->valdata->after.exposed,
800706f2543Smrg			       &totalClip, &pParent->clipList);
801706f2543Smrg	/* fall through */
802706f2543Smrg    case VTMap:
803706f2543Smrg	RegionCopy(&pParent->clipList, &totalClip);
804706f2543Smrg	pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
805706f2543Smrg	break;
806706f2543Smrg    }
807706f2543Smrg
808706f2543Smrg    RegionUninit(&totalClip);
809706f2543Smrg    RegionUninit(&exposed);
810706f2543Smrg    if (pScreen->ClipNotify)
811706f2543Smrg	(*pScreen->ClipNotify) (pParent, 0, 0);
812706f2543Smrg    return 1;
813706f2543Smrg}
814