e644d2e73f
The -wm (when mapped) option for the BackingStore support has been
causing the server to dereference a NULL pointer.
This has probably been the case since backing store has been
implemented on top of Composite.
It looks like (some of?) Composite didn’t expect its WIndowPtr
argument to be the root window.
In Composite’s compCheckRedirect() function we now avoid calling
compAllocPixmap() and compFreePixmap() when the pWin pointer’s
parent member is NULL, as is it the case with a server’s root window.
This addresses:
https://bugs.freedesktop.org/show_bug.cgi?id=15878
(cherry picked from commit 04211c3532
)
824 lines
23 KiB
C
824 lines
23 KiB
C
/*
|
|
* Copyright © 2006 Sun Microsystems
|
|
*
|
|
* 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 Sun Microsystems not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. Sun Microsystems makes no
|
|
* representations about the suitability of this software for any purpose. It
|
|
* is provided "as is" without express or implied warranty.
|
|
*
|
|
* SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL SUN MICROSYSTEMS 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.
|
|
*
|
|
* 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_DIX_CONFIG_H
|
|
#include <dix-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 == RedirectDrawNone);
|
|
assert (pWinPixmap == pScreenPixmap);
|
|
}
|
|
else if (pWin->redirectDraw != RedirectDrawNone)
|
|
{
|
|
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;
|
|
int rc = dixLookupWindow(&pWindow, (XID)closure, pClient, DixWriteAccess);
|
|
|
|
if (rc == Success) {
|
|
RegionRec exposed;
|
|
|
|
REGION_NULL(pScreen, &exposed);
|
|
REGION_SUBTRACT(pScreen, &exposed, &pWindow->borderClip, &pWindow->winSize);
|
|
miPaintWindow(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 != RedirectDrawNone)
|
|
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);
|
|
CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
|
|
Bool should;
|
|
|
|
should = pWin->realized && (pWin->drawable.class != InputOnly) &&
|
|
(cw != NULL) && (pWin->parent != NULL);
|
|
|
|
/* Never redirect the overlay window */
|
|
if (cs->pOverlayWin != NULL) {
|
|
if (pWin == cs->pOverlayWin) {
|
|
should = FALSE;
|
|
}
|
|
}
|
|
|
|
if (should != (pWin->redirectDraw != RedirectDrawNone))
|
|
{
|
|
if (should)
|
|
return compAllocPixmap (pWin);
|
|
else
|
|
compFreePixmap (pWin);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static int
|
|
updateOverlayWindow(ScreenPtr pScreen)
|
|
{
|
|
CompScreenPtr cs;
|
|
WindowPtr pWin; /* overlay window */
|
|
XID vlist[2];
|
|
|
|
cs = GetCompScreen(pScreen);
|
|
if ((pWin = cs->pOverlayWin) != NULL) {
|
|
if ((pWin->drawable.width == pScreen->width) &&
|
|
(pWin->drawable.height == pScreen->height))
|
|
return Success;
|
|
|
|
/* Let's resize the overlay window. */
|
|
vlist[0] = pScreen->width;
|
|
vlist[1] = pScreen->height;
|
|
return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin));
|
|
}
|
|
|
|
/* Let's be on the safe side and not assume an overlay window is always allocated. */
|
|
return Success;
|
|
}
|
|
|
|
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 != RedirectDrawNone) !=
|
|
(pWin->viewable && (GetCompWindow(pWin) != NULL)))
|
|
abort ();
|
|
#endif
|
|
if (pWin->redirectDraw != RedirectDrawNone)
|
|
{
|
|
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);
|
|
if (updateOverlayWindow(pScreen) != Success)
|
|
ret = FALSE;
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* 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 < cs->numAlternateVisuals; 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 != RedirectDrawNone)
|
|
{
|
|
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 != RedirectDrawNone)
|
|
{
|
|
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 != RedirectDrawNone)
|
|
{
|
|
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 != RedirectDrawNone)
|
|
{
|
|
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 != RedirectDrawNone)
|
|
{
|
|
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 != RedirectDrawNone)
|
|
{
|
|
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 == RedirectDrawNone)
|
|
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 != RedirectDrawNone)
|
|
{
|
|
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 != RedirectDrawNone)
|
|
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;
|
|
}
|
|
|
|
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 != RedirectDrawNone)
|
|
{
|
|
CompWindowPtr cw = GetCompWindow(pWin);
|
|
|
|
if (cw->damaged)
|
|
{
|
|
compWindowUpdateAutomatic (pWin);
|
|
cw->damaged = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
WindowPtr
|
|
CompositeRealChildHead (WindowPtr pWin)
|
|
{
|
|
WindowPtr pChild, pChildBefore;
|
|
CompScreenPtr cs;
|
|
|
|
if (!pWin->parent &&
|
|
(screenIsSaved == SCREEN_SAVER_ON) &&
|
|
(HasSaverWindow (pWin->drawable.pScreen->myNum))) {
|
|
|
|
/* First child is the screen saver; see if next child is the overlay */
|
|
pChildBefore = pWin->firstChild;
|
|
pChild = pChildBefore->nextSib;
|
|
|
|
} else {
|
|
pChildBefore = NullWindow;
|
|
pChild = pWin->firstChild;
|
|
}
|
|
|
|
if (!pChild) {
|
|
return NullWindow;
|
|
}
|
|
|
|
cs = GetCompScreen(pWin->drawable.pScreen);
|
|
if (pChild == cs->pOverlayWin) {
|
|
return pChild;
|
|
} else {
|
|
return pChildBefore;
|
|
}
|
|
}
|