825 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			825 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
| 
 | |
| /***********************************************************
 | |
| 
 | |
| Copyright 1987, 1998  The Open Group
 | |
| 
 | |
| Permission to use, copy, modify, distribute, and sell this software and its
 | |
| documentation for any purpose is hereby granted without fee, provided that
 | |
| the above copyright notice appear in all copies and that both that
 | |
| copyright notice and this permission notice appear in supporting
 | |
| documentation.
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in
 | |
| all copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | |
| OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | |
| AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| 
 | |
| Except as contained in this notice, the name of The Open Group shall not be
 | |
| used in advertising or otherwise to promote the sale, use or other dealings
 | |
| in this Software without prior written authorization from The Open Group.
 | |
| 
 | |
| 
 | |
| Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 | |
| 
 | |
|                         All Rights Reserved
 | |
| 
 | |
| Permission to use, copy, modify, and distribute this software and its 
 | |
| documentation for any purpose and without fee is hereby granted, 
 | |
| provided that the above copyright notice appear in all copies and that
 | |
| both that copyright notice and this permission notice appear in 
 | |
| supporting documentation, and that the name of Digital not be
 | |
| used in advertising or publicity pertaining to distribution of the
 | |
| software without specific, written prior permission.  
 | |
| 
 | |
| DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 | |
| ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 | |
| DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 | |
| ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 | |
| WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | |
| ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 | |
| SOFTWARE.
 | |
| 
 | |
| ******************************************************************/
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <X11/X.h>
 | |
| #include <X11/extensions/shapeconst.h>
 | |
| #include "regionstr.h"
 | |
| #include "region.h"
 | |
| #include "mi.h"
 | |
| #include "windowstr.h"
 | |
| #include "scrnintstr.h"
 | |
| #include "pixmapstr.h"
 | |
| #include "mivalidate.h"
 | |
| 
 | |
| void
 | |
| miClearToBackground(WindowPtr pWin,
 | |
|                     int x, int y, int w, int h,
 | |
|                     Bool generateExposures)
 | |
| {
 | |
|     BoxRec box;
 | |
|     RegionRec	reg;
 | |
|     BoxPtr  extents;
 | |
|     int	    x1, y1, x2, y2;
 | |
| 
 | |
|     /* compute everything using ints to avoid overflow */
 | |
| 
 | |
|     x1 = pWin->drawable.x + x;
 | |
|     y1 = pWin->drawable.y + y;
 | |
|     if (w)
 | |
|         x2 = x1 + (int) w;
 | |
|     else
 | |
|         x2 = x1 + (int) pWin->drawable.width - (int) x;
 | |
|     if (h)
 | |
|         y2 = y1 + h;	
 | |
|     else
 | |
|         y2 = y1 + (int) pWin->drawable.height - (int) y;
 | |
| 
 | |
|     extents = &pWin->clipList.extents;
 | |
|     
 | |
|     /* clip the resulting rectangle to the window clipList extents.  This
 | |
|      * makes sure that the result will fit in a box, given that the
 | |
|      * screen is < 32768 on a side.
 | |
|      */
 | |
| 
 | |
|     if (x1 < extents->x1)
 | |
| 	x1 = extents->x1;
 | |
|     if (x2 > extents->x2)
 | |
| 	x2 = extents->x2;
 | |
|     if (y1 < extents->y1)
 | |
| 	y1 = extents->y1;
 | |
|     if (y2 > extents->y2)
 | |
| 	y2 = extents->y2;
 | |
| 
 | |
|     if (x2 <= x1 || y2 <= y1)
 | |
|     {
 | |
| 	x2 = x1 = 0;
 | |
| 	y2 = y1 = 0;
 | |
|     }
 | |
| 
 | |
|     box.x1 = x1;
 | |
|     box.x2 = x2;
 | |
|     box.y1 = y1;
 | |
|     box.y2 = y2;
 | |
| 
 | |
|     RegionInit(®, &box, 1);
 | |
| 
 | |
|     RegionIntersect(®, ®, &pWin->clipList);
 | |
|     if (generateExposures)
 | |
| 	(*pWin->drawable.pScreen->WindowExposures)(pWin, ®, NULL);
 | |
|     else if (pWin->backgroundState != None)
 | |
| 	miPaintWindow(pWin, ®, PW_BACKGROUND);
 | |
|     RegionUninit(®);
 | |
| }
 | |
