miwindow.c revision 4642e01f
1/***********************************************************
2
3Copyright 1987, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25
26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
45
46******************************************************************/
47#ifdef HAVE_DIX_CONFIG_H
48#include <dix-config.h>
49#endif
50
51#include <X11/X.h>
52#include "regionstr.h"
53#include "region.h"
54#include "mi.h"
55#include "windowstr.h"
56#include "scrnintstr.h"
57#include "pixmapstr.h"
58#include "mivalidate.h"
59
60_X_EXPORT void
61miClearToBackground(WindowPtr pWin,
62                    int x, int y, int w, int h,
63                    Bool generateExposures)
64{
65    BoxRec box;
66    RegionRec	reg;
67    RegionPtr pBSReg = NullRegion;
68    ScreenPtr	pScreen;
69    BoxPtr  extents;
70    int	    x1, y1, x2, y2;
71
72    /* compute everything using ints to avoid overflow */
73
74    x1 = pWin->drawable.x + x;
75    y1 = pWin->drawable.y + y;
76    if (w)
77        x2 = x1 + (int) w;
78    else
79        x2 = x1 + (int) pWin->drawable.width - (int) x;
80    if (h)
81        y2 = y1 + h;
82    else
83        y2 = y1 + (int) pWin->drawable.height - (int) y;
84
85    extents = &pWin->clipList.extents;
86
87    /* clip the resulting rectangle to the window clipList extents.  This
88     * makes sure that the result will fit in a box, given that the
89     * screen is < 32768 on a side.
90     */
91
92    if (x1 < extents->x1)
93	x1 = extents->x1;
94    if (x2 > extents->x2)
95	x2 = extents->x2;
96    if (y1 < extents->y1)
97	y1 = extents->y1;
98    if (y2 > extents->y2)
99	y2 = extents->y2;
100
101    if (x2 <= x1 || y2 <= y1)
102    {
103	x2 = x1 = 0;
104	y2 = y1 = 0;
105    }
106
107    box.x1 = x1;
108    box.x2 = x2;
109    box.y1 = y1;
110    box.y2 = y2;
111
112    pScreen = pWin->drawable.pScreen;
113    REGION_INIT(pScreen, &reg, &box, 1);
114
115    REGION_INTERSECT(pScreen, &reg, &reg, &pWin->clipList);
116    if (generateExposures)
117	(*pScreen->WindowExposures)(pWin, &reg, pBSReg);
118    else if (pWin->backgroundState != None)
119	miPaintWindow(pWin, &reg, PW_BACKGROUND);
120    REGION_UNINIT(pScreen, &reg);
121    if (pBSReg)
122	REGION_DESTROY(pScreen, pBSReg);
123}
124
125void
126miMarkWindow(WindowPtr pWin)
127{
128    ValidatePtr val;
129
130    if (pWin->valdata)
131	return;
132    val = (ValidatePtr)xnfalloc(sizeof(ValidateRec));
133    val->before.oldAbsCorner.x = pWin->drawable.x;
134    val->before.oldAbsCorner.y = pWin->drawable.y;
135    val->before.borderVisible = NullRegion;
136    val->before.resized = FALSE;
137    pWin->valdata = val;
138}
139
140Bool
141miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
142{
143    BoxPtr box;
144    WindowPtr pChild, pLast;
145    Bool anyMarked = FALSE;
146    MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow;
147    ScreenPtr pScreen;
148
149    pScreen = pWin->drawable.pScreen;
150
151    /* single layered systems are easy */
152    if (ppLayerWin) *ppLayerWin = pWin;
153
154    if (pWin == pFirst)
155    {
156	/* Blindly mark pWin and all of its inferiors.	 This is a slight
157	 * overkill if there are mapped windows that outside pWin's border,
158	 * but it's better than wasting time on RectIn checks.
159	 */
160	pChild = pWin;
161	while (1)
162	{
163	    if (pChild->viewable)
164	    {
165		if (REGION_BROKEN (pScreen, &pChild->winSize))
166		    SetWinSize (pChild);
167		if (REGION_BROKEN (pScreen, &pChild->borderSize))
168		    SetBorderSize (pChild);
169		(* MarkWindow)(pChild);
170		if (pChild->firstChild)
171		{
172		    pChild = pChild->firstChild;
173		    continue;
174		}
175	    }
176	    while (!pChild->nextSib && (pChild != pWin))
177		pChild = pChild->parent;
178	    if (pChild == pWin)
179		break;
180	    pChild = pChild->nextSib;
181	}
182	anyMarked = TRUE;
183	pFirst = pFirst->nextSib;
184    }
185    if ( (pChild = pFirst) )
186    {
187	box = REGION_EXTENTS(pChild->drawable.pScreen, &pWin->borderSize);
188	pLast = pChild->parent->lastChild;
189	while (1)
190	{
191	    if (pChild->viewable)
192	    {
193		if (REGION_BROKEN (pScreen, &pChild->winSize))
194		    SetWinSize (pChild);
195		if (REGION_BROKEN (pScreen, &pChild->borderSize))
196		    SetBorderSize (pChild);
197		if (RECT_IN_REGION(pScreen, &pChild->borderSize, box))
198		{
199		    (* MarkWindow)(pChild);
200		    anyMarked = TRUE;
201		    if (pChild->firstChild)
202		    {
203			pChild = pChild->firstChild;
204			continue;
205		    }
206		}
207	    }
208	    while (!pChild->nextSib && (pChild != pLast))
209		pChild = pChild->parent;
210	    if (pChild == pLast)
211		break;
212	    pChild = pChild->nextSib;
213	}
214    }
215    if (anyMarked)
216	(* MarkWindow)(pWin->parent);
217    return anyMarked;
218}
219
220/*****
221 *  miHandleValidateExposures(pWin)
222 *    starting at pWin, draw background in any windows that have exposure
223 *    regions, translate the regions, restore any backing store,
224 *    and then send any regions still exposed to the client
225 *****/
226void
227miHandleValidateExposures(WindowPtr pWin)
228{
229    WindowPtr pChild;
230    ValidatePtr val;
231    ScreenPtr pScreen;
232    WindowExposuresProcPtr WindowExposures;
233
234    pScreen = pWin->drawable.pScreen;
235
236    pChild = pWin;
237    WindowExposures = pChild->drawable.pScreen->WindowExposures;
238    while (1)
239    {
240	if ( (val = pChild->valdata) )
241	{
242	    if (REGION_NOTEMPTY(pScreen, &val->after.borderExposed))
243		miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
244	    REGION_UNINIT(pScreen, &val->after.borderExposed);
245	    (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
246	    REGION_UNINIT(pScreen, &val->after.exposed);
247	    xfree(val);
248	    pChild->valdata = (ValidatePtr)NULL;
249	    if (pChild->firstChild)
250	    {
251		pChild = pChild->firstChild;
252		continue;
253	    }
254	}
255	while (!pChild->nextSib && (pChild != pWin))
256	    pChild = pChild->parent;
257	if (pChild == pWin)
258	    break;
259	pChild = pChild->nextSib;
260    }
261}
262
263void
264miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
265{
266    WindowPtr pParent;
267    Bool WasViewable = (Bool)(pWin->viewable);
268    short bw;
269    RegionPtr oldRegion = NULL;
270    DDXPointRec oldpt;
271    Bool anyMarked = FALSE;
272    ScreenPtr pScreen;
273    WindowPtr windowToValidate;
274    WindowPtr pLayerWin;
275
276    /* if this is a root window, can't be moved */
277    if (!(pParent = pWin->parent))
278       return ;
279    pScreen = pWin->drawable.pScreen;
280    bw = wBorderWidth (pWin);
281
282    oldpt.x = pWin->drawable.x;
283    oldpt.y = pWin->drawable.y;
284    if (WasViewable)
285    {
286	oldRegion = REGION_CREATE(pScreen, NullBox, 1);
287	REGION_COPY(pScreen, oldRegion, &pWin->borderClip);
288	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
289    }
290    pWin->origin.x = x + (int)bw;
291    pWin->origin.y = y + (int)bw;
292    x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
293    y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
294
295    SetWinSize (pWin);
296    SetBorderSize (pWin);
297
298    (*pScreen->PositionWindow)(pWin, x, y);
299
300    windowToValidate = MoveWindowInStack(pWin, pNextSib);
301
302    ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
303
304    if (WasViewable)
305    {
306	if (pLayerWin == pWin)
307	    anyMarked |= (*pScreen->MarkOverlappedWindows)
308				(pWin, windowToValidate, (WindowPtr *)NULL);
309	else
310	    anyMarked |= (*pScreen->MarkOverlappedWindows)
311				(pWin, pLayerWin, (WindowPtr *)NULL);
312
313
314	if (anyMarked)
315	{
316	    (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind);
317	    (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion);
318	    REGION_DESTROY(pScreen, oldRegion);
319	    /* XXX need to retile border if ParentRelative origin */
320	    (*pScreen->HandleExposures)(pLayerWin->parent);
321	}
322	if (anyMarked && pScreen->PostValidateTree)
323	    (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind);
324    }
325    if (pWin->realized)
326	WindowsRestructured ();
327}
328
329
330/*
331 * pValid is a region of the screen which has been
332 * successfully copied -- recomputed exposed regions for affected windows
333 */
334
335static int
336miRecomputeExposures (
337    WindowPtr	pWin,
338    pointer		value) /* must conform to VisitWindowProcPtr */
339{
340    ScreenPtr	pScreen;
341    RegionPtr	pValid = (RegionPtr)value;
342
343    if (pWin->valdata)
344    {
345#ifdef COMPOSITE
346	/*
347	 * Redirected windows are not affected by parent window
348	 * gravity manipulations, so don't recompute their
349	 * exposed areas here.
350	 */
351	if (pWin->redirectDraw != RedirectDrawNone)
352	    return WT_DONTWALKCHILDREN;
353#endif
354	pScreen = pWin->drawable.pScreen;
355	/*
356	 * compute exposed regions of this window
357	 */
358	REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
359			&pWin->clipList, pValid);
360	/*
361	 * compute exposed regions of the border
362	 */
363	REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
364			     &pWin->borderClip, &pWin->winSize);
365	REGION_SUBTRACT(pScreen, &pWin->valdata->after.borderExposed,
366			     &pWin->valdata->after.borderExposed, pValid);
367	return WT_WALKCHILDREN;
368    }
369    return WT_NOMATCH;
370}
371
372void
373miSlideAndSizeWindow(WindowPtr pWin,
374                     int x, int y,
375                     unsigned int w, unsigned int h,
376                     WindowPtr pSib)
377{
378    WindowPtr pParent;
379    Bool WasViewable = (Bool)(pWin->viewable);
380    unsigned short width = pWin->drawable.width,
381		   height = pWin->drawable.height;
382    short oldx = pWin->drawable.x,
383	  oldy = pWin->drawable.y;
384    int bw = wBorderWidth (pWin);
385    short dw, dh;
386    DDXPointRec oldpt;
387    RegionPtr oldRegion = NULL;
388    Bool anyMarked = FALSE;
389    ScreenPtr pScreen;
390    WindowPtr pFirstChange;
391    WindowPtr pChild;
392    RegionPtr	gravitate[StaticGravity + 1];
393    unsigned g;
394    int		nx, ny;		/* destination x,y */
395    int		newx, newy;	/* new inner window position */
396    RegionPtr	pRegion = NULL;
397    RegionPtr	destClip;	/* portions of destination already written */
398    RegionPtr	oldWinClip = NULL;	/* old clip list for window */
399    RegionPtr	borderVisible = NullRegion; /* visible area of the border */
400    Bool	shrunk = FALSE; /* shrunk in an inner dimension */
401    Bool	moved = FALSE;	/* window position changed */
402    WindowPtr  pLayerWin;
403
404    /* if this is a root window, can't be resized */
405    if (!(pParent = pWin->parent))
406	return ;
407
408    pScreen = pWin->drawable.pScreen;
409    newx = pParent->drawable.x + x + bw;
410    newy = pParent->drawable.y + y + bw;
411    if (WasViewable)
412    {
413	anyMarked = FALSE;
414	/*
415	 * save the visible region of the window
416	 */
417	oldRegion = REGION_CREATE(pScreen, NullBox, 1);
418	REGION_COPY(pScreen, oldRegion, &pWin->winSize);
419
420	/*
421	 * categorize child windows into regions to be moved
422	 */
423	for (g = 0; g <= StaticGravity; g++)
424	    gravitate[g] = (RegionPtr) NULL;
425	for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
426	{
427	    g = pChild->winGravity;
428	    if (g != UnmapGravity)
429	    {
430		if (!gravitate[g])
431		    gravitate[g] = REGION_CREATE(pScreen, NullBox, 1);
432		REGION_UNION(pScreen, gravitate[g],
433				   gravitate[g], &pChild->borderClip);
434	    }
435	    else
436	    {
437		UnmapWindow(pChild, TRUE);
438		anyMarked = TRUE;
439	    }
440	}
441	anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
442						       &pLayerWin);
443
444	oldWinClip = NULL;
445	if (pWin->bitGravity != ForgetGravity)
446	{
447	    oldWinClip = REGION_CREATE(pScreen, NullBox, 1);
448	    REGION_COPY(pScreen, oldWinClip, &pWin->clipList);
449	}
450	/*
451	 * if the window is changing size, borderExposed
452	 * can't be computed correctly without some help.
453	 */
454	if (pWin->drawable.height > h || pWin->drawable.width > w)
455	    shrunk = TRUE;
456
457	if (newx != oldx || newy != oldy)
458	    moved = TRUE;
459
460	if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
461	    HasBorder (pWin))
462	{
463	    borderVisible = REGION_CREATE(pScreen, NullBox, 1);
464	    /* for tiled borders, we punt and draw the whole thing */
465	    if (pWin->borderIsPixel || !moved)
466	    {
467		if (shrunk || moved)
468		    REGION_SUBTRACT(pScreen, borderVisible,
469					  &pWin->borderClip,
470					  &pWin->winSize);
471		else
472		    REGION_COPY(pScreen, borderVisible,
473					    &pWin->borderClip);
474	    }
475	}
476    }
477    pWin->origin.x = x + bw;
478    pWin->origin.y = y + bw;
479    pWin->drawable.height = h;
480    pWin->drawable.width = w;
481
482    x = pWin->drawable.x = newx;
483    y = pWin->drawable.y = newy;
484
485    SetWinSize (pWin);
486    SetBorderSize (pWin);
487
488    dw = (int)w - (int)width;
489    dh = (int)h - (int)height;
490    ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
491
492    /* let the hardware adjust background and border pixmaps, if any */
493    (*pScreen->PositionWindow)(pWin, x, y);
494
495    pFirstChange = MoveWindowInStack(pWin, pSib);
496
497    if (WasViewable)
498    {
499	pRegion = REGION_CREATE(pScreen, NullBox, 1);
500
501	if (pLayerWin == pWin)
502	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
503						(WindowPtr *)NULL);
504	else
505	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
506						(WindowPtr *)NULL);
507
508	if (pWin->valdata)
509	{
510	    pWin->valdata->before.resized = TRUE;
511	    pWin->valdata->before.borderVisible = borderVisible;
512	}
513
514
515	if (anyMarked)
516	    (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther);
517	/*
518	 * the entire window is trashed unless bitGravity
519	 * recovers portions of it
520	 */
521	REGION_COPY(pScreen, &pWin->valdata->after.exposed, &pWin->clipList);
522    }
523
524    GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
525
526    if (WasViewable)
527    {
528	/* avoid the border */
529	if (HasBorder (pWin))
530	{
531	    int	offx, offy, dx, dy;
532
533	    /* kruft to avoid double translates for each gravity */
534	    offx = 0;
535	    offy = 0;
536	    for (g = 0; g <= StaticGravity; g++)
537	    {
538		if (!gravitate[g])
539		    continue;
540
541		/* align winSize to gravitate[g].
542		 * winSize is in new coordinates,
543		 * gravitate[g] is still in old coordinates */
544		GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
545
546		dx = (oldx - nx) - offx;
547		dy = (oldy - ny) - offy;
548		if (dx || dy)
549		{
550		    REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy);
551		    offx += dx;
552		    offy += dy;
553		}
554		REGION_INTERSECT(pScreen, gravitate[g], gravitate[g],
555				 &pWin->winSize);
556	    }
557	    /* get winSize back where it belongs */
558	    if (offx || offy)
559		REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy);
560	}
561	/*
562	 * add screen bits to the appropriate bucket
563	 */
564
565	if (oldWinClip)
566	{
567	    /*
568	     * clip to new clipList
569	     */
570	    REGION_COPY(pScreen, pRegion, oldWinClip);
571	    REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy);
572	    REGION_INTERSECT(pScreen, oldWinClip, pRegion, &pWin->clipList);
573	    /*
574	     * don't step on any gravity bits which will be copied after this
575	     * region.	Note -- this assumes that the regions will be copied
576	     * in gravity order.
577	     */
578	    for (g = pWin->bitGravity + 1; g <= StaticGravity; g++)
579	    {
580		if (gravitate[g])
581		    REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip,
582					gravitate[g]);
583	    }
584	    REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny);
585	    g = pWin->bitGravity;
586	    if (!gravitate[g])
587		gravitate[g] = oldWinClip;
588	    else
589	    {
590		REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip);
591		REGION_DESTROY(pScreen, oldWinClip);
592	    }
593	}
594
595	/*
596	 * move the bits on the screen
597	 */
598
599	destClip = NULL;
600
601	for (g = 0; g <= StaticGravity; g++)
602	{
603	    if (!gravitate[g])
604		continue;
605
606	    GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
607
608	    oldpt.x = oldx + (x - nx);
609	    oldpt.y = oldy + (y - ny);
610
611	    /* Note that gravitate[g] is *translated* by CopyWindow */
612
613	    /* only copy the remaining useful bits */
614
615	    REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion);
616
617	    /* clip to not overwrite already copied areas */
618
619	    if (destClip) {
620		REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y);
621		REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip);
622		REGION_TRANSLATE(pScreen, destClip, x - oldpt.x, y - oldpt.y);
623	    }
624
625	    /* and move those bits */
626
627	    if (oldpt.x != x || oldpt.y != y
628#ifdef COMPOSITE
629		|| pWin->redirectDraw
630#endif
631		)
632	    {
633		(*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]);
634	    }
635
636	    /* remove any overwritten bits from the remaining useful bits */
637
638	    REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]);
639
640	    /*
641	     * recompute exposed regions of child windows
642	     */
643
644	    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
645	    {
646		if (pChild->winGravity != g)
647		    continue;
648		REGION_INTERSECT(pScreen, pRegion,
649				       &pChild->borderClip, gravitate[g]);
650		TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion);
651	    }
652
653	    /*
654	     * remove the successfully copied regions of the
655	     * window from its exposed region
656	     */
657
658	    if (g == pWin->bitGravity)
659		REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
660				     &pWin->valdata->after.exposed, gravitate[g]);
661	    if (!destClip)
662		destClip = gravitate[g];
663	    else
664	    {
665		REGION_UNION(pScreen, destClip, destClip, gravitate[g]);
666		REGION_DESTROY(pScreen, gravitate[g]);
667	    }
668	}
669
670	REGION_DESTROY(pScreen, oldRegion);
671	REGION_DESTROY(pScreen, pRegion);
672	if (destClip)
673	    REGION_DESTROY(pScreen, destClip);
674	if (anyMarked)
675	    (*pScreen->HandleExposures)(pLayerWin->parent);
676	if (anyMarked && pScreen->PostValidateTree)
677	    (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange,
678					  VTOther);
679    }
680    if (pWin->realized)
681	WindowsRestructured ();
682}
683
684WindowPtr
685miGetLayerWindow(WindowPtr pWin)
686{
687    return pWin->firstChild;
688}
689
690/******
691 *
692 * miSetShape
693 *    The border/window shape has changed.  Recompute winSize/borderSize
694 *    and send appropriate exposure events
695 */
696
697void
698miSetShape(WindowPtr pWin)
699{
700    Bool	WasViewable = (Bool)(pWin->viewable);
701    ScreenPtr 	pScreen = pWin->drawable.pScreen;
702    Bool	anyMarked = FALSE;
703    WindowPtr   pLayerWin;
704
705    if (WasViewable)
706    {
707	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
708						      &pLayerWin);
709	if (pWin->valdata)
710	{
711	    if (HasBorder (pWin))
712	    {
713		RegionPtr	borderVisible;
714
715		borderVisible = REGION_CREATE(pScreen, NullBox, 1);
716		REGION_SUBTRACT(pScreen, borderVisible,
717				      &pWin->borderClip, &pWin->winSize);
718		pWin->valdata->before.borderVisible = borderVisible;
719	    }
720	    pWin->valdata->before.resized = TRUE;
721	}
722    }
723
724    SetWinSize (pWin);
725    SetBorderSize (pWin);
726
727    ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
728
729    if (WasViewable)
730    {
731	anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
732						(WindowPtr *)NULL);
733
734
735	if (anyMarked)
736	    (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, VTOther);
737    }
738
739    if (WasViewable)
740    {
741	if (anyMarked)
742	    (*pScreen->HandleExposures)(pLayerWin->parent);
743	if (anyMarked && pScreen->PostValidateTree)
744	    (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, VTOther);
745    }
746    if (pWin->realized)
747	WindowsRestructured ();
748    CheckCursorConfinement(pWin);
749}
750
751/* Keeps the same inside(!) origin */
752
753void
754miChangeBorderWidth(WindowPtr pWin, unsigned int width)
755{
756    int oldwidth;
757    Bool anyMarked = FALSE;
758    ScreenPtr pScreen;
759    Bool WasViewable = (Bool)(pWin->viewable);
760    Bool HadBorder;
761    WindowPtr  pLayerWin;
762
763    oldwidth = wBorderWidth (pWin);
764    if (oldwidth == width)
765	return;
766    HadBorder = HasBorder(pWin);
767    pScreen = pWin->drawable.pScreen;
768    if (WasViewable && width < oldwidth)
769	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
770
771    pWin->borderWidth = width;
772    SetBorderSize (pWin);
773
774    if (WasViewable)
775    {
776	if (width > oldwidth)
777	{
778	    anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
779							  &pLayerWin);
780	    /*
781	     * save the old border visible region to correctly compute
782	     * borderExposed.
783	     */
784	    if (pWin->valdata && HadBorder)
785	    {
786		RegionPtr   borderVisible;
787		borderVisible = REGION_CREATE(pScreen, NULL, 1);
788		REGION_SUBTRACT(pScreen, borderVisible,
789				      &pWin->borderClip, &pWin->winSize);
790		pWin->valdata->before.borderVisible = borderVisible;
791	    }
792	}
793
794	if (anyMarked)
795	{
796	    (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
797	    (*pScreen->HandleExposures)(pLayerWin->parent);
798	}
799	if (anyMarked && pScreen->PostValidateTree)
800	    (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin,
801					  VTOther);
802    }
803    if (pWin->realized)
804	WindowsRestructured ();
805}
806
807void
808miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure)
809{
810    if ((pChild != pWin) || fromConfigure)
811    {
812	REGION_EMPTY(pChild->drawable.pScreen, &pChild->clipList);
813	if (pChild->drawable.pScreen->ClipNotify)
814	    (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
815	REGION_EMPTY(pChild->drawable.pScreen, &pChild->borderClip);
816    }
817}
818
819_X_EXPORT void
820miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
821{
822    ScreenPtr pScreen;
823    WindowPtr pChild;
824
825    pScreen = pWin->drawable.pScreen;
826
827    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
828    {
829	if (pChild->drawable.depth == depth)
830	    REGION_UNION(pScreen, pReg, pReg, &pChild->borderClip);
831
832	if (pChild->firstChild)
833	    miSegregateChildren(pChild, pReg, depth);
834    }
835}
836