xenocara/xserver/composite/compwindow.c

833 lines
23 KiB
C
Raw Normal View History

2006-11-26 11:13:41 -07:00
/*
2011-11-05 07:32:40 -06:00
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
2006-11-26 11:13:41 -07:00
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
2006-11-26 11:13:41 -07:00
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
2006-11-26 11:13:41 -07:00
*
* 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"
2011-11-05 07:32:40 -06:00
#ifdef PANORAMIX
#include "panoramiXsrv.h"
#endif
2006-11-26 11:13:41 -07:00
#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);
2006-11-26 11:13:41 -07:00
if (!pWin->parent)
{
2007-11-24 10:55:21 -07:00
assert (pWin->redirectDraw == RedirectDrawNone);
2006-11-26 11:13:41 -07:00
assert (pWinPixmap == pScreenPixmap);
}
2007-11-24 10:55:21 -07:00
else if (pWin->redirectDraw != RedirectDrawNone)
2006-11-26 11:13:41 -07:00
{
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)
{
2007-11-24 10:55:21 -07:00
WindowPtr pWindow;
int rc = dixLookupWindow(&pWindow, (XID)(intptr_t)closure, pClient, DixWriteAccess);
2006-11-26 11:13:41 -07:00
2007-11-24 10:55:21 -07:00
if (rc == Success) {
2006-11-26 11:13:41 -07:00
RegionRec exposed;
RegionNull(&exposed);
RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize);
miPaintWindow(pWindow, &exposed, PW_BORDER);
RegionUninit(&exposed);
2006-11-26 11:13:41 -07:00
}
return TRUE;
}
static int
compSetPixmapVisitWindow (WindowPtr pWindow, pointer data)
{
CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data;
ScreenPtr pScreen = pWindow->drawable.pScreen;
2007-11-24 10:55:21 -07:00
if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone)
2006-11-26 11:13:41 -07:00
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)(intptr_t) pWindow->drawable.id);
2006-11-26 11:13:41 -07:00
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);
2006-11-26 11:13:41 -07:00
/* Never redirect the overlay window */
if (cs->pOverlayWin != NULL) {
if (pWin == cs->pOverlayWin) {
should = FALSE;
}
}
2007-11-24 10:55:21 -07:00
if (should != (pWin->redirectDraw != RedirectDrawNone))
2006-11-26 11:13:41 -07:00
{
if (should)
return compAllocPixmap (pWin);
2011-11-05 07:32:40 -06:00
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;
2006-11-26 11:13:41 -07:00
else
2011-11-05 07:32:40 -06:00
pWin->redirectDraw = RedirectDrawManual;
2006-11-26 11:13:41 -07:00
}
return TRUE;
}
static int
updateOverlayWindow(ScreenPtr pScreen)
{
CompScreenPtr cs;
WindowPtr pWin; /* overlay window */
XID vlist[2];
2011-11-05 07:32:40 -06:00
int w = pScreen->width;
int h = pScreen->height;
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
w = PanoramiXPixWidth;
h = PanoramiXPixHeight;
}
#endif
cs = GetCompScreen(pScreen);
if ((pWin = cs->pOverlayWin) != NULL) {
2011-11-05 07:32:40 -06:00
if ((pWin->drawable.width == w) &&
(pWin->drawable.height == h))
return Success;
/* Let's resize the overlay window. */
2011-11-05 07:32:40 -06:00
vlist[0] = w;
vlist[1] = h;
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;
}
2006-11-26 11:13:41 -07:00
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
2007-11-24 10:55:21 -07:00
if ((pWin->redirectDraw != RedirectDrawNone) !=
(pWin->viewable && (GetCompWindow(pWin) != NULL)))
OsAbort ();
2006-11-26 11:13:41 -07:00
#endif
2007-11-24 10:55:21 -07:00
if (pWin->redirectDraw != RedirectDrawNone)
2006-11-26 11:13:41 -07:00
{
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;
2006-11-26 11:13:41 -07:00
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);
2006-11-26 11:13:41 -07:00
if (cw)
{
if (cw->borderClipX != pWin->drawable.x ||
2006-11-26 11:13:41 -07:00
cw->borderClipY != pWin->drawable.y)
{
RegionTranslate(&cw->borderClip,
2006-11-26 11:13:41 -07:00
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);
2006-11-26 11:13:41 -07:00
if (winVisual != parentVisual &&
(compIsAlternateVisual (pScreen, winVisual) ||
compIsAlternateVisual (pScreen, parentVisual)))
return TRUE;
}
return FALSE;
}
static void compFreeOldPixmap(WindowPtr pWin)
2006-11-26 11:13:41 -07:00
{
ScreenPtr pScreen = pWin->drawable.pScreen;
2007-11-24 10:55:21 -07:00
if (pWin->redirectDraw != RedirectDrawNone)
2006-11-26 11:13:41 -07:00
{
CompWindowPtr cw = GetCompWindow (pWin);
if (cw->pOldPixmap)
{
(*pScreen->DestroyPixmap) (cw->pOldPixmap);
cw->pOldPixmap = NullPixmap;
}
}
}
void
compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
CompScreenPtr cs = GetCompScreen (pScreen);
2006-11-26 11:13:41 -07:00
pScreen->MoveWindow = cs->MoveWindow;
(*pScreen->MoveWindow) (pWin, x, y, pSib, kind);
cs->MoveWindow = pScreen->MoveWindow;
pScreen->MoveWindow = compMoveWindow;
compFreeOldPixmap(pWin);
2006-11-26 11:13:41 -07:00
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);
pScreen->ResizeWindow = cs->ResizeWindow;
(*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
cs->ResizeWindow = pScreen->ResizeWindow;
pScreen->ResizeWindow = compResizeWindow;
compFreeOldPixmap(pWin);
2006-11-26 11:13:41 -07:00
compCheckTree (pWin->drawable.pScreen);
}
void
compChangeBorderWidth (WindowPtr pWin, unsigned int bw)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
CompScreenPtr cs = GetCompScreen (pScreen);
pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
(*pScreen->ChangeBorderWidth) (pWin, bw);
cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
pScreen->ChangeBorderWidth = compChangeBorderWidth;
compFreeOldPixmap(pWin);
2006-11-26 11:13:41 -07:00
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);
2006-11-26 11:13:41 -07:00
/*
* Allocate any necessary redirect pixmap
* (this actually should never be true; pWin is always unmapped)
*/
compCheckRedirect (pWin);
2006-11-26 11:13:41 -07:00
/*
* Reset pixmap pointers as appropriate
*/
2007-11-24 10:55:21 -07:00
if (pWin->parent && pWin->redirectDraw == RedirectDrawNone)
2006-11-26 11:13:41 -07:00
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;
2007-11-24 10:55:21 -07:00
if (pWin->redirectDraw != RedirectDrawNone)
2006-11-26 11:13:41 -07:00
{
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
CompWindowPtr cw = GetCompWindow (pWin);
2006-11-26 11:13:41 -07:00
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;
2006-11-26 11:13:41 -07:00
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
RegionTranslate(prgnSrc, -dx, -dy);
2006-11-26 11:13:41 -07:00
RegionNull(&rgnDst);
2006-11-26 11:13:41 -07:00
RegionIntersect(&rgnDst,
2006-11-26 11:13:41 -07:00
&pWin->borderClip, prgnSrc);
RegionTranslate(&rgnDst,
2006-11-26 11:13:41 -07:00
-pPixmap->screen_x, -pPixmap->screen_y);
2006-11-26 11:13:41 -07:00
dx = dx + pPixmap->screen_x - cw->oldx;
dy = dy + pPixmap->screen_y - cw->oldy;
pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
if (pGC)
{
BoxPtr pBox = RegionRects (&rgnDst);
int nBox = RegionNumRects (&rgnDst);
2006-11-26 11:13:41 -07:00
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;
}
2006-11-26 11:13:41 -07:00
pScreen->CopyWindow = cs->CopyWindow;
if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y)
{
if (dx || dy)
RegionTranslate(prgnSrc, dx, dy);
2006-11-26 11:13:41 -07:00
(*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
if (dx || dy)
RegionTranslate(prgnSrc, -dx, -dy);
2006-11-26 11:13:41 -07:00
}
else
{
ptOldOrg.x -= dx;
ptOldOrg.y -= dy;
RegionTranslate(prgnSrc,
2006-11-26 11:13:41 -07:00
pWin->drawable.x - ptOldOrg.x,
pWin->drawable.y - ptOldOrg.y);
DamageDamageRegion(&pWin->drawable, prgnSrc);
2006-11-26 11:13:41 -07:00
}
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);
2011-11-05 07:32:40 -06:00
if (pWin->redirectDraw != RedirectDrawNone) {
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
compSetParentPixmap (pWin);
(*pScreen->DestroyPixmap) (pPixmap);
}
2006-11-26 11:13:41 -07:00
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;
RegionNull(&damage);
2006-11-26 11:13:41 -07:00
/*
* Align old border clip with new border clip
*/
RegionTranslate(&cw->borderClip,
2006-11-26 11:13:41 -07:00
pWin->drawable.x - cw->borderClipX,
pWin->drawable.y - cw->borderClipY);
/*
* Compute newly visible portion of window for repaint
*/
RegionSubtract(&damage, pRegion, &cw->borderClip);
2006-11-26 11:13:41 -07:00
/*
* Report that as damaged so it will be redrawn
*/
DamageDamageRegion(&pWin->drawable, &damage);
RegionUninit(&damage);
2006-11-26 11:13:41 -07:00
/*
* Save the new border clip region
*/
RegionCopy(&cw->borderClip, pRegion);
2006-11-26 11:13:41 -07:00
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;
}
2007-11-24 10:55:21 -07:00
PictFormatPtr
2006-11-26 11:13:41 -07:00
compWindowFormat (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
2006-11-26 11:13:41 -07:00
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,
2006-11-26 11:13:41 -07:00
0, 0,
serverClient,
&error);
XID subwindowMode = IncludeInferiors;
PicturePtr pDstPicture = CreatePicture (0, &pParent->drawable,
pDstFormat,
CPSubwindowMode,
2006-11-26 11:13:41 -07:00
&subwindowMode,
serverClient,
&error);
2006-11-26 11:13:41 -07:00
/*
* First move the region from window to screen coordinates
*/
RegionTranslate(pRegion,
2006-11-26 11:13:41 -07:00
pWin->drawable.x, pWin->drawable.y);
2006-11-26 11:13:41 -07:00
/*
* Clip against the "real" border clip
*/
RegionIntersect(pRegion, pRegion, &cw->borderClip);
2006-11-26 11:13:41 -07:00
/*
* Now translate from screen to dest coordinates
*/
RegionTranslate(pRegion,
2006-11-26 11:13:41 -07:00
-pParent->drawable.x, -pParent->drawable.y);
2006-11-26 11:13:41 -07:00
/*
* Clip the picture
*/
SetPictureClipRegion (pDstPicture, 0, 0, pRegion);
2006-11-26 11:13:41 -07:00
/*
* 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);
}
2011-11-05 07:32:40 -06:00
static void
compPaintWindowToParent (WindowPtr pWin)
2006-11-26 11:13:41 -07:00
{
2011-11-05 07:32:40 -06:00
compPaintChildrenToWindow (pWin);
2006-11-26 11:13:41 -07:00
2007-11-24 10:55:21 -07:00
if (pWin->redirectDraw != RedirectDrawNone)
2006-11-26 11:13:41 -07:00
{
CompWindowPtr cw = GetCompWindow(pWin);
if (cw->damaged)
{
compWindowUpdateAutomatic (pWin);
cw->damaged = FALSE;
}
}
}
2011-11-05 07:32:40 -06:00
void
compPaintChildrenToWindow (WindowPtr pWin)
{
WindowPtr pChild;
if (!pWin->damagedDescendants)
return;
for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
compPaintWindowToParent (pChild);
pWin->damagedDescendants = FALSE;
}
2006-11-26 11:13:41 -07:00
WindowPtr
CompositeRealChildHead (WindowPtr pWin)
{
WindowPtr pChild, pChildBefore;
CompScreenPtr cs;
if (!pWin->parent &&
(screenIsSaved == SCREEN_SAVER_ON) &&
(HasSaverWindow (pWin->drawable.pScreen))) {
2006-11-26 11:13:41 -07:00
/* 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;
}
2006-11-26 11:13:41 -07:00
cs = GetCompScreen(pWin->drawable.pScreen);
if (pChild == cs->pOverlayWin) {
return pChild;
} else {
return pChildBefore;
}
}
int
compConfigNotify(WindowPtr pWin, int x, int y, int w, int h,
int bw, WindowPtr pSib)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
CompScreenPtr cs = GetCompScreen (pScreen);
Bool ret = 0;
WindowPtr pParent = pWin->parent;
int draw_x, draw_y;
Bool alloc_ret;
if (cs->ConfigNotify)
{
pScreen->ConfigNotify = cs->ConfigNotify;
ret = (*pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib);
cs->ConfigNotify = pScreen->ConfigNotify;
pScreen->ConfigNotify = compConfigNotify;
if (ret)
return ret;
}
if (pWin->redirectDraw == RedirectDrawNone)
return Success;
compCheckTree (pScreen);
draw_x = pParent->drawable.x + x + bw;
draw_y = pParent->drawable.y + y + bw;
alloc_ret = compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
if (alloc_ret == FALSE)
return BadAlloc;
return Success;
}