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