Home | History | Annotate | Line # | Download | only in mi
      1 
      2 /***********************************************************
      3 
      4 Copyright 1987, 1998  The Open Group
      5 
      6 Permission to use, copy, modify, distribute, and sell this software and its
      7 documentation for any purpose is hereby granted without fee, provided that
      8 the above copyright notice appear in all copies and that both that
      9 copyright notice and this permission notice appear in supporting
     10 documentation.
     11 
     12 The above copyright notice and this permission notice shall be included in
     13 all copies or substantial portions of the Software.
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21 
     22 Except as contained in this notice, the name of The Open Group shall not be
     23 used in advertising or otherwise to promote the sale, use or other dealings
     24 in this Software without prior written authorization from The Open Group.
     25 
     26 
     27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
     28 
     29                         All Rights Reserved
     30 
     31 Permission to use, copy, modify, and distribute this software and its
     32 documentation for any purpose and without fee is hereby granted,
     33 provided that the above copyright notice appear in all copies and that
     34 both that copyright notice and this permission notice appear in
     35 supporting documentation, and that the name of Digital not be
     36 used in advertising or publicity pertaining to distribution of the
     37 software without specific, written prior permission.
     38 
     39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     45 SOFTWARE.
     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 
     62 void
     63 miClearToBackground(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 
    122 void
    123 miMarkWindow(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 
    137 Bool
    138 miMarkOverlappedWindows(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  *****/
    220 void
    221 miHandleValidateExposures(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 
    254 void
    255 miMoveWindow(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 
    326 static int
    327 miRecomputeExposures (
    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 
    361 void
    362 miSlideAndSizeWindow(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 
    673 WindowPtr
    674 miGetLayerWindow(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 
    686 void
    687 miSetShape(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 
    745 void
    746 miChangeBorderWidth(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 
    799 void
    800 miMarkUnrealizedWindow(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 
    811 void
    812 miSegregateChildren(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