/* * Copyright (c) 2006, Oracle and/or its affiliates. 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 #endif #include "compint.h" #ifdef PANORAMIX #include "panoramiXsrv.h" #endif #ifdef COMPOSITE_DEBUG static int compCheckWindow(WindowPtr pWin, void *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; int bw; } CompPixmapVisitRec, *CompPixmapVisitPtr; static Bool compRepaintBorder(ClientPtr pClient, void *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); pWindow->drawable.pScreen->PaintWindow(pWindow, &exposed, PW_BORDER); RegionUninit(&exposed); } return TRUE; } static int compSetPixmapVisitWindow(WindowPtr pWindow, void *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 (pVisit->bw) QueueWorkProc(compRepaintBorder, serverClient, (void *) (intptr_t) pWindow->drawable.id); return WT_WALKCHILDREN; } void compSetPixmap(WindowPtr pWindow, PixmapPtr pPixmap, int bw) { CompPixmapVisitRec visitRec; visitRec.pWindow = pWindow; visitRec.pPixmap = pPixmap; visitRec.bw = bw; TraverseTree(pWindow, compSetPixmapVisitWindow, (void *) &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 { ScreenPtr pScreen = pWin->drawable.pScreen; PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); compSetParentPixmap(pWin); compRestoreWindow(pWin, pPixmap); (*pScreen->DestroyPixmap) (pPixmap); } } else if (should) { if (cw->update == CompositeRedirectAutomatic) pWin->redirectDraw = RedirectDrawAutomatic; else pWin->redirectDraw = RedirectDrawManual; } return TRUE; } static int updateOverlayWindow(ScreenPtr pScreen) { CompScreenPtr cs; WindowPtr pWin; /* overlay window */ XID vlist[2]; 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) { if ((pWin->drawable.width == w) && (pWin->drawable.height == h)) return Success; /* Let's resize the overlay window. */ 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; } 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 compIsImplicitRedirectException(ScreenPtr pScreen, XID parentVisual, XID winVisual) { CompScreenPtr cs = GetCompScreen(pScreen); int i; for (i = 0; i < cs->numImplicitRedirectExceptions; i++) if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual && cs->implicitRedirectExceptions[i].winVisual == winVisual) 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 (compIsImplicitRedirectException(pScreen, parentVisual, winVisual)) return FALSE; if (winVisual != parentVisual && (compIsAlternateVisual(pScreen, winVisual) || compIsAlternateVisual(pScreen, parentVisual))) return TRUE; } return FALSE; } static void compFreeOldPixmap(WindowPtr pWin) { ScreenPtr pScreen = pWin->drawable.pScreen; if (pWin->redirectDraw != RedirectDrawNone) { 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); pScreen->MoveWindow = cs->MoveWindow; (*pScreen->MoveWindow) (pWin, x, y, pSib, kind); cs->MoveWindow = pScreen->MoveWindow; pScreen->MoveWindow = compMoveWindow; compFreeOldPixmap(pWin); 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); 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); 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), pWin->borderWidth); /* * 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; 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); } RegionUninit(&rgnDst); 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); 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; PixmapPtr parent_pixmap = (*pScreen->GetWindowPixmap)(pWin->parent); PixmapPtr window_pixmap = (*pScreen->GetWindowPixmap)(pWin); if (window_pixmap != parent_pixmap) (*pScreen->SetWindowPixmap) (pWin, parent_pixmap); 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) { PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); compSetParentPixmap(pWin); (*pScreen->DestroyPixmap) (pPixmap); } 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 */ DamageDamageRegion(&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 void compWindowUpdateAutomatic(WindowPtr pWin) { CompWindowPtr cw = GetCompWindow(pWin); ScreenPtr pScreen = pWin->drawable.pScreen; WindowPtr pParent = pWin->parent; PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin); PictFormatPtr pSrcFormat = PictureWindowFormat(pWin); PictFormatPtr pDstFormat = PictureWindowFormat(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); } static void compPaintWindowToParent(WindowPtr pWin) { compPaintChildrenToWindow(pWin); if (pWin->redirectDraw != RedirectDrawNone) { CompWindowPtr cw = GetCompWindow(pWin); if (cw->damaged) { compWindowUpdateAutomatic(pWin); cw->damaged = FALSE; } } } void compPaintChildrenToWindow(WindowPtr pWin) { WindowPtr pChild; if (!pWin->damagedDescendants) return; for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) compPaintWindowToParent(pChild); pWin->damagedDescendants = 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; 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; }