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