diff options
author | marha <marha@users.sourceforge.net> | 2010-06-11 12:14:52 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2010-06-11 12:14:52 +0000 |
commit | 4c61bf84b11e26e6f22648668c95ea760a379163 (patch) | |
tree | 0ac762ab2815eae283dded7447ad7cb5a54b926a /xorg-server/composite/compwindow.c | |
parent | e1dabd2ce8be0d70c6c15353b58de256129dfd1f (diff) | |
download | vcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.tar.gz vcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.tar.bz2 vcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.zip |
xserver git update 11/6/2010
Diffstat (limited to 'xorg-server/composite/compwindow.c')
-rw-r--r-- | xorg-server/composite/compwindow.c | 1567 |
1 files changed, 743 insertions, 824 deletions
diff --git a/xorg-server/composite/compwindow.c b/xorg-server/composite/compwindow.c index f2f6ea3cd..82f9b4cfd 100644 --- a/xorg-server/composite/compwindow.c +++ b/xorg-server/composite/compwindow.c @@ -1,824 +1,743 @@ -/* - * Copyright © 2006 Sun Microsystems, Inc. All rights reserved. - * - * 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: - * - * 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. - * - * 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)(intptr_t)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)(intptr_t) 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))) - OsAbort (); -#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); - DamageRegionAppend(&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 - */ - DamageRegionAppend(&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; - } -} +/*
+ * Copyright © 2006 Sun Microsystems, Inc. All rights reserved.
+ *
+ * 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:
+ *
+ * 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.
+ *
+ * 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)(intptr_t)closure, pClient, DixWriteAccess);
+
+ if (rc == Success) {
+ RegionRec exposed;
+
+ RegionNull(&exposed);
+ RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize);
+ miPaintWindow(pWindow, &exposed, PW_BORDER);
+ RegionUninit(&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)(intptr_t) 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)))
+ OsAbort ();
+#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)
+ {
+ RegionTranslate(&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
+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;
+ RegionTranslate(prgnSrc, -dx, -dy);
+
+ RegionNull(&rgnDst);
+
+ RegionIntersect(&rgnDst,
+ &pWin->borderClip, prgnSrc);
+
+ RegionTranslate(&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 = RegionRects (&rgnDst);
+ int nBox = RegionNumRects (&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)
+ RegionTranslate(prgnSrc, dx, dy);
+ (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
+ if (dx || dy)
+ RegionTranslate(prgnSrc, -dx, -dy);
+ }
+ else
+ {
+ ptOldOrg.x -= dx;
+ ptOldOrg.y -= dy;
+ RegionTranslate(prgnSrc,
+ pWin->drawable.x - ptOldOrg.x,
+ pWin->drawable.y - ptOldOrg.y);
+ DamageRegionAppend(&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;
+
+ RegionNull(&damage);
+ /*
+ * Align old border clip with new border clip
+ */
+ RegionTranslate(&cw->borderClip,
+ pWin->drawable.x - cw->borderClipX,
+ pWin->drawable.y - cw->borderClipY);
+ /*
+ * Compute newly visible portion of window for repaint
+ */
+ RegionSubtract(&damage, pRegion, &cw->borderClip);
+ /*
+ * Report that as damaged so it will be redrawn
+ */
+ DamageRegionAppend(&pWin->drawable, &damage);
+ RegionUninit(&damage);
+ /*
+ * Save the new border clip region
+ */
+ RegionCopy(&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
+ */
+ RegionTranslate(pRegion,
+ pWin->drawable.x, pWin->drawable.y);
+
+ /*
+ * Clip against the "real" border clip
+ */
+ RegionIntersect(pRegion, pRegion, &cw->borderClip);
+
+ /*
+ * Now translate from screen to dest coordinates
+ */
+ RegionTranslate(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))) {
+
+ /* 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;
+ }
+}
+
+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;
+ CompWindowPtr cw;
+ 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);
+
+ cw = GetCompWindow (pWin);
+ if (cw->pOldPixmap)
+ {
+ (*pScreen->DestroyPixmap) (cw->pOldPixmap);
+ cw->pOldPixmap = NullPixmap;
+ }
+ compCheckTree (pScreen);
+
+ if (alloc_ret == FALSE)
+ return BadAlloc;
+ return Success;
+}
|