Example #1
0
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 = REGION_CREATE(pScreen, NullBox, 1);
	REGION_COPY(pScreen, 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] = REGION_CREATE(pScreen, NullBox, 1);
		REGION_UNION(pScreen, 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 = REGION_CREATE(pScreen, NullBox, 1);
	    REGION_COPY(pScreen, 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 = REGION_CREATE(pScreen, NullBox, 1);
	    /* for tiled borders, we punt and draw the whole thing */
	    if (pWin->borderIsPixel || !moved)
	    {
		if (shrunk || moved)
		    REGION_SUBTRACT(pScreen, borderVisible,
					  &pWin->borderClip,
					  &pWin->winSize);
		else
		    REGION_COPY(pScreen, 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 = REGION_CREATE(pScreen, 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
	 */
	REGION_COPY(pScreen, &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)
		{
		    REGION_TRANSLATE(pScreen, &pWin->winSize, dx, dy);
		    offx += dx;
		    offy += dy;
		}
		REGION_INTERSECT(pScreen, gravitate[g], gravitate[g],
				 &pWin->winSize);
	    }
	    /* get winSize back where it belongs */
	    if (offx || offy)
		REGION_TRANSLATE(pScreen, &pWin->winSize, -offx, -offy);
	}
	/*
	 * add screen bits to the appropriate bucket
	 */

	if (oldWinClip)
	{
	    /*
	     * clip to new clipList
	     */
	    REGION_COPY(pScreen, pRegion, oldWinClip);
	    REGION_TRANSLATE(pScreen, pRegion, nx - oldx, ny - oldy);
	    REGION_INTERSECT(pScreen, 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])
		    REGION_SUBTRACT(pScreen, oldWinClip, oldWinClip,
					gravitate[g]);
	    }
	    REGION_TRANSLATE(pScreen, oldWinClip, oldx - nx, oldy - ny);
	    g = pWin->bitGravity;
	    if (!gravitate[g])
		gravitate[g] = oldWinClip;
	    else
	    {
		REGION_UNION(pScreen, gravitate[g], gravitate[g], oldWinClip);
		REGION_DESTROY(pScreen, 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 */

	    REGION_INTERSECT(pScreen, gravitate[g], gravitate[g], oldRegion);

	    /* clip to not overwrite already copied areas */

	    if (destClip) {
		REGION_TRANSLATE(pScreen, destClip, oldpt.x - x, oldpt.y - y);
		REGION_SUBTRACT(pScreen, gravitate[g], gravitate[g], destClip);
		REGION_TRANSLATE(pScreen, 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 */

	    REGION_SUBTRACT(pScreen, oldRegion, oldRegion, gravitate[g]);

	    /*
	     * recompute exposed regions of child windows
	     */
	
	    for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
	    {
		if (pChild->winGravity != g)
		    continue;
		REGION_INTERSECT(pScreen, 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)
		REGION_SUBTRACT(pScreen, &pWin->valdata->after.exposed,
				     &pWin->valdata->after.exposed, gravitate[g]);
	    if (!destClip)
		destClip = gravitate[g];
	    else
	    {
		REGION_UNION(pScreen, destClip, destClip, gravitate[g]);
		REGION_DESTROY(pScreen, gravitate[g]);
	    }
	}

	REGION_DESTROY(pScreen, oldRegion);
	REGION_DESTROY(pScreen, pRegion);
	if (destClip)
	    REGION_DESTROY(pScreen, destClip);
	if (anyMarked)
	    (*pScreen->HandleExposures)(pLayerWin->parent);
	if (anyMarked && pScreen->PostValidateTree)
	    (*pScreen->PostValidateTree)(pLayerWin->parent, pFirstChange,
					  VTOther);
    }
    if (pWin->realized)
	WindowsRestructured ();
}
Example #2
0
static Bool
miDbePositionWindow(WindowPtr pWin, int x, int y)
{
    ScreenPtr pScreen;
    DbeScreenPrivPtr pDbeScreenPriv;
    DbeWindowPrivPtr pDbeWindowPriv;
    int width, height;
    int dx, dy, dw, dh;
    int sourcex, sourcey;
    int destx, desty;
    int savewidth, saveheight;
    PixmapPtr pFrontBuffer;
    PixmapPtr pBackBuffer;
    Bool clear;
    GCPtr pGC;
    xRectangle clearRect;
    Bool ret;

    /*
     **************************************************************************
     ** 1. Unwrap the member routine.
     **************************************************************************
     */

    pScreen = pWin->drawable.pScreen;
    pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
    pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;

    /*
     **************************************************************************
     ** 2. Do any work necessary before the member routine is called.
     **
     **    In this case we do not need to do anything.
     **************************************************************************
     */

    /*
     **************************************************************************
     ** 3. Call the member routine, saving its result if necessary.
     **************************************************************************
     */

    ret = (*pScreen->PositionWindow) (pWin, x, y);

    /*
     **************************************************************************
     ** 4. Rewrap the member routine, restoring the wrapper value first in case
     **    the wrapper (or something that it wrapped) change this value.
     **************************************************************************
     */

    pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
    pScreen->PositionWindow = miDbePositionWindow;

    /*
     **************************************************************************
     ** 5. Do any work necessary after the member routine has been called.
     **************************************************************************
     */

    if (!(pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) {
        return ret;
    }

    if (pDbeWindowPriv->width == pWin->drawable.width &&
        pDbeWindowPriv->height == pWin->drawable.height) {
        return ret;
    }

    width = pWin->drawable.width;
    height = pWin->drawable.height;

    dx = pWin->drawable.x - pDbeWindowPriv->x;
    dy = pWin->drawable.y - pDbeWindowPriv->y;
    dw = width - pDbeWindowPriv->width;
    dh = height - pDbeWindowPriv->height;

    GravityTranslate(0, 0, -dx, -dy, dw, dh, pWin->bitGravity, &destx, &desty);

    clear = ((pDbeWindowPriv->width < (unsigned short) width) ||
             (pDbeWindowPriv->height < (unsigned short) height) ||
             (pWin->bitGravity == ForgetGravity));

    sourcex = 0;
    sourcey = 0;
    savewidth = pDbeWindowPriv->width;
    saveheight = pDbeWindowPriv->height;

    /* Clip rectangle to source and destination. */
    if (destx < 0) {
        savewidth += destx;
        sourcex -= destx;
        destx = 0;
    }

    if (destx + savewidth > width) {
        savewidth = width - destx;
    }

    if (desty < 0) {
        saveheight += desty;
        sourcey -= desty;
        desty = 0;
    }

    if (desty + saveheight > height) {
        saveheight = height - desty;
    }

    pDbeWindowPriv->width = width;
    pDbeWindowPriv->height = height;
    pDbeWindowPriv->x = pWin->drawable.x;
    pDbeWindowPriv->y = pWin->drawable.y;

    pGC = GetScratchGC(pWin->drawable.depth, pScreen);

    if (clear) {
        if ((*pDbeScreenPriv->SetupBackgroundPainter) (pWin, pGC)) {
            clearRect.x = 0;
            clearRect.y = 0;
            clearRect.width = width;
            clearRect.height = height;
        }
        else {
            clear = FALSE;
        }
    }

    /* Create DBE buffer pixmaps equal to size of resized window. */
    pFrontBuffer = (*pScreen->CreatePixmap) (pScreen, width, height,
                                             pWin->drawable.depth, 0);

    pBackBuffer = (*pScreen->CreatePixmap) (pScreen, width, height,
                                            pWin->drawable.depth, 0);

    if (!pFrontBuffer || !pBackBuffer) {
        /* We failed at creating 1 or 2 of the pixmaps. */

        if (pFrontBuffer) {
            (*pScreen->DestroyPixmap) (pFrontBuffer);
        }

        if (pBackBuffer) {
            (*pScreen->DestroyPixmap) (pBackBuffer);
        }

        /* Destroy all buffers for this window. */
        while (pDbeWindowPriv) {
            /* DbeWindowPrivDelete() will free the window private if there no
             * more buffer IDs associated with this window.
             */
            FreeResource(pDbeWindowPriv->IDs[0], RT_NONE);
            pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
        }

        FreeScratchGC(pGC);
        return FALSE;
    }

    else {
        /* Clear out the new DBE buffer pixmaps. */

        /* I suppose this could avoid quite a bit of work if
         * it computed the minimal area required.
         */
        ValidateGC(&pFrontBuffer->drawable, pGC);
        if (clear) {
            (*pGC->ops->PolyFillRect) ((DrawablePtr) pFrontBuffer, pGC, 1,
                                       &clearRect);
        }
        /* Copy the contents of the old front pixmap to the new one. */
        if (pWin->bitGravity != ForgetGravity) {
            (*pGC->ops->CopyArea) ((DrawablePtr) pDbeWindowPriv->pFrontBuffer,
				   (DrawablePtr) pFrontBuffer, pGC,
				   sourcex, sourcey, savewidth, saveheight,
                                   destx, desty);
        }

        ValidateGC(&pBackBuffer->drawable, pGC);
        if (clear) {
            (*pGC->ops->PolyFillRect) ((DrawablePtr) pBackBuffer, pGC, 1,
                                       &clearRect);
        }
        /* Copy the contents of the old back pixmap to the new one. */
        if (pWin->bitGravity != ForgetGravity) {
            (*pGC->ops->CopyArea) ((DrawablePtr) pDbeWindowPriv->pBackBuffer,
				   (DrawablePtr) pBackBuffer, pGC,
                                   sourcex, sourcey, savewidth, saveheight,
                                   destx, desty);
        }

        /* Destroy the old pixmaps, and point the DBE window priv to the new
         * pixmaps.
         */

        (*pScreen->DestroyPixmap) (pDbeWindowPriv->pFrontBuffer);
        (*pScreen->DestroyPixmap) (pDbeWindowPriv->pBackBuffer);

        pDbeWindowPriv->pFrontBuffer = pFrontBuffer;
        pDbeWindowPriv->pBackBuffer = pBackBuffer;

        /* Make sure all XID are associated with the new back pixmap. */
        miDbeAliasBuffers(pDbeWindowPriv);

        FreeScratchGC(pGC);
    }

    return ret;

}                               /* miDbePositionWindow() */