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

View File

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

View File

@ -164,8 +164,18 @@ compCheckRedirect (WindowPtr pWin)
{ {
if (should) if (should)
return compAllocPixmap (pWin); 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 else
compFreePixmap (pWin); pWin->redirectDraw = RedirectDrawManual;
} }
return TRUE; return TRUE;
} }
@ -583,8 +593,11 @@ compDestroyWindow (WindowPtr pWin)
while ((csw = GetCompSubwindows (pWin))) while ((csw = GetCompSubwindows (pWin)))
FreeResource (csw->clients->id, RT_NONE); FreeResource (csw->clients->id, RT_NONE);
if (pWin->redirectDraw != RedirectDrawNone) if (pWin->redirectDraw != RedirectDrawNone) {
compFreePixmap (pWin); PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
compSetParentPixmap (pWin);
(*pScreen->DestroyPixmap) (pPixmap);
}
ret = (*pScreen->DestroyWindow) (pWin); ret = (*pScreen->DestroyWindow) (pWin);
cs->DestroyWindow = pScreen->DestroyWindow; cs->DestroyWindow = pScreen->DestroyWindow;
pScreen->DestroyWindow = compDestroyWindow; pScreen->DestroyWindow = compDestroyWindow;