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 (); }
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() */