| 
 | |
| void
 | |
| miMarkWindow(WindowPtr pWin)
 | |
| {
 | |
|     ValidatePtr val;
 | |
| 
 | |
|     if (pWin->valdata)
 | |
| 	return;
 | |
|     val = (ValidatePtr)xnfalloc(sizeof(ValidateRec));
 | |
|     val->before.oldAbsCorner.x = pWin->drawable.x;
 | |
|     val->before.oldAbsCorner.y = pWin->drawable.y;
 | |
|     val->before.borderVisible = NullRegion;
 | |
|     val->before.resized = FALSE;
 | |
|     pWin->valdata = val;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
 | |
| {
 | |
|     BoxPtr box;
 | |
|     WindowPtr pChild, pLast;
 | |
|     Bool anyMarked = FALSE;
 | |
|     MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow;
 | |
| 
 | |
|     /* single layered systems are easy */
 | |
|     if (ppLayerWin) *ppLayerWin = pWin;
 | |
| 
 | |
|     if (pWin == pFirst)
 | |
|     {
 | |
| 	/* Blindly mark pWin and all of its inferiors.	 This is a slight
 | |
| 	 * overkill if there are mapped windows that outside pWin's border,
 | |
| 	 * but it's better than wasting time on RectIn checks.
 | |
| 	 */
 | |
| 	pChild = pWin;
 | |
| 	while (1)
 | |
| 	{
 | |
| 	    if (pChild->viewable)
 | |
| 	    {
 | |
| 		if (RegionBroken(&pChild->winSize))
 | |
| 		    SetWinSize (pChild);
 | |
| 		if (RegionBroken(&pChild->borderSize))
 | |
| 		    SetBorderSize (pChild);
 | |
| 		(* MarkWindow)(pChild);
 | |
| 		if (pChild->firstChild)
 | |
| 		{
 | |
| 		    pChild = pChild->firstChild;
 | |
| 		    continue;
 | |
| 		}
 | |
| 	    }
 | |
| 	    while (!pChild->nextSib && (pChild != pWin))
 | |
| 		pChild = pChild->parent;
 | |
| 	    if (pChild == pWin)
 | |
| 		break;
 | |
| 	    pChild = pChild->nextSib;
 | |
| 	}
 | |
| 	anyMarked = TRUE;
 | |
| 	pFirst = pFirst->nextSib;
 | |
|     }
 | |
|     if ( (pChild = pFirst) )
 | |
|     {
 | |
| 	box = RegionExtents(&pWin->borderSize);
 | |
| 	pLast = pChild->parent->lastChild;
 | |
| 	while (1)
 | |
| 	{
 | |
| 	    if (pChild->viewable)
 | |
| 	    {
 | |
| 		if (RegionBroken(&pChild->winSize))
 | |
| 		    SetWinSize (pChild);
 | |
| 		if (RegionBroken(&pChild->borderSize))
 | |
| 		    SetBorderSize (pChild);
 | |
| 		if (RegionContainsRect(&pChild->borderSize, box))
 | |
| 		{
 | |
| 		    (* MarkWindow)(pChild);
 | |
| 		    anyMarked = TRUE;
 | |
| 		    if (pChild->firstChild)
 | |
| 		    {
 | |
| 			pChild = pChild->firstChild;
 | |
| 			continue;
 | |
| 		    }
 | |
| 		}
 | |
| 	    }
 | |
| 	    while (!pChild->nextSib && (pChild != pLast))
 | |
| 		pChild = pChild->parent;
 | |
| 	    if (pChild == pLast)
 | |
| 		break;
 | |
| 	    pChild = pChild->nextSib;
 | |
| 	}
 | |
|     }
 | |
|     if (anyMarked)
 | |
| 	(* MarkWindow)(pWin->parent);
 | |
|     return anyMarked;
 | |
| }
 | |
| 
 | |
| /*****
 | |
|  *  miHandleValidateExposures(pWin)
 | |
|  *    starting at pWin, draw background in any windows that have exposure
 | |
|  *    regions, translate the regions, restore any backing store,
 | |
|  *    and then send any regions still exposed to the client
 | |
|  *****/
 | |
| void
 | |
| miHandleValidateExposures(WindowPtr pWin)
 | |
| {
 | |
|     WindowPtr pChild;
 | |
|     ValidatePtr val;
 | |
|     WindowExposuresProcPtr WindowExposures;
 | |
| 
 | |
|     pChild = pWin;
 | |
|     WindowExposures = pChild->drawable.pScreen->WindowExposures;
 | |
|     while (1)
 | |
|     {
 | |
| 	if ( (val = pChild->valdata) )
 | |
| 	{
 | |
| 	    if (RegionNotEmpty(&val->after.borderExposed))
 | |
| 		miPaintWindow(pChild, &val->after.borderExposed, PW_BORDER);
 | |
| 	    RegionUninit(&val->after.borderExposed);
 | |
| 	    (*WindowExposures)(pChild, &val->after.exposed, NullRegion);
 | |
| 	    RegionUninit(&val->after.exposed);
 | |
| 	    free(val);
 | |
| 	    pChild->valdata = NULL;
 | |
| 	    if (pChild->firstChild)
 | |
| 	    {
 | |
| 		pChild = pChild->firstChild;
 | |
| 		continue;
 | |
| 	    }
 | |
| 	}
 | |
| 	while (!pChild->nextSib && (pChild != pWin))
 | |
| 	    pChild = pChild->parent;
 | |
| 	if (pChild == pWin)
 | |
| 	    break;
 | |
| 	pChild = pChild->nextSib;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| miMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pNextSib, VTKind kind)
 | |
| {
 | |
|     WindowPtr pParent;
 | |
|     Bool WasViewable = (Bool)(pWin->viewable);
 | |
|     short bw;
 | |
|     RegionPtr oldRegion = NULL;
 | |
|     DDXPointRec oldpt;
 | |
|     Bool anyMarked = FALSE;
 | |
|     ScreenPtr pScreen;
 | |
|     WindowPtr windowToValidate;
 | |
|     WindowPtr pLayerWin;
 | |
| 
 | |
|     /* if this is a root window, can't be moved */
 | |
|     if (!(pParent = pWin->parent))
 | |
|        return ;
 | |
|     pScreen = pWin->drawable.pScreen;
 | |
|     bw = wBorderWidth (pWin);
 | |
| 
 | |
|     oldpt.x = pWin->drawable.x;
 | |
|     oldpt.y = pWin->drawable.y;
 | |
|     if (WasViewable)
 | |
|     {
 | |
| 	oldRegion = RegionCreate(NullBox, 1);
 | |
| 	RegionCopy(oldRegion, &pWin->borderClip);
 | |
| 	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
 | |
|     }
 | |
|     pWin->origin.x = x + (int)bw;
 | |
|     pWin->origin.y = y + (int)bw;
 | |
|     x = pWin->drawable.x = pParent->drawable.x + x + (int)bw;
 | |
|     y = pWin->drawable.y = pParent->drawable.y + y + (int)bw;
 | |
| 
 | |
|     SetWinSize (pWin);
 | |
|     SetBorderSize (pWin);
 | |
| 
 | |
|     (*pScreen->PositionWindow)(pWin, x, y);
 | |
| 
 | |
|     windowToValidate = MoveWindowInStack(pWin, pNextSib);
 | |
| 
 | |
|     ResizeChildrenWinSize(pWin, x - oldpt.x, y - oldpt.y, 0, 0);
 | |
| 
 | |
|     if (WasViewable)
 | |
|     {
 | |
| 	if (pLayerWin == pWin)
 | |
| 	    anyMarked |= (*pScreen->MarkOverlappedWindows)
 | |
| 				(pWin, windowToValidate, NULL);
 | |
| 	else
 | |
| 	    anyMarked |= (*pScreen->MarkOverlappedWindows)
 | |
| 				(pWin, pLayerWin, NULL);
 | |
| 
 | |
| 
 | |
| 	if (anyMarked)
 | |
| 	{
 | |
| 	    (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow, kind);
 | |
| 	    (* pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, oldRegion);
 | |
| 	    RegionDestroy(oldRegion);
 | |
| 	    /* XXX need to retile border if ParentRelative origin */
 | |
| 	    (*pScreen->HandleExposures)(pLayerWin->parent);
 | |
| 	}
 | |
| 	if (anyMarked && pScreen->PostValidateTree)
 | |
| 	    (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow, kind);
 | |
|     }
 | |
|     if (pWin->realized)
 | |
| 	WindowsRestructured ();
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * pValid is a region of the screen which has been
 | |
|  * successfully copied -- recomputed exposed regions for affected windows
 | |
|  */
 | |
| 
 | |
| static int
 | |
| miRecomputeExposures (
 | |
|     WindowPtr	pWin,
 | |
|     pointer		value) /* must conform to VisitWindowProcPtr */
 | |
| {
 | |
|     RegionPtr	pValid = (RegionPtr)value;
 | |
| 
 | |
|     if (pWin->valdata)
 | |
|     {
 | |
| #ifdef COMPOSITE
 | |
| 	/*
 | |
| 	 * Redirected windows are not affected by parent window
 | |
| 	 * gravity manipulations, so don't recompute their
 | |
| 	 * exposed areas here.
 | |
| 	 */
 | |
| 	if (pWin->redirectDraw != RedirectDrawNone)
 | |
| 	    return WT_DONTWALKCHILDREN;
 | |
| #endif
 | |
| 	/*
 | |
| 	 * compute exposed regions of this window
 | |
| 	 */
 | |
| 	RegionSubtract(&pWin->valdata->after.exposed,
 | |
| 			&pWin->clipList, pValid);
 | |
| 	/*
 | |
| 	 * compute exposed regions of the border
 | |
| 	 */
 | |
| 	RegionSubtract(&pWin->valdata->after.borderExposed,
 | |
| 			     &pWin->borderClip, &pWin->winSize);
 | |
| 	RegionSubtract(&pWin->valdata->after.borderExposed,
 | |
| 			     &pWin->valdata->after.borderExposed, pValid);
 | |
| 	return WT_WALKCHILDREN;
 | |
|     }
 | |
|     return WT_NOMATCH;
 | |
| }
 | |
| 
 | |
| void
 | |
| miSlideAndSizeWindow(WindowPtr pWin,
 | |
|                      int x, int y,
 | |
|                      unsigned int w, unsigned int h,
 | |
|                      WindowPtr pSib)
 | |
| {
 | |
|     WindowPtr pParent;
 | |
|     Bool WasViewable = (Bool)(pWin->viewable);
 | |
|     unsigned short width = pWin->drawable.width,
 | |
| 		   height = pWin->drawable.height;
 | |
|     short oldx = pWin->drawable.x,
 | |
| 	  oldy = pWin->drawable.y;
 | |
|     int bw = wBorderWidth (pWin);
 | |
|     short dw, dh;
 | |
|     DDXPointRec oldpt;
 | |
|     RegionPtr oldRegion = NULL;
 | |
|     Bool anyMarked = FALSE;
 | |
|     ScreenPtr pScreen;
 | |
|     WindowPtr pFirstChange;
 | |
|     WindowPtr pChild;
 | |
|     RegionPtr	gravitate[StaticGravity + 1];
 | |
|     unsigned g;
 | |
|     int		nx, ny;		/* destination x,y */
 | |
|     int		newx, newy;	/* new inner window position */
 | |
|     RegionPtr	pRegion = NULL;
 | |
|     RegionPtr	destClip;	/* portions of destination already written */
 | |
|     RegionPtr	oldWinClip = NULL;	/* old clip list for window */
 | |
|     RegionPtr	borderVisible = NullRegion; /* visible area of the border */
 | |
|     Bool	shrunk = FALSE; /* shrunk in an inner dimension */
 | |
|     Bool	moved = FALSE;	/* window position changed */
 | |
|     WindowPtr  pLayerWin;
 | |
| 
 | |
|     /* if this is a root window, can't be resized */
 | |
|     if (!(pParent = pWin->parent))
 | |
| 	return ;
 | |
| 
 | |
|     pScreen = pWin->drawable.pScreen;
 | |
|     newx = pParent->drawable.x + x + bw;
 | |
|     newy = pParent->drawable.y + y + bw;
 | |
|     if (WasViewable)
 | |
|     {
 | |
| 	anyMarked = FALSE;
 | |
| 	/*
 | |
| 	 * save the visible region of the window
 | |
| 	 */
 | |
| 	oldRegion = RegionCreate(NullBox, 1);
 | |
| 	RegionCopy(oldRegion, &pWin->winSize);
 | |
| 
 | |
| 	/*
 | |
| 	 * categorize child windows into regions to be moved
 | |
| 	 */
 | |
| 	for (g = 0; g <= StaticGravity; g++)
 | |
| 	    gravitate[g] = (RegionPtr) NULL;
 | |
| 	for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
 | |
| 	{
 | |
| 	    g = pChild->winGravity;
 | |
| 	    if (g != UnmapGravity)
 | |
| 	    {
 | |
| 		if (!gravitate[g])
 | |
| 		    gravitate[g] = RegionCreate(NullBox, 1);
 | |
| 		RegionUnion(gravitate[g],
 | |
| 				   gravitate[g], &pChild->borderClip);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		UnmapWindow(pChild, TRUE);
 | |
| 		anyMarked = TRUE;
 | |
| 	    }
 | |
| 	}
 | |
| 	anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin, 
 | |
| 						       &pLayerWin);
 | |
| 
 | |
| 	oldWinClip = NULL;
 | |
| 	if (pWin->bitGravity != ForgetGravity)
 | |
| 	{
 | |
| 	    oldWinClip = RegionCreate(NullBox, 1);
 | |
| 	    RegionCopy(oldWinClip, &pWin->clipList);
 | |
| 	}
 | |
| 	/*
 | |
| 	 * if the window is changing size, borderExposed
 | |
| 	 * can't be computed correctly without some help.
 | |
| 	 */
 | |
| 	if (pWin->drawable.height > h || pWin->drawable.width > w)
 | |
| 	    shrunk = TRUE;
 | |
| 
 | |
| 	if (newx != oldx || newy != oldy)
 | |
| 	    moved = TRUE;
 | |
| 
 | |
| 	if ((pWin->drawable.height != h || pWin->drawable.width != w) &&
 | |
| 	    HasBorder (pWin))
 | |
| 	{
 | |
| 	    borderVisible = RegionCreate(NullBox, 1);
 | |
| 	    /* for tiled borders, we punt and draw the whole thing */
 | |
| 	    if (pWin->borderIsPixel || !moved)
 | |
| 	    {
 | |
| 		if (shrunk || moved)
 | |
| 		    RegionSubtract(borderVisible,
 | |
| 					  &pWin->borderClip,
 | |
| 					  &pWin->winSize);
 | |
| 		else
 | |
| 		    RegionCopy(borderVisible,
 | |
| 					    &pWin->borderClip);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     pWin->origin.x = x + bw;
 | |
|     pWin->origin.y = y + bw;
 | |
|     pWin->drawable.height = h;
 | |
|     pWin->drawable.width = w;
 | |
| 
 | |
|     x = pWin->drawable.x = newx;
 | |
|     y = pWin->drawable.y = newy;
 | |
| 
 | |
|     SetWinSize (pWin);
 | |
|     SetBorderSize (pWin);
 | |
| 
 | |
|     dw = (int)w - (int)width;
 | |
|     dh = (int)h - (int)height;
 | |
|     ResizeChildrenWinSize(pWin, x - oldx, y - oldy, dw, dh);
 | |
| 
 | |
|     /* let the hardware adjust background and border pixmaps, if any */
 | |
|     (*pScreen->PositionWindow)(pWin, x, y);
 | |
| 
 | |
|     pFirstChange = MoveWindowInStack(pWin, pSib);
 | |
| 
 | |
|     if (WasViewable)
 | |
|     {
 | |
| 	pRegion = RegionCreate(NullBox, 1);
 | |
| 
 | |
| 	if (pLayerWin == pWin)
 | |
| 	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pFirstChange,
 | |
| 						NULL);
 | |
| 	else
 | |
| 	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pLayerWin,
 | |
| 						NULL);
 | |
| 
 | |
| 	if (pWin->valdata)
 | |
| 	{
 | |
| 	    pWin->valdata->before.resized = TRUE;
 | |
| 	    pWin->valdata->before.borderVisible = borderVisible;
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	if (anyMarked)
 | |
| 	    (*pScreen->ValidateTree)(pLayerWin->parent, pFirstChange, VTOther);
 | |
| 	/*
 | |
| 	 * the entire window is trashed unless bitGravity
 | |
| 	 * recovers portions of it
 | |
| 	 */
 | |
| 	RegionCopy(&pWin->valdata->after.exposed, &pWin->clipList);
 | |
|     }
 | |
| 
 | |
|     GravityTranslate (x, y, oldx, oldy, dw, dh, pWin->bitGravity, &nx, &ny);
 | |
| 
 | |
|     if (WasViewable)
 | |
|     {
 | |
| 	/* avoid the border */
 | |
| 	if (HasBorder (pWin))
 | |
| 	{
 | |
| 	    int	offx, offy, dx, dy;
 | |
| 
 | |
| 	    /* kruft to avoid double translates for each gravity */
 | |
| 	    offx = 0;
 | |
| 	    offy = 0;
 | |
| 	    for (g = 0; g <= StaticGravity; g++)
 | |
| 	    {
 | |
| 		if (!gravitate[g])
 | |
| 		    continue;
 | |
| 
 | |
| 		/* align winSize to gravitate[g].
 | |
| 		 * winSize is in new coordinates,
 | |
| 		 * gravitate[g] is still in old coordinates */
 | |
| 		GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
 | |
| 		
 | |
| 		dx = (oldx - nx) - offx;
 | |
| 		dy = (oldy - ny) - offy;
 | |
| 		if (dx || dy)
 | |
| 		{
 | |
| 		    RegionTranslate(&pWin->winSize, dx, dy);
 | |
| 		    offx += dx;
 | |
| 		    offy += dy;
 | |
| 		}
 | |
| 		RegionIntersect(gravitate[g], gravitate[g],
 | |
| 				 &pWin->winSize);
 | |
| 	    }
 | |
| 	    /* get winSize back where it belongs */
 | |
| 	    if (offx || offy)
 | |
| 		RegionTranslate(&pWin->winSize, -offx, -offy);
 | |
| 	}
 | |
| 	/*
 | |
| 	 * add screen bits to the appropriate bucket
 | |
| 	 */
 | |
| 
 | |
| 	if (oldWinClip)
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * clip to new clipList
 | |
| 	     */
 | |
| 	    RegionCopy(pRegion, oldWinClip);
 | |
| 	    RegionTranslate(pRegion, nx - oldx, ny - oldy);
 | |
| 	    RegionIntersect(oldWinClip, pRegion, &pWin->clipList);
 | |
| 	    /*
 | |
| 	     * don't step on any gravity bits which will be copied after this
 | |
| 	     * region.	Note -- this assumes that the regions will be copied
 | |
| 	     * in gravity order.
 | |
| 	     */
 | |
| 	    for (g = pWin->bitGravity + 1; g <= StaticGravity; g++)
 | |
| 	    {
 | |
| 		if (gravitate[g])
 | |
| 		    RegionSubtract(oldWinClip, oldWinClip,
 | |
| 					gravitate[g]);
 | |
| 	    }
 | |
| 	    RegionTranslate(oldWinClip, oldx - nx, oldy - ny);
 | |
| 	    g = pWin->bitGravity;
 | |
| 	    if (!gravitate[g])
 | |
| 		gravitate[g] = oldWinClip;
 | |
| 	    else
 | |
| 	    {
 | |
| 		RegionUnion(gravitate[g], gravitate[g], oldWinClip);
 | |
| 		RegionDestroy(oldWinClip);
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * move the bits on the screen
 | |
| 	 */
 | |
| 
 | |
| 	destClip = NULL;
 | |
| 
 | |
| 	for (g = 0; g <= StaticGravity; g++)
 | |
| 	{
 | |
| 	    if (!gravitate[g])
 | |
| 		continue;
 | |
| 
 | |
| 	    GravityTranslate (x, y, oldx, oldy, dw, dh, g, &nx, &ny);
 | |
| 
 | |
| 	    oldpt.x = oldx + (x - nx);
 | |
| 	    oldpt.y = oldy + (y - ny);
 | |
| 
 | |
| 	    /* Note that gravitate[g] is *translated* by CopyWindow */
 | |
| 
 | |
| 	    /* only copy the remaining useful bits */
 | |
| 
 | |
| 	    RegionIntersect(gravitate[g], gravitate[g], oldRegion);
 | |
| 
 | |
| 	    /* clip to not overwrite already copied areas */
 | |
| 
 | |
| 	    if (destClip) {
 | |
| 		RegionTranslate(destClip, oldpt.x - x, oldpt.y - y);
 | |
| 		RegionSubtract(gravitate[g], gravitate[g], destClip);
 | |
| 		RegionTranslate(destClip, x - oldpt.x, y - oldpt.y);
 | |
| 	    }
 | |
| 
 | |
| 	    /* and move those bits */
 | |
| 
 | |
| 	    if (oldpt.x != x || oldpt.y != y
 | |
| #ifdef COMPOSITE
 | |
| 		|| pWin->redirectDraw
 | |
| #endif
 | |
| 		)
 | |
| 	    {
 | |
| 		(*pWin->drawable.pScreen->CopyWindow)(pWin, oldpt, gravitate[g]);
 | |
| 	    }
 | |
| 
 | |
| 	    /* remove any overwritten bits from the remaining useful bits */
 | |
| 
 | |
| 	    RegionSubtract(oldRegion, oldRegion, gravitate[g]);
 | |
| 
 | |
| 	    /*
 | |
| 	     * recompute exposed regions of child windows
 | |
| 	     */
 | |
| 	
 | |
| 	    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
 | |
| 	    {
 | |
| 		if (pChild->winGravity != g)
 | |
| 		    continue;
 | |
| 		RegionIntersect(pRegion,
 | |
| 				       &pChild->borderClip, gravitate[g]);
 | |
| 		TraverseTree (pChild, miRecomputeExposures, (pointer)pRegion);
 | |
| 	    }
 | |
| 
 | |
| 	    /*
 | |
| 	     * remove the successfully copied regions of the
 | |
| 	     * window from its exposed region
 | |
| 	     */
 | |
| 
 | |
| 	    if (g == pWin->bitGravity)
 | |
| 		RegionSubtract(&pWin->valdata->after.exposed,
 | |
| 				     &pWin->valdata->after.exposed, gravitate[g]);
 | |
| 	    if (!destClip)
 | |
| 		destClip = gravitate[g];
 | |
| 	    else
 | |
| 	    {
 | |
| 		RegionUnion(destClip, destClip, gravitate[g]);
 | |
| 		RegionDestroy(gravitate[g]);
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	RegionDestroy(oldRegion);
 | |
| 	RegionDestroy(pRegion);
 | |
| 	if (destClip)
 | |
| 	    RegionDestroy(destClip);
 | |
| 	if (anyMarked)
 | |
| 	    (*pScreen->HandleExposures)(pLayerWin->parent);
 | |
| 	if (anyMarked && pScreen->PostValidateTree)
 | |
| 	    (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange,
 | |
| 					  VTOther);
 | |
|     }
 | |
|     if (pWin->realized)
 | |
| 	WindowsRestructured ();
 | |
| }
 | |
| 
 | |
| WindowPtr
 | |
| miGetLayerWindow(WindowPtr pWin)
 | |
| {
 | |
|     return pWin->firstChild;
 | |
| }
 | |
| 
 | |
| /******
 | |
|  *
 | |
|  * miSetShape
 | |
|  *    The border/window shape has changed.  Recompute winSize/borderSize
 | |
|  *    and send appropriate exposure events
 | |
|  */
 | |
| 
 | |
| void
 | |
| miSetShape(WindowPtr pWin, int kind)
 | |
| {
 | |
|     Bool        WasViewable = (Bool)(pWin->viewable);
 | |
|     ScreenPtr   pScreen = pWin->drawable.pScreen;
 | |
|     Bool        anyMarked = FALSE;
 | |
|     WindowPtr   pLayerWin;
 | |
| 
 | |
|     if (kind != ShapeInput) {
 | |
|         if (WasViewable)
 | |
|         {
 | |
|             anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
 | |
|                                                           &pLayerWin);
 | |
|             if (pWin->valdata)
 | |
|             {
 | |
|                 if (HasBorder (pWin))
 | |
|                 {
 | |
|                     RegionPtr borderVisible;
 | |
| 
 | |
|                     borderVisible = RegionCreate(NullBox, 1);
 | |
|                     RegionSubtract(borderVisible,
 | |
|                                     &pWin->borderClip, &pWin->winSize);
 | |
|                     pWin->valdata->before.borderVisible = borderVisible;
 | |
|                 }
 | |
|                 pWin->valdata->before.resized = TRUE;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         SetWinSize (pWin);
 | |
|         SetBorderSize (pWin);
 | |
| 
 | |
|         ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
 | |
| 
 | |
|         if (WasViewable)
 | |
|         {
 | |
|             anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin, pWin,
 | |
|                                                            NULL);
 | |
| 
 | |
|             if (anyMarked)
 | |
|                 (*pScreen->ValidateTree)(pLayerWin->parent, NullWindow,
 | |
|                                          VTOther);
 | |
|         }
 | |
| 
 | |
|         if (WasViewable)
 | |
|         {
 | |
|             if (anyMarked)
 | |
|                 (*pScreen->HandleExposures)(pLayerWin->parent);
 | |
|             if (anyMarked && pScreen->PostValidateTree)
 | |
|                 (*pScreen->PostValidateTree)(pLayerWin->parent, NullWindow,
 | |
|                                              VTOther);
 | |
|         }
 | |
|     }
 | |
|     if (pWin->realized)
 | |
|         WindowsRestructured ();
 | |
|     CheckCursorConfinement(pWin);
 | |
| }
 | |
| 
 | |
| /* Keeps the same inside(!) origin */
 | |
| 
 | |
| void
 | |
| miChangeBorderWidth(WindowPtr pWin, unsigned int width)
 | |
| {
 | |
|     int oldwidth;
 | |
|     Bool anyMarked = FALSE;
 | |
|     ScreenPtr pScreen;
 | |
|     Bool WasViewable = (Bool)(pWin->viewable);
 | |
|     Bool HadBorder;
 | |
|     WindowPtr  pLayerWin;
 | |
| 
 | |
|     oldwidth = wBorderWidth (pWin);
 | |
|     if (oldwidth == width)
 | |
| 	return;
 | |
|     HadBorder = HasBorder(pWin);
 | |
|     pScreen = pWin->drawable.pScreen;
 | |
|     if (WasViewable && width < oldwidth)
 | |
| 	anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
 | |
| 
 | |
|     pWin->borderWidth = width;
 | |
|     SetBorderSize (pWin);
 | |
| 
 | |
|     if (WasViewable)
 | |
|     {
 | |
| 	if (width > oldwidth)
 | |
| 	{
 | |
| 	    anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
 | |
| 							  &pLayerWin);
 | |
| 	    /*
 | |
| 	     * save the old border visible region to correctly compute
 | |
| 	     * borderExposed.
 | |
| 	     */
 | |
| 	    if (pWin->valdata && HadBorder)
 | |
| 	    {
 | |
| 		RegionPtr   borderVisible;
 | |
| 		borderVisible = RegionCreate(NULL, 1);
 | |
| 		RegionSubtract(borderVisible,
 | |
| 				      &pWin->borderClip, &pWin->winSize);
 | |
| 		pWin->valdata->before.borderVisible = borderVisible;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	if (anyMarked)
 | |
| 	{
 | |
| 	    (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
 | |
| 	    (*pScreen->HandleExposures)(pLayerWin->parent);
 | |
| 	}
 | |
| 	if (anyMarked && pScreen->PostValidateTree)
 | |
| 	    (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin,
 | |
| 					  VTOther);
 | |
|     }
 | |
|     if (pWin->realized)
 | |
| 	WindowsRestructured ();
 | |
| }
 | |
| 
 | |
| void
 | |
| miMarkUnrealizedWindow(WindowPtr pChild, WindowPtr pWin, Bool fromConfigure)
 | |
| {
 | |
|     if ((pChild != pWin) || fromConfigure)
 | |
|     {
 | |
| 	RegionEmpty(&pChild->clipList);
 | |
| 	if (pChild->drawable.pScreen->ClipNotify)
 | |
| 	    (* pChild->drawable.pScreen->ClipNotify)(pChild, 0, 0);
 | |
| 	RegionEmpty(&pChild->borderClip);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth)
 | |
| {
 | |
|     WindowPtr pChild;
 | |
| 
 | |
|     for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
 | |
|     {
 | |
| 	if (pChild->drawable.depth == depth)
 | |
| 	    RegionUnion(pReg, pReg, &pChild->borderClip);
 | |
| 
 | |
| 	if (pChild->firstChild)
 | |
| 	    miSegregateChildren(pChild, pReg, depth);
 | |
|     }
 | |
| }
 |