miwindow.c revision 6747b715
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    RegionPtr pBSReg = NullRegion;
70    BoxPtr  extents;
71    int	    x1, y1, x2, y2;
72
73    /* compute everything using ints to avoid overflow */
74
75    x1 = pWin->drawable.x + x;
76    y1 = pWin->drawable.y + y;
77    if (w)
78        x2 = x1 + (int) w;
79    else
80        x2 = x1 + (int) pWin->drawable.width - (int) x;
81    if (h)
82        y2 = y1 + h;
83    else
84        y2 = y1 + (int) pWin->drawable.height - (int) y;
85
86    extents = &pWin->clipList.extents;
87
88    /* clip the resulting rectangle to the window clipList extents.  This
89     * makes sure that the result will fit in a box, given that the
90     * screen is < 32768 on a side.
91     */
92
93    if (x1 < extents->x1)
94	x1 = extents->x1;
95    if (x2 > extents->x2)
96	x2 = extents->x2;
97    if (y1 < extents->y1)
98	y1 = extents->y1;
99    if (y2 > extents->y2)
100	y2 = extents->y2;
101
102    if (x2 <= x1 || y2 <= y1)
103    {
104	x2 = x1 = 0;
105	y2 = y1 = 0;
106    }
107
108    box.x1 = x1;
109    box.x2 = x2;
110    box.y1 = y1;
111    box.y2 = y2;
112
113    RegionInit(&reg, &box, 1);
114
115    RegionIntersect(&reg, &reg, &pWin->clipList);
116    if (generateExposures)
117	(*pWin->drawable.pScreen->WindowExposures)(pWin, &reg, pBSReg);
118    else if (pWin->backgroundState != None)
119	miPaintWindow(pWin, &reg, PW_BACKGROUND);
120    RegionUninit(&reg);
121    if (pBSReg)
122	RegionDestroy(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
148    /* single layered systems are easy */
149    if (ppLayerWin) *ppLayerWin = pWin;
150
151    if (pWin == pFirst)
152    {
153	/* Blindly mark pWin and all of its inferiors.	 This is a slight
154	 * overkill if there are mapped windows that outside pWin's border,
155	 * but it's better than wasting time on RectIn checks.
156	 */
157	pChild = pWin;
158	while (1)
159	{
160	    if (pChild->viewable)
161	    {
162		if (RegionBroken(&pChild->winSize))
163		    SetWinSize (pChild);
164		if (RegionBroken(&pChild->borderSize))
165		    SetBorderSize (pChild);
166		(* MarkWindow)(pChild);
167		if (pChild->firstChild)
168		{
169		    pChild = pChild->firstChild;
170		    continue;
171		}
172	    }
173	    while (!pChild->nextSib && (pChild != pWin))
174		pChild = pChild->parent;
175	    if (pChild == pWin)
176		break;
177	    pChild = pChild->nextSib;
178	}
179	anyMarked = TRUE;
180	pFirst = pFirst->nextSib;
181    }
182    if ( (pChild = pFirst) )
183    {
184	box = RegionExtents(&pWin->borderSize);
185	pLast = pChild->parent->lastChild;
186	while (1)
187	{
188	    if (pChild->viewable)
189	    {
190		if (RegionBroken(&pChild->winSize))
191		    SetWinSize (pChild);
192		if (RegionBroken(&pChild->borderSize))
193		    SetBorderSize (pChild);
194		if (RegionContainsRect(&pChild->borderSize, box))
195		{
196		    (* MarkWindow)(pChild);
197		    anyMarked = TRUE;
198		    if (pChild->firstChild)
199		    {
200			pChild = pChild->firstChild;
201			continue;
202		    }
203		}
204	    }
205	    while (!pChild->nextSib && (pChild != pLast))
206		pChild = pChild->parent;
207	    if (pChild == pLast)
208		break;
209	    pChild = pChild->nextSib;
210	}
211    }
212    if (anyMarked)
213	(* MarkWindow)(pWin->parent);
214    return anyMarked;
215}
216
217/*****
218 *  miHandleValidateExposures(pWin)
219 *    starting at pWin, draw background in any windows that have exposure
220 *    regions, translate the regions, restore any backing store,
221 *    and then send any regions still exposed to the client
222 *****/
223void
224miHandleValidateExposures(WindowPtr pWin)
225{
226    WindowPtr pChild;
227    ValidatePtr val;
228    WindowExposuresProcPtr WindowExposures;
229
230    pChild = pWin;
231    WindowExposures = pChild->drawable.pScreen->WindowExposures;
232    while (1)
233    {
234	if ( (val = pChild->valdata) )
235	{
236	    if (RegionNotEmpty(&val->after.borderExposed))
237		miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
238	    RegionUninit(&val->after.borderExposed);
239	    (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
240	    RegionUninit(&val->after.exposed);
241	    free(val);
242	    pChild->valdata = NULL;
243	    if (pChild->firstChild)
244	    {
245		pChild = pChild->firstChild;
246		continue;
247	    }
248	}
249	while (!pChild->nextSib && (pChild != pWin))
250	    pChild = pChild->parent;
251	if (pChild == pWin)
252	    break;
253	pChild = pChild->nextSib;
254    }
255}
256
257void
258miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
259{
260    WindowPtr pParent;
261    Bool WasViewable = (Bool)(pWin->viewable);
262    short bw;
263    RegionPtr oldRegion = NULL;
264    DDXPointRec oldpt;
265    Bool anyMarked = FALSE;
266    ScreenPtr pScreen;
267    WindowPtr windowToValidate;
268    WindowPtr pLayerWin;
269
270    /* if this is a root window, can't be moved */
271    if (!(pParent = pWin->parent))
272       return ;
273    pScreen = pWin->drawable.pScreen;
274    bw = wBorderWidth (pWin);
275
276    oldpt.x = pWin->drawable.x;
277    oldpt.y = pWin->drawable.y;
278    if (WasViewable)
279    {
280	oldRegion = RegionCreate(NullBox, 1);
281	RegionCopy(oldRegion, &pWin->borderClip);
282	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
283    }
284    pWin->origin.x = x + (int)bw;
285    pWin->origin.y = y + (int)bw;
286    x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
287    y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
288
289    SetWinSize (pWin);
290    SetBorderSize (pWin);
291
292    (*pScreen->PositionWindow)(pWin, x, y);
293
294    windowToValidate = MoveWindowInStack(pWin, pNextSib);
295
296    ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
297
298    if (WasViewable)
299    {
300	if (pLayerWin == pWin)
301	    anyMarked |= (*pScreen->MarkOverlappedWindows)
302				(pWin, windowToValidate, NULL);
303	else
304	    anyMarked |= (*pScreen->MarkOverlappedWindows)
305				(pWin, pLayerWin, NULL);
306
307
308	if (anyMarked)
309	{
310	    (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind);
311	    (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion);
312	    RegionDestroy(oldRegion);
313	    /* XXX need to retile border if ParentRelative origin */
314	    (*pScreen->HandleExposures)(pLayerWin->parent);
315	}
316	if (anyMarked && pScreen->PostValidateTree)
317	    (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind);
318    }
319    if (pWin->realized)
320	WindowsRestructured ();
321}
322
323
324/*
325 * pValid is a region of the screen which has been
326 * successfully copied -- recomputed exposed regions for affected windows
327 */
328
329static int
330miRecomputeExposures (
331    WindowPtr	pWin,
332    pointer		value) /* must conform to VisitWindowProcPtr */
333{
334    RegionPtr	pValid = (RegionPtr)value;
335
336    if (pWin->valdata)
337    {
338#ifdef COMPOSITE
339	/*
340	 * Redirected windows are not affected by parent window
341	 * gravity manipulations, so don't recompute their
342	 * exposed areas here.
343	 */
344	if (pWin->redirectDraw != RedirectDrawNone)
345	    return WT_DONTWALKCHILDREN;
346#endif
347	/*
348	 * compute exposed regions of this window
349	 */
350	RegionSubtract(&pWin->valdata->after.exposed,
351			&pWin->clipList, pValid);
352	/*
353	 * compute exposed regions of the border
354	 */
355	RegionSubtract(&pWin->valdata->after.borderExposed,
356			     &pWin->borderClip, &pWin->winSize);
357	RegionSubtract(&pWin->valdata->after.borderExposed,
358			     &pWin->valdata->after.borderExposed, pValid);
359	return WT_WALKCHILDREN;
360    }
361    return WT_NOMATCH;
362}
363
364void
365miSlideAndSizeWindow(WindowPtr pWin,
366                     int x, int y,
367                     unsigned int w, unsigned int h,
368                     WindowPtr pSib)
369{
370    WindowPtr pParent;
371    Bool WasViewable = (Bool)(pWin->viewable);
372    unsigned short width = pWin->drawable.width,
373		   height = pWin->drawable.height;
374    short oldx = pWin->drawable.x,
375	  oldy = pWin->drawable.y;
376    int bw = wBorderWidth (pWin);
377    short dw, dh;
378    DDXPointRec oldpt;
379    RegionPtr oldRegion = NULL;
380    Bool anyMarked = FALSE;
381    ScreenPtr pScreen;
382    WindowPtr pFirstChange;
383    WindowPtr pChild;
384    RegionPtr	gravitate[StaticGravity + 1];
385    unsigned g;
386    int		nx, ny;		/* destination x,y */
387    int		newx, newy;	/* new inner window position */
388    RegionPtr	pRegion = NULL;
389    RegionPtr	destClip;	/* portions of destination already written */
390    RegionPtr	oldWinClip = NULL;	/* old clip list for window */
391    RegionPtr	borderVisible = NullRegion; /* visible area of the border */
392    Bool	shrunk = FALSE; /* shrunk in an inner dimension */
393    Bool	moved = FALSE;	/* window position changed */
394    WindowPtr  pLayerWin;
395
396    /* if this is a root window, can't be resized */
397    if (!(pParent = pWin->parent))
398	return ;
399
400    pScreen = pWin->drawable.pScreen;
401    newx = pParent->drawable.x + x + bw;
402    newy = pParent->drawable.y + y + bw;
403    if (WasViewable)
404    {
405	anyMarked = FALSE;
406	/*
407	 * save the visible region of the window
408	 */
409	oldRegion = RegionCreate(NullBox, 1);
410	RegionCopy(oldRegion, &pWin->winSize);
411
412	/*
413	 * categorize child windows into regions to be moved
414	 */
415	for (g = 0; g <= StaticGravity; g++)
416	    gravitate[g] = (RegionPtr) NULL;
417	for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
418	{
419	    g = pChild->winGravity;
420	    if (g != UnmapGravity)
421	    {
422		if (!gravitate[g])
423		    gravitate[g] = RegionCreate(NullBox, 1);
424		RegionUnion(gravitate[g],
425				   gravitate[g], &pChild->borderClip);
426	    }
427	    else
428	    {
429		UnmapWindow(pChild, TRUE);
430		anyMarked = TRUE;
431	    }
432	}
433	anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
434						       &pLayerWin);
435
436	oldWinClip = NULL;
437	if (pWin->bitGravity != ForgetGravity)
438	{
439	    oldWinClip = RegionCreate(NullBox, 1);
440	    RegionCopy(oldWinClip, &pWin->clipList);
441	}
442	/*
443	 * if the window is changing size, borderExposed
444	 * can't be computed correctly without some help.
445	 */
446	if (pWin->drawable.height > h || pWin->drawable.width > w)
447	    shrunk = TRUE;
448
449	if (newx != oldx || newy != oldy)
450	    moved = TRUE;
451
452	if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
453	    HasBorder (pWin))
454	{
455	    borderVisible = RegionCreate(NullBox, 1);
456	    /* for tiled borders, we punt and draw the whole thing */
457	    if (pWin->borderIsPixel || !moved)
458	    {
459		if (shrunk || moved)
460		    RegionSubtract(borderVisible,
461					  &pWin->borderClip,
462					  &pWin->winSize);
463		else
464		    RegionCopy(borderVisible,
465					    &pWin->borderClip);
466	    }
467	}
468    }
469    pWin->origin.x = x + bw;
470    pWin->origin.y = y + bw;
471    pWin->drawable.height = h;
472    pWin->drawable.width = w;
473
474    x = pWin->drawable.x = newx;
475    y = pWin->drawable.y = newy;
476
477    SetWinSize (pWin);
478    SetBorderSize (pWin);
479
480    dw = (int)w - (int)width;
481    dh = (int)h - (int)height;
482    ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
483
484    /* let the hardware adjust background and border pixmaps, if any */
485    (*pScreen->PositionWindow)(pWin, x, y);
486
487    pFirstChange = MoveWindowInStack(pWin, pSib);
488
489    if (WasViewable)
490    {
491	pRegion = RegionCreate(NullBox, 1);
492
493	if (pLayerWin == pWin)
494	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
495						NULL);
496	else
497	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
498						NULL);
499
500	if (pWin->valdata)
501	{
502	    pWin->valdata->before.resized = TRUE;
503	    pWin->valdata->before.borderVisible = borderVisible;
504	}
505
506
507	if (anyMarked)
508	    (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther);
509	/*
510	 * the entire window is trashed unless bitGravity
511	 * recovers portions of it
512	 */
513	RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
514    }
515
516    GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
517
518    if (WasViewable)
519    {
520	/* avoid the border */
521	if (HasBorder (pWin))
522	{
523	    int	offx, offy, dx, dy;
524
525	    /* kruft to avoid double translates for each gravity */
526	    offx = 0;
527	    offy = 0;
528	    for (g = 0; g <= StaticGravity; g++)
529	    {
530		if (!gravitate[g])
531		    continue;
532
533		/* align winSize to gravitate[g].
534		 * winSize is in new coordinates,
535		 * gravitate[g] is still in old coordinates */
536		GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
537
538		dx = (oldx - nx) - offx;
539		dy = (oldy - ny) - offy;
540		if (dx || dy)
541		{
542		    RegionTranslate(&pWin->winSize, dx, dy);
543		    offx += dx;
544		    offy += dy;
545		}
546		RegionIntersect(gravitate[g], gravitate[g],
547				 &pWin->winSize);
548	    }
549	    /* get winSize back where it belongs */
550	    if (offx || offy)
551		RegionTranslate(&pWin->winSize, -offx, -offy);
552	}
553	/*
554	 * add screen bits to the appropriate bucket
555	 */
556
557	if (oldWinClip)
558	{
559	    /*
560	     * clip to new clipList
561	     */
562	    RegionCopy(pRegion, oldWinClip);
563	    RegionTranslate(pRegion, nx - oldx, ny - oldy);
564	    RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
565	    /*
566	     * don't step on any gravity bits which will be copied after this
567	     * region.	Note -- this assumes that the regions will be copied
568	     * in gravity order.
569	     */
570	    for (g = pWin->bitGravity + 1; g <= StaticGravity; g++)
571	    {
572		if (gravitate[g])
573		    RegionSubtract(oldWinClip, oldWinClip,
574					gravitate[g]);
575	    }
576	    RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
577	    g = pWin->bitGravity;
578	    if (!gravitate[g])
579		gravitate[g] = oldWinClip;
580	    else
581	    {
582		RegionUnion(gravitate[g], gravitate[g], oldWinClip);
583		RegionDestroy(oldWinClip);
584	    }
585	}
586
587	/*
588	 * move the bits on the screen
589	 */
590
591	destClip = NULL;
592
593	for (g = 0; g <= StaticGravity; g++)
594	{
595	    if (!gravitate[g])
596		continue;
597
598	    GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
599
600	    oldpt.x = oldx + (x - nx);
601	    oldpt.y = oldy + (y - ny);
602
603	    /* Note that gravitate[g] is *translated* by CopyWindow */
604
605	    /* only copy the remaining useful bits */
606
607	    RegionIntersect(gravitate[g], gravitate[g], oldRegion);
608
609	    /* clip to not overwrite already copied areas */
610
611	    if (destClip) {
612		RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
613		RegionSubtract(gravitate[g], gravitate[g], destClip);
614		RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
615	    }
616
617	    /* and move those bits */
618
619	    if (oldpt.x != x || oldpt.y != y
620#ifdef COMPOSITE
621		|| pWin->redirectDraw
622#endif
623		)
624	    {
625		(*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]);
626	    }
627
628	    /* remove any overwritten bits from the remaining useful bits */
629
630	    RegionSubtract(oldRegion, oldRegion, gravitate[g]);
631
632	    /*
633	     * recompute exposed regions of child windows
634	     */
635
636	    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
637	    {
638		if (pChild->winGravity != g)
639		    continue;
640		RegionIntersect(pRegion,
641				       &pChild->borderClip, gravitate[g]);
642		TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion);
643	    }
644
645	    /*
646	     * remove the successfully copied regions of the
647	     * window from its exposed region
648	     */
649
650	    if (g == pWin->bitGravity)
651		RegionSubtract(&pWin->valdata->after.exposed,
652				     &pWin->valdata->after.exposed, gravitate[g]);
653	    if (!destClip)
654		destClip = gravitate[g];
655	    else
656	    {
657		RegionUnion(destClip, destClip, gravitate[g]);
658		RegionDestroy(gravitate[g]);
659	    }
660	}
661
662	RegionDestroy(oldRegion);
663	RegionDestroy(pRegion);
664	if (destClip)
665	    RegionDestroy(destClip);
666	if (anyMarked)
667	    (*pScreen->HandleExposures)(pLayerWin->parent);
668	if (anyMarked && pScreen->PostValidateTree)
669	    (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange,
670					  VTOther);
671    }
672    if (pWin->realized)
673	WindowsRestructured ();
674}
675
676WindowPtr
677miGetLayerWindow(WindowPtr pWin)
678{
679    return pWin->firstChild;
680}
681
682/******
683 *
684 * miSetShape
685 *    The border/window shape has changed.  Recompute winSize/borderSize
686 *    and send appropriate exposure events
687 */
688
689void
690miSetShape(WindowPtr pWin, int kind)
691{
692    Bool        WasViewable = (Bool)(pWin->viewable);
693    ScreenPtr   pScreen = pWin->drawable.pScreen;
694    Bool        anyMarked = FALSE;
695    WindowPtr   pLayerWin;
696
697    if (kind != ShapeInput) {
698        if (WasViewable)
699        {
700            anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
701                                                          &pLayerWin);
702            if (pWin->valdata)
703            {
704                if (HasBorder (pWin))
705                {
706                    RegionPtr borderVisible;
707
708                    borderVisible = RegionCreate(NullBox, 1);
709                    RegionSubtract(borderVisible,
710                                    &pWin->borderClip, &pWin->winSize);
711                    pWin->valdata->before.borderVisible = borderVisible;
712                }
713                pWin->valdata->before.resized = TRUE;
714            }
715        }
716
717        SetWinSize (pWin);
718        SetBorderSize (pWin);
719
720        ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
721
722        if (WasViewable)
723        {
724            anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
725                                                           NULL);
726
727            if (anyMarked)
728                (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow,
729                                         VTOther);
730        }
731
732        if (WasViewable)
733        {
734            if (anyMarked)
735                (*pScreen->HandleExposures)(pLayerWin->parent);
736            if (anyMarked && pScreen->PostValidateTree)
737                (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow,
738                                             VTOther);
739        }
740    }
741    if (pWin->realized)
742        WindowsRestructured ();
743    CheckCursorConfinement(pWin);
744}
745
746/* Keeps the same inside(!) origin */
747
748void
749miChangeBorderWidth(WindowPtr pWin, unsigned int width)
750{
751    int oldwidth;
752    Bool anyMarked = FALSE;
753    ScreenPtr pScreen;
754    Bool WasViewable = (Bool)(pWin->viewable);
755    Bool HadBorder;
756    WindowPtr  pLayerWin;
757
758    oldwidth = wBorderWidth (pWin);
759    if (oldwidth == width)
760	return;
761    HadBorder = HasBorder(pWin);
762    pScreen = pWin->drawable.pScreen;
763    if (WasViewable && width < oldwidth)
764	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
765
766    pWin->borderWidth = width;
767    SetBorderSize (pWin);
768
769    if (WasViewable)
770    {
771	if (width > oldwidth)
772	{
773	    anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
774							  &pLayerWin);
775	    /*
776	     * save the old border visible region to correctly compute
777	     * borderExposed.
778	     */
779	    if (pWin->valdata && HadBorder)
780	    {
781		RegionPtr   borderVisible;
782		borderVisible = RegionCreate(NULL, 1);
783		RegionSubtract(borderVisible,
784				      &pWin->borderClip, &pWin->winSize);
785		pWin->valdata->before.borderVisible = borderVisible;
786	    }
787	}
788
789	if (anyMarked)
790	{
791	    (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
792	    (*pScreen->HandleExposures)(pLayerWin->parent);
793	}
794	if (anyMarked && pScreen->PostValidateTree)
795	    (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin,
796					  VTOther);
797    }
798    if (pWin->realized)
799	WindowsRestructured ();
800}
801
802void
803miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure)
804{
805    if ((pChild != pWin) || fromConfigure)
806    {
807	RegionEmpty(&pChild->clipList);
808	if (pChild->drawable.pScreen->ClipNotify)
809	    (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
810	RegionEmpty(&pChild->borderClip);
811    }
812}
813
814void
815miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
816{
817    WindowPtr pChild;
818
819    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
820    {
821	if (pChild->drawable.depth == depth)
822	    RegionUnion(pReg, pReg, &pChild->borderClip);
823
824	if (pChild->firstChild)
825	    miSegregateChildren(pChild, pReg, depth);
826    }
827}
828