9da0c214ab
to me. Clean up transition between cheap and expensive GC wrappers by using the prologue and epilogue macros. Before, the GC would be left unvalidated sometimes which would cause all kinds of entertaining bugs against a DDX which cares (XAA).
755 lines
20 KiB
C
755 lines
20 KiB
C
/*
|
|
* $Id$
|
|
*
|
|
* Copyright © 2003 Keith Packard
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Keith Packard not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. Keith Packard makes no
|
|
* representations about the suitability of this software for any purpose. It
|
|
* is provided "as is" without express or implied warranty.
|
|
*
|
|
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
#include "compint.h"
|
|
|
|
#ifdef COMPOSITE_DEBUG
|
|
static int
|
|
compCheckWindow (WindowPtr pWin, pointer data)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin);
|
|
PixmapPtr pParentPixmap = pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0;
|
|
PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen);
|
|
|
|
if (!pWin->parent)
|
|
{
|
|
assert (!pWin->redirectDraw);
|
|
assert (pWinPixmap == pScreenPixmap);
|
|
}
|
|
else if (pWin->redirectDraw)
|
|
{
|
|
assert (pWinPixmap != pParentPixmap);
|
|
assert (pWinPixmap != pScreenPixmap);
|
|
}
|
|
else
|
|
{
|
|
assert (pWinPixmap == pParentPixmap);
|
|
}
|
|
assert (0 < pWinPixmap->refcnt && pWinPixmap->refcnt < 3);
|
|
assert (0 < pScreenPixmap->refcnt && pScreenPixmap->refcnt < 3);
|
|
if (pParentPixmap)
|
|
assert (0 <= pParentPixmap->refcnt && pParentPixmap->refcnt < 3);
|
|
return WT_WALKCHILDREN;
|
|
}
|
|
|
|
void
|
|
compCheckTree (ScreenPtr pScreen)
|
|
{
|
|
WalkTree (pScreen, compCheckWindow, 0);
|
|
}
|
|
#endif
|
|
|
|
typedef struct _compPixmapVisit {
|
|
WindowPtr pWindow;
|
|
PixmapPtr pPixmap;
|
|
} CompPixmapVisitRec, *CompPixmapVisitPtr;
|
|
|
|
static Bool
|
|
compRepaintBorder (ClientPtr pClient, pointer closure)
|
|
{
|
|
WindowPtr pWindow = LookupWindow ((XID) closure, pClient);
|
|
|
|
if (pWindow)
|
|
{
|
|
RegionRec exposed;
|
|
|
|
REGION_NULL(pScreen, &exposed);
|
|
REGION_SUBTRACT(pScreen, &exposed, &pWindow->borderClip, &pWindow->winSize);
|
|
(*pWindow->drawable.pScreen->PaintWindowBorder)(pWindow, &exposed, PW_BORDER);
|
|
REGION_UNINIT(pScreen, &exposed);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static int
|
|
compSetPixmapVisitWindow (WindowPtr pWindow, pointer data)
|
|
{
|
|
CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data;
|
|
ScreenPtr pScreen = pWindow->drawable.pScreen;
|
|
|
|
if (pWindow != pVisit->pWindow && pWindow->redirectDraw)
|
|
return WT_DONTWALKCHILDREN;
|
|
(*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap);
|
|
/*
|
|
* Recompute winSize and borderSize. This is duplicate effort
|
|
* when resizing pixmaps, but necessary when changing redirection.
|
|
* Might be nice to fix this.
|
|
*/
|
|
SetWinSize (pWindow);
|
|
SetBorderSize (pWindow);
|
|
if (HasBorder (pWindow))
|
|
QueueWorkProc (compRepaintBorder, serverClient,
|
|
(pointer) pWindow->drawable.id);
|
|
return WT_WALKCHILDREN;
|
|
}
|
|
|
|
void
|
|
compSetPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
|
|
{
|
|
CompPixmapVisitRec visitRec;
|
|
|
|
visitRec.pWindow = pWindow;
|
|
visitRec.pPixmap = pPixmap;
|
|
TraverseTree (pWindow, compSetPixmapVisitWindow, (pointer) &visitRec);
|
|
compCheckTree (pWindow->drawable.pScreen);
|
|
}
|
|
|
|
Bool
|
|
compCheckRedirect (WindowPtr pWin)
|
|
{
|
|
CompWindowPtr cw = GetCompWindow (pWin);
|
|
Bool should;
|
|
|
|
should = pWin->realized && (pWin->drawable.class != InputOnly) &&
|
|
(cw != NULL);
|
|
|
|
if (should != pWin->redirectDraw)
|
|
{
|
|
if (should)
|
|
return compAllocPixmap (pWin);
|
|
else
|
|
compFreePixmap (pWin);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
compPositionWindow (WindowPtr pWin, int x, int y)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
Bool ret = TRUE;
|
|
|
|
pScreen->PositionWindow = cs->PositionWindow;
|
|
/*
|
|
* "Shouldn't need this as all possible places should be wrapped
|
|
*
|
|
compCheckRedirect (pWin);
|
|
*/
|
|
#ifdef COMPOSITE_DEBUG
|
|
if (pWin->redirectDraw != (pWin->viewable && (GetCompWindow(pWin) != NULL)))
|
|
abort ();
|
|
#endif
|
|
if (pWin->redirectDraw)
|
|
{
|
|
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
|
|
int bw = wBorderWidth (pWin);
|
|
int nx = pWin->drawable.x - bw;
|
|
int ny = pWin->drawable.y - bw;
|
|
|
|
if (pPixmap->screen_x != nx || pPixmap->screen_y != ny)
|
|
{
|
|
pPixmap->screen_x = nx;
|
|
pPixmap->screen_y = ny;
|
|
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
|
}
|
|
}
|
|
|
|
if (!(*pScreen->PositionWindow) (pWin, x, y))
|
|
ret = FALSE;
|
|
cs->PositionWindow = pScreen->PositionWindow;
|
|
pScreen->PositionWindow = compPositionWindow;
|
|
compCheckTree (pWin->drawable.pScreen);
|
|
return ret;
|
|
}
|
|
|
|
Bool
|
|
compRealizeWindow (WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
Bool ret = TRUE;
|
|
|
|
pScreen->RealizeWindow = cs->RealizeWindow;
|
|
compCheckRedirect (pWin);
|
|
if (!(*pScreen->RealizeWindow) (pWin))
|
|
ret = FALSE;
|
|
cs->RealizeWindow = pScreen->RealizeWindow;
|
|
pScreen->RealizeWindow = compRealizeWindow;
|
|
compCheckTree (pWin->drawable.pScreen);
|
|
return ret;
|
|
}
|
|
|
|
Bool
|
|
compUnrealizeWindow (WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
Bool ret = TRUE;
|
|
|
|
pScreen->UnrealizeWindow = cs->UnrealizeWindow;
|
|
compCheckRedirect (pWin);
|
|
if (!(*pScreen->UnrealizeWindow) (pWin))
|
|
ret = FALSE;
|
|
cs->UnrealizeWindow = pScreen->UnrealizeWindow;
|
|
pScreen->UnrealizeWindow = compUnrealizeWindow;
|
|
compCheckTree (pWin->drawable.pScreen);
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
compPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompSubwindowsPtr csw = GetCompSubwindows (pWin);
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
|
|
if (csw && csw->update == CompositeRedirectManual)
|
|
return;
|
|
pScreen->PaintWindowBackground = cs->PaintWindowBackground;
|
|
(*pScreen->PaintWindowBackground) (pWin, pRegion, what);
|
|
cs->PaintWindowBackground = pScreen->PaintWindowBackground;
|
|
pScreen->PaintWindowBackground = compPaintWindowBackground;
|
|
}
|
|
|
|
/*
|
|
* Called after the borderClip for the window has settled down
|
|
* We use this to make sure our extra borderClip has the right origin
|
|
*/
|
|
|
|
void
|
|
compClipNotify (WindowPtr pWin, int dx, int dy)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
CompWindowPtr cw = GetCompWindow (pWin);
|
|
|
|
if (cw)
|
|
{
|
|
if (cw->borderClipX != pWin->drawable.x ||
|
|
cw->borderClipY != pWin->drawable.y)
|
|
{
|
|
REGION_TRANSLATE (pScreen, &cw->borderClip,
|
|
pWin->drawable.x - cw->borderClipX,
|
|
pWin->drawable.y - cw->borderClipY);
|
|
cw->borderClipX = pWin->drawable.x;
|
|
cw->borderClipY = pWin->drawable.y;
|
|
}
|
|
}
|
|
if (cs->ClipNotify)
|
|
{
|
|
pScreen->ClipNotify = cs->ClipNotify;
|
|
(*pScreen->ClipNotify) (pWin, dx, dy);
|
|
cs->ClipNotify = pScreen->ClipNotify;
|
|
pScreen->ClipNotify = compClipNotify;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Returns TRUE if the window needs server-provided automatic redirect,
|
|
* which is true if the child and parent aren't both regular or ARGB visuals
|
|
*/
|
|
|
|
static Bool
|
|
compIsAlternateVisual (ScreenPtr pScreen,
|
|
XID visual)
|
|
{
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
int i;
|
|
|
|
for (i = 0; i < NUM_COMP_ALTERNATE_VISUALS; i++)
|
|
if (cs->alternateVisuals[i] == visual)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
static Bool
|
|
compImplicitRedirect (WindowPtr pWin, WindowPtr pParent)
|
|
{
|
|
if (pParent)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
XID winVisual = wVisual (pWin);
|
|
XID parentVisual = wVisual (pParent);
|
|
|
|
if (winVisual != parentVisual &&
|
|
(compIsAlternateVisual (pScreen, winVisual) ||
|
|
compIsAlternateVisual (pScreen, parentVisual)))
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
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;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
|
|
pScreen->ReparentWindow = cs->ReparentWindow;
|
|
/*
|
|
* Remove any implicit redirect due to synthesized visual
|
|
*/
|
|
if (compImplicitRedirect (pWin, pPriorParent))
|
|
compUnredirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
|
|
/*
|
|
* Handle subwindows redirection
|
|
*/
|
|
compUnredirectOneSubwindow (pPriorParent, pWin);
|
|
compRedirectOneSubwindow (pWin->parent, pWin);
|
|
/*
|
|
* Add any implict redirect due to synthesized visual
|
|
*/
|
|
if (compImplicitRedirect (pWin, pWin->parent))
|
|
compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
|
|
|
|
/*
|
|
* Allocate any necessary redirect pixmap
|
|
* (this actually should never be true; pWin is always unmapped)
|
|
*/
|
|
compCheckRedirect (pWin);
|
|
|
|
/*
|
|
* Reset pixmap pointers as appropriate
|
|
*/
|
|
if (pWin->parent && !pWin->redirectDraw)
|
|
compSetPixmap (pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
|
|
/*
|
|
* Call down to next function
|
|
*/
|
|
if (pScreen->ReparentWindow)
|
|
(*pScreen->ReparentWindow) (pWin, pPriorParent);
|
|
cs->ReparentWindow = pScreen->ReparentWindow;
|
|
pScreen->ReparentWindow = compReparentWindow;
|
|
compCheckTree (pWin->drawable.pScreen);
|
|
}
|
|
|
|
void
|
|
compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
int dx = 0, dy = 0;
|
|
|
|
if (pWin->redirectDraw)
|
|
{
|
|
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
|
|
CompWindowPtr cw = GetCompWindow (pWin);
|
|
|
|
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_NULL (pWin->drawable.pScreen, &rgnDst);
|
|
|
|
REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst,
|
|
&pWin->borderClip, prgnSrc);
|
|
|
|
REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
|
|
-pPixmap->screen_x, -pPixmap->screen_y);
|
|
|
|
dx = dx + pPixmap->screen_x - cw->oldx;
|
|
dy = dy + pPixmap->screen_y - cw->oldy;
|
|
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)
|
|
REGION_TRANSLATE (pScreen, prgnSrc, dx, dy);
|
|
(*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
|
|
if (dx || dy)
|
|
REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
|
|
}
|
|
else
|
|
{
|
|
ptOldOrg.x -= dx;
|
|
ptOldOrg.y -= dy;
|
|
REGION_TRANSLATE (prgnSrc, prgnSrc,
|
|
pWin->drawable.x - ptOldOrg.x,
|
|
pWin->drawable.y - ptOldOrg.y);
|
|
DamageDamageRegion (&pWin->drawable, prgnSrc);
|
|
}
|
|
cs->CopyWindow = pScreen->CopyWindow;
|
|
pScreen->CopyWindow = compCopyWindow;
|
|
compCheckTree (pWin->drawable.pScreen);
|
|
}
|
|
|
|
Bool
|
|
compCreateWindow (WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
Bool ret;
|
|
|
|
pScreen->CreateWindow = cs->CreateWindow;
|
|
ret = (*pScreen->CreateWindow) (pWin);
|
|
if (pWin->parent && ret)
|
|
{
|
|
CompSubwindowsPtr csw = GetCompSubwindows (pWin->parent);
|
|
CompClientWindowPtr ccw;
|
|
|
|
(*pScreen->SetWindowPixmap) (pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
|
|
if (csw)
|
|
for (ccw = csw->clients; ccw; ccw = ccw->next)
|
|
compRedirectWindow (clients[CLIENT_ID(ccw->id)],
|
|
pWin, ccw->update);
|
|
if (compImplicitRedirect (pWin, pWin->parent))
|
|
compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
|
|
}
|
|
cs->CreateWindow = pScreen->CreateWindow;
|
|
pScreen->CreateWindow = compCreateWindow;
|
|
compCheckTree (pWin->drawable.pScreen);
|
|
return ret;
|
|
}
|
|
|
|
Bool
|
|
compDestroyWindow (WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
CompScreenPtr cs = GetCompScreen (pScreen);
|
|
CompWindowPtr cw;
|
|
CompSubwindowsPtr csw;
|
|
Bool ret;
|
|
|
|
pScreen->DestroyWindow = cs->DestroyWindow;
|
|
while ((cw = GetCompWindow (pWin)))
|
|
FreeResource (cw->clients->id, RT_NONE);
|
|
while ((csw = GetCompSubwindows (pWin)))
|
|
FreeResource (csw->clients->id, RT_NONE);
|
|
|
|
if (pWin->redirectDraw)
|
|
compFreePixmap (pWin);
|
|
ret = (*pScreen->DestroyWindow) (pWin);
|
|
cs->DestroyWindow = pScreen->DestroyWindow;
|
|
pScreen->DestroyWindow = compDestroyWindow;
|
|
/* compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
compSetRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion)
|
|
{
|
|
CompWindowPtr cw = GetCompWindow (pWin);
|
|
RegionRec damage;
|
|
|
|
REGION_NULL (pScreen, &damage);
|
|
/*
|
|
* Align old border clip with new border clip
|
|
*/
|
|
REGION_TRANSLATE (pScreen, &cw->borderClip,
|
|
pWin->drawable.x - cw->borderClipX,
|
|
pWin->drawable.y - cw->borderClipY);
|
|
/*
|
|
* Compute newly visible portion of window for repaint
|
|
*/
|
|
REGION_SUBTRACT (pScreen, &damage, pRegion, &cw->borderClip);
|
|
/*
|
|
* Report that as damaged so it will be redrawn
|
|
*/
|
|
DamageDamageRegion (&pWin->drawable, &damage);
|
|
REGION_UNINIT (pScreen, &damage);
|
|
/*
|
|
* Save the new border clip region
|
|
*/
|
|
REGION_COPY (pScreen, &cw->borderClip, pRegion);
|
|
cw->borderClipX = pWin->drawable.x;
|
|
cw->borderClipY = pWin->drawable.y;
|
|
}
|
|
|
|
RegionPtr
|
|
compGetRedirectBorderClip (WindowPtr pWin)
|
|
{
|
|
CompWindowPtr cw = GetCompWindow (pWin);
|
|
|
|
return &cw->borderClip;
|
|
}
|
|
|
|
static VisualPtr
|
|
compGetWindowVisual (WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
VisualID vid = wVisual (pWin);
|
|
int i;
|
|
|
|
for (i = 0; i < pScreen->numVisuals; i++)
|
|
if (pScreen->visuals[i].vid == vid)
|
|
return &pScreen->visuals[i];
|
|
return 0;
|
|
}
|
|
|
|
static PictFormatPtr
|
|
compWindowFormat (WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
|
|
return PictureMatchVisual (pScreen, pWin->drawable.depth,
|
|
compGetWindowVisual (pWin));
|
|
}
|
|
|
|
static void
|
|
compWindowUpdateAutomatic (WindowPtr pWin)
|
|
{
|
|
CompWindowPtr cw = GetCompWindow (pWin);
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
WindowPtr pParent = pWin->parent;
|
|
PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin);
|
|
PictFormatPtr pSrcFormat = compWindowFormat (pWin);
|
|
PictFormatPtr pDstFormat = compWindowFormat (pWin->parent);
|
|
int error;
|
|
RegionPtr pRegion = DamageRegion (cw->damage);
|
|
PicturePtr pSrcPicture = CreatePicture (0, &pSrcPixmap->drawable,
|
|
pSrcFormat,
|
|
0, 0,
|
|
serverClient,
|
|
&error);
|
|
XID subwindowMode = IncludeInferiors;
|
|
PicturePtr pDstPicture = CreatePicture (0, &pParent->drawable,
|
|
pDstFormat,
|
|
CPSubwindowMode,
|
|
&subwindowMode,
|
|
serverClient,
|
|
&error);
|
|
|
|
/*
|
|
* First move the region from window to screen coordinates
|
|
*/
|
|
REGION_TRANSLATE (pScreen, pRegion,
|
|
pWin->drawable.x, pWin->drawable.y);
|
|
|
|
/*
|
|
* Clip against the "real" border clip
|
|
*/
|
|
REGION_INTERSECT (pScreen, pRegion, pRegion, &cw->borderClip);
|
|
|
|
/*
|
|
* Now translate from screen to dest coordinates
|
|
*/
|
|
REGION_TRANSLATE (pScreen, pRegion,
|
|
-pParent->drawable.x, -pParent->drawable.y);
|
|
|
|
/*
|
|
* Clip the picture
|
|
*/
|
|
SetPictureClipRegion (pDstPicture, 0, 0, pRegion);
|
|
|
|
/*
|
|
* And paint
|
|
*/
|
|
CompositePicture (PictOpSrc,
|
|
pSrcPicture,
|
|
0,
|
|
pDstPicture,
|
|
0, 0, /* src_x, src_y */
|
|
0, 0, /* msk_x, msk_y */
|
|
pSrcPixmap->screen_x - pParent->drawable.x,
|
|
pSrcPixmap->screen_y - pParent->drawable.y,
|
|
pSrcPixmap->drawable.width,
|
|
pSrcPixmap->drawable.height);
|
|
FreePicture (pSrcPicture, 0);
|
|
FreePicture (pDstPicture, 0);
|
|
/*
|
|
* Empty the damage region. This has the nice effect of
|
|
* rendering the translations above harmless
|
|
*/
|
|
DamageEmpty (cw->damage);
|
|
}
|
|
|
|
void
|
|
compWindowUpdate (WindowPtr pWin)
|
|
{
|
|
WindowPtr pChild;
|
|
|
|
for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
|
|
compWindowUpdate (pChild);
|
|
if (pWin->redirectDraw)
|
|
{
|
|
CompWindowPtr cw = GetCompWindow(pWin);
|
|
|
|
if (cw->damaged)
|
|
{
|
|
compWindowUpdateAutomatic (pWin);
|
|
cw->damaged = FALSE;
|
|
}
|
|
}
|
|
}
|