[xserver-commit] xserver/composite compalloc.c,1.6,1.7 compext.c,1.3,1.4 compinit.c,1.7,1.8 compint.h,1.6,1.7 compwindow.c,1.8,1.9
Keith Packard
xserver-commit@pdx.freedesktop.org
Wed, 19 Nov 2003 19:31:31 -0800
Committed by: keithp
Update of /cvs/xserver/xserver/composite
In directory pdx:/tmp/cvs-serv11614/composite
Modified Files:
compalloc.c compext.c compinit.c compint.h compwindow.c
Log Message:
* composite/compalloc.c: (compFreePixmap), (compReallocPixmap):
* composite/compext.c:
* composite/compinit.c: (compCloseScreen), (compScreenInit):
* composite/compint.h:
* composite/compwindow.c: (compCheckRedirect),
(compPositionWindow), (compMoveWindow), (compResizeWindow),
(compChangeBorderWidth), (compCopyWindow):
* dix/window.c:
(Yes, these are all related changes). Rework window manipulation
while Composite is enabled. The basic problem was when the
window was resized, the offscreen pixmap would get resized and if
that shrunk, the eventual CopyWindow call would not be able to get
bits. Now, all resizes are managed by allocating a new pixmap
and hanging on to the old one until after all of the CopyWindow
calls are done.
A related change was to reset the borderClip back to the
parent-limited version when removing redirection from a window
so that the UnmapWindow operation within that uses the correct
value
Index: compalloc.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compalloc.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- compalloc.c 18 Nov 2003 03:41:37 -0000 1.6
+++ compalloc.c 20 Nov 2003 03:31:29 -0000 1.7
@@ -455,11 +455,18 @@
PixmapPtr pRedirectPixmap, pParentPixmap;
CompWindowPtr cw = GetCompWindow (pWin);
- if (cw && cw->damageRegistered)
+ if (cw->damageRegistered)
{
DamageUnregister (&pWin->drawable, cw->damage);
cw->damageRegistered = FALSE;
}
+ /*
+ * Move the parent-constrained border clip region back into
+ * the window so that ValidateTree will handle the unmap
+ * case correctly. Unmap adds the window borderClip to the
+ * parent exposed area; regions beyond the parent cause crashes
+ */
+ REGION_COPY (pScreen, &pWin->borderClip, &cw->borderClip);
pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
pWin->redirectDraw = FALSE;
@@ -469,55 +476,61 @@
/*
* Make sure the pixmap is the right size and offset. Allocate a new
- * pixmap to change size, adjust origin to change offset
+ * pixmap to change size, adjust origin to change offset, leaving the
+ * old pixmap in cw->pOldPixmap so bits can be recovered
*/
Bool
-compReallocPixmap (WindowPtr pWin)
+compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y,
+ unsigned int w, unsigned int h, int bw)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
- PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
+ PixmapPtr pNew;
CompWindowPtr cw = GetCompWindow (pWin);
- int bw = (int) pWin->borderWidth;
- int x, y, w, h;
+ int pix_x, pix_y;
+ unsigned int pix_w, pix_h;
- x = pWin->drawable.x - bw;
- y = pWin->drawable.y - bw;
- w = pWin->drawable.width + (bw << 1);
- h = pWin->drawable.height + (bw << 1);
- if (w != pPixmap->drawable.width ||
- h != pPixmap->drawable.height)
+ assert (cw && pWin->redirectDraw);
+ pix_x = draw_x - bw;
+ pix_y = draw_y - bw;
+ pix_w = w + (bw << 1);
+ pix_h = h + (bw << 1);
+ cw->oldx = pOld->screen_x;
+ cw->oldy = pOld->screen_y;
+ if (pix_w != pOld->drawable.width ||
+ pix_h != pOld->drawable.height)
{
- GCPtr pGC;
- PixmapPtr pNew;
+ GCPtr pGC;
- pPixmap->refcnt++;
- compFreePixmap (pWin);
- if (!compAllocPixmap (pWin))
+ pNew = (*pScreen->CreatePixmap) (pScreen, pix_w, pix_h, pWin->drawable.depth);
+ if (!pNew)
return FALSE;
- cw->oldx = pPixmap->screen_x;
- cw->oldy = pPixmap->screen_y;
- pNew = (*pScreen->GetWindowPixmap) (pWin);
+ cw->pOldPixmap = pOld;
+ compSetPixmap (pWin, pNew);
+ /*
+ * Copy new bits to align at same place on the screen. CopyWindow
+ * calls will patch up any differences
+ */
pGC = GetScratchGC (pNew->drawable.depth, pScreen);
if (pGC)
{
ValidateGC(&pNew->drawable, pGC);
- (void) (*pGC->ops->CopyArea) (&pPixmap->drawable,
- &pNew->drawable,
- pGC,
- 0, 0,
- pNew->drawable.width,
- pNew->drawable.height,
- 0, 0);
+ (*pGC->ops->CopyArea) (&pOld->drawable,
+ &pNew->drawable,
+ pGC,
+ pWin->drawable.x - draw_x,
+ pWin->drawable.y - draw_y,
+ pix_w, pix_h,
+ 0, 0);
FreeScratchGC (pGC);
}
- (*pScreen->DestroyPixmap) (pPixmap);
}
else
{
- cw->oldx = pPixmap->screen_x;
- cw->oldy = pPixmap->screen_y;
- pPixmap->screen_x = x;
- pPixmap->screen_y = y;
+ pNew = pOld;
+ cw->pOldPixmap = 0;
}
+ pNew->screen_x = pix_x;
+ pNew->screen_y = pix_y;
return TRUE;
}
Index: compext.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compext.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- compext.c 11 Nov 2003 09:02:22 -0000 1.3
+++ compext.c 20 Nov 2003 03:31:29 -0000 1.4
@@ -26,8 +26,6 @@
#include <config.h>
#endif
#include "compint.h"
-#undef NDEBUG
-#include <assert.h>
int CompositeClientPrivateIndex;
Index: compinit.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compinit.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- compinit.c 13 Nov 2003 09:14:29 -0000 1.7
+++ compinit.c 20 Nov 2003 03:31:29 -0000 1.8
@@ -41,6 +41,10 @@
pScreen->CloseScreen = cs->CloseScreen;
pScreen->BlockHandler = cs->BlockHandler;
pScreen->ReparentWindow = cs->ReparentWindow;
+ pScreen->MoveWindow = cs->MoveWindow;
+ pScreen->ResizeWindow = cs->ResizeWindow;
+ pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
+
pScreen->PaintWindowBackground = cs->PaintWindowBackground;
pScreen->UnrealizeWindow = cs->UnrealizeWindow;
pScreen->RealizeWindow = cs->RealizeWindow;
@@ -269,6 +273,15 @@
cs->PaintWindowBackground = pScreen->PaintWindowBackground;
pScreen->PaintWindowBackground = compPaintWindowBackground;
+ cs->MoveWindow = pScreen->MoveWindow;
+ pScreen->MoveWindow = compMoveWindow;
+
+ cs->ResizeWindow = pScreen->ResizeWindow;
+ pScreen->ResizeWindow = compResizeWindow;
+
+ cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
+ pScreen->ChangeBorderWidth = compChangeBorderWidth;
+
cs->ReparentWindow = pScreen->ReparentWindow;
pScreen->ReparentWindow = compReparentWindow;
Index: compint.h
===================================================================
RCS file: /cvs/xserver/xserver/composite/compint.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- compint.h 13 Nov 2003 09:14:29 -0000 1.6
+++ compint.h 20 Nov 2003 03:31:29 -0000 1.7
@@ -47,6 +47,7 @@
#include "damageextint.h"
#include "xfixes.h"
#include <X11/extensions/compositeproto.h>
+#include <assert.h>
typedef struct _CompClientWindow {
struct _CompClientWindow *next;
@@ -63,6 +64,7 @@
CompClientWindowPtr clients;
int oldx;
int oldy;
+ PixmapPtr pOldPixmap;
int borderClipX, borderClipY;
} CompWindowRec, *CompWindowPtr;
@@ -83,7 +85,19 @@
RealizeWindowProcPtr RealizeWindow;
UnrealizeWindowProcPtr UnrealizeWindow;
PaintWindowProcPtr PaintWindowBackground;
+ /*
+ * Called from ConfigureWindow, these
+ * three track changes to the offscreen storage
+ * geometry
+ */
+ MoveWindowProcPtr MoveWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ ChangeBorderWidthProcPtr ChangeBorderWidth;
+ /*
+ * Reparenting has an effect on Subwindows redirect
+ */
ReparentWindowProcPtr ReparentWindow;
+
ScreenBlockHandlerProcPtr BlockHandler;
CloseScreenProcPtr CloseScreen;
Bool damaged;
@@ -143,7 +157,8 @@
compFreePixmap (WindowPtr pWin);
Bool
-compReallocPixmap (WindowPtr pWin);
+compReallocPixmap (WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, int bw);
/*
* compext.c
@@ -163,8 +178,12 @@
* compwindow.c
*/
+#ifdef NDEBUG
+#define compCheckTree(s)
+#else
void
compCheckTree (ScreenPtr pScreen);
+#endif
void
compSetPixmap (WindowPtr pWin, PixmapPtr pPixmap);
@@ -185,6 +204,16 @@
compPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what);
void
+compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind);
+
+void
+compResizeWindow (WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib);
+
+void
+compChangeBorderWidth (WindowPtr pWin, unsigned int border_width);
+
+void
compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent);
Bool
Index: compwindow.c
===================================================================
RCS file: /cvs/xserver/xserver/composite/compwindow.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- compwindow.c 18 Nov 2003 03:41:37 -0000 1.8
+++ compwindow.c 20 Nov 2003 03:31:29 -0000 1.9
@@ -26,9 +26,8 @@
#include <config.h>
#endif
#include "compint.h"
-#undef NDEBUG
-#include <assert.h>
+#ifndef NDEBUG
static int
compCheckWindow (WindowPtr pWin, pointer data)
{
@@ -63,6 +62,7 @@
{
WalkTree (pScreen, compCheckWindow, 0);
}
+#endif
typedef struct _compPixmapVisit {
WindowPtr pWindow;
@@ -112,8 +112,6 @@
else
compFreePixmap (pWin);
}
- else if (pWin->redirectDraw)
- return compReallocPixmap (pWin);
return TRUE;
}
@@ -125,7 +123,14 @@
Bool ret = TRUE;
pScreen->PositionWindow = cs->PositionWindow;
+ /*
+ * "Shouldn't need this as all possible places should be wrapped
+ *
compCheckRedirect (pWin);
+ */
+ if (pWin->redirectDraw != (pWin->viewable && (GetCompWindow(pWin) != NULL)))
+ abort ();
+
if (!(*pScreen->PositionWindow) (pWin, x, y))
ret = FALSE;
cs->PositionWindow = pScreen->PositionWindow;
@@ -200,6 +205,132 @@
}
void
+compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ compCheckTree (pScreen);
+ if (pWin->redirectDraw)
+ {
+ WindowPtr pParent;
+ int draw_x, draw_y;
+ unsigned int w, h, bw;
+
+ /* if this is a root window, can't be moved */
+ if (!(pParent = pWin->parent))
+ return;
+
+ bw = wBorderWidth (pWin);
+ draw_x = pParent->drawable.x + x + (int)bw;
+ draw_y = pParent->drawable.y + y + (int)bw;
+ w = pWin->drawable.width;
+ h = pWin->drawable.height;
+ compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
+ }
+ compCheckTree (pScreen);
+
+ pScreen->MoveWindow = cs->MoveWindow;
+ (*pScreen->MoveWindow) (pWin, x, y, pSib, kind);
+ cs->MoveWindow = pScreen->MoveWindow;
+ pScreen->MoveWindow = compMoveWindow;
+
+ if (pWin->redirectDraw)
+ {
+ CompWindowPtr cw = GetCompWindow (pWin);
+ if (cw->pOldPixmap)
+ {
+ (*pScreen->DestroyPixmap) (cw->pOldPixmap);
+ cw->pOldPixmap = NullPixmap;
+ }
+ }
+
+ compCheckTree (pScreen);
+}
+
+void
+compResizeWindow (WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ compCheckTree (pScreen);
+ if (pWin->redirectDraw)
+ {
+ WindowPtr pParent;
+ int draw_x, draw_y;
+ unsigned int bw;
+
+ /* if this is a root window, can't be moved */
+ if (!(pParent = pWin->parent))
+ return;
+
+ bw = wBorderWidth (pWin);
+ draw_x = pParent->drawable.x + x + (int)bw;
+ draw_y = pParent->drawable.y + y + (int)bw;
+ compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
+ }
+ compCheckTree (pScreen);
+
+ pScreen->ResizeWindow = cs->ResizeWindow;
+ (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
+ cs->ResizeWindow = pScreen->ResizeWindow;
+ pScreen->ResizeWindow = compResizeWindow;
+ if (pWin->redirectDraw)
+ {
+ CompWindowPtr cw = GetCompWindow (pWin);
+ if (cw->pOldPixmap)
+ {
+ (*pScreen->DestroyPixmap) (cw->pOldPixmap);
+ cw->pOldPixmap = NullPixmap;
+ }
+ }
+ compCheckTree (pWin->drawable.pScreen);
+}
+
+void
+compChangeBorderWidth (WindowPtr pWin, unsigned int bw)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ compCheckTree (pScreen);
+ if (pWin->redirectDraw)
+ {
+ WindowPtr pParent;
+ int draw_x, draw_y;
+ unsigned int w, h;
+
+ /* if this is a root window, can't be moved */
+ if (!(pParent = pWin->parent))
+ return;
+
+ draw_x = pWin->drawable.x;
+ draw_y = pWin->drawable.y;
+ w = pWin->drawable.width;
+ h = pWin->drawable.height;
+ compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
+ }
+ compCheckTree (pScreen);
+
+ pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
+ (*pScreen->ChangeBorderWidth) (pWin, bw);
+ cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
+ pScreen->ChangeBorderWidth = compChangeBorderWidth;
+ if (pWin->redirectDraw)
+ {
+ CompWindowPtr cw = GetCompWindow (pWin);
+ if (cw->pOldPixmap)
+ {
+ (*pScreen->DestroyPixmap) (cw->pOldPixmap);
+ cw->pOldPixmap = NullPixmap;
+ }
+ }
+ compCheckTree (pWin->drawable.pScreen);
+}
+
+void
compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
@@ -250,7 +381,6 @@
CompScreenPtr cs = GetCompScreen (pScreen);
int dx = 0, dy = 0;
- pScreen->CopyWindow = cs->CopyWindow;
if (pWin->redirectDraw)
{
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
@@ -258,11 +388,57 @@
assert (cw->oldx != COMP_ORIGIN_INVALID);
assert (cw->oldy != COMP_ORIGIN_INVALID);
+ if (cw->pOldPixmap)
+ {
+ /*
+ * Ok, the old bits are available in pOldPixmap and
+ * need to be copied to pNewPixmap.
+ */
+ RegionRec rgnDst;
+ PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ GCPtr pGC;
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst,
+ &pWin->borderClip, prgnSrc);
+ if (pPixmap->screen_x || pPixmap->screen_y)
+ REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
+ -pPixmap->screen_x, -pPixmap->screen_y);
+
+ pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+ if (pGC)
+ {
+ BoxPtr pBox = REGION_RECTS (&rgnDst);
+ int nBox = REGION_NUM_RECTS (&rgnDst);
+
+ ValidateGC(&pPixmap->drawable, pGC);
+ while (nBox--)
+ {
+ (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable,
+ &pPixmap->drawable,
+ pGC,
+ pBox->x1 + dx, pBox->y1 + dy,
+ pBox->x2 - pBox->x1,
+ pBox->y2 - pBox->y1,
+ pBox->x1, pBox->y1);
+ pBox++;
+ }
+ FreeScratchGC (pGC);
+ }
+ return;
+ }
dx = pPixmap->screen_x - cw->oldx;
dy = pPixmap->screen_y - cw->oldy;
ptOldOrg.x += dx;
ptOldOrg.y += dy;
}
+
+ pScreen->CopyWindow = cs->CopyWindow;
if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y)
{
if (dx || dy)