From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- xorg-server/composite/compalloc.c | 1456 ++++++++++++++++++------------------- 1 file changed, 728 insertions(+), 728 deletions(-) (limited to 'xorg-server/composite/compalloc.c') diff --git a/xorg-server/composite/compalloc.c b/xorg-server/composite/compalloc.c index e64d1061b..c4430af43 100644 --- a/xorg-server/composite/compalloc.c +++ b/xorg-server/composite/compalloc.c @@ -1,728 +1,728 @@ -/* - * 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" - -static void -compScreenUpdate (ScreenPtr pScreen) -{ - compCheckTree (pScreen); - compPaintChildrenToWindow (pScreen->root); -} - -static void -compBlockHandler (int i, - pointer blockData, - pointer pTimeout, - pointer pReadmask) -{ - ScreenPtr pScreen = screenInfo.screens[i]; - CompScreenPtr cs = GetCompScreen (pScreen); - - pScreen->BlockHandler = cs->BlockHandler; - compScreenUpdate (pScreen); - (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); - - /* Next damage will restore the block handler */ - cs->BlockHandler = NULL; -} - -static void -compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) -{ - WindowPtr pWin = (WindowPtr) closure; - ScreenPtr pScreen = pWin->drawable.pScreen; - CompScreenPtr cs = GetCompScreen (pScreen); - CompWindowPtr cw = GetCompWindow (pWin); - - if (!cs->BlockHandler) { - cs->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = compBlockHandler; - } - cw->damaged = TRUE; - - /* Mark the ancestors */ - pWin = pWin->parent; - while (pWin) { - if (pWin->damagedDescendants) - break; - pWin->damagedDescendants = TRUE; - pWin = pWin->parent; - } -} - -static void -compDestroyDamage (DamagePtr pDamage, void *closure) -{ - WindowPtr pWin = (WindowPtr) closure; - CompWindowPtr cw = GetCompWindow (pWin); - - cw->damage = 0; -} - -static Bool -compMarkWindows(WindowPtr pWin, - WindowPtr *ppLayerWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - WindowPtr pLayerWin = pWin; - - if (!pWin->viewable) - return FALSE; - - (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); - (*pScreen->MarkWindow)(pLayerWin->parent); - - *ppLayerWin = pLayerWin; - - return TRUE; -} - -static void -compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - - (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); - (*pScreen->HandleExposures)(pLayerWin->parent); - if (pScreen->PostValidateTree) - (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTOther); -} - -/* - * Redirect one window for one client - */ -int -compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) -{ - CompWindowPtr cw = GetCompWindow (pWin); - CompClientWindowPtr ccw; - CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); - WindowPtr pLayerWin; - Bool anyMarked = FALSE; - - if (pWin == cs->pOverlayWin) { - return Success; - } - - if (!pWin->parent) - return BadMatch; - - /* - * Only one Manual update is allowed - */ - if (cw && update == CompositeRedirectManual) - for (ccw = cw->clients; ccw; ccw = ccw->next) - if (ccw->update == CompositeRedirectManual) - return BadAccess; - - /* - * Allocate per-client per-window structure - * The client *could* allocate multiple, but while supported, - * it is not expected to be common - */ - ccw = malloc(sizeof (CompClientWindowRec)); - if (!ccw) - return BadAlloc; - ccw->id = FakeClientID (pClient->index); - ccw->update = update; - /* - * Now make sure there's a per-window structure to hang this from - */ - if (!cw) - { - cw = calloc (1,sizeof (CompWindowRec)); - if (!cw) - { - free(ccw); - return BadAlloc; - } - cw->damage = DamageCreate (compReportDamage, - compDestroyDamage, - DamageReportNonEmpty, - FALSE, - pWin->drawable.pScreen, - pWin); - if (!cw->damage) - { - free(ccw); - free(cw); - return BadAlloc; - } - - anyMarked = compMarkWindows (pWin, &pLayerWin); - - /* Make sure our borderClip is correct for ValidateTree */ - RegionNull(&cw->borderClip); - RegionCopy(&cw->borderClip, &pWin->borderClip); - cw->borderClipX = pWin->drawable.x; - cw->borderClipY = pWin->drawable.y; - cw->update = CompositeRedirectAutomatic; - cw->clients = 0; - cw->oldx = COMP_ORIGIN_INVALID; - cw->oldy = COMP_ORIGIN_INVALID; - cw->damageRegistered = FALSE; - cw->damaged = FALSE; - cw->pOldPixmap = NullPixmap; - dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); - } - ccw->next = cw->clients; - cw->clients = ccw; - if (!AddResource (ccw->id, CompositeClientWindowType, pWin)) - return BadAlloc; - if (ccw->update == CompositeRedirectManual) - { - if (!anyMarked) - anyMarked = compMarkWindows (pWin, &pLayerWin); - - if (cw->damageRegistered) - { - DamageUnregister (&pWin->drawable, cw->damage); - cw->damageRegistered = FALSE; - } - cw->update = CompositeRedirectManual; - } - else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { - if (!anyMarked) - anyMarked = compMarkWindows (pWin, &pLayerWin); - } - - if (!compCheckRedirect (pWin)) - { - FreeResource (ccw->id, RT_NONE); - return BadAlloc; - } - - if (anyMarked) - compHandleMarkedWindows (pWin, pLayerWin); - - return Success; -} - -void -compRestoreWindow (WindowPtr pWin, PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - WindowPtr pParent = pWin->parent; - - if (pParent->drawable.depth == pWin->drawable.depth) { - GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen); - int bw = (int) pWin->borderWidth; - int x = bw; - int y = bw; - int w = pWin->drawable.width; - int h = pWin->drawable.height; - - if (pGC) { - ChangeGCVal val; - val.val = IncludeInferiors; - ChangeGC (NullClient, pGC, GCSubwindowMode, &val); - ValidateGC(&pWin->drawable, pGC); - (*pGC->ops->CopyArea) (&pPixmap->drawable, - &pWin->drawable, - pGC, - x, y, w, h, 0, 0); - FreeScratchGC (pGC); - } - } -} - -/* - * Free one of the per-client per-window resources, clearing - * redirect and the per-window pointer as appropriate - */ -void -compFreeClientWindow (WindowPtr pWin, XID id) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - CompWindowPtr cw = GetCompWindow (pWin); - CompClientWindowPtr ccw, *prev; - Bool anyMarked = FALSE; - WindowPtr pLayerWin; - PixmapPtr pPixmap = NULL; - - if (!cw) - return; - for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) - { - if (ccw->id == id) - { - *prev = ccw->next; - if (ccw->update == CompositeRedirectManual) - cw->update = CompositeRedirectAutomatic; - free(ccw); - break; - } - } - if (!cw->clients) - { - anyMarked = compMarkWindows (pWin, &pLayerWin); - - if (pWin->redirectDraw != RedirectDrawNone) { - pPixmap = (*pScreen->GetWindowPixmap) (pWin); - compSetParentPixmap (pWin); - } - - if (cw->damage) - DamageDestroy (cw->damage); - - RegionUninit(&cw->borderClip); - - dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL); - free(cw); - } - else if (cw->update == CompositeRedirectAutomatic && - !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) - { - anyMarked = compMarkWindows (pWin, &pLayerWin); - - DamageRegister (&pWin->drawable, cw->damage); - cw->damageRegistered = TRUE; - pWin->redirectDraw = RedirectDrawAutomatic; - DamageDamageRegion(&pWin->drawable, &pWin->borderSize); - } - - if (anyMarked) - compHandleMarkedWindows (pWin, pLayerWin); - - if (pPixmap) { - compRestoreWindow (pWin, pPixmap); - (*pScreen->DestroyPixmap) (pPixmap); - } -} - -/* - * This is easy, just free the appropriate resource. - */ - -int -compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update) -{ - CompWindowPtr cw = GetCompWindow (pWin); - CompClientWindowPtr ccw; - - if (!cw) - return BadValue; - - for (ccw = cw->clients; ccw; ccw = ccw->next) - if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) - { - FreeResource (ccw->id, RT_NONE); - return Success; - } - return BadValue; -} - -/* - * Redirect all subwindows for one client - */ - -int -compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) -{ - CompSubwindowsPtr csw = GetCompSubwindows (pWin); - CompClientWindowPtr ccw; - WindowPtr pChild; - - /* - * Only one Manual update is allowed - */ - if (csw && update == CompositeRedirectManual) - for (ccw = csw->clients; ccw; ccw = ccw->next) - if (ccw->update == CompositeRedirectManual) - return BadAccess; - /* - * Allocate per-client per-window structure - * The client *could* allocate multiple, but while supported, - * it is not expected to be common - */ - ccw = malloc(sizeof (CompClientWindowRec)); - if (!ccw) - return BadAlloc; - ccw->id = FakeClientID (pClient->index); - ccw->update = update; - /* - * Now make sure there's a per-window structure to hang this from - */ - if (!csw) - { - csw = malloc(sizeof (CompSubwindowsRec)); - if (!csw) - { - free(ccw); - return BadAlloc; - } - csw->update = CompositeRedirectAutomatic; - csw->clients = 0; - dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw); - } - /* - * Redirect all existing windows - */ - for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) - { - int ret = compRedirectWindow (pClient, pChild, update); - if (ret != Success) - { - for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib) - (void) compUnredirectWindow (pClient, pChild, update); - if (!csw->clients) - { - free(csw); - dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0); - } - free(ccw); - return ret; - } - } - /* - * Hook into subwindows list - */ - ccw->next = csw->clients; - csw->clients = ccw; - if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin)) - return BadAlloc; - if (ccw->update == CompositeRedirectManual) - { - csw->update = CompositeRedirectManual; - /* - * tell damage extension that damage events for this client are - * critical output - */ - DamageExtSetCritical (pClient, TRUE); - pWin->inhibitBGPaint = TRUE; - } - return Success; -} - -/* - * Free one of the per-client per-subwindows resources, - * which frees one redirect per subwindow - */ -void -compFreeClientSubwindows (WindowPtr pWin, XID id) -{ - CompSubwindowsPtr csw = GetCompSubwindows (pWin); - CompClientWindowPtr ccw, *prev; - WindowPtr pChild; - - if (!csw) - return; - for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) - { - if (ccw->id == id) - { - ClientPtr pClient = clients[CLIENT_ID(id)]; - - *prev = ccw->next; - if (ccw->update == CompositeRedirectManual) - { - /* - * tell damage extension that damage events for this client are - * critical output - */ - DamageExtSetCritical (pClient, FALSE); - csw->update = CompositeRedirectAutomatic; - pWin->inhibitBGPaint = FALSE; - if (pWin->mapped) - (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE); - } - - /* - * Unredirect all existing subwindows - */ - for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) - (void) compUnredirectWindow (pClient, pChild, ccw->update); - - free(ccw); - break; - } - } - - /* - * Check if all of the per-client records are gone - */ - if (!csw->clients) - { - dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL); - free(csw); - } -} - -/* - * This is easy, just free the appropriate resource. - */ - -int -compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) -{ - CompSubwindowsPtr csw = GetCompSubwindows (pWin); - CompClientWindowPtr ccw; - - if (!csw) - return BadValue; - for (ccw = csw->clients; ccw; ccw = ccw->next) - if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) - { - FreeResource (ccw->id, RT_NONE); - return Success; - } - return BadValue; -} - -/* - * Add redirection information for one subwindow (during reparent) - */ - -int -compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin) -{ - CompSubwindowsPtr csw = GetCompSubwindows (pParent); - CompClientWindowPtr ccw; - - if (!csw) - return Success; - for (ccw = csw->clients; ccw; ccw = ccw->next) - { - int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)], - pWin, ccw->update); - if (ret != Success) - return ret; - } - return Success; -} - -/* - * Remove redirection information for one subwindow (during reparent) - */ - -int -compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin) -{ - CompSubwindowsPtr csw = GetCompSubwindows (pParent); - CompClientWindowPtr ccw; - - if (!csw) - return Success; - for (ccw = csw->clients; ccw; ccw = ccw->next) - { - int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)], - pWin, ccw->update); - if (ret != Success) - return ret; - } - return Success; -} - -static PixmapPtr -compNewPixmap (WindowPtr pWin, int x, int y, int w, int h) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - WindowPtr pParent = pWin->parent; - PixmapPtr pPixmap; - - pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth, - CREATE_PIXMAP_USAGE_BACKING_PIXMAP); - - if (!pPixmap) - return 0; - - pPixmap->screen_x = x; - pPixmap->screen_y = y; - - if (pParent->drawable.depth == pWin->drawable.depth) - { - GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen); - - if (pGC) - { - ChangeGCVal val; - val.val = IncludeInferiors; - ChangeGC (NullClient, pGC, GCSubwindowMode, &val); - ValidateGC(&pPixmap->drawable, pGC); - (*pGC->ops->CopyArea) (&pParent->drawable, - &pPixmap->drawable, - pGC, - x - pParent->drawable.x, - y - pParent->drawable.y, - w, h, 0, 0); - FreeScratchGC (pGC); - } - } - else - { - PictFormatPtr pSrcFormat = compWindowFormat (pParent); - PictFormatPtr pDstFormat = compWindowFormat (pWin); - XID inferiors = IncludeInferiors; - int error; - - PicturePtr pSrcPicture = CreatePicture (None, - &pParent->drawable, - pSrcFormat, - CPSubwindowMode, - &inferiors, - serverClient, &error); - - PicturePtr pDstPicture = CreatePicture (None, - &pPixmap->drawable, - pDstFormat, - 0, 0, - serverClient, &error); - - if (pSrcPicture && pDstPicture) - { - CompositePicture (PictOpSrc, - pSrcPicture, - NULL, - pDstPicture, - x - pParent->drawable.x, - y - pParent->drawable.y, - 0, 0, 0, 0, w, h); - } - if (pSrcPicture) - FreePicture (pSrcPicture, 0); - if (pDstPicture) - FreePicture (pDstPicture, 0); - } - return pPixmap; -} - -Bool -compAllocPixmap (WindowPtr pWin) -{ - int bw = (int) pWin->borderWidth; - int x = pWin->drawable.x - bw; - int y = pWin->drawable.y - bw; - int w = pWin->drawable.width + (bw << 1); - int h = pWin->drawable.height + (bw << 1); - PixmapPtr pPixmap = compNewPixmap (pWin, x, y, w, h); - CompWindowPtr cw = GetCompWindow (pWin); - - if (!pPixmap) - return FALSE; - if (cw->update == CompositeRedirectAutomatic) - pWin->redirectDraw = RedirectDrawAutomatic; - else - pWin->redirectDraw = RedirectDrawManual; - - compSetPixmap (pWin, pPixmap); - cw->oldx = COMP_ORIGIN_INVALID; - cw->oldy = COMP_ORIGIN_INVALID; - cw->damageRegistered = FALSE; - if (cw->update == CompositeRedirectAutomatic) - { - DamageRegister (&pWin->drawable, cw->damage); - cw->damageRegistered = TRUE; - } - return TRUE; -} - -void -compSetParentPixmap (WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - PixmapPtr pParentPixmap; - CompWindowPtr cw = GetCompWindow (pWin); - - if (cw->damageRegistered) - { - DamageUnregister (&pWin->drawable, cw->damage); - cw->damageRegistered = FALSE; - DamageEmpty (cw->damage); - } - /* - * Move the parent-constrained border clip region back into - * the window so that ValidateTree will handle the unmap - * case correctly. Unmap adds the window borderClip to the - * parent exposed area; regions beyond the parent cause crashes - */ - RegionCopy(&pWin->borderClip, &cw->borderClip); - pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); - pWin->redirectDraw = RedirectDrawNone; - compSetPixmap (pWin, pParentPixmap); -} - -/* - * Make sure the pixmap is the right size and offset. Allocate a new - * pixmap to change size, adjust origin to change offset, leaving the - * old pixmap in cw->pOldPixmap so bits can be recovered - */ -Bool -compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y, - unsigned int w, unsigned int h, int bw) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin); - PixmapPtr pNew; - CompWindowPtr cw = GetCompWindow (pWin); - int pix_x, pix_y; - int pix_w, pix_h; - - assert (cw && pWin->redirectDraw != RedirectDrawNone); - cw->oldx = pOld->screen_x; - cw->oldy = pOld->screen_y; - pix_x = draw_x - bw; - pix_y = draw_y - bw; - pix_w = w + (bw << 1); - pix_h = h + (bw << 1); - if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) - { - pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h); - if (!pNew) - return FALSE; - cw->pOldPixmap = pOld; - compSetPixmap (pWin, pNew); - } - else - { - pNew = pOld; - cw->pOldPixmap = 0; - } - pNew->screen_x = pix_x; - pNew->screen_y = pix_y; - return TRUE; -} +/* + * 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" + +static void +compScreenUpdate (ScreenPtr pScreen) +{ + compCheckTree (pScreen); + compPaintChildrenToWindow (pScreen->root); +} + +static void +compBlockHandler (int i, + pointer blockData, + pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + CompScreenPtr cs = GetCompScreen (pScreen); + + pScreen->BlockHandler = cs->BlockHandler; + compScreenUpdate (pScreen); + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + /* Next damage will restore the block handler */ + cs->BlockHandler = NULL; +} + +static void +compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + WindowPtr pWin = (WindowPtr) closure; + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen (pScreen); + CompWindowPtr cw = GetCompWindow (pWin); + + if (!cs->BlockHandler) { + cs->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = compBlockHandler; + } + cw->damaged = TRUE; + + /* Mark the ancestors */ + pWin = pWin->parent; + while (pWin) { + if (pWin->damagedDescendants) + break; + pWin->damagedDescendants = TRUE; + pWin = pWin->parent; + } +} + +static void +compDestroyDamage (DamagePtr pDamage, void *closure) +{ + WindowPtr pWin = (WindowPtr) closure; + CompWindowPtr cw = GetCompWindow (pWin); + + cw->damage = 0; +} + +static Bool +compMarkWindows(WindowPtr pWin, + WindowPtr *ppLayerWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + if (!pWin->viewable) + return FALSE; + + (*pScreen->MarkOverlappedWindows)(pWin, pWin, &pLayerWin); + (*pScreen->MarkWindow)(pLayerWin->parent); + + *ppLayerWin = pLayerWin; + + return TRUE; +} + +static void +compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures)(pLayerWin->parent); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTOther); +} + +/* + * Redirect one window for one client + */ +int +compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) +{ + CompWindowPtr cw = GetCompWindow (pWin); + CompClientWindowPtr ccw; + CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); + WindowPtr pLayerWin; + Bool anyMarked = FALSE; + + if (pWin == cs->pOverlayWin) { + return Success; + } + + if (!pWin->parent) + return BadMatch; + + /* + * Only one Manual update is allowed + */ + if (cw && update == CompositeRedirectManual) + for (ccw = cw->clients; ccw; ccw = ccw->next) + if (ccw->update == CompositeRedirectManual) + return BadAccess; + + /* + * Allocate per-client per-window structure + * The client *could* allocate multiple, but while supported, + * it is not expected to be common + */ + ccw = malloc(sizeof (CompClientWindowRec)); + if (!ccw) + return BadAlloc; + ccw->id = FakeClientID (pClient->index); + ccw->update = update; + /* + * Now make sure there's a per-window structure to hang this from + */ + if (!cw) + { + cw = calloc (1,sizeof (CompWindowRec)); + if (!cw) + { + free(ccw); + return BadAlloc; + } + cw->damage = DamageCreate (compReportDamage, + compDestroyDamage, + DamageReportNonEmpty, + FALSE, + pWin->drawable.pScreen, + pWin); + if (!cw->damage) + { + free(ccw); + free(cw); + return BadAlloc; + } + + anyMarked = compMarkWindows (pWin, &pLayerWin); + + /* Make sure our borderClip is correct for ValidateTree */ + RegionNull(&cw->borderClip); + RegionCopy(&cw->borderClip, &pWin->borderClip); + cw->borderClipX = pWin->drawable.x; + cw->borderClipY = pWin->drawable.y; + cw->update = CompositeRedirectAutomatic; + cw->clients = 0; + cw->oldx = COMP_ORIGIN_INVALID; + cw->oldy = COMP_ORIGIN_INVALID; + cw->damageRegistered = FALSE; + cw->damaged = FALSE; + cw->pOldPixmap = NullPixmap; + dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); + } + ccw->next = cw->clients; + cw->clients = ccw; + if (!AddResource (ccw->id, CompositeClientWindowType, pWin)) + return BadAlloc; + if (ccw->update == CompositeRedirectManual) + { + if (!anyMarked) + anyMarked = compMarkWindows (pWin, &pLayerWin); + + if (cw->damageRegistered) + { + DamageUnregister (&pWin->drawable, cw->damage); + cw->damageRegistered = FALSE; + } + cw->update = CompositeRedirectManual; + } + else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { + if (!anyMarked) + anyMarked = compMarkWindows (pWin, &pLayerWin); + } + + if (!compCheckRedirect (pWin)) + { + FreeResource (ccw->id, RT_NONE); + return BadAlloc; + } + + if (anyMarked) + compHandleMarkedWindows (pWin, pLayerWin); + + return Success; +} + +void +compRestoreWindow (WindowPtr pWin, PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pParent = pWin->parent; + + if (pParent->drawable.depth == pWin->drawable.depth) { + GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen); + int bw = (int) pWin->borderWidth; + int x = bw; + int y = bw; + int w = pWin->drawable.width; + int h = pWin->drawable.height; + + if (pGC) { + ChangeGCVal val; + val.val = IncludeInferiors; + ChangeGC (NullClient, pGC, GCSubwindowMode, &val); + ValidateGC(&pWin->drawable, pGC); + (*pGC->ops->CopyArea) (&pPixmap->drawable, + &pWin->drawable, + pGC, + x, y, w, h, 0, 0); + FreeScratchGC (pGC); + } + } +} + +/* + * Free one of the per-client per-window resources, clearing + * redirect and the per-window pointer as appropriate + */ +void +compFreeClientWindow (WindowPtr pWin, XID id) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompWindowPtr cw = GetCompWindow (pWin); + CompClientWindowPtr ccw, *prev; + Bool anyMarked = FALSE; + WindowPtr pLayerWin; + PixmapPtr pPixmap = NULL; + + if (!cw) + return; + for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) + { + if (ccw->id == id) + { + *prev = ccw->next; + if (ccw->update == CompositeRedirectManual) + cw->update = CompositeRedirectAutomatic; + free(ccw); + break; + } + } + if (!cw->clients) + { + anyMarked = compMarkWindows (pWin, &pLayerWin); + + if (pWin->redirectDraw != RedirectDrawNone) { + pPixmap = (*pScreen->GetWindowPixmap) (pWin); + compSetParentPixmap (pWin); + } + + if (cw->damage) + DamageDestroy (cw->damage); + + RegionUninit(&cw->borderClip); + + dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL); + free(cw); + } + else if (cw->update == CompositeRedirectAutomatic && + !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) + { + anyMarked = compMarkWindows (pWin, &pLayerWin); + + DamageRegister (&pWin->drawable, cw->damage); + cw->damageRegistered = TRUE; + pWin->redirectDraw = RedirectDrawAutomatic; + DamageDamageRegion(&pWin->drawable, &pWin->borderSize); + } + + if (anyMarked) + compHandleMarkedWindows (pWin, pLayerWin); + + if (pPixmap) { + compRestoreWindow (pWin, pPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + } +} + +/* + * This is easy, just free the appropriate resource. + */ + +int +compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update) +{ + CompWindowPtr cw = GetCompWindow (pWin); + CompClientWindowPtr ccw; + + if (!cw) + return BadValue; + + for (ccw = cw->clients; ccw; ccw = ccw->next) + if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) + { + FreeResource (ccw->id, RT_NONE); + return Success; + } + return BadValue; +} + +/* + * Redirect all subwindows for one client + */ + +int +compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pWin); + CompClientWindowPtr ccw; + WindowPtr pChild; + + /* + * Only one Manual update is allowed + */ + if (csw && update == CompositeRedirectManual) + for (ccw = csw->clients; ccw; ccw = ccw->next) + if (ccw->update == CompositeRedirectManual) + return BadAccess; + /* + * Allocate per-client per-window structure + * The client *could* allocate multiple, but while supported, + * it is not expected to be common + */ + ccw = malloc(sizeof (CompClientWindowRec)); + if (!ccw) + return BadAlloc; + ccw->id = FakeClientID (pClient->index); + ccw->update = update; + /* + * Now make sure there's a per-window structure to hang this from + */ + if (!csw) + { + csw = malloc(sizeof (CompSubwindowsRec)); + if (!csw) + { + free(ccw); + return BadAlloc; + } + csw->update = CompositeRedirectAutomatic; + csw->clients = 0; + dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw); + } + /* + * Redirect all existing windows + */ + for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) + { + int ret = compRedirectWindow (pClient, pChild, update); + if (ret != Success) + { + for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib) + (void) compUnredirectWindow (pClient, pChild, update); + if (!csw->clients) + { + free(csw); + dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0); + } + free(ccw); + return ret; + } + } + /* + * Hook into subwindows list + */ + ccw->next = csw->clients; + csw->clients = ccw; + if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin)) + return BadAlloc; + if (ccw->update == CompositeRedirectManual) + { + csw->update = CompositeRedirectManual; + /* + * tell damage extension that damage events for this client are + * critical output + */ + DamageExtSetCritical (pClient, TRUE); + pWin->inhibitBGPaint = TRUE; + } + return Success; +} + +/* + * Free one of the per-client per-subwindows resources, + * which frees one redirect per subwindow + */ +void +compFreeClientSubwindows (WindowPtr pWin, XID id) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pWin); + CompClientWindowPtr ccw, *prev; + WindowPtr pChild; + + if (!csw) + return; + for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) + { + if (ccw->id == id) + { + ClientPtr pClient = clients[CLIENT_ID(id)]; + + *prev = ccw->next; + if (ccw->update == CompositeRedirectManual) + { + /* + * tell damage extension that damage events for this client are + * critical output + */ + DamageExtSetCritical (pClient, FALSE); + csw->update = CompositeRedirectAutomatic; + pWin->inhibitBGPaint = FALSE; + if (pWin->mapped) + (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE); + } + + /* + * Unredirect all existing subwindows + */ + for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) + (void) compUnredirectWindow (pClient, pChild, ccw->update); + + free(ccw); + break; + } + } + + /* + * Check if all of the per-client records are gone + */ + if (!csw->clients) + { + dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL); + free(csw); + } +} + +/* + * This is easy, just free the appropriate resource. + */ + +int +compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pWin); + CompClientWindowPtr ccw; + + if (!csw) + return BadValue; + for (ccw = csw->clients; ccw; ccw = ccw->next) + if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) + { + FreeResource (ccw->id, RT_NONE); + return Success; + } + return BadValue; +} + +/* + * Add redirection information for one subwindow (during reparent) + */ + +int +compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pParent); + CompClientWindowPtr ccw; + + if (!csw) + return Success; + for (ccw = csw->clients; ccw; ccw = ccw->next) + { + int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)], + pWin, ccw->update); + if (ret != Success) + return ret; + } + return Success; +} + +/* + * Remove redirection information for one subwindow (during reparent) + */ + +int +compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin) +{ + CompSubwindowsPtr csw = GetCompSubwindows (pParent); + CompClientWindowPtr ccw; + + if (!csw) + return Success; + for (ccw = csw->clients; ccw; ccw = ccw->next) + { + int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)], + pWin, ccw->update); + if (ret != Success) + return ret; + } + return Success; +} + +static PixmapPtr +compNewPixmap (WindowPtr pWin, int x, int y, int w, int h) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pParent = pWin->parent; + PixmapPtr pPixmap; + + pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth, + CREATE_PIXMAP_USAGE_BACKING_PIXMAP); + + if (!pPixmap) + return 0; + + pPixmap->screen_x = x; + pPixmap->screen_y = y; + + if (pParent->drawable.depth == pWin->drawable.depth) + { + GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen); + + if (pGC) + { + ChangeGCVal val; + val.val = IncludeInferiors; + ChangeGC (NullClient, pGC, GCSubwindowMode, &val); + ValidateGC(&pPixmap->drawable, pGC); + (*pGC->ops->CopyArea) (&pParent->drawable, + &pPixmap->drawable, + pGC, + x - pParent->drawable.x, + y - pParent->drawable.y, + w, h, 0, 0); + FreeScratchGC (pGC); + } + } + else + { + PictFormatPtr pSrcFormat = compWindowFormat (pParent); + PictFormatPtr pDstFormat = compWindowFormat (pWin); + XID inferiors = IncludeInferiors; + int error; + + PicturePtr pSrcPicture = CreatePicture (None, + &pParent->drawable, + pSrcFormat, + CPSubwindowMode, + &inferiors, + serverClient, &error); + + PicturePtr pDstPicture = CreatePicture (None, + &pPixmap->drawable, + pDstFormat, + 0, 0, + serverClient, &error); + + if (pSrcPicture && pDstPicture) + { + CompositePicture (PictOpSrc, + pSrcPicture, + NULL, + pDstPicture, + x - pParent->drawable.x, + y - pParent->drawable.y, + 0, 0, 0, 0, w, h); + } + if (pSrcPicture) + FreePicture (pSrcPicture, 0); + if (pDstPicture) + FreePicture (pDstPicture, 0); + } + return pPixmap; +} + +Bool +compAllocPixmap (WindowPtr pWin) +{ + int bw = (int) pWin->borderWidth; + int x = pWin->drawable.x - bw; + int y = pWin->drawable.y - bw; + int w = pWin->drawable.width + (bw << 1); + int h = pWin->drawable.height + (bw << 1); + PixmapPtr pPixmap = compNewPixmap (pWin, x, y, w, h); + CompWindowPtr cw = GetCompWindow (pWin); + + if (!pPixmap) + return FALSE; + if (cw->update == CompositeRedirectAutomatic) + pWin->redirectDraw = RedirectDrawAutomatic; + else + pWin->redirectDraw = RedirectDrawManual; + + compSetPixmap (pWin, pPixmap); + cw->oldx = COMP_ORIGIN_INVALID; + cw->oldy = COMP_ORIGIN_INVALID; + cw->damageRegistered = FALSE; + if (cw->update == CompositeRedirectAutomatic) + { + DamageRegister (&pWin->drawable, cw->damage); + cw->damageRegistered = TRUE; + } + return TRUE; +} + +void +compSetParentPixmap (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + PixmapPtr pParentPixmap; + CompWindowPtr cw = GetCompWindow (pWin); + + if (cw->damageRegistered) + { + DamageUnregister (&pWin->drawable, cw->damage); + cw->damageRegistered = FALSE; + DamageEmpty (cw->damage); + } + /* + * Move the parent-constrained border clip region back into + * the window so that ValidateTree will handle the unmap + * case correctly. Unmap adds the window borderClip to the + * parent exposed area; regions beyond the parent cause crashes + */ + RegionCopy(&pWin->borderClip, &cw->borderClip); + pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); + pWin->redirectDraw = RedirectDrawNone; + compSetPixmap (pWin, pParentPixmap); +} + +/* + * Make sure the pixmap is the right size and offset. Allocate a new + * pixmap to change size, adjust origin to change offset, leaving the + * old pixmap in cw->pOldPixmap so bits can be recovered + */ +Bool +compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y, + unsigned int w, unsigned int h, int bw) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin); + PixmapPtr pNew; + CompWindowPtr cw = GetCompWindow (pWin); + int pix_x, pix_y; + int pix_w, pix_h; + + assert (cw && pWin->redirectDraw != RedirectDrawNone); + cw->oldx = pOld->screen_x; + cw->oldy = pOld->screen_y; + pix_x = draw_x - bw; + pix_y = draw_y - bw; + pix_w = w + (bw << 1); + pix_h = h + (bw << 1); + if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) + { + pNew = compNewPixmap (pWin, pix_x, pix_y, pix_w, pix_h); + if (!pNew) + return FALSE; + cw->pOldPixmap = pOld; + compSetPixmap (pWin, pNew); + } + else + { + pNew = pOld; + cw->pOldPixmap = 0; + } + pNew->screen_x = pix_x; + pNew->screen_y = pix_y; + return TRUE; +} -- cgit v1.2.3