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