Merge remote-tracking branch 'vsyrjala/composite_validatetree_2'

This commit is contained in:
Keith Packard 2011-05-13 13:52:18 -07:00
commit 4d02c53971
3 changed files with 116 additions and 55 deletions

View File

@ -104,6 +104,35 @@ compDestroyDamage (DamagePtr pDamage, void *closure)
cw->damage = 0;
}
static Bool
compMarkWindows(WindowPtr pWin,
WindowPtr *ppLayerWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
WindowPtr pLayerWin = pWin;
if (!pWin->viewable)
return FALSE;
(*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin);
(*pScreen->MarkWindow)(pLayerWin->parent);
*ppLayerWin = pLayerWin;
return TRUE;
}
static void
compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
(*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
(*pScreen->HandleExposures)(pLayerWin->parent);
if (pScreen->PostValidateTree)
(*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTOther);
}
/*
* Redirect one window for one client
*/
@ -112,8 +141,9 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
{
CompWindowPtr cw = GetCompWindow (pWin);
CompClientWindowPtr ccw;
Bool wasMapped = pWin->mapped;
CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
WindowPtr pLayerWin;
Bool anyMarked = FALSE;
if (pWin == cs->pOverlayWin) {
return Success;
@ -163,16 +193,14 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
free(cw);
return BadAlloc;
}
if (wasMapped)
{
DisableMapUnmapEvents (pWin);
UnmapWindow (pWin, FALSE);
EnableMapUnmapEvents (pWin);
}
anyMarked = compMarkWindows (pWin, &pLayerWin);
/* Make sure our borderClip is correct for ValidateTree */
RegionNull(&cw->borderClip);
cw->borderClipX = 0;
cw->borderClipY = 0;
RegionCopy(&cw->borderClip, &pWin->borderClip);
cw->borderClipX = pWin->drawable.x;
cw->borderClipY = pWin->drawable.y;
cw->update = CompositeRedirectAutomatic;
cw->clients = 0;
cw->oldx = COMP_ORIGIN_INVALID;
@ -188,16 +216,9 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
return BadAlloc;
if (ccw->update == CompositeRedirectManual)
{
/* If the window was CompositeRedirectAutomatic, then
* unmap the window so that the parent clip list will
* be correctly recomputed.
*/
if (pWin->mapped)
{
DisableMapUnmapEvents (pWin);
UnmapWindow (pWin, FALSE);
EnableMapUnmapEvents (pWin);
}
if (!anyMarked)
anyMarked = compMarkWindows (pWin, &pLayerWin);
if (cw->damageRegistered)
{
DamageUnregister (&pWin->drawable, cw->damage);
@ -205,25 +226,51 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
}
cw->update = CompositeRedirectManual;
}
else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) {
if (!anyMarked)
anyMarked = compMarkWindows (pWin, &pLayerWin);
}
if (!compCheckRedirect (pWin))
{
FreeResource (ccw->id, RT_NONE);
return BadAlloc;
}
if (wasMapped && !pWin->mapped)
{
Bool overrideRedirect = pWin->overrideRedirect;
pWin->overrideRedirect = TRUE;
DisableMapUnmapEvents (pWin);
MapWindow (pWin, pClient);
EnableMapUnmapEvents (pWin);
pWin->overrideRedirect = overrideRedirect;
}
if (anyMarked)
compHandleMarkedWindows (pWin, pLayerWin);
return Success;
}
void
compRestoreWindow (WindowPtr pWin, PixmapPtr pPixmap)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
WindowPtr pParent = pWin->parent;
if (pParent->drawable.depth == pWin->drawable.depth) {
GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen);
int bw = (int) pWin->borderWidth;
int x = bw;
int y = bw;
int w = pWin->drawable.width;
int h = pWin->drawable.height;
if (pGC) {
ChangeGCVal val;
val.val = IncludeInferiors;
ChangeGC (NullClient, pGC, GCSubwindowMode, &val);
ValidateGC(&pWin->drawable, pGC);
(*pGC->ops->CopyArea) (&pPixmap->drawable,
&pWin->drawable,
pGC,
x, y, w, h, 0, 0);
FreeScratchGC (pGC);
}
}
}
/*
* Free one of the per-client per-window resources, clearing
* redirect and the per-window pointer as appropriate
@ -231,9 +278,12 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
void
compFreeClientWindow (WindowPtr pWin, XID id)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
CompWindowPtr cw = GetCompWindow (pWin);
CompClientWindowPtr ccw, *prev;
Bool wasMapped = pWin->mapped;
Bool anyMarked = FALSE;
WindowPtr pLayerWin;
PixmapPtr pPixmap = NULL;
if (!cw)
return;
@ -250,15 +300,12 @@ compFreeClientWindow (WindowPtr pWin, XID id)
}
if (!cw->clients)
{
if (wasMapped)
{
DisableMapUnmapEvents (pWin);
UnmapWindow (pWin, FALSE);
EnableMapUnmapEvents (pWin);
}
anyMarked = compMarkWindows (pWin, &pLayerWin);
if (pWin->redirectDraw != RedirectDrawNone)
compFreePixmap (pWin);
if (pWin->redirectDraw != RedirectDrawNone) {
pPixmap = (*pScreen->GetWindowPixmap) (pWin);
compSetParentPixmap (pWin);
}
if (cw->damage)
DamageDestroy (cw->damage);
@ -271,19 +318,20 @@ compFreeClientWindow (WindowPtr pWin, XID id)
else if (cw->update == CompositeRedirectAutomatic &&
!cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone)
{
anyMarked = compMarkWindows (pWin, &pLayerWin);
DamageRegister (&pWin->drawable, cw->damage);
cw->damageRegistered = TRUE;
pWin->redirectDraw = RedirectDrawAutomatic;
DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
}
if (wasMapped && !pWin->mapped)
{
Bool overrideRedirect = pWin->overrideRedirect;
pWin->overrideRedirect = TRUE;
DisableMapUnmapEvents (pWin);
MapWindow (pWin, clients[CLIENT_ID(id)]);
EnableMapUnmapEvents (pWin);
pWin->overrideRedirect = overrideRedirect;
if (anyMarked)
compHandleMarkedWindows (pWin, pLayerWin);
if (pPixmap) {
compRestoreWindow (pWin, pPixmap);
(*pScreen->DestroyPixmap) (pPixmap);
}
}
@ -536,9 +584,8 @@ compNewPixmap (WindowPtr pWin, int x, int y, int w, int h, Bool map)
{
ChangeGCVal val;
val.val = IncludeInferiors;
ChangeGC (NullClient, pGC, GCSubwindowMode, &val);
ValidateGC(&pPixmap->drawable, pGC);
ChangeGC (serverClient, pGC, GCSubwindowMode, &val);
(*pGC->ops->CopyArea) (&pParent->drawable,
&pPixmap->drawable,
pGC,
@ -617,10 +664,10 @@ compAllocPixmap (WindowPtr pWin)
}
void
compFreePixmap (WindowPtr pWin)
compSetParentPixmap (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
PixmapPtr pRedirectPixmap, pParentPixmap;
PixmapPtr pParentPixmap;
CompWindowPtr cw = GetCompWindow (pWin);
if (cw->damageRegistered)
@ -636,11 +683,9 @@ compFreePixmap (WindowPtr pWin)
* parent exposed area; regions beyond the parent cause crashes
*/
RegionCopy(&pWin->borderClip, &cw->borderClip);
pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
pWin->redirectDraw = RedirectDrawNone;
compSetPixmap (pWin, pParentPixmap);
(*pScreen->DestroyPixmap) (pRedirectPixmap);
}
/*

View File

@ -215,7 +215,10 @@ Bool
compAllocPixmap (WindowPtr pWin);
void
compFreePixmap (WindowPtr pWin);
compSetParentPixmap (WindowPtr pWin);
void
compRestoreWindow (WindowPtr pWin, PixmapPtr pPixmap);
Bool
compReallocPixmap (WindowPtr pWin, int x, int y,

View File

@ -164,8 +164,18 @@ compCheckRedirect (WindowPtr pWin)
{
if (should)
return compAllocPixmap (pWin);
else {
ScreenPtr pScreen = pWin->drawable.pScreen;
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
compSetParentPixmap (pWin);
compRestoreWindow (pWin, pPixmap);
(*pScreen->DestroyPixmap) (pPixmap);
}
} else if (should) {
if (cw->update == CompositeRedirectAutomatic)
pWin->redirectDraw = RedirectDrawAutomatic;
else
compFreePixmap (pWin);
pWin->redirectDraw = RedirectDrawManual;
}
return TRUE;
}
@ -583,8 +593,11 @@ compDestroyWindow (WindowPtr pWin)
while ((csw = GetCompSubwindows (pWin)))
FreeResource (csw->clients->id, RT_NONE);
if (pWin->redirectDraw != RedirectDrawNone)
compFreePixmap (pWin);
if (pWin->redirectDraw != RedirectDrawNone) {
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
compSetParentPixmap (pWin);
(*pScreen->DestroyPixmap) (pPixmap);
}
ret = (*pScreen->DestroyWindow) (pWin);
cs->DestroyWindow = pScreen->DestroyWindow;
pScreen->DestroyWindow = compDestroyWindow;