105b261ecSmrg/* 29ace9065Smrg * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. 305b261ecSmrg * 46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 56747b715Smrg * copy of this software and associated documentation files (the "Software"), 66747b715Smrg * to deal in the Software without restriction, including without limitation 76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 96747b715Smrg * Software is furnished to do so, subject to the following conditions: 1005b261ecSmrg * 116747b715Smrg * The above copyright notice and this permission notice (including the next 126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 136747b715Smrg * Software. 146747b715Smrg * 156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 216747b715Smrg * DEALINGS IN THE SOFTWARE. 2205b261ecSmrg * 2305b261ecSmrg * Copyright © 2003 Keith Packard 2405b261ecSmrg * 2505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 2605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 2705b261ecSmrg * the above copyright notice appear in all copies and that both that 2805b261ecSmrg * copyright notice and this permission notice appear in supporting 2905b261ecSmrg * documentation, and that the name of Keith Packard not be used in 3005b261ecSmrg * advertising or publicity pertaining to distribution of the software without 3105b261ecSmrg * specific, written prior permission. Keith Packard makes no 3205b261ecSmrg * representations about the suitability of this software for any purpose. It 3305b261ecSmrg * is provided "as is" without express or implied warranty. 3405b261ecSmrg * 3505b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 3605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 3705b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 3805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 3905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 4005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 4105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 4205b261ecSmrg */ 4305b261ecSmrg 4405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 4505b261ecSmrg#include <dix-config.h> 4605b261ecSmrg#endif 4705b261ecSmrg 4805b261ecSmrg#include "compint.h" 4905b261ecSmrg 501b5d61b8Smrgstatic Bool 511b5d61b8SmrgcompScreenUpdate(ClientPtr pClient, void *closure) 529ace9065Smrg{ 531b5d61b8Smrg ScreenPtr pScreen = closure; 541b5d61b8Smrg CompScreenPtr cs = GetCompScreen(pScreen); 551b5d61b8Smrg 5635c4bbdfSmrg compCheckTree(pScreen); 5735c4bbdfSmrg compPaintChildrenToWindow(pScreen->root); 581b5d61b8Smrg 591b5d61b8Smrg /* Next damage will restore the worker */ 601b5d61b8Smrg cs->pendingScreenUpdate = FALSE; 611b5d61b8Smrg return TRUE; 629ace9065Smrg} 639ace9065Smrg 641b5d61b8Smrgvoid 651b5d61b8SmrgcompMarkAncestors(WindowPtr pWin) 669ace9065Smrg{ 671b5d61b8Smrg pWin = pWin->parent; 681b5d61b8Smrg while (pWin) { 691b5d61b8Smrg if (pWin->damagedDescendants) 701b5d61b8Smrg return; 711b5d61b8Smrg pWin->damagedDescendants = TRUE; 721b5d61b8Smrg pWin = pWin->parent; 731b5d61b8Smrg } 749ace9065Smrg} 759ace9065Smrg 7605b261ecSmrgstatic void 7735c4bbdfSmrgcompReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure) 7805b261ecSmrg{ 7935c4bbdfSmrg WindowPtr pWin = (WindowPtr) closure; 8035c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 8135c4bbdfSmrg CompScreenPtr cs = GetCompScreen(pScreen); 8235c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 8305b261ecSmrg 841b5d61b8Smrg if (!cs->pendingScreenUpdate) { 851b5d61b8Smrg QueueWorkProc(compScreenUpdate, serverClient, pScreen); 861b5d61b8Smrg cs->pendingScreenUpdate = TRUE; 879ace9065Smrg } 8805b261ecSmrg cw->damaged = TRUE; 899ace9065Smrg 901b5d61b8Smrg compMarkAncestors(pWin); 9105b261ecSmrg} 9205b261ecSmrg 9305b261ecSmrgstatic void 9435c4bbdfSmrgcompDestroyDamage(DamagePtr pDamage, void *closure) 9505b261ecSmrg{ 9635c4bbdfSmrg WindowPtr pWin = (WindowPtr) closure; 9735c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 9805b261ecSmrg 9905b261ecSmrg cw->damage = 0; 100ed6184dfSmrg cw->damaged = 0; 101ed6184dfSmrg cw->damageRegistered = 0; 10205b261ecSmrg} 10305b261ecSmrg 10435c4bbdfSmrgstatic Bool 10535c4bbdfSmrgcompMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin) 10635c4bbdfSmrg{ 10735c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 10835c4bbdfSmrg WindowPtr pLayerWin = pWin; 10935c4bbdfSmrg 11035c4bbdfSmrg if (!pWin->viewable) 11135c4bbdfSmrg return FALSE; 11235c4bbdfSmrg 11335c4bbdfSmrg (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); 11435c4bbdfSmrg (*pScreen->MarkWindow) (pLayerWin->parent); 11535c4bbdfSmrg 11635c4bbdfSmrg *ppLayerWin = pLayerWin; 11735c4bbdfSmrg 11835c4bbdfSmrg return TRUE; 11935c4bbdfSmrg} 12035c4bbdfSmrg 12135c4bbdfSmrgstatic void 12235c4bbdfSmrgcompHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin) 12335c4bbdfSmrg{ 12435c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 12535c4bbdfSmrg 12635c4bbdfSmrg (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther); 12735c4bbdfSmrg (*pScreen->HandleExposures) (pLayerWin->parent); 12835c4bbdfSmrg if (pScreen->PostValidateTree) 12935c4bbdfSmrg (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther); 13035c4bbdfSmrg} 13135c4bbdfSmrg 13205b261ecSmrg/* 13305b261ecSmrg * Redirect one window for one client 13405b261ecSmrg */ 13505b261ecSmrgint 13635c4bbdfSmrgcompRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update) 13705b261ecSmrg{ 13835c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 13935c4bbdfSmrg CompClientWindowPtr ccw; 14035c4bbdfSmrg CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); 14135c4bbdfSmrg WindowPtr pLayerWin; 14235c4bbdfSmrg Bool anyMarked = FALSE; 143f2346221Smrg int status = Success; 14435c4bbdfSmrg 14505b261ecSmrg if (pWin == cs->pOverlayWin) { 14635c4bbdfSmrg return Success; 14705b261ecSmrg } 14805b261ecSmrg 1494642e01fSmrg if (!pWin->parent) 15035c4bbdfSmrg return BadMatch; 1514642e01fSmrg 15205b261ecSmrg /* 15305b261ecSmrg * Only one Manual update is allowed 15405b261ecSmrg */ 15505b261ecSmrg if (cw && update == CompositeRedirectManual) 15635c4bbdfSmrg for (ccw = cw->clients; ccw; ccw = ccw->next) 15735c4bbdfSmrg if (ccw->update == CompositeRedirectManual) 15835c4bbdfSmrg return BadAccess; 15935c4bbdfSmrg 16005b261ecSmrg /* 16135c4bbdfSmrg * Allocate per-client per-window structure 16205b261ecSmrg * The client *could* allocate multiple, but while supported, 16305b261ecSmrg * it is not expected to be common 16405b261ecSmrg */ 16535c4bbdfSmrg ccw = malloc(sizeof(CompClientWindowRec)); 16605b261ecSmrg if (!ccw) 16735c4bbdfSmrg return BadAlloc; 16835c4bbdfSmrg ccw->id = FakeClientID(pClient->index); 16905b261ecSmrg ccw->update = update; 17005b261ecSmrg /* 17105b261ecSmrg * Now make sure there's a per-window structure to hang this from 17205b261ecSmrg */ 17335c4bbdfSmrg if (!cw) { 17435c4bbdfSmrg cw = malloc(sizeof(CompWindowRec)); 17535c4bbdfSmrg if (!cw) { 17635c4bbdfSmrg free(ccw); 17735c4bbdfSmrg return BadAlloc; 17835c4bbdfSmrg } 17935c4bbdfSmrg cw->damage = DamageCreate(compReportDamage, 18035c4bbdfSmrg compDestroyDamage, 18135c4bbdfSmrg DamageReportNonEmpty, 18235c4bbdfSmrg FALSE, pWin->drawable.pScreen, pWin); 18335c4bbdfSmrg if (!cw->damage) { 18435c4bbdfSmrg free(ccw); 18535c4bbdfSmrg free(cw); 18635c4bbdfSmrg return BadAlloc; 18735c4bbdfSmrg } 18835c4bbdfSmrg 18935c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 19035c4bbdfSmrg 19135c4bbdfSmrg RegionNull(&cw->borderClip); 19235c4bbdfSmrg cw->update = CompositeRedirectAutomatic; 19335c4bbdfSmrg cw->clients = 0; 19435c4bbdfSmrg cw->oldx = COMP_ORIGIN_INVALID; 19535c4bbdfSmrg cw->oldy = COMP_ORIGIN_INVALID; 19635c4bbdfSmrg cw->damageRegistered = FALSE; 19735c4bbdfSmrg cw->damaged = FALSE; 19835c4bbdfSmrg cw->pOldPixmap = NullPixmap; 19935c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); 20005b261ecSmrg } 20105b261ecSmrg ccw->next = cw->clients; 20205b261ecSmrg cw->clients = ccw; 20335c4bbdfSmrg if (!AddResource(ccw->id, CompositeClientWindowType, pWin)) 20435c4bbdfSmrg return BadAlloc; 20535c4bbdfSmrg if (ccw->update == CompositeRedirectManual) { 20635c4bbdfSmrg if (!anyMarked) 20735c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 20835c4bbdfSmrg 20935c4bbdfSmrg if (cw->damageRegistered) { 21035c4bbdfSmrg DamageUnregister(cw->damage); 21135c4bbdfSmrg cw->damageRegistered = FALSE; 21235c4bbdfSmrg } 21335c4bbdfSmrg cw->update = CompositeRedirectManual; 21405b261ecSmrg } 21535c4bbdfSmrg else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { 21635c4bbdfSmrg if (!anyMarked) 21735c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 21805b261ecSmrg } 21935c4bbdfSmrg 22035c4bbdfSmrg if (!compCheckRedirect(pWin)) { 22135c4bbdfSmrg FreeResource(ccw->id, RT_NONE); 222f2346221Smrg status = BadAlloc; 22305b261ecSmrg } 22435c4bbdfSmrg 22535c4bbdfSmrg if (anyMarked) 22635c4bbdfSmrg compHandleMarkedWindows(pWin, pLayerWin); 22735c4bbdfSmrg 228f2346221Smrg return status; 22905b261ecSmrg} 23005b261ecSmrg 23135c4bbdfSmrgvoid 23235c4bbdfSmrgcompRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap) 23335c4bbdfSmrg{ 23435c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 23535c4bbdfSmrg WindowPtr pParent = pWin->parent; 23635c4bbdfSmrg 23735c4bbdfSmrg if (pParent->drawable.depth == pWin->drawable.depth) { 23835c4bbdfSmrg GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); 23935c4bbdfSmrg int bw = (int) pWin->borderWidth; 24035c4bbdfSmrg int x = bw; 24135c4bbdfSmrg int y = bw; 24235c4bbdfSmrg int w = pWin->drawable.width; 24335c4bbdfSmrg int h = pWin->drawable.height; 24435c4bbdfSmrg 24535c4bbdfSmrg if (pGC) { 24635c4bbdfSmrg ChangeGCVal val; 24735c4bbdfSmrg 24835c4bbdfSmrg val.val = IncludeInferiors; 24935c4bbdfSmrg ChangeGC(NullClient, pGC, GCSubwindowMode, &val); 25035c4bbdfSmrg ValidateGC(&pWin->drawable, pGC); 25135c4bbdfSmrg (*pGC->ops->CopyArea) (&pPixmap->drawable, 25235c4bbdfSmrg &pWin->drawable, pGC, x, y, w, h, 0, 0); 25335c4bbdfSmrg FreeScratchGC(pGC); 25435c4bbdfSmrg } 25535c4bbdfSmrg } 25635c4bbdfSmrg} 25735c4bbdfSmrg 25805b261ecSmrg/* 25905b261ecSmrg * Free one of the per-client per-window resources, clearing 26005b261ecSmrg * redirect and the per-window pointer as appropriate 26105b261ecSmrg */ 26205b261ecSmrgvoid 26335c4bbdfSmrgcompFreeClientWindow(WindowPtr pWin, XID id) 26405b261ecSmrg{ 26535c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 26635c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 26735c4bbdfSmrg CompClientWindowPtr ccw, *prev; 26835c4bbdfSmrg Bool anyMarked = FALSE; 26935c4bbdfSmrg WindowPtr pLayerWin; 27035c4bbdfSmrg PixmapPtr pPixmap = NULL; 27105b261ecSmrg 27205b261ecSmrg if (!cw) 27335c4bbdfSmrg return; 27435c4bbdfSmrg for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) { 27535c4bbdfSmrg if (ccw->id == id) { 27635c4bbdfSmrg *prev = ccw->next; 27735c4bbdfSmrg if (ccw->update == CompositeRedirectManual) 27835c4bbdfSmrg cw->update = CompositeRedirectAutomatic; 27935c4bbdfSmrg free(ccw); 28035c4bbdfSmrg break; 28135c4bbdfSmrg } 28205b261ecSmrg } 28335c4bbdfSmrg if (!cw->clients) { 28435c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 28535c4bbdfSmrg 28635c4bbdfSmrg if (pWin->redirectDraw != RedirectDrawNone) { 28735c4bbdfSmrg pPixmap = (*pScreen->GetWindowPixmap) (pWin); 28835c4bbdfSmrg compSetParentPixmap(pWin); 28935c4bbdfSmrg } 29035c4bbdfSmrg 29135c4bbdfSmrg if (cw->damage) 29235c4bbdfSmrg DamageDestroy(cw->damage); 29335c4bbdfSmrg 29435c4bbdfSmrg RegionUninit(&cw->borderClip); 29535c4bbdfSmrg 29635c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL); 29735c4bbdfSmrg free(cw); 29805b261ecSmrg } 29905b261ecSmrg else if (cw->update == CompositeRedirectAutomatic && 30035c4bbdfSmrg !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) { 30135c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 30235c4bbdfSmrg 30335c4bbdfSmrg DamageRegister(&pWin->drawable, cw->damage); 30435c4bbdfSmrg cw->damageRegistered = TRUE; 30535c4bbdfSmrg pWin->redirectDraw = RedirectDrawAutomatic; 30635c4bbdfSmrg DamageDamageRegion(&pWin->drawable, &pWin->borderSize); 30705b261ecSmrg } 30835c4bbdfSmrg 30935c4bbdfSmrg if (anyMarked) 31035c4bbdfSmrg compHandleMarkedWindows(pWin, pLayerWin); 31135c4bbdfSmrg 31235c4bbdfSmrg if (pPixmap) { 31335c4bbdfSmrg compRestoreWindow(pWin, pPixmap); 31435c4bbdfSmrg (*pScreen->DestroyPixmap) (pPixmap); 31505b261ecSmrg } 31605b261ecSmrg} 31705b261ecSmrg 31805b261ecSmrg/* 31905b261ecSmrg * This is easy, just free the appropriate resource. 32005b261ecSmrg */ 32105b261ecSmrg 32205b261ecSmrgint 32335c4bbdfSmrgcompUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update) 32405b261ecSmrg{ 32535c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 32635c4bbdfSmrg CompClientWindowPtr ccw; 32705b261ecSmrg 32805b261ecSmrg if (!cw) 32935c4bbdfSmrg return BadValue; 33005b261ecSmrg 33105b261ecSmrg for (ccw = cw->clients; ccw; ccw = ccw->next) 33235c4bbdfSmrg if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) { 33335c4bbdfSmrg FreeResource(ccw->id, RT_NONE); 33435c4bbdfSmrg return Success; 33535c4bbdfSmrg } 33605b261ecSmrg return BadValue; 33705b261ecSmrg} 33835c4bbdfSmrg 33905b261ecSmrg/* 34005b261ecSmrg * Redirect all subwindows for one client 34105b261ecSmrg */ 34205b261ecSmrg 34305b261ecSmrgint 34435c4bbdfSmrgcompRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update) 34505b261ecSmrg{ 34635c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pWin); 34735c4bbdfSmrg CompClientWindowPtr ccw; 34835c4bbdfSmrg WindowPtr pChild; 34905b261ecSmrg 35005b261ecSmrg /* 35105b261ecSmrg * Only one Manual update is allowed 35205b261ecSmrg */ 35305b261ecSmrg if (csw && update == CompositeRedirectManual) 35435c4bbdfSmrg for (ccw = csw->clients; ccw; ccw = ccw->next) 35535c4bbdfSmrg if (ccw->update == CompositeRedirectManual) 35635c4bbdfSmrg return BadAccess; 35705b261ecSmrg /* 35835c4bbdfSmrg * Allocate per-client per-window structure 35905b261ecSmrg * The client *could* allocate multiple, but while supported, 36005b261ecSmrg * it is not expected to be common 36105b261ecSmrg */ 36235c4bbdfSmrg ccw = malloc(sizeof(CompClientWindowRec)); 36305b261ecSmrg if (!ccw) 36435c4bbdfSmrg return BadAlloc; 36535c4bbdfSmrg ccw->id = FakeClientID(pClient->index); 36605b261ecSmrg ccw->update = update; 36705b261ecSmrg /* 36805b261ecSmrg * Now make sure there's a per-window structure to hang this from 36905b261ecSmrg */ 37035c4bbdfSmrg if (!csw) { 37135c4bbdfSmrg csw = malloc(sizeof(CompSubwindowsRec)); 37235c4bbdfSmrg if (!csw) { 37335c4bbdfSmrg free(ccw); 37435c4bbdfSmrg return BadAlloc; 37535c4bbdfSmrg } 37635c4bbdfSmrg csw->update = CompositeRedirectAutomatic; 37735c4bbdfSmrg csw->clients = 0; 37835c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw); 37905b261ecSmrg } 38005b261ecSmrg /* 38105b261ecSmrg * Redirect all existing windows 38205b261ecSmrg */ 38335c4bbdfSmrg for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) { 38435c4bbdfSmrg int ret = compRedirectWindow(pClient, pChild, update); 38535c4bbdfSmrg 38635c4bbdfSmrg if (ret != Success) { 38735c4bbdfSmrg for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib) 38835c4bbdfSmrg (void) compUnredirectWindow(pClient, pChild, update); 38935c4bbdfSmrg if (!csw->clients) { 39035c4bbdfSmrg free(csw); 39135c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0); 39235c4bbdfSmrg } 39335c4bbdfSmrg free(ccw); 39435c4bbdfSmrg return ret; 39535c4bbdfSmrg } 39605b261ecSmrg } 39705b261ecSmrg /* 39805b261ecSmrg * Hook into subwindows list 39905b261ecSmrg */ 40005b261ecSmrg ccw->next = csw->clients; 40105b261ecSmrg csw->clients = ccw; 40235c4bbdfSmrg if (!AddResource(ccw->id, CompositeClientSubwindowsType, pWin)) 40335c4bbdfSmrg return BadAlloc; 40435c4bbdfSmrg if (ccw->update == CompositeRedirectManual) { 40535c4bbdfSmrg csw->update = CompositeRedirectManual; 40635c4bbdfSmrg /* 40735c4bbdfSmrg * tell damage extension that damage events for this client are 40835c4bbdfSmrg * critical output 40935c4bbdfSmrg */ 41035c4bbdfSmrg DamageExtSetCritical(pClient, TRUE); 41135c4bbdfSmrg pWin->inhibitBGPaint = TRUE; 41205b261ecSmrg } 41305b261ecSmrg return Success; 41405b261ecSmrg} 41505b261ecSmrg 41605b261ecSmrg/* 41705b261ecSmrg * Free one of the per-client per-subwindows resources, 41805b261ecSmrg * which frees one redirect per subwindow 41905b261ecSmrg */ 42005b261ecSmrgvoid 42135c4bbdfSmrgcompFreeClientSubwindows(WindowPtr pWin, XID id) 42205b261ecSmrg{ 42335c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pWin); 42435c4bbdfSmrg CompClientWindowPtr ccw, *prev; 42535c4bbdfSmrg WindowPtr pChild; 42605b261ecSmrg 42705b261ecSmrg if (!csw) 42835c4bbdfSmrg return; 42935c4bbdfSmrg for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) { 43035c4bbdfSmrg if (ccw->id == id) { 43135c4bbdfSmrg ClientPtr pClient = clients[CLIENT_ID(id)]; 43235c4bbdfSmrg 43335c4bbdfSmrg *prev = ccw->next; 43435c4bbdfSmrg if (ccw->update == CompositeRedirectManual) { 43535c4bbdfSmrg /* 43635c4bbdfSmrg * tell damage extension that damage events for this client are 43735c4bbdfSmrg * critical output 43835c4bbdfSmrg */ 43935c4bbdfSmrg DamageExtSetCritical(pClient, FALSE); 44035c4bbdfSmrg csw->update = CompositeRedirectAutomatic; 44135c4bbdfSmrg pWin->inhibitBGPaint = FALSE; 44235c4bbdfSmrg if (pWin->mapped) 44335c4bbdfSmrg (*pWin->drawable.pScreen->ClearToBackground) (pWin, 0, 0, 0, 44435c4bbdfSmrg 0, TRUE); 44535c4bbdfSmrg } 44635c4bbdfSmrg 44735c4bbdfSmrg /* 44835c4bbdfSmrg * Unredirect all existing subwindows 44935c4bbdfSmrg */ 45035c4bbdfSmrg for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) 45135c4bbdfSmrg (void) compUnredirectWindow(pClient, pChild, ccw->update); 45235c4bbdfSmrg 45335c4bbdfSmrg free(ccw); 45435c4bbdfSmrg break; 45535c4bbdfSmrg } 45605b261ecSmrg } 45705b261ecSmrg 45805b261ecSmrg /* 45905b261ecSmrg * Check if all of the per-client records are gone 46005b261ecSmrg */ 46135c4bbdfSmrg if (!csw->clients) { 46235c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL); 46335c4bbdfSmrg free(csw); 46405b261ecSmrg } 46505b261ecSmrg} 46605b261ecSmrg 46705b261ecSmrg/* 46805b261ecSmrg * This is easy, just free the appropriate resource. 46905b261ecSmrg */ 47005b261ecSmrg 47105b261ecSmrgint 47235c4bbdfSmrgcompUnredirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update) 47305b261ecSmrg{ 47435c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pWin); 47535c4bbdfSmrg CompClientWindowPtr ccw; 47635c4bbdfSmrg 47705b261ecSmrg if (!csw) 47835c4bbdfSmrg return BadValue; 47905b261ecSmrg for (ccw = csw->clients; ccw; ccw = ccw->next) 48035c4bbdfSmrg if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) { 48135c4bbdfSmrg FreeResource(ccw->id, RT_NONE); 48235c4bbdfSmrg return Success; 48335c4bbdfSmrg } 48405b261ecSmrg return BadValue; 48505b261ecSmrg} 48605b261ecSmrg 48705b261ecSmrg/* 48805b261ecSmrg * Add redirection information for one subwindow (during reparent) 48905b261ecSmrg */ 49005b261ecSmrg 49105b261ecSmrgint 49235c4bbdfSmrgcompRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin) 49305b261ecSmrg{ 49435c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pParent); 49535c4bbdfSmrg CompClientWindowPtr ccw; 49605b261ecSmrg 49705b261ecSmrg if (!csw) 49835c4bbdfSmrg return Success; 49935c4bbdfSmrg for (ccw = csw->clients; ccw; ccw = ccw->next) { 50035c4bbdfSmrg int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)], 50135c4bbdfSmrg pWin, ccw->update); 50235c4bbdfSmrg 50335c4bbdfSmrg if (ret != Success) 50435c4bbdfSmrg return ret; 50505b261ecSmrg } 50605b261ecSmrg return Success; 50705b261ecSmrg} 50805b261ecSmrg 50905b261ecSmrg/* 51005b261ecSmrg * Remove redirection information for one subwindow (during reparent) 51105b261ecSmrg */ 51205b261ecSmrg 51305b261ecSmrgint 51435c4bbdfSmrgcompUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin) 51505b261ecSmrg{ 51635c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pParent); 51735c4bbdfSmrg CompClientWindowPtr ccw; 51805b261ecSmrg 51905b261ecSmrg if (!csw) 52035c4bbdfSmrg return Success; 52135c4bbdfSmrg for (ccw = csw->clients; ccw; ccw = ccw->next) { 52235c4bbdfSmrg int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)], 52335c4bbdfSmrg pWin, ccw->update); 52435c4bbdfSmrg 52535c4bbdfSmrg if (ret != Success) 52635c4bbdfSmrg return ret; 52705b261ecSmrg } 52805b261ecSmrg return Success; 52905b261ecSmrg} 53005b261ecSmrg 53105b261ecSmrgstatic PixmapPtr 53235c4bbdfSmrgcompNewPixmap(WindowPtr pWin, int x, int y, int w, int h) 53305b261ecSmrg{ 53435c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 53535c4bbdfSmrg WindowPtr pParent = pWin->parent; 53635c4bbdfSmrg PixmapPtr pPixmap; 53705b261ecSmrg 5384642e01fSmrg pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth, 53935c4bbdfSmrg CREATE_PIXMAP_USAGE_BACKING_PIXMAP); 54005b261ecSmrg 54105b261ecSmrg if (!pPixmap) 54235c4bbdfSmrg return 0; 54335c4bbdfSmrg 54405b261ecSmrg pPixmap->screen_x = x; 54505b261ecSmrg pPixmap->screen_y = y; 5469ace9065Smrg 54735c4bbdfSmrg if (pParent->drawable.depth == pWin->drawable.depth) { 54835c4bbdfSmrg GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); 54935c4bbdfSmrg 55035c4bbdfSmrg if (pGC) { 55135c4bbdfSmrg ChangeGCVal val; 55235c4bbdfSmrg 55335c4bbdfSmrg val.val = IncludeInferiors; 55435c4bbdfSmrg ChangeGC(NullClient, pGC, GCSubwindowMode, &val); 55535c4bbdfSmrg ValidateGC(&pPixmap->drawable, pGC); 55635c4bbdfSmrg (*pGC->ops->CopyArea) (&pParent->drawable, 55735c4bbdfSmrg &pPixmap->drawable, 55835c4bbdfSmrg pGC, 55935c4bbdfSmrg x - pParent->drawable.x, 56035c4bbdfSmrg y - pParent->drawable.y, w, h, 0, 0); 56135c4bbdfSmrg FreeScratchGC(pGC); 56235c4bbdfSmrg } 56305b261ecSmrg } 56435c4bbdfSmrg else { 56535c4bbdfSmrg PictFormatPtr pSrcFormat = PictureWindowFormat(pParent); 56635c4bbdfSmrg PictFormatPtr pDstFormat = PictureWindowFormat(pWin); 56735c4bbdfSmrg XID inferiors = IncludeInferiors; 56835c4bbdfSmrg int error; 56935c4bbdfSmrg 57035c4bbdfSmrg PicturePtr pSrcPicture = CreatePicture(None, 57135c4bbdfSmrg &pParent->drawable, 57235c4bbdfSmrg pSrcFormat, 57335c4bbdfSmrg CPSubwindowMode, 57435c4bbdfSmrg &inferiors, 57535c4bbdfSmrg serverClient, &error); 57635c4bbdfSmrg 57735c4bbdfSmrg PicturePtr pDstPicture = CreatePicture(None, 57835c4bbdfSmrg &pPixmap->drawable, 57935c4bbdfSmrg pDstFormat, 58035c4bbdfSmrg 0, 0, 58135c4bbdfSmrg serverClient, &error); 58235c4bbdfSmrg 58335c4bbdfSmrg if (pSrcPicture && pDstPicture) { 58435c4bbdfSmrg CompositePicture(PictOpSrc, 58535c4bbdfSmrg pSrcPicture, 58635c4bbdfSmrg NULL, 58735c4bbdfSmrg pDstPicture, 58835c4bbdfSmrg x - pParent->drawable.x, 58935c4bbdfSmrg y - pParent->drawable.y, 0, 0, 0, 0, w, h); 59035c4bbdfSmrg } 59135c4bbdfSmrg if (pSrcPicture) 59235c4bbdfSmrg FreePicture(pSrcPicture, 0); 59335c4bbdfSmrg if (pDstPicture) 59435c4bbdfSmrg FreePicture(pDstPicture, 0); 59505b261ecSmrg } 59605b261ecSmrg return pPixmap; 59705b261ecSmrg} 59805b261ecSmrg 59905b261ecSmrgBool 60035c4bbdfSmrgcompAllocPixmap(WindowPtr pWin) 60105b261ecSmrg{ 60235c4bbdfSmrg int bw = (int) pWin->borderWidth; 60335c4bbdfSmrg int x = pWin->drawable.x - bw; 60435c4bbdfSmrg int y = pWin->drawable.y - bw; 60535c4bbdfSmrg int w = pWin->drawable.width + (bw << 1); 60635c4bbdfSmrg int h = pWin->drawable.height + (bw << 1); 60735c4bbdfSmrg PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h); 60835c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 609f2346221Smrg Bool status; 61005b261ecSmrg 611f2346221Smrg if (!pPixmap) { 612f2346221Smrg status = FALSE; 613f2346221Smrg goto out; 614f2346221Smrg } 61505b261ecSmrg if (cw->update == CompositeRedirectAutomatic) 61635c4bbdfSmrg pWin->redirectDraw = RedirectDrawAutomatic; 61705b261ecSmrg else 61835c4bbdfSmrg pWin->redirectDraw = RedirectDrawManual; 61905b261ecSmrg 6201b5d61b8Smrg compSetPixmap(pWin, pPixmap, bw); 62105b261ecSmrg cw->oldx = COMP_ORIGIN_INVALID; 62205b261ecSmrg cw->oldy = COMP_ORIGIN_INVALID; 62305b261ecSmrg cw->damageRegistered = FALSE; 62435c4bbdfSmrg if (cw->update == CompositeRedirectAutomatic) { 62535c4bbdfSmrg DamageRegister(&pWin->drawable, cw->damage); 62635c4bbdfSmrg cw->damageRegistered = TRUE; 62705b261ecSmrg } 628f2346221Smrg status = TRUE; 62935c4bbdfSmrg 630f2346221Smrgout: 63135c4bbdfSmrg /* Make sure our borderClip is up to date */ 63235c4bbdfSmrg RegionUninit(&cw->borderClip); 63335c4bbdfSmrg RegionCopy(&cw->borderClip, &pWin->borderClip); 63435c4bbdfSmrg cw->borderClipX = pWin->drawable.x; 63535c4bbdfSmrg cw->borderClipY = pWin->drawable.y; 63635c4bbdfSmrg 637f2346221Smrg return status; 63805b261ecSmrg} 63905b261ecSmrg 64005b261ecSmrgvoid 64135c4bbdfSmrgcompSetParentPixmap(WindowPtr pWin) 64205b261ecSmrg{ 64335c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 64435c4bbdfSmrg PixmapPtr pParentPixmap; 64535c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 64635c4bbdfSmrg 64735c4bbdfSmrg if (cw->damageRegistered) { 64835c4bbdfSmrg DamageUnregister(cw->damage); 64935c4bbdfSmrg cw->damageRegistered = FALSE; 65035c4bbdfSmrg DamageEmpty(cw->damage); 65105b261ecSmrg } 65205b261ecSmrg /* 65305b261ecSmrg * Move the parent-constrained border clip region back into 65405b261ecSmrg * the window so that ValidateTree will handle the unmap 65505b261ecSmrg * case correctly. Unmap adds the window borderClip to the 65605b261ecSmrg * parent exposed area; regions beyond the parent cause crashes 65705b261ecSmrg */ 6586747b715Smrg RegionCopy(&pWin->borderClip, &cw->borderClip); 65905b261ecSmrg pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); 66005b261ecSmrg pWin->redirectDraw = RedirectDrawNone; 6611b5d61b8Smrg compSetPixmap(pWin, pParentPixmap, pWin->borderWidth); 66205b261ecSmrg} 66305b261ecSmrg 66405b261ecSmrg/* 66505b261ecSmrg * Make sure the pixmap is the right size and offset. Allocate a new 66605b261ecSmrg * pixmap to change size, adjust origin to change offset, leaving the 66705b261ecSmrg * old pixmap in cw->pOldPixmap so bits can be recovered 66805b261ecSmrg */ 66905b261ecSmrgBool 67035c4bbdfSmrgcompReallocPixmap(WindowPtr pWin, int draw_x, int draw_y, 67135c4bbdfSmrg unsigned int w, unsigned int h, int bw) 67205b261ecSmrg{ 67335c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 67435c4bbdfSmrg PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin); 67535c4bbdfSmrg PixmapPtr pNew; 67635c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 67735c4bbdfSmrg int pix_x, pix_y; 67835c4bbdfSmrg int pix_w, pix_h; 67935c4bbdfSmrg 680ed6184dfSmrg assert(cw); 681ed6184dfSmrg assert(pWin->redirectDraw != RedirectDrawNone); 68205b261ecSmrg cw->oldx = pOld->screen_x; 68305b261ecSmrg cw->oldy = pOld->screen_y; 68405b261ecSmrg pix_x = draw_x - bw; 68505b261ecSmrg pix_y = draw_y - bw; 68605b261ecSmrg pix_w = w + (bw << 1); 68705b261ecSmrg pix_h = h + (bw << 1); 68835c4bbdfSmrg if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) { 68935c4bbdfSmrg pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h); 69035c4bbdfSmrg if (!pNew) 69135c4bbdfSmrg return FALSE; 69235c4bbdfSmrg cw->pOldPixmap = pOld; 6931b5d61b8Smrg compSetPixmap(pWin, pNew, bw); 69405b261ecSmrg } 69535c4bbdfSmrg else { 69635c4bbdfSmrg pNew = pOld; 69735c4bbdfSmrg cw->pOldPixmap = 0; 69805b261ecSmrg } 69905b261ecSmrg pNew->screen_x = pix_x; 70005b261ecSmrg pNew->screen_y = pix_y; 70105b261ecSmrg return TRUE; 70205b261ecSmrg} 703