mioverlay.c revision 05b261ec
1
2#ifdef HAVE_DIX_CONFIG_H
3#include <dix-config.h>
4#endif
5
6#include <X11/X.h>
7#include "scrnintstr.h"
8#include "validate.h"
9#include "windowstr.h"
10#include "mi.h"
11#include "gcstruct.h"
12#include "regionstr.h"
13#include "mivalidate.h"
14#include "mioverlay.h"
15#include "migc.h"
16
17#include "globals.h"
18
19
20typedef struct {
21   RegionRec 	exposed;
22   RegionRec	borderExposed;
23   RegionPtr	borderVisible;
24   DDXPointRec	oldAbsCorner;
25} miOverlayValDataRec, *miOverlayValDataPtr;
26
27typedef struct _TreeRec {
28   WindowPtr		pWin;
29   struct _TreeRec 	*parent;
30   struct _TreeRec 	*firstChild;
31   struct _TreeRec 	*lastChild;
32   struct _TreeRec 	*prevSib;
33   struct _TreeRec 	*nextSib;
34   RegionRec 		borderClip;
35   RegionRec 		clipList;
36   unsigned		visibility;
37   miOverlayValDataPtr  valdata;
38} miOverlayTreeRec, *miOverlayTreePtr;
39
40typedef struct {
41   miOverlayTreePtr	tree;
42} miOverlayWindowRec, *miOverlayWindowPtr;
43
44typedef struct {
45   CloseScreenProcPtr   	CloseScreen;
46   CreateWindowProcPtr  	CreateWindow;
47   DestroyWindowProcPtr 	DestroyWindow;
48   UnrealizeWindowProcPtr	UnrealizeWindow;
49   RealizeWindowProcPtr		RealizeWindow;
50   miOverlayTransFunc		MakeTransparent;
51   miOverlayInOverlayFunc	InOverlay;
52   Bool				underlayMarked;
53   Bool				copyUnderlay;
54} miOverlayScreenRec, *miOverlayScreenPtr;
55
56static unsigned long miOverlayGeneration = 0;
57static int miOverlayWindowIndex = -1;
58static int miOverlayScreenIndex = -1;
59
60static void RebuildTree(WindowPtr);
61static Bool HasUnderlayChildren(WindowPtr);
62static void MarkUnderlayWindow(WindowPtr);
63static Bool CollectUnderlayChildrenRegions(WindowPtr, RegionPtr);
64
65static Bool miOverlayCloseScreen(int, ScreenPtr);
66static Bool miOverlayCreateWindow(WindowPtr);
67static Bool miOverlayDestroyWindow(WindowPtr);
68static Bool miOverlayUnrealizeWindow(WindowPtr);
69static Bool miOverlayRealizeWindow(WindowPtr);
70static void miOverlayMarkWindow(WindowPtr);
71static void miOverlayReparentWindow(WindowPtr, WindowPtr);
72static void miOverlayRestackWindow(WindowPtr, WindowPtr);
73static Bool miOverlayMarkOverlappedWindows(WindowPtr, WindowPtr, WindowPtr*);
74static void miOverlayMarkUnrealizedWindow(WindowPtr, WindowPtr, Bool);
75static int miOverlayValidateTree(WindowPtr, WindowPtr, VTKind);
76static void miOverlayHandleExposures(WindowPtr);
77static void miOverlayMoveWindow(WindowPtr, int, int, WindowPtr, VTKind);
78static void miOverlayWindowExposures(WindowPtr, RegionPtr, RegionPtr);
79static void miOverlayResizeWindow(WindowPtr, int, int, unsigned int,
80					unsigned int, WindowPtr);
81static void miOverlayClearToBackground(WindowPtr, int, int, int, int, Bool);
82
83#ifdef SHAPE
84static void miOverlaySetShape(WindowPtr);
85#endif
86static void miOverlayChangeBorderWidth(WindowPtr, unsigned int);
87
88#define MIOVERLAY_GET_SCREEN_PRIVATE(pScreen) \
89	((miOverlayScreenPtr)((pScreen)->devPrivates[miOverlayScreenIndex].ptr))
90#define MIOVERLAY_GET_WINDOW_PRIVATE(pWin) \
91	((miOverlayWindowPtr)((pWin)->devPrivates[miOverlayWindowIndex].ptr))
92#define MIOVERLAY_GET_WINDOW_TREE(pWin) \
93	(MIOVERLAY_GET_WINDOW_PRIVATE(pWin)->tree)
94
95#define IN_UNDERLAY(w) MIOVERLAY_GET_WINDOW_TREE(w)
96#define IN_OVERLAY(w) !MIOVERLAY_GET_WINDOW_TREE(w)
97
98#define MARK_OVERLAY(w) miMarkWindow(w)
99#define MARK_UNDERLAY(w) MarkUnderlayWindow(w)
100
101#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
102                                    HasBorder(w) && \
103                                    (w)->backgroundState == ParentRelative)
104
105_X_EXPORT Bool
106miInitOverlay(
107    ScreenPtr pScreen,
108    miOverlayInOverlayFunc inOverlayFunc,
109    miOverlayTransFunc transFunc
110){
111    miOverlayScreenPtr	pScreenPriv;
112
113    if(!inOverlayFunc || !transFunc) return FALSE;
114
115    if(miOverlayGeneration != serverGeneration) {
116	if(((miOverlayScreenIndex = AllocateScreenPrivateIndex()) < 0) ||
117	   ((miOverlayWindowIndex = AllocateWindowPrivateIndex()) < 0))
118	    return FALSE;
119
120	miOverlayGeneration = serverGeneration;
121    }
122
123    if(!AllocateWindowPrivate(pScreen, miOverlayWindowIndex,
124				sizeof(miOverlayWindowRec)))
125	return FALSE;
126
127    if(!(pScreenPriv = xalloc(sizeof(miOverlayScreenRec))))
128	return FALSE;
129
130    pScreen->devPrivates[miOverlayScreenIndex].ptr = (pointer)pScreenPriv;
131
132    pScreenPriv->InOverlay = inOverlayFunc;
133    pScreenPriv->MakeTransparent = transFunc;
134    pScreenPriv->underlayMarked = FALSE;
135
136
137    pScreenPriv->CloseScreen = pScreen->CloseScreen;
138    pScreenPriv->CreateWindow = pScreen->CreateWindow;
139    pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
140    pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow;
141    pScreenPriv->RealizeWindow = pScreen->RealizeWindow;
142
143    pScreen->CloseScreen = miOverlayCloseScreen;
144    pScreen->CreateWindow = miOverlayCreateWindow;
145    pScreen->DestroyWindow = miOverlayDestroyWindow;
146    pScreen->UnrealizeWindow = miOverlayUnrealizeWindow;
147    pScreen->RealizeWindow = miOverlayRealizeWindow;
148
149    pScreen->ReparentWindow = miOverlayReparentWindow;
150    pScreen->RestackWindow = miOverlayRestackWindow;
151    pScreen->MarkOverlappedWindows = miOverlayMarkOverlappedWindows;
152    pScreen->MarkUnrealizedWindow = miOverlayMarkUnrealizedWindow;
153    pScreen->ValidateTree = miOverlayValidateTree;
154    pScreen->HandleExposures = miOverlayHandleExposures;
155    pScreen->MoveWindow = miOverlayMoveWindow;
156    pScreen->WindowExposures = miOverlayWindowExposures;
157    pScreen->ResizeWindow = miOverlayResizeWindow;
158    pScreen->MarkWindow = miOverlayMarkWindow;
159    pScreen->ClearToBackground = miOverlayClearToBackground;
160#ifdef SHAPE
161    pScreen->SetShape = miOverlaySetShape;
162#endif
163    pScreen->ChangeBorderWidth = miOverlayChangeBorderWidth;
164
165    return TRUE;
166}
167
168
169static Bool
170miOverlayCloseScreen(int i, ScreenPtr pScreen)
171{
172   miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
173
174   pScreen->CloseScreen = pScreenPriv->CloseScreen;
175   pScreen->CreateWindow = pScreenPriv->CreateWindow;
176   pScreen->DestroyWindow = pScreenPriv->DestroyWindow;
177   pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow;
178   pScreen->RealizeWindow = pScreenPriv->RealizeWindow;
179
180   xfree(pScreenPriv);
181
182   return (*pScreen->CloseScreen)(i, pScreen);
183}
184
185
186static Bool
187miOverlayCreateWindow(WindowPtr pWin)
188{
189    ScreenPtr pScreen = pWin->drawable.pScreen;
190    miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
191    miOverlayWindowPtr pWinPriv = MIOVERLAY_GET_WINDOW_PRIVATE(pWin);
192    miOverlayTreePtr pTree = NULL;
193    Bool result = TRUE;
194
195    pWinPriv->tree = NULL;
196
197    if(!pWin->parent || !((*pScreenPriv->InOverlay)(pWin))) {
198	if(!(pTree = (miOverlayTreePtr)xcalloc(1, sizeof(miOverlayTreeRec))))
199	   return FALSE;
200    }
201
202    if(pScreenPriv->CreateWindow) {
203	pScreen->CreateWindow = pScreenPriv->CreateWindow;
204	result = (*pScreen->CreateWindow)(pWin);
205	pScreen->CreateWindow = miOverlayCreateWindow;
206    }
207
208    if (pTree) {
209	if(result) {
210	    pTree->pWin = pWin;
211	    pTree->visibility = VisibilityNotViewable;
212	    pWinPriv->tree = pTree;
213	    if(pWin->parent) {
214		REGION_NULL(pScreen, &(pTree->borderClip));
215		REGION_NULL(pScreen, &(pTree->clipList));
216		RebuildTree(pWin);
217	    } else {
218		BoxRec fullBox;
219		fullBox.x1 = 0;
220		fullBox.y1 = 0;
221		fullBox.x2 = pScreen->width;
222		fullBox.y2 = pScreen->height;
223		REGION_INIT(pScreen, &(pTree->borderClip), &fullBox, 1);
224		REGION_INIT(pScreen, &(pTree->clipList), &fullBox, 1);
225	    }
226	} else xfree(pTree);
227    }
228
229    return TRUE;
230}
231
232
233static Bool
234miOverlayDestroyWindow(WindowPtr pWin)
235{
236    ScreenPtr pScreen = pWin->drawable.pScreen;
237    miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
238    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
239    Bool result = TRUE;
240
241    if (pTree) {
242	if(pTree->prevSib)
243	   pTree->prevSib->nextSib = pTree->nextSib;
244	else if(pTree->parent)
245	   pTree->parent->firstChild = pTree->nextSib;
246
247	if(pTree->nextSib)
248	   pTree->nextSib->prevSib = pTree->prevSib;
249	else if(pTree->parent)
250	   pTree->parent->lastChild = pTree->prevSib;
251
252	REGION_UNINIT(pScreen, &(pTree->borderClip));
253	REGION_UNINIT(pScreen, &(pTree->clipList));
254	xfree(pTree);
255    }
256
257    if(pScreenPriv->DestroyWindow) {
258	pScreen->DestroyWindow = pScreenPriv->DestroyWindow;
259	result = (*pScreen->DestroyWindow)(pWin);
260	pScreen->DestroyWindow = miOverlayDestroyWindow;
261    }
262
263    return result;
264}
265
266static Bool
267miOverlayUnrealizeWindow(WindowPtr pWin)
268{
269    ScreenPtr pScreen = pWin->drawable.pScreen;
270    miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
271    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
272    Bool result = TRUE;
273
274    if(pTree) pTree->visibility = VisibilityNotViewable;
275
276    if(pScreenPriv->UnrealizeWindow) {
277	pScreen->UnrealizeWindow = pScreenPriv->UnrealizeWindow;
278	result = (*pScreen->UnrealizeWindow)(pWin);
279	pScreen->UnrealizeWindow = miOverlayUnrealizeWindow;
280    }
281
282    return result;
283}
284
285
286static Bool
287miOverlayRealizeWindow(WindowPtr pWin)
288{
289    ScreenPtr pScreen = pWin->drawable.pScreen;
290    miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
291    Bool result = TRUE;
292
293    if(pScreenPriv->RealizeWindow) {
294	pScreen->RealizeWindow = pScreenPriv->RealizeWindow;
295	result = (*pScreen->RealizeWindow)(pWin);
296	pScreen->RealizeWindow = miOverlayRealizeWindow;
297    }
298
299    /* we only need to catch the root window realization */
300
301    if(result && !pWin->parent && !((*pScreenPriv->InOverlay)(pWin)))
302    {
303	BoxRec box;
304	box.x1 = box.y1 = 0;
305	box.x2 = pWin->drawable.width;
306	box.y2 = pWin->drawable.height;
307	(*pScreenPriv->MakeTransparent)(pScreen, 1, &box);
308    }
309
310    return result;
311}
312
313
314static void
315miOverlayReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
316{
317    if(IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) {
318	/* This could probably be more optimal */
319	RebuildTree(WindowTable[pWin->drawable.pScreen->myNum]->firstChild);
320    }
321}
322
323static void
324miOverlayRestackWindow(WindowPtr pWin, WindowPtr oldNextSib)
325{
326    if(IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin)) {
327	/* This could probably be more optimal */
328	RebuildTree(pWin);
329    }
330}
331
332
333static Bool
334miOverlayMarkOverlappedWindows(
335    WindowPtr pWin,
336    WindowPtr pFirst,
337    WindowPtr *pLayerWin
338){
339    ScreenPtr pScreen = pWin->drawable.pScreen;
340    WindowPtr pChild, pLast;
341    Bool overMarked, underMarked, doUnderlay, markAll;
342    miOverlayTreePtr pTree = NULL, tLast, tChild;
343    BoxPtr box;
344
345    overMarked = underMarked = markAll = FALSE;
346
347    if(pLayerWin) *pLayerWin = pWin; /* hah! */
348
349    doUnderlay = (IN_UNDERLAY(pWin) || HasUnderlayChildren(pWin));
350
351    box = REGION_EXTENTS(pScreen, &pWin->borderSize);
352
353    if((pChild = pFirst)) {
354	pLast = pChild->parent->lastChild;
355	while (1) {
356	    if (pChild == pWin) markAll = TRUE;
357
358	    if(doUnderlay && IN_UNDERLAY(pChild))
359		pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
360
361	    if(pChild->viewable) {
362                if (REGION_BROKEN (pScreen, &pChild->winSize))
363                    SetWinSize (pChild);
364                if (REGION_BROKEN (pScreen, &pChild->borderSize))
365		    SetBorderSize (pChild);
366
367	    	if (markAll ||
368		    RECT_IN_REGION(pScreen, &pChild->borderSize, box))
369		{
370		    MARK_OVERLAY(pChild);
371		    overMarked = TRUE;
372		    if(doUnderlay && IN_UNDERLAY(pChild)) {
373			MARK_UNDERLAY(pChild);
374			underMarked = TRUE;
375		    }
376		    if (pChild->firstChild) {
377			pChild = pChild->firstChild;
378			continue;
379		    }
380		}
381	    }
382	    while (!pChild->nextSib && (pChild != pLast)) {
383		pChild = pChild->parent;
384		if(doUnderlay && IN_UNDERLAY(pChild))
385		    pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
386	    }
387
388	    if(pChild == pWin) markAll = FALSE;
389
390	    if (pChild == pLast) break;
391
392	    pChild = pChild->nextSib;
393	}
394	if(overMarked)
395	    MARK_OVERLAY(pWin->parent);
396    }
397
398    if(doUnderlay && !pTree) {
399	if(!(pTree = MIOVERLAY_GET_WINDOW_TREE(pWin))) {
400 	    pChild = pWin->lastChild;
401	    while(1) {
402		if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild)))
403		    break;
404
405		if(pChild->lastChild) {
406		    pChild = pChild->lastChild;
407		    continue;
408		}
409
410		while(!pChild->prevSib) pChild = pChild->parent;
411
412		pChild = pChild->prevSib;
413	    }
414	}
415    }
416
417    if(pTree && pTree->nextSib) {
418	tChild = pTree->parent->lastChild;
419	tLast = pTree->nextSib;
420
421	while(1) {
422	    if(tChild->pWin->viewable) {
423                if (REGION_BROKEN (pScreen, &tChild->pWin->winSize))
424                    SetWinSize (tChild->pWin);
425                if (REGION_BROKEN (pScreen, &tChild->pWin->borderSize))
426		    SetBorderSize (tChild->pWin);
427
428		if(RECT_IN_REGION(pScreen, &(tChild->pWin->borderSize), box))
429	        {
430		    MARK_UNDERLAY(tChild->pWin);
431		    underMarked = TRUE;
432	        }
433	    }
434
435	    if(tChild->lastChild) {
436		tChild = tChild->lastChild;
437		continue;
438	    }
439
440	    while(!tChild->prevSib && (tChild != tLast))
441		tChild = tChild->parent;
442
443	    if(tChild == tLast) break;
444
445	    tChild = tChild->prevSib;
446	}
447    }
448
449    if(underMarked) {
450	MARK_UNDERLAY(pTree->parent->pWin);
451	MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->underlayMarked = TRUE;
452    }
453
454    return (underMarked || overMarked);
455}
456
457
458static void
459miOverlayComputeClips(
460    WindowPtr pParent,
461    RegionPtr universe,
462    VTKind kind,
463    RegionPtr exposed
464){
465    ScreenPtr pScreen = pParent->drawable.pScreen;
466    int oldVis, newVis, dx, dy;
467    BoxRec borderSize;
468    RegionPtr borderVisible;
469    RegionRec childUniverse, childUnion;
470    miOverlayTreePtr tParent = MIOVERLAY_GET_WINDOW_TREE(pParent);
471    miOverlayTreePtr tChild;
472    Bool overlap;
473
474    borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
475    borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
476    dx = (int) pParent->drawable.x + (int) pParent->drawable.width +
477						wBorderWidth(pParent);
478    if (dx > 32767) dx = 32767;
479    borderSize.x2 = dx;
480    dy = (int) pParent->drawable.y + (int) pParent->drawable.height +
481						wBorderWidth(pParent);
482    if (dy > 32767) dy = 32767;
483    borderSize.y2 = dy;
484
485    oldVis = tParent->visibility;
486    switch (RECT_IN_REGION( pScreen, universe, &borderSize)) {
487	case rgnIN:
488	    newVis = VisibilityUnobscured;
489	    break;
490	case rgnPART:
491	    newVis = VisibilityPartiallyObscured;
492#ifdef SHAPE
493	    {
494		RegionPtr   pBounding;
495
496		if ((pBounding = wBoundingShape (pParent))) {
497		    switch (miShapedWindowIn (pScreen, universe, pBounding,
498					      &borderSize,
499					      pParent->drawable.x,
500 					      pParent->drawable.y))
501		    {
502		    case rgnIN:
503			newVis = VisibilityUnobscured;
504			break;
505		    case rgnOUT:
506			newVis = VisibilityFullyObscured;
507			break;
508		    }
509		}
510	    }
511#endif
512	    break;
513	default:
514	    newVis = VisibilityFullyObscured;
515	    break;
516    }
517    tParent->visibility = newVis;
518
519    dx = pParent->drawable.x - tParent->valdata->oldAbsCorner.x;
520    dy = pParent->drawable.y - tParent->valdata->oldAbsCorner.y;
521
522    switch (kind) {
523    case VTMap:
524    case VTStack:
525    case VTUnmap:
526	break;
527    case VTMove:
528	if ((oldVis == newVis) &&
529	    ((oldVis == VisibilityFullyObscured) ||
530	     (oldVis == VisibilityUnobscured)))
531	{
532	    tChild = tParent;
533	    while (1) {
534		if (tChild->pWin->viewable) {
535		    if (tChild->visibility != VisibilityFullyObscured) {
536			REGION_TRANSLATE( pScreen, &tChild->borderClip, dx, dy);
537			REGION_TRANSLATE( pScreen, &tChild->clipList, dx, dy);
538
539			tChild->pWin->drawable.serialNumber =
540							 NEXT_SERIAL_NUMBER;
541                        if (pScreen->ClipNotify)
542                            (* pScreen->ClipNotify) (tChild->pWin, dx, dy);
543		    }
544		    if (tChild->valdata) {
545			REGION_NULL(pScreen, &tChild->valdata->borderExposed);
546			if (HasParentRelativeBorder(tChild->pWin)){
547			    REGION_SUBTRACT(pScreen,
548					 &tChild->valdata->borderExposed,
549					 &tChild->borderClip,
550					 &tChild->pWin->winSize);
551			}
552			REGION_NULL(pScreen, &tChild->valdata->exposed);
553		    }
554		    if (tChild->firstChild) {
555			tChild = tChild->firstChild;
556			continue;
557		    }
558		}
559		while (!tChild->nextSib && (tChild != tParent))
560		    tChild = tChild->parent;
561		if (tChild == tParent)
562		    break;
563		tChild = tChild->nextSib;
564	    }
565	    return;
566	}
567	/* fall through */
568    default:
569    	if (dx || dy)  {
570	    REGION_TRANSLATE( pScreen, &tParent->borderClip, dx, dy);
571	    REGION_TRANSLATE( pScreen, &tParent->clipList, dx, dy);
572    	}
573	break;
574    case VTBroken:
575	REGION_EMPTY (pScreen, &tParent->borderClip);
576	REGION_EMPTY (pScreen, &tParent->clipList);
577	break;
578    }
579
580    borderVisible = tParent->valdata->borderVisible;
581    REGION_NULL(pScreen, &tParent->valdata->borderExposed);
582    REGION_NULL(pScreen, &tParent->valdata->exposed);
583
584    if (HasBorder (pParent)) {
585    	if (borderVisible) {
586	    REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
587	    REGION_DESTROY( pScreen, borderVisible);
588    	} else
589	    REGION_SUBTRACT( pScreen, exposed, universe, &tParent->borderClip);
590
591	if (HasParentRelativeBorder(pParent) && (dx || dy))
592	    REGION_SUBTRACT( pScreen, &tParent->valdata->borderExposed,
593				  universe, &pParent->winSize);
594	else
595	    REGION_SUBTRACT( pScreen, &tParent->valdata->borderExposed,
596			       exposed, &pParent->winSize);
597
598    	REGION_COPY( pScreen, &tParent->borderClip, universe);
599    	REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
600    }
601    else
602    	REGION_COPY( pScreen, &tParent->borderClip, universe);
603
604    if ((tChild = tParent->firstChild) && pParent->mapped) {
605	REGION_NULL(pScreen, &childUniverse);
606	REGION_NULL(pScreen, &childUnion);
607
608	for (; tChild; tChild = tChild->nextSib) {
609	    if (tChild->pWin->viewable)
610		REGION_APPEND( pScreen, &childUnion, &tChild->pWin->borderSize);
611	}
612
613	REGION_VALIDATE( pScreen, &childUnion, &overlap);
614
615	for (tChild = tParent->firstChild;
616	     tChild;
617	     tChild = tChild->nextSib)
618 	{
619	    if (tChild->pWin->viewable) {
620		if (tChild->valdata) {
621		    REGION_INTERSECT( pScreen, &childUniverse, universe,
622					    &tChild->pWin->borderSize);
623		    miOverlayComputeClips (tChild->pWin, &childUniverse,
624						kind, exposed);
625		}
626		if (overlap)
627		    REGION_SUBTRACT( pScreen, universe, universe,
628					  &tChild->pWin->borderSize);
629	    }
630	}
631	if (!overlap)
632	    REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
633	REGION_UNINIT( pScreen, &childUnion);
634	REGION_UNINIT( pScreen, &childUniverse);
635    }
636
637    if (oldVis == VisibilityFullyObscured ||
638	oldVis == VisibilityNotViewable)
639    {
640	REGION_COPY( pScreen, &tParent->valdata->exposed, universe);
641    }
642    else if (newVis != VisibilityFullyObscured &&
643	     newVis != VisibilityNotViewable)
644    {
645    	REGION_SUBTRACT( pScreen, &tParent->valdata->exposed,
646			       universe, &tParent->clipList);
647    }
648
649    /* HACK ALERT - copying contents of regions, instead of regions */
650    {
651	RegionRec   tmp;
652
653	tmp = tParent->clipList;
654	tParent->clipList = *universe;
655	*universe = tmp;
656    }
657
658    pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
659
660    if (pScreen->ClipNotify)
661        (* pScreen->ClipNotify) (pParent, dx, dy);
662}
663
664
665static void
666miOverlayMarkWindow(WindowPtr pWin)
667{
668    miOverlayTreePtr pTree = NULL;
669    WindowPtr pChild, pGrandChild;
670
671    miMarkWindow(pWin);
672
673    /* look for UnmapValdata among immediate children */
674
675    if(!(pChild = pWin->firstChild)) return;
676
677    for( ; pChild; pChild = pChild->nextSib) {
678	if(pChild->valdata == UnmapValData) {
679	    if(IN_UNDERLAY(pChild)) {
680		pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
681		pTree->valdata = (miOverlayValDataPtr)UnmapValData;
682		continue;
683	    } else {
684	        if(!(pGrandChild = pChild->firstChild))
685		   continue;
686
687		while(1) {
688		    if(IN_UNDERLAY(pGrandChild)) {
689			pTree = MIOVERLAY_GET_WINDOW_TREE(pGrandChild);
690			pTree->valdata = (miOverlayValDataPtr)UnmapValData;
691		    } else if(pGrandChild->firstChild) {
692			pGrandChild = pGrandChild->firstChild;
693			continue;
694		    }
695
696		    while(!pGrandChild->nextSib && (pGrandChild != pChild))
697			pGrandChild = pGrandChild->parent;
698
699		    if(pChild == pGrandChild) break;
700
701		    pGrandChild = pGrandChild->nextSib;
702		}
703	    }
704        }
705    }
706
707    if(pTree) {
708	MARK_UNDERLAY(pTree->parent->pWin);
709	MIOVERLAY_GET_SCREEN_PRIVATE(
710		pWin->drawable.pScreen)->underlayMarked = TRUE;
711    }
712}
713
714static void
715miOverlayMarkUnrealizedWindow(
716    WindowPtr pChild,
717    WindowPtr pWin,
718    Bool fromConfigure
719){
720    if ((pChild != pWin) || fromConfigure) {
721	miOverlayTreePtr pTree;
722
723        REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList);
724        if (pChild->drawable.pScreen->ClipNotify)
725            (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
726        REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip);
727	if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
728	    if(pTree->valdata != (miOverlayValDataPtr)UnmapValData) {
729		REGION_EMPTY(pChild->drawable.pScreen, &pTree->clipList);
730		REGION_EMPTY(pChild->drawable.pScreen, &pTree->borderClip);
731	    }
732	}
733    }
734}
735
736
737static int
738miOverlayValidateTree(
739    WindowPtr pParent,
740    WindowPtr pChild,   /* first child effected */
741    VTKind    kind
742){
743    ScreenPtr pScreen = pParent->drawable.pScreen;
744    miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
745    RegionRec totalClip, childClip, exposed;
746    miOverlayTreePtr tParent, tChild, tWin;
747    Bool overlap;
748    WindowPtr newParent;
749
750    if(!pPriv->underlayMarked)
751	goto SKIP_UNDERLAY;
752
753    if (!pChild) pChild = pParent->firstChild;
754
755    REGION_NULL(pScreen, &totalClip);
756    REGION_NULL(pScreen, &childClip);
757    REGION_NULL(pScreen, &exposed);
758
759    newParent = pParent;
760
761    while(IN_OVERLAY(newParent))
762    	newParent = newParent->parent;
763
764    tParent = MIOVERLAY_GET_WINDOW_TREE(newParent);
765
766    if(IN_UNDERLAY(pChild))
767	tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
768    else
769	tChild = tParent->firstChild;
770
771    if (REGION_BROKEN (pScreen, &tParent->clipList) &&
772        !REGION_BROKEN (pScreen, &tParent->borderClip))
773    {
774	kind = VTBroken;
775	REGION_COPY (pScreen, &totalClip, &tParent->borderClip);
776	REGION_INTERSECT (pScreen, &totalClip, &totalClip,
777						 &tParent->pWin->winSize);
778
779        for (tWin = tParent->firstChild; tWin != tChild; tWin = tWin->nextSib) {
780            if (tWin->pWin->viewable)
781                REGION_SUBTRACT (pScreen, &totalClip, &totalClip,
782					&tWin->pWin->borderSize);
783        }
784        REGION_EMPTY (pScreen, &tParent->clipList);
785    } else {
786	for(tWin = tChild; tWin; tWin = tWin->nextSib) {
787	    if(tWin->valdata)
788		REGION_APPEND(pScreen, &totalClip, &tWin->borderClip);
789	}
790	REGION_VALIDATE(pScreen, &totalClip, &overlap);
791    }
792
793    if(kind != VTStack)
794	REGION_UNION(pScreen, &totalClip, &totalClip, &tParent->clipList);
795
796    for(tWin = tChild; tWin; tWin = tWin->nextSib) {
797	if(tWin->valdata) {
798	    if(tWin->pWin->viewable) {
799		REGION_INTERSECT(pScreen, &childClip, &totalClip,
800					&tWin->pWin->borderSize);
801		miOverlayComputeClips(tWin->pWin, &childClip, kind, &exposed);
802		REGION_SUBTRACT(pScreen, &totalClip, &totalClip,
803					&tWin->pWin->borderSize);
804	    } else {  /* Means we are unmapping */
805                REGION_EMPTY(pScreen, &tWin->clipList);
806                REGION_EMPTY( pScreen, &tWin->borderClip);
807		tWin->valdata = NULL;
808	    }
809	}
810    }
811
812    REGION_UNINIT(pScreen, &childClip);
813
814    if(!((*pPriv->InOverlay)(newParent))) {
815	REGION_NULL(pScreen, &tParent->valdata->exposed);
816	REGION_NULL(pScreen, &tParent->valdata->borderExposed);
817    }
818
819    switch (kind) {
820    case VTStack:
821	break;
822    default:
823    	if(!((*pPriv->InOverlay)(newParent)))
824	    REGION_SUBTRACT(pScreen, &tParent->valdata->exposed, &totalClip,
825						&tParent->clipList);
826	/* fall through */
827    case VTMap:
828	REGION_COPY( pScreen, &tParent->clipList, &totalClip);
829    	if(!((*pPriv->InOverlay)(newParent)))
830	    newParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
831	break;
832    }
833
834    REGION_UNINIT( pScreen, &totalClip);
835    REGION_UNINIT( pScreen, &exposed);
836
837SKIP_UNDERLAY:
838
839    miValidateTree(pParent, pChild, kind);
840
841    return 1;
842}
843
844
845static void
846miOverlayHandleExposures(WindowPtr pWin)
847{
848    ScreenPtr pScreen = pWin->drawable.pScreen;
849    miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
850    WindowPtr pChild;
851    ValidatePtr val;
852    void (* WindowExposures)(WindowPtr, RegionPtr, RegionPtr);
853
854    WindowExposures = pWin->drawable.pScreen->WindowExposures;
855    if(pPriv->underlayMarked) {
856	miOverlayTreePtr pTree;
857	miOverlayValDataPtr mival;
858
859	pChild = pWin;
860	while(IN_OVERLAY(pChild))
861	    pChild = pChild->parent;
862
863	pTree = MIOVERLAY_GET_WINDOW_TREE(pChild);
864
865	while (1) {
866	    if((mival = pTree->valdata)) {
867		if(!((*pPriv->InOverlay)(pTree->pWin))) {
868		    if (REGION_NOTEMPTY(pScreen, &mival->borderExposed))
869			(*pWin->drawable.pScreen->PaintWindowBorder)(
870				pTree->pWin, &mival->borderExposed, PW_BORDER);
871		    REGION_UNINIT(pScreen, &mival->borderExposed);
872
873		    (*WindowExposures)(pTree->pWin,&mival->exposed,NullRegion);
874		    REGION_UNINIT(pScreen, &mival->exposed);
875		}
876		xfree(mival);
877		pTree->valdata = NULL;
878		if (pTree->firstChild) {
879		    pTree = pTree->firstChild;
880		    continue;
881		}
882	    }
883	    while (!pTree->nextSib && (pTree->pWin != pChild))
884	    	pTree = pTree->parent;
885	    if (pTree->pWin == pChild)
886		break;
887	    pTree = pTree->nextSib;
888        }
889	pPriv->underlayMarked = FALSE;
890    }
891
892    pChild = pWin;
893    while (1) {
894	if ( (val = pChild->valdata) ) {
895	    if(!((*pPriv->InOverlay)(pChild))) {
896		REGION_UNION(pScreen, &val->after.exposed, &val->after.exposed,
897			&val->after.borderExposed);
898
899		if (REGION_NOTEMPTY(pScreen, &val->after.exposed)) {
900		   (*(MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent))(
901				pScreen,
902				REGION_NUM_RECTS(&val->after.exposed),
903				REGION_RECTS(&val->after.exposed));
904		}
905	    } else {
906		if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed))
907		    (*pChild->drawable.pScreen->PaintWindowBorder)(pChild,
908						    &val->after.borderExposed,
909						    PW_BORDER);
910		(*WindowExposures)(pChild, &val->after.exposed, NullRegion);
911	    }
912	    REGION_UNINIT(pScreen, &val->after.borderExposed);
913	    REGION_UNINIT(pScreen, &val->after.exposed);
914	    xfree(val);
915	    pChild->valdata = (ValidatePtr)NULL;
916	    if (pChild->firstChild)
917	    {
918		pChild = pChild->firstChild;
919		continue;
920	    }
921	}
922	while (!pChild->nextSib && (pChild != pWin))
923	    pChild = pChild->parent;
924	if (pChild == pWin)
925	    break;
926	pChild = pChild->nextSib;
927    }
928}
929
930
931static void
932miOverlayMoveWindow(
933    WindowPtr pWin,
934    int x,
935    int y,
936    WindowPtr pNextSib,
937    VTKind kind
938){
939    ScreenPtr pScreen = pWin->drawable.pScreen;
940    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
941    WindowPtr pParent, windowToValidate;
942    Bool WasViewable = (Bool)(pWin->viewable);
943    short bw;
944    RegionRec overReg, underReg;
945    DDXPointRec oldpt;
946#ifdef DO_SAVE_UNDERS
947    Bool dosave = FALSE;
948#endif
949
950    if (!(pParent = pWin->parent))
951       return ;
952    bw = wBorderWidth (pWin);
953
954    oldpt.x = pWin->drawable.x;
955    oldpt.y = pWin->drawable.y;
956    if (WasViewable) {
957	REGION_NULL(pScreen, &overReg);
958	REGION_NULL(pScreen, &underReg);
959	if(pTree) {
960	    REGION_COPY(pScreen, &overReg, &pWin->borderClip);
961	    REGION_COPY(pScreen, &underReg, &pTree->borderClip);
962        } else {
963	    REGION_COPY(pScreen, &overReg, &pWin->borderClip);
964	    CollectUnderlayChildrenRegions(pWin, &underReg);
965	}
966	(*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
967    }
968    pWin->origin.x = x + (int)bw;
969    pWin->origin.y = y + (int)bw;
970    x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
971    y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
972
973    SetWinSize (pWin);
974    SetBorderSize (pWin);
975
976    (*pScreen->PositionWindow)(pWin, x, y);
977
978    windowToValidate = MoveWindowInStack(pWin, pNextSib);
979
980    ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
981
982    if (WasViewable) {
983	miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
984	(*pScreen->MarkOverlappedWindows) (pWin, windowToValidate, NULL);
985
986#ifdef DO_SAVE_UNDERS
987	if (DO_SAVE_UNDERS(pWin))
988	    dosave = (*pScreen->ChangeSaveUnder)(pWin, windowToValidate);
989#endif /* DO_SAVE_UNDERS */
990
991	(*pScreen->ValidateTree)(pWin->parent, NullWindow, kind);
992	if(REGION_NOTEMPTY(pScreen, &underReg)) {
993	    pPriv->copyUnderlay = TRUE;
994	    (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, &underReg);
995	}
996	REGION_UNINIT(pScreen, &underReg);
997	if(REGION_NOTEMPTY(pScreen, &overReg)) {
998	    pPriv->copyUnderlay = FALSE;
999	    (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, &overReg);
1000	}
1001	REGION_UNINIT(pScreen, &overReg);
1002	(*pScreen->HandleExposures)(pWin->parent);
1003
1004#ifdef DO_SAVE_UNDERS
1005	if (dosave)
1006	    (*pScreen->PostChangeSaveUnder)(pWin, windowToValidate);
1007#endif /* DO_SAVE_UNDERS */
1008	if (pScreen->PostValidateTree)
1009	    (*pScreen->PostValidateTree)(pWin->parent, NullWindow, kind);
1010    }
1011    if (pWin->realized)
1012	WindowsRestructured ();
1013}
1014
1015#ifndef RECTLIMIT
1016#define RECTLIMIT 25
1017#endif
1018
1019static void
1020miOverlayWindowExposures(
1021    WindowPtr pWin,
1022    RegionPtr prgn,
1023    RegionPtr other_exposed
1024){
1025    RegionPtr   exposures = prgn;
1026    ScreenPtr pScreen = pWin->drawable.pScreen;
1027
1028    if (pWin->backStorage && prgn)
1029	exposures = (*pScreen->RestoreAreas)(pWin, prgn);
1030    if ((prgn && !REGION_NIL(prgn)) ||
1031	(exposures && !REGION_NIL(exposures)) || other_exposed)
1032    {
1033	RegionRec   expRec;
1034	int	    clientInterested;
1035
1036	clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) &
1037		 	    ExposureMask;
1038	if (other_exposed) {
1039	    if (exposures) {
1040		REGION_UNION(pScreen, other_exposed, exposures, other_exposed);
1041		if (exposures != prgn)
1042		    REGION_DESTROY(pScreen, exposures);
1043	    }
1044	    exposures = other_exposed;
1045	}
1046	if (clientInterested && exposures &&
1047	   (REGION_NUM_RECTS(exposures) > RECTLIMIT))
1048	{
1049            miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
1050	    BoxRec box;
1051
1052	    box = *REGION_EXTENTS(pScreen, exposures);
1053	    if (exposures == prgn) {
1054		exposures = &expRec;
1055		REGION_INIT(pScreen, exposures, &box, 1);
1056		REGION_RESET(pScreen, prgn, &box);
1057	    } else {
1058		REGION_RESET(pScreen, exposures, &box);
1059		REGION_UNION(pScreen, prgn, prgn, exposures);
1060	    }
1061	    /* This is the only reason why we are replacing mi's version
1062               of this file */
1063
1064	    if(!((*pPriv->InOverlay)(pWin))) {
1065		miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1066		REGION_INTERSECT(pScreen, prgn, prgn, &pTree->clipList);
1067	    } else
1068		REGION_INTERSECT(pScreen, prgn, prgn, &pWin->clipList);
1069
1070	    /* need to clear out new areas of backing store, too */
1071	    if (pWin->backStorage)
1072		(void) (*pScreen->ClearBackingStore)(
1073					     pWin,
1074					     box.x1 - pWin->drawable.x,
1075					     box.y1 - pWin->drawable.y,
1076					     box.x2 - box.x1,
1077					     box.y2 - box.y1,
1078					     FALSE);
1079	}
1080	if (prgn && !REGION_NIL(prgn))
1081	    (*pScreen->PaintWindowBackground)(
1082			pWin, prgn, PW_BACKGROUND);
1083	if (clientInterested && exposures && !REGION_NIL(exposures))
1084	    miSendExposures(pWin, exposures,
1085			    pWin->drawable.x, pWin->drawable.y);
1086	if (exposures == &expRec) {
1087	    REGION_UNINIT(pScreen, exposures);
1088	}
1089	else if (exposures && exposures != prgn && exposures != other_exposed)
1090	    REGION_DESTROY(pScreen, exposures);
1091	if (prgn)
1092	    REGION_EMPTY(pScreen, prgn);
1093    }
1094    else if (exposures && exposures != prgn)
1095	REGION_DESTROY(pScreen, exposures);
1096}
1097
1098
1099typedef struct {
1100   RegionPtr over;
1101   RegionPtr under;
1102} miOverlayTwoRegions;
1103
1104static int
1105miOverlayRecomputeExposures (
1106    WindowPtr	pWin,
1107    pointer	value
1108){
1109    ScreenPtr pScreen;
1110    miOverlayTwoRegions	*pValid = (miOverlayTwoRegions*)value;
1111    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1112
1113    /* This prevents warning about pScreen not being used. */
1114    pWin->drawable.pScreen = pScreen = pWin->drawable.pScreen;
1115
1116    if (pWin->valdata) {
1117	/*
1118	 * compute exposed regions of this window
1119	 */
1120	REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
1121			&pWin->clipList, pValid->over);
1122	/*
1123	 * compute exposed regions of the border
1124	 */
1125	REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
1126			     &pWin->borderClip, &pWin->winSize);
1127	REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
1128			     &pWin->valdata->after.borderExposed, pValid->over);
1129    }
1130
1131    if(pTree && pTree->valdata) {
1132	REGION_SUBTRACT(pScreen, &pTree->valdata->exposed,
1133			&pTree->clipList, pValid->under);
1134	REGION_SUBTRACT(pScreen, &pTree->valdata->borderExposed,
1135			     &pTree->borderClip, &pWin->winSize);
1136	REGION_SUBTRACT(pScreen, &pTree->valdata->borderExposed,
1137			     &pTree->valdata->borderExposed, pValid->under);
1138    } else if (!pWin->valdata)
1139	return WT_NOMATCH;
1140
1141    return WT_WALKCHILDREN;
1142}
1143
1144static void
1145miOverlayResizeWindow(
1146    WindowPtr pWin,
1147    int x, int y,
1148    unsigned int w, unsigned int h,
1149    WindowPtr pSib
1150){
1151    ScreenPtr pScreen = pWin->drawable.pScreen;
1152    WindowPtr pParent;
1153    miOverlayTreePtr tChild, pTree;
1154    Bool WasViewable = (Bool)(pWin->viewable);
1155    unsigned short width = pWin->drawable.width;
1156    unsigned short height = pWin->drawable.height;
1157    short oldx = pWin->drawable.x;
1158    short oldy = pWin->drawable.y;
1159    int bw = wBorderWidth (pWin);
1160    short dw, dh;
1161    DDXPointRec oldpt;
1162    RegionPtr oldRegion = NULL, oldRegion2 = NULL;
1163    WindowPtr pFirstChange;
1164    WindowPtr pChild;
1165    RegionPtr	gravitate[StaticGravity + 1];
1166    RegionPtr	gravitate2[StaticGravity + 1];
1167    unsigned 	g;
1168    int		nx, ny;		/* destination x,y */
1169    int		newx, newy;	/* new inner window position */
1170    RegionPtr	pRegion = NULL;
1171    RegionPtr	destClip, destClip2;
1172    RegionPtr	oldWinClip = NULL, oldWinClip2 = NULL;
1173    RegionPtr	borderVisible = NullRegion;
1174    RegionPtr	borderVisible2 = NullRegion;
1175    RegionPtr	bsExposed = NullRegion;	    /* backing store exposures */
1176    Bool	shrunk = FALSE; /* shrunk in an inner dimension */
1177    Bool	moved = FALSE;	/* window position changed */
1178#ifdef DO_SAVE_UNDERS
1179    Bool	dosave = FALSE;
1180#endif
1181    Bool	doUnderlay;
1182
1183    /* if this is a root window, can't be resized */
1184    if (!(pParent = pWin->parent))
1185	return ;
1186
1187    pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1188    doUnderlay = ((pTree) || HasUnderlayChildren(pWin));
1189    newx = pParent->drawable.x + x + bw;
1190    newy = pParent->drawable.y + y + bw;
1191    if (WasViewable)
1192    {
1193	/*
1194	 * save the visible region of the window
1195	 */
1196	oldRegion = REGION_CREATE(pScreen, NullBox, 1);
1197	REGION_COPY(pScreen, oldRegion, &pWin->winSize);
1198	if(doUnderlay) {
1199	    oldRegion2 = REGION_CREATE(pScreen, NullBox, 1);
1200	    REGION_COPY(pScreen, oldRegion2, &pWin->winSize);
1201	}
1202
1203	/*
1204	 * categorize child windows into regions to be moved
1205	 */
1206	for (g = 0; g <= StaticGravity; g++)
1207	    gravitate[g] = gravitate2[g] = NULL;
1208	for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
1209	    g = pChild->winGravity;
1210	    if (g != UnmapGravity) {
1211		if (!gravitate[g])
1212		    gravitate[g] = REGION_CREATE(pScreen, NullBox, 1);
1213		REGION_UNION(pScreen, gravitate[g],
1214				   gravitate[g], &pChild->borderClip);
1215
1216		if(doUnderlay) {
1217		    if (!gravitate2[g])
1218			gravitate2[g] = REGION_CREATE(pScreen, NullBox, 0);
1219
1220		    if((tChild = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
1221		        REGION_UNION(pScreen, gravitate2[g],
1222				   gravitate2[g], &tChild->borderClip);
1223		    } else
1224			CollectUnderlayChildrenRegions(pChild, gravitate2[g]);
1225		}
1226	    } else {
1227		UnmapWindow(pChild, TRUE);
1228	    }
1229	}
1230	(*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
1231
1232
1233	oldWinClip = oldWinClip2 = NULL;
1234	if (pWin->bitGravity != ForgetGravity) {
1235	    oldWinClip = REGION_CREATE(pScreen, NullBox, 1);
1236	    REGION_COPY(pScreen, oldWinClip, &pWin->clipList);
1237	    if(pTree) {
1238		oldWinClip2 = REGION_CREATE(pScreen, NullBox, 1);
1239		REGION_COPY(pScreen, oldWinClip2, &pTree->clipList);
1240	    }
1241	}
1242	/*
1243	 * if the window is changing size, borderExposed
1244	 * can't be computed correctly without some help.
1245	 */
1246	if (pWin->drawable.height > h || pWin->drawable.width > w)
1247	    shrunk = TRUE;
1248
1249	if (newx != oldx || newy != oldy)
1250	    moved = TRUE;
1251
1252	if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
1253	    HasBorder (pWin))
1254	{
1255	    borderVisible = REGION_CREATE(pScreen, NullBox, 1);
1256	    if(pTree)
1257		borderVisible2 = REGION_CREATE(pScreen, NullBox, 1);
1258	    /* for tiled borders, we punt and draw the whole thing */
1259	    if (pWin->borderIsPixel || !moved)
1260	    {
1261		if (shrunk || moved)
1262		    REGION_SUBTRACT(pScreen, borderVisible,
1263					  &pWin->borderClip,
1264					  &pWin->winSize);
1265		else
1266		    REGION_COPY(pScreen, borderVisible,
1267					    &pWin->borderClip);
1268		if(pTree) {
1269		    if (shrunk || moved)
1270			REGION_SUBTRACT(pScreen, borderVisible,
1271					  &pTree->borderClip,
1272					  &pWin->winSize);
1273		    else
1274			REGION_COPY(pScreen, borderVisible,
1275					    &pTree->borderClip);
1276		}
1277	    }
1278	}
1279    }
1280    pWin->origin.x = x + bw;
1281    pWin->origin.y = y + bw;
1282    pWin->drawable.height = h;
1283    pWin->drawable.width = w;
1284
1285    x = pWin->drawable.x = newx;
1286    y = pWin->drawable.y = newy;
1287
1288    SetWinSize (pWin);
1289    SetBorderSize (pWin);
1290
1291    dw = (int)w - (int)width;
1292    dh = (int)h - (int)height;
1293    ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
1294
1295    /* let the hardware adjust background and border pixmaps, if any */
1296    (*pScreen->PositionWindow)(pWin, x, y);
1297
1298    pFirstChange = MoveWindowInStack(pWin, pSib);
1299
1300    if (WasViewable) {
1301	pRegion = REGION_CREATE(pScreen, NullBox, 1);
1302	if (pWin->backStorage)
1303	    REGION_COPY(pScreen, pRegion, &pWin->clipList);
1304
1305	(*pScreen->MarkOverlappedWindows)(pWin, pFirstChange, NULL);
1306
1307	pWin->valdata->before.resized = TRUE;
1308	pWin->valdata->before.borderVisible = borderVisible;
1309	if(pTree)
1310	    pTree->valdata->borderVisible = borderVisible2;
1311
1312#ifdef DO_SAVE_UNDERS
1313	if (DO_SAVE_UNDERS(pWin))
1314	    dosave = (*pScreen->ChangeSaveUnder)(pWin, pFirstChange);
1315#endif /* DO_SAVE_UNDERS */
1316
1317	(*pScreen->ValidateTree)(pWin->parent, pFirstChange, VTOther);
1318	/*
1319	 * the entire window is trashed unless bitGravity
1320	 * recovers portions of it
1321	 */
1322	REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList);
1323	if(pTree)
1324	    REGION_COPY(pScreen, &pTree->valdata->exposed, &pTree->clipList);
1325    }
1326
1327    GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
1328
1329    if (pWin->backStorage && ((pWin->backingStore == Always) || WasViewable)) {
1330	if (!WasViewable)
1331	    pRegion = &pWin->clipList; /* a convenient empty region */
1332	if (pWin->bitGravity == ForgetGravity)
1333	    bsExposed = (*pScreen->TranslateBackingStore)
1334				(pWin, 0, 0, NullRegion, oldx, oldy);
1335	else
1336	    bsExposed = (*pScreen->TranslateBackingStore)
1337			     (pWin, nx - x, ny - y, pRegion, oldx, oldy);
1338    }
1339
1340    if (WasViewable) {
1341	miOverlayScreenPtr pPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
1342	miOverlayTwoRegions TwoRegions;
1343
1344	/* avoid the border */
1345	if (HasBorder (pWin)) {
1346	    int	offx, offy, dx, dy;
1347
1348	    /* kruft to avoid double translates for each gravity */
1349	    offx = 0;
1350	    offy = 0;
1351	    for (g = 0; g <= StaticGravity; g++) {
1352		if (!gravitate[g] && !gravitate2[g])
1353		    continue;
1354
1355		/* align winSize to gravitate[g].
1356		 * winSize is in new coordinates,
1357		 * gravitate[g] is still in old coordinates */
1358		GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
1359
1360		dx = (oldx - nx) - offx;
1361		dy = (oldy - ny) - offy;
1362		if (dx || dy) {
1363		    REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy);
1364		    offx += dx;
1365		    offy += dy;
1366		}
1367		if(gravitate[g])
1368		    REGION_INTERSECT(pScreen, gravitate[g], gravitate[g],
1369				 &pWin->winSize);
1370		if(gravitate2[g])
1371		    REGION_INTERSECT(pScreen, gravitate2[g], gravitate2[g],
1372				 &pWin->winSize);
1373	    }
1374	    /* get winSize back where it belongs */
1375	    if (offx || offy)
1376		REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy);
1377	}
1378	/*
1379	 * add screen bits to the appropriate bucket
1380	 */
1381
1382	if (oldWinClip2)
1383	{
1384	    REGION_COPY(pScreen, pRegion, oldWinClip2);
1385	    REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy);
1386	    REGION_INTERSECT(pScreen, oldWinClip2, pRegion, &pTree->clipList);
1387
1388	    for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
1389		if (gravitate2[g])
1390		    REGION_SUBTRACT(pScreen, oldWinClip2, oldWinClip2,
1391					gravitate2[g]);
1392	    }
1393	    REGION_TRANSLATE(pScreen, oldWinClip2, oldx - nx, oldy - ny);
1394	    g = pWin->bitGravity;
1395	    if (!gravitate2[g])
1396		gravitate2[g] = oldWinClip2;
1397	    else {
1398		REGION_UNION(pScreen,gravitate2[g],gravitate2[g],oldWinClip2);
1399		REGION_DESTROY(pScreen, oldWinClip2);
1400	    }
1401	}
1402
1403	if (oldWinClip)
1404	{
1405	    /*
1406	     * clip to new clipList
1407	     */
1408	    REGION_COPY(pScreen, pRegion, oldWinClip);
1409	    REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy);
1410	    REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList);
1411	    /*
1412	     * don't step on any gravity bits which will be copied after this
1413	     * region.	Note -- this assumes that the regions will be copied
1414	     * in gravity order.
1415	     */
1416	    for (g = pWin->bitGravity + 1; g <= StaticGravity; g++) {
1417		if (gravitate[g])
1418		    REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip,
1419					gravitate[g]);
1420	    }
1421	    REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny);
1422	    g = pWin->bitGravity;
1423	    if (!gravitate[g])
1424		gravitate[g] = oldWinClip;
1425	    else {
1426		REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip);
1427		REGION_DESTROY(pScreen, oldWinClip);
1428	    }
1429	}
1430
1431	/*
1432	 * move the bits on the screen
1433	 */
1434
1435	destClip = destClip2 = NULL;
1436
1437	for (g = 0; g <= StaticGravity; g++) {
1438	    if (!gravitate[g] && !gravitate2[g])
1439		continue;
1440
1441	    GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
1442
1443	    oldpt.x = oldx + (x - nx);
1444	    oldpt.y = oldy + (y - ny);
1445
1446	    /* Note that gravitate[g] is *translated* by CopyWindow */
1447
1448	    /* only copy the remaining useful bits */
1449
1450	    if(gravitate[g])
1451		REGION_INTERSECT(pScreen, gravitate[g],
1452				 gravitate[g], oldRegion);
1453	    if(gravitate2[g])
1454		REGION_INTERSECT(pScreen, gravitate2[g],
1455				 gravitate2[g], oldRegion2);
1456
1457	    /* clip to not overwrite already copied areas */
1458
1459	    if (destClip && gravitate[g]) {
1460		REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y);
1461		REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip);
1462		REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y);
1463	    }
1464	    if (destClip2 && gravitate2[g]) {
1465		REGION_TRANSLATE(pScreen, destClip2, oldpt.x - x, oldpt.y - y);
1466		REGION_SUBTRACT(pScreen,gravitate2[g],gravitate2[g],destClip2);
1467		REGION_TRANSLATE(pScreen, destClip2, x - oldpt.x, y - oldpt.y);
1468	    }
1469
1470	    /* and move those bits */
1471
1472	    if (oldpt.x != x || oldpt.y != y) {
1473		if(gravitate2[g]) {
1474		    pPriv->copyUnderlay = TRUE;
1475		    (*pWin->drawable.pScreen->CopyWindow)(
1476						pWin, oldpt, gravitate2[g]);
1477		}
1478		if(gravitate[g]) {
1479		    pPriv->copyUnderlay = FALSE;
1480		    (*pWin->drawable.pScreen->CopyWindow)(
1481						pWin, oldpt, gravitate[g]);
1482		}
1483	    }
1484
1485	    /* remove any overwritten bits from the remaining useful bits */
1486
1487	    if(gravitate[g])
1488		REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]);
1489	    if(gravitate2[g])
1490		REGION_SUBTRACT(pScreen, oldRegion2, oldRegion2, gravitate2[g]);
1491
1492	    /*
1493	     * recompute exposed regions of child windows
1494	     */
1495
1496
1497	    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
1498		if (pChild->winGravity != g)
1499		    continue;
1500
1501		TwoRegions.over = gravitate[g];
1502		TwoRegions.under = gravitate2[g];
1503
1504		TraverseTree (pChild, miOverlayRecomputeExposures,
1505					(pointer)(&TwoRegions));
1506	    }
1507
1508	    /*
1509	     * remove the successfully copied regions of the
1510	     * window from its exposed region
1511	     */
1512
1513	    if (g == pWin->bitGravity) {
1514		if(gravitate[g])
1515		    REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
1516				&pWin->valdata->after.exposed, gravitate[g]);
1517		if(gravitate2[g] && pTree)
1518		    REGION_SUBTRACT(pScreen, &pTree->valdata->exposed,
1519				&pTree->valdata->exposed, gravitate2[g]);
1520	    }
1521	    if(gravitate[g]) {
1522		if (!destClip)
1523		    destClip = gravitate[g];
1524		else {
1525		    REGION_UNION(pScreen, destClip, destClip, gravitate[g]);
1526		    REGION_DESTROY(pScreen, gravitate[g]);
1527		}
1528	    }
1529	    if(gravitate2[g]) {
1530		if (!destClip2)
1531		    destClip2 = gravitate2[g];
1532		else {
1533		    REGION_UNION(pScreen, destClip2, destClip2, gravitate2[g]);
1534		    REGION_DESTROY(pScreen, gravitate2[g]);
1535		}
1536	    }
1537	}
1538
1539	REGION_DESTROY(pScreen, pRegion);
1540	REGION_DESTROY(pScreen, oldRegion);
1541	if(doUnderlay)
1542	    REGION_DESTROY(pScreen, oldRegion2);
1543	if (destClip)
1544	    REGION_DESTROY(pScreen, destClip);
1545	if (destClip2)
1546	    REGION_DESTROY(pScreen, destClip2);
1547	if (bsExposed) {
1548	    RegionPtr	valExposed = NullRegion;
1549
1550	    if (pWin->valdata)
1551		valExposed = &pWin->valdata->after.exposed;
1552	    (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
1553	    if (valExposed)
1554		REGION_EMPTY(pScreen, valExposed);
1555	    REGION_DESTROY(pScreen, bsExposed);
1556	}
1557	(*pScreen->HandleExposures)(pWin->parent);
1558#ifdef DO_SAVE_UNDERS
1559	if (dosave)
1560	    (*pScreen->PostChangeSaveUnder)(pWin, pFirstChange);
1561#endif /* DO_SAVE_UNDERS */
1562	if (pScreen->PostValidateTree)
1563	    (*pScreen->PostValidateTree)(pWin->parent, pFirstChange, VTOther);
1564    }
1565    else if (bsExposed) {
1566	(*pScreen->WindowExposures) (pWin, NullRegion, bsExposed);
1567	REGION_DESTROY(pScreen, bsExposed);
1568    }
1569    if (pWin->realized)
1570	WindowsRestructured ();
1571}
1572
1573
1574#ifdef SHAPE
1575static void
1576miOverlaySetShape(WindowPtr pWin)
1577{
1578    Bool	WasViewable = (Bool)(pWin->viewable);
1579    ScreenPtr 	pScreen = pWin->drawable.pScreen;
1580    RegionPtr	pOldClip = NULL, bsExposed;
1581#ifdef DO_SAVE_UNDERS
1582    Bool	dosave = FALSE;
1583#endif
1584
1585    if (WasViewable) {
1586	(*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
1587
1588	if (HasBorder (pWin)) {
1589	    RegionPtr borderVisible;
1590
1591	    borderVisible = REGION_CREATE(pScreen, NullBox, 1);
1592	    REGION_SUBTRACT(pScreen, borderVisible,
1593				      &pWin->borderClip, &pWin->winSize);
1594	    pWin->valdata->before.borderVisible = borderVisible;
1595	    pWin->valdata->before.resized = TRUE;
1596	    if(IN_UNDERLAY(pWin)) {
1597		miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1598		RegionPtr borderVisible2;
1599
1600		borderVisible2 = REGION_CREATE(pScreen, NULL, 1);
1601		REGION_SUBTRACT(pScreen, borderVisible2,
1602				      &pTree->borderClip, &pWin->winSize);
1603		pTree->valdata->borderVisible = borderVisible2;
1604	    }
1605	}
1606    }
1607
1608    SetWinSize (pWin);
1609    SetBorderSize (pWin);
1610
1611    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
1612
1613    if (WasViewable) {
1614	if (pWin->backStorage) {
1615	    pOldClip = REGION_CREATE(pScreen, NullBox, 1);
1616	    REGION_COPY(pScreen, pOldClip, &pWin->clipList);
1617	}
1618
1619	(*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
1620
1621#ifdef DO_SAVE_UNDERS
1622	if (DO_SAVE_UNDERS(pWin))
1623	    dosave = (*pScreen->ChangeSaveUnder)(pWin, pWin);
1624#endif /* DO_SAVE_UNDERS */
1625
1626	(*pScreen->ValidateTree)(pWin->parent, NullWindow, VTOther);
1627    }
1628
1629    if (pWin->backStorage && ((pWin->backingStore == Always) || WasViewable)) {
1630	if (!WasViewable)
1631	    pOldClip = &pWin->clipList; /* a convenient empty region */
1632	bsExposed = (*pScreen->TranslateBackingStore)
1633			     (pWin, 0, 0, pOldClip,
1634			      pWin->drawable.x, pWin->drawable.y);
1635	if (WasViewable)
1636	    REGION_DESTROY(pScreen, pOldClip);
1637	if (bsExposed)
1638	{
1639	    RegionPtr	valExposed = NullRegion;
1640
1641	    if (pWin->valdata)
1642		valExposed = &pWin->valdata->after.exposed;
1643	    (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
1644	    if (valExposed)
1645		REGION_EMPTY(pScreen, valExposed);
1646	    REGION_DESTROY(pScreen, bsExposed);
1647	}
1648    }
1649    if (WasViewable) {
1650	(*pScreen->HandleExposures)(pWin->parent);
1651#ifdef DO_SAVE_UNDERS
1652	if (dosave)
1653	    (*pScreen->PostChangeSaveUnder)(pWin, pWin);
1654#endif /* DO_SAVE_UNDERS */
1655	if (pScreen->PostValidateTree)
1656	    (*pScreen->PostValidateTree)(pWin->parent, NullWindow, VTOther);
1657    }
1658    if (pWin->realized)
1659	WindowsRestructured ();
1660    CheckCursorConfinement(pWin);
1661}
1662#endif
1663
1664
1665
1666static void
1667miOverlayChangeBorderWidth(
1668    WindowPtr pWin,
1669    unsigned int width
1670){
1671    int oldwidth;
1672    ScreenPtr pScreen;
1673    Bool WasViewable = (Bool)(pWin->viewable);
1674    Bool HadBorder;
1675#ifdef DO_SAVE_UNDERS
1676    Bool	dosave = FALSE;
1677#endif
1678
1679    oldwidth = wBorderWidth (pWin);
1680    if (oldwidth == width)
1681	return;
1682    HadBorder = HasBorder(pWin);
1683    pScreen = pWin->drawable.pScreen;
1684    if (WasViewable && (width < oldwidth))
1685	(*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
1686
1687    pWin->borderWidth = width;
1688    SetBorderSize (pWin);
1689
1690    if (WasViewable) {
1691	if (width > oldwidth) {
1692	    (*pScreen->MarkOverlappedWindows)(pWin, pWin, NULL);
1693
1694	    if (HadBorder) {
1695		RegionPtr   borderVisible;
1696		borderVisible = REGION_CREATE(pScreen, NULL, 1);
1697		REGION_SUBTRACT(pScreen, borderVisible,
1698				      &pWin->borderClip, &pWin->winSize);
1699		pWin->valdata->before.borderVisible = borderVisible;
1700		if(IN_UNDERLAY(pWin)) {
1701		    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1702		    RegionPtr borderVisible2;
1703
1704		    borderVisible2 = REGION_CREATE(pScreen, NULL, 1);
1705		    REGION_SUBTRACT(pScreen, borderVisible2,
1706				      &pTree->borderClip, &pWin->winSize);
1707		    pTree->valdata->borderVisible = borderVisible2;
1708		}
1709	    }
1710	}
1711#ifdef DO_SAVE_UNDERS
1712	if (DO_SAVE_UNDERS(pWin))
1713	    dosave = (*pScreen->ChangeSaveUnder)(pWin, pWin->nextSib);
1714#endif /* DO_SAVE_UNDERS */
1715	(*pScreen->ValidateTree)(pWin->parent, pWin, VTOther);
1716	(*pScreen->HandleExposures)(pWin->parent);
1717
1718#ifdef DO_SAVE_UNDERS
1719	if (dosave)
1720	    (*pScreen->PostChangeSaveUnder)(pWin, pWin->nextSib);
1721#endif /* DO_SAVE_UNDERS */
1722	if (pScreen->PostValidateTree)
1723	    (*pScreen->PostValidateTree)(pWin->parent, pWin, VTOther);
1724    }
1725    if (pWin->realized)
1726	WindowsRestructured ();
1727}
1728
1729/*  We need this as an addition since the xf86 common code doesn't
1730    know about the second tree which is static to this file.  */
1731
1732_X_EXPORT void
1733miOverlaySetRootClip(ScreenPtr pScreen, Bool enable)
1734{
1735    WindowPtr pRoot = WindowTable[pScreen->myNum];
1736    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pRoot);
1737
1738    MARK_UNDERLAY(pRoot);
1739
1740    if(enable) {
1741	BoxRec box;
1742
1743	box.x1 = 0;
1744	box.y1 = 0;
1745	box.x2 = pScreen->width;
1746	box.y2 = pScreen->height;
1747
1748	REGION_RESET(pScreen, &pTree->borderClip, &box);
1749    } else
1750	REGION_EMPTY(pScreen, &pTree->borderClip);
1751
1752    REGION_BREAK(pScreen, &pTree->clipList);
1753}
1754
1755static void
1756miOverlayClearToBackground(
1757    WindowPtr pWin,
1758    int x, int y,
1759    int w, int h,
1760    Bool generateExposures
1761)
1762{
1763    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1764    BoxRec box;
1765    RegionRec reg;
1766    RegionPtr pBSReg = NullRegion;
1767    ScreenPtr pScreen = pWin->drawable.pScreen;
1768    miOverlayScreenPtr pScreenPriv = MIOVERLAY_GET_SCREEN_PRIVATE(pScreen);
1769    RegionPtr clipList;
1770    BoxPtr  extents;
1771    int     x1, y1, x2, y2;
1772
1773    x1 = pWin->drawable.x + x;
1774    y1 = pWin->drawable.y + y;
1775    if (w)
1776        x2 = x1 + (int) w;
1777    else
1778        x2 = x1 + (int) pWin->drawable.width - (int) x;
1779    if (h)
1780        y2 = y1 + h;
1781    else
1782        y2 = y1 + (int) pWin->drawable.height - (int) y;
1783
1784    clipList = ((*pScreenPriv->InOverlay)(pWin)) ? &pWin->clipList :
1785                                                 &pTree->clipList;
1786
1787    extents = REGION_EXTENTS(pScreen, clipList);
1788
1789    if (x1 < extents->x1) x1 = extents->x1;
1790    if (x2 > extents->x2) x2 = extents->x2;
1791    if (y1 < extents->y1) y1 = extents->y1;
1792    if (y2 > extents->y2) y2 = extents->y2;
1793
1794    if (x2 <= x1 || y2 <= y1)
1795        x2 = x1 = y2 = y1 = 0;
1796
1797    box.x1 = x1; box.x2 = x2;
1798    box.y1 = y1; box.y2 = y2;
1799
1800    REGION_INIT(pScreen, &reg, &box, 1);
1801    if (pWin->backStorage) {
1802        pBSReg = (* pScreen->ClearBackingStore)(pWin, x, y, w, h,
1803                                                 generateExposures);
1804    }
1805
1806    REGION_INTERSECT(pScreen, &reg, &reg, clipList);
1807    if (generateExposures)
1808        (*pScreen->WindowExposures)(pWin, &reg, pBSReg);
1809    else if (pWin->backgroundState != None)
1810        (*pScreen->PaintWindowBackground)(pWin, &reg, PW_BACKGROUND);
1811    REGION_UNINIT(pScreen, &reg);
1812    if (pBSReg)
1813        REGION_DESTROY(pScreen, pBSReg);
1814}
1815
1816
1817/****************************************************************/
1818
1819/* not used */
1820_X_EXPORT Bool
1821miOverlayGetPrivateClips(
1822    WindowPtr pWin,
1823    RegionPtr *borderClip,
1824    RegionPtr *clipList
1825){
1826    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1827
1828    if(pTree) {
1829 	*borderClip = &(pTree->borderClip);
1830	*clipList = &(pTree->clipList);
1831	return TRUE;
1832    }
1833
1834    *borderClip = *clipList = NULL;
1835
1836    return FALSE;
1837}
1838
1839_X_EXPORT void
1840miOverlaySetTransFunction (
1841   ScreenPtr pScreen,
1842   miOverlayTransFunc transFunc
1843){
1844    MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->MakeTransparent = transFunc;
1845}
1846
1847_X_EXPORT Bool
1848miOverlayCopyUnderlay(ScreenPtr pScreen)
1849{
1850    return MIOVERLAY_GET_SCREEN_PRIVATE(pScreen)->copyUnderlay;
1851}
1852
1853_X_EXPORT void
1854miOverlayComputeCompositeClip(GCPtr pGC, WindowPtr pWin)
1855{
1856    ScreenPtr       pScreen = pGC->pScreen;
1857    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1858    RegionPtr       pregWin;
1859    Bool            freeTmpClip, freeCompClip;
1860
1861    if(!pTree) {
1862	miComputeCompositeClip(pGC, &pWin->drawable);
1863	return;
1864    }
1865
1866    if (pGC->subWindowMode == IncludeInferiors) {
1867	pregWin = REGION_CREATE(pScreen, NullBox, 1);
1868	freeTmpClip = TRUE;
1869	if (pWin->parent || (screenIsSaved != SCREEN_SAVER_ON) ||
1870		!HasSaverWindow (pScreen->myNum))
1871	{
1872            REGION_INTERSECT(pScreen,pregWin,&pTree->borderClip,&pWin->winSize);
1873	}
1874    } else {
1875	pregWin = &pTree->clipList;
1876	freeTmpClip = FALSE;
1877    }
1878    freeCompClip = pGC->freeCompClip;
1879    if (pGC->clientClipType == CT_NONE) {
1880	if (freeCompClip)
1881	    REGION_DESTROY(pScreen, pGC->pCompositeClip);
1882	pGC->pCompositeClip = pregWin;
1883	pGC->freeCompClip = freeTmpClip;
1884    } else {
1885	REGION_TRANSLATE(pScreen, pGC->clientClip,
1886				pWin->drawable.x + pGC->clipOrg.x,
1887				pWin->drawable.y + pGC->clipOrg.y);
1888
1889	if (freeCompClip) {
1890	    REGION_INTERSECT(pGC->pScreen, pGC->pCompositeClip,
1891					    pregWin, pGC->clientClip);
1892	    if (freeTmpClip)
1893		REGION_DESTROY(pScreen, pregWin);
1894	} else if (freeTmpClip) {
1895	    REGION_INTERSECT(pScreen, pregWin, pregWin, pGC->clientClip);
1896	    pGC->pCompositeClip = pregWin;
1897	} else {
1898	    pGC->pCompositeClip = REGION_CREATE(pScreen, NullBox, 0);
1899	    REGION_INTERSECT(pScreen, pGC->pCompositeClip,
1900				       pregWin, pGC->clientClip);
1901	}
1902	pGC->freeCompClip = TRUE;
1903	REGION_TRANSLATE(pScreen, pGC->clientClip,
1904				-(pWin->drawable.x + pGC->clipOrg.x),
1905				-(pWin->drawable.y + pGC->clipOrg.y));
1906    }
1907}
1908
1909_X_EXPORT Bool
1910miOverlayCollectUnderlayRegions(
1911    WindowPtr pWin,
1912    RegionPtr *region
1913){
1914    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1915
1916    if(pTree) {
1917	*region = &pTree->borderClip;
1918	return FALSE;
1919    }
1920
1921    *region = REGION_CREATE(pWin->drawable.pScreen, NullBox, 0);
1922
1923    CollectUnderlayChildrenRegions(pWin, *region);
1924
1925    return TRUE;
1926}
1927
1928
1929static miOverlayTreePtr
1930DoLeaf(
1931    WindowPtr pWin,
1932    miOverlayTreePtr parent,
1933    miOverlayTreePtr prevSib
1934){
1935    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
1936
1937    pTree->parent = parent;
1938    pTree->firstChild = NULL;
1939    pTree->lastChild = NULL;
1940    pTree->prevSib = prevSib;
1941    pTree->nextSib = NULL;
1942
1943    if(prevSib)
1944	prevSib->nextSib = pTree;
1945
1946    if(!parent->firstChild)
1947	parent->firstChild = parent->lastChild = pTree;
1948    else if(parent->lastChild == prevSib)
1949	parent->lastChild = pTree;
1950
1951    return pTree;
1952}
1953
1954static void
1955RebuildTree(WindowPtr pWin)
1956{
1957    miOverlayTreePtr parent, prevSib, tChild;
1958    WindowPtr pChild;
1959
1960    prevSib = tChild = NULL;
1961
1962    pWin = pWin->parent;
1963
1964    while(IN_OVERLAY(pWin))
1965	pWin = pWin->parent;
1966
1967    parent = MIOVERLAY_GET_WINDOW_TREE(pWin);
1968
1969    pChild = pWin->firstChild;
1970    parent->firstChild = parent->lastChild = NULL;
1971
1972    while(1) {
1973	if(IN_UNDERLAY(pChild))
1974	   prevSib = tChild = DoLeaf(pChild, parent, prevSib);
1975
1976	if(pChild->firstChild) {
1977	    if(IN_UNDERLAY(pChild)) {
1978		parent = tChild;
1979		prevSib = NULL;
1980	    }
1981	    pChild = pChild->firstChild;
1982	    continue;
1983	}
1984
1985	while(!pChild->nextSib) {
1986	    pChild = pChild->parent;
1987	    if(pChild == pWin) return;
1988	    if(IN_UNDERLAY(pChild)) {
1989		prevSib = tChild = MIOVERLAY_GET_WINDOW_TREE(pChild);
1990		parent = tChild->parent;
1991	    }
1992	}
1993
1994	pChild = pChild->nextSib;
1995    }
1996}
1997
1998
1999static Bool
2000HasUnderlayChildren(WindowPtr pWin)
2001{
2002    WindowPtr pChild;
2003
2004    if(!(pChild = pWin->firstChild))
2005	return FALSE;
2006
2007    while(1) {
2008	if(IN_UNDERLAY(pChild))
2009	   return TRUE;
2010
2011	if(pChild->firstChild) {
2012	    pChild = pChild->firstChild;
2013	    continue;
2014	}
2015
2016	while(!pChild->nextSib && (pWin != pChild))
2017	    pChild = pChild->parent;
2018
2019	if(pChild == pWin) break;
2020
2021	pChild = pChild->nextSib;
2022    }
2023
2024    return FALSE;
2025}
2026
2027
2028static Bool
2029CollectUnderlayChildrenRegions(WindowPtr pWin, RegionPtr pReg)
2030{
2031    WindowPtr pChild;
2032    miOverlayTreePtr pTree;
2033    Bool hasUnderlay;
2034
2035    if(!(pChild = pWin->firstChild))
2036	return FALSE;
2037
2038    hasUnderlay = FALSE;
2039
2040    while(1) {
2041	if((pTree = MIOVERLAY_GET_WINDOW_TREE(pChild))) {
2042	    REGION_APPEND(pScreen, pReg, &pTree->borderClip);
2043	    hasUnderlay = TRUE;
2044	} else
2045	if(pChild->firstChild) {
2046	    pChild = pChild->firstChild;
2047	    continue;
2048	}
2049
2050	while(!pChild->nextSib && (pWin != pChild))
2051	    pChild = pChild->parent;
2052
2053	if(pChild == pWin) break;
2054
2055	pChild = pChild->nextSib;
2056    }
2057
2058    if(hasUnderlay) {
2059	Bool overlap;
2060	REGION_VALIDATE(pScreen, pReg, &overlap);
2061    }
2062
2063    return hasUnderlay;
2064}
2065
2066
2067static void
2068MarkUnderlayWindow(WindowPtr pWin)
2069{
2070    miOverlayTreePtr pTree = MIOVERLAY_GET_WINDOW_TREE(pWin);
2071
2072    if(pTree->valdata) return;
2073    pTree->valdata = (miOverlayValDataPtr)xnfalloc(sizeof(miOverlayValDataRec));
2074    pTree->valdata->oldAbsCorner.x = pWin->drawable.x;
2075    pTree->valdata->oldAbsCorner.y = pWin->drawable.y;
2076    pTree->valdata->borderVisible = NullRegion;
2077}
2078