compalloc.c revision 1b5d61b8
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; 10005b261ecSmrg} 10105b261ecSmrg 10235c4bbdfSmrgstatic Bool 10335c4bbdfSmrgcompMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin) 10435c4bbdfSmrg{ 10535c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 10635c4bbdfSmrg WindowPtr pLayerWin = pWin; 10735c4bbdfSmrg 10835c4bbdfSmrg if (!pWin->viewable) 10935c4bbdfSmrg return FALSE; 11035c4bbdfSmrg 11135c4bbdfSmrg (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); 11235c4bbdfSmrg (*pScreen->MarkWindow) (pLayerWin->parent); 11335c4bbdfSmrg 11435c4bbdfSmrg *ppLayerWin = pLayerWin; 11535c4bbdfSmrg 11635c4bbdfSmrg return TRUE; 11735c4bbdfSmrg} 11835c4bbdfSmrg 11935c4bbdfSmrgstatic void 12035c4bbdfSmrgcompHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin) 12135c4bbdfSmrg{ 12235c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 12335c4bbdfSmrg 12435c4bbdfSmrg (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther); 12535c4bbdfSmrg (*pScreen->HandleExposures) (pLayerWin->parent); 12635c4bbdfSmrg if (pScreen->PostValidateTree) 12735c4bbdfSmrg (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther); 12835c4bbdfSmrg} 12935c4bbdfSmrg 13005b261ecSmrg/* 13105b261ecSmrg * Redirect one window for one client 13205b261ecSmrg */ 13305b261ecSmrgint 13435c4bbdfSmrgcompRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update) 13505b261ecSmrg{ 13635c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 13735c4bbdfSmrg CompClientWindowPtr ccw; 13835c4bbdfSmrg CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); 13935c4bbdfSmrg WindowPtr pLayerWin; 14035c4bbdfSmrg Bool anyMarked = FALSE; 14135c4bbdfSmrg 14205b261ecSmrg if (pWin == cs->pOverlayWin) { 14335c4bbdfSmrg return Success; 14405b261ecSmrg } 14505b261ecSmrg 1464642e01fSmrg if (!pWin->parent) 14735c4bbdfSmrg return BadMatch; 1484642e01fSmrg 14905b261ecSmrg /* 15005b261ecSmrg * Only one Manual update is allowed 15105b261ecSmrg */ 15205b261ecSmrg if (cw && update == CompositeRedirectManual) 15335c4bbdfSmrg for (ccw = cw->clients; ccw; ccw = ccw->next) 15435c4bbdfSmrg if (ccw->update == CompositeRedirectManual) 15535c4bbdfSmrg return BadAccess; 15635c4bbdfSmrg 15705b261ecSmrg /* 15835c4bbdfSmrg * Allocate per-client per-window structure 15905b261ecSmrg * The client *could* allocate multiple, but while supported, 16005b261ecSmrg * it is not expected to be common 16105b261ecSmrg */ 16235c4bbdfSmrg ccw = malloc(sizeof(CompClientWindowRec)); 16305b261ecSmrg if (!ccw) 16435c4bbdfSmrg return BadAlloc; 16535c4bbdfSmrg ccw->id = FakeClientID(pClient->index); 16605b261ecSmrg ccw->update = update; 16705b261ecSmrg /* 16805b261ecSmrg * Now make sure there's a per-window structure to hang this from 16905b261ecSmrg */ 17035c4bbdfSmrg if (!cw) { 17135c4bbdfSmrg cw = malloc(sizeof(CompWindowRec)); 17235c4bbdfSmrg if (!cw) { 17335c4bbdfSmrg free(ccw); 17435c4bbdfSmrg return BadAlloc; 17535c4bbdfSmrg } 17635c4bbdfSmrg cw->damage = DamageCreate(compReportDamage, 17735c4bbdfSmrg compDestroyDamage, 17835c4bbdfSmrg DamageReportNonEmpty, 17935c4bbdfSmrg FALSE, pWin->drawable.pScreen, pWin); 18035c4bbdfSmrg if (!cw->damage) { 18135c4bbdfSmrg free(ccw); 18235c4bbdfSmrg free(cw); 18335c4bbdfSmrg return BadAlloc; 18435c4bbdfSmrg } 18535c4bbdfSmrg 18635c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 18735c4bbdfSmrg 18835c4bbdfSmrg RegionNull(&cw->borderClip); 18935c4bbdfSmrg cw->update = CompositeRedirectAutomatic; 19035c4bbdfSmrg cw->clients = 0; 19135c4bbdfSmrg cw->oldx = COMP_ORIGIN_INVALID; 19235c4bbdfSmrg cw->oldy = COMP_ORIGIN_INVALID; 19335c4bbdfSmrg cw->damageRegistered = FALSE; 19435c4bbdfSmrg cw->damaged = FALSE; 19535c4bbdfSmrg cw->pOldPixmap = NullPixmap; 19635c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw); 19705b261ecSmrg } 19805b261ecSmrg ccw->next = cw->clients; 19905b261ecSmrg cw->clients = ccw; 20035c4bbdfSmrg if (!AddResource(ccw->id, CompositeClientWindowType, pWin)) 20135c4bbdfSmrg return BadAlloc; 20235c4bbdfSmrg if (ccw->update == CompositeRedirectManual) { 20335c4bbdfSmrg if (!anyMarked) 20435c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 20535c4bbdfSmrg 20635c4bbdfSmrg if (cw->damageRegistered) { 20735c4bbdfSmrg DamageUnregister(cw->damage); 20835c4bbdfSmrg cw->damageRegistered = FALSE; 20935c4bbdfSmrg } 21035c4bbdfSmrg cw->update = CompositeRedirectManual; 21105b261ecSmrg } 21235c4bbdfSmrg else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { 21335c4bbdfSmrg if (!anyMarked) 21435c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 21505b261ecSmrg } 21635c4bbdfSmrg 21735c4bbdfSmrg if (!compCheckRedirect(pWin)) { 21835c4bbdfSmrg FreeResource(ccw->id, RT_NONE); 21935c4bbdfSmrg return BadAlloc; 22005b261ecSmrg } 22135c4bbdfSmrg 22235c4bbdfSmrg if (anyMarked) 22335c4bbdfSmrg compHandleMarkedWindows(pWin, pLayerWin); 22435c4bbdfSmrg 22505b261ecSmrg return Success; 22605b261ecSmrg} 22705b261ecSmrg 22835c4bbdfSmrgvoid 22935c4bbdfSmrgcompRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap) 23035c4bbdfSmrg{ 23135c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 23235c4bbdfSmrg WindowPtr pParent = pWin->parent; 23335c4bbdfSmrg 23435c4bbdfSmrg if (pParent->drawable.depth == pWin->drawable.depth) { 23535c4bbdfSmrg GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); 23635c4bbdfSmrg int bw = (int) pWin->borderWidth; 23735c4bbdfSmrg int x = bw; 23835c4bbdfSmrg int y = bw; 23935c4bbdfSmrg int w = pWin->drawable.width; 24035c4bbdfSmrg int h = pWin->drawable.height; 24135c4bbdfSmrg 24235c4bbdfSmrg if (pGC) { 24335c4bbdfSmrg ChangeGCVal val; 24435c4bbdfSmrg 24535c4bbdfSmrg val.val = IncludeInferiors; 24635c4bbdfSmrg ChangeGC(NullClient, pGC, GCSubwindowMode, &val); 24735c4bbdfSmrg ValidateGC(&pWin->drawable, pGC); 24835c4bbdfSmrg (*pGC->ops->CopyArea) (&pPixmap->drawable, 24935c4bbdfSmrg &pWin->drawable, pGC, x, y, w, h, 0, 0); 25035c4bbdfSmrg FreeScratchGC(pGC); 25135c4bbdfSmrg } 25235c4bbdfSmrg } 25335c4bbdfSmrg} 25435c4bbdfSmrg 25505b261ecSmrg/* 25605b261ecSmrg * Free one of the per-client per-window resources, clearing 25705b261ecSmrg * redirect and the per-window pointer as appropriate 25805b261ecSmrg */ 25905b261ecSmrgvoid 26035c4bbdfSmrgcompFreeClientWindow(WindowPtr pWin, XID id) 26105b261ecSmrg{ 26235c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 26335c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 26435c4bbdfSmrg CompClientWindowPtr ccw, *prev; 26535c4bbdfSmrg Bool anyMarked = FALSE; 26635c4bbdfSmrg WindowPtr pLayerWin; 26735c4bbdfSmrg PixmapPtr pPixmap = NULL; 26805b261ecSmrg 26905b261ecSmrg if (!cw) 27035c4bbdfSmrg return; 27135c4bbdfSmrg for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) { 27235c4bbdfSmrg if (ccw->id == id) { 27335c4bbdfSmrg *prev = ccw->next; 27435c4bbdfSmrg if (ccw->update == CompositeRedirectManual) 27535c4bbdfSmrg cw->update = CompositeRedirectAutomatic; 27635c4bbdfSmrg free(ccw); 27735c4bbdfSmrg break; 27835c4bbdfSmrg } 27905b261ecSmrg } 28035c4bbdfSmrg if (!cw->clients) { 28135c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 28235c4bbdfSmrg 28335c4bbdfSmrg if (pWin->redirectDraw != RedirectDrawNone) { 28435c4bbdfSmrg pPixmap = (*pScreen->GetWindowPixmap) (pWin); 28535c4bbdfSmrg compSetParentPixmap(pWin); 28635c4bbdfSmrg } 28735c4bbdfSmrg 28835c4bbdfSmrg if (cw->damage) 28935c4bbdfSmrg DamageDestroy(cw->damage); 29035c4bbdfSmrg 29135c4bbdfSmrg RegionUninit(&cw->borderClip); 29235c4bbdfSmrg 29335c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL); 29435c4bbdfSmrg free(cw); 29505b261ecSmrg } 29605b261ecSmrg else if (cw->update == CompositeRedirectAutomatic && 29735c4bbdfSmrg !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) { 29835c4bbdfSmrg anyMarked = compMarkWindows(pWin, &pLayerWin); 29935c4bbdfSmrg 30035c4bbdfSmrg DamageRegister(&pWin->drawable, cw->damage); 30135c4bbdfSmrg cw->damageRegistered = TRUE; 30235c4bbdfSmrg pWin->redirectDraw = RedirectDrawAutomatic; 30335c4bbdfSmrg DamageDamageRegion(&pWin->drawable, &pWin->borderSize); 30405b261ecSmrg } 30535c4bbdfSmrg 30635c4bbdfSmrg if (anyMarked) 30735c4bbdfSmrg compHandleMarkedWindows(pWin, pLayerWin); 30835c4bbdfSmrg 30935c4bbdfSmrg if (pPixmap) { 31035c4bbdfSmrg compRestoreWindow(pWin, pPixmap); 31135c4bbdfSmrg (*pScreen->DestroyPixmap) (pPixmap); 31205b261ecSmrg } 31305b261ecSmrg} 31405b261ecSmrg 31505b261ecSmrg/* 31605b261ecSmrg * This is easy, just free the appropriate resource. 31705b261ecSmrg */ 31805b261ecSmrg 31905b261ecSmrgint 32035c4bbdfSmrgcompUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update) 32105b261ecSmrg{ 32235c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 32335c4bbdfSmrg CompClientWindowPtr ccw; 32405b261ecSmrg 32505b261ecSmrg if (!cw) 32635c4bbdfSmrg return BadValue; 32705b261ecSmrg 32805b261ecSmrg for (ccw = cw->clients; ccw; ccw = ccw->next) 32935c4bbdfSmrg if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) { 33035c4bbdfSmrg FreeResource(ccw->id, RT_NONE); 33135c4bbdfSmrg return Success; 33235c4bbdfSmrg } 33305b261ecSmrg return BadValue; 33405b261ecSmrg} 33535c4bbdfSmrg 33605b261ecSmrg/* 33705b261ecSmrg * Redirect all subwindows for one client 33805b261ecSmrg */ 33905b261ecSmrg 34005b261ecSmrgint 34135c4bbdfSmrgcompRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update) 34205b261ecSmrg{ 34335c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pWin); 34435c4bbdfSmrg CompClientWindowPtr ccw; 34535c4bbdfSmrg WindowPtr pChild; 34605b261ecSmrg 34705b261ecSmrg /* 34805b261ecSmrg * Only one Manual update is allowed 34905b261ecSmrg */ 35005b261ecSmrg if (csw && update == CompositeRedirectManual) 35135c4bbdfSmrg for (ccw = csw->clients; ccw; ccw = ccw->next) 35235c4bbdfSmrg if (ccw->update == CompositeRedirectManual) 35335c4bbdfSmrg return BadAccess; 35405b261ecSmrg /* 35535c4bbdfSmrg * Allocate per-client per-window structure 35605b261ecSmrg * The client *could* allocate multiple, but while supported, 35705b261ecSmrg * it is not expected to be common 35805b261ecSmrg */ 35935c4bbdfSmrg ccw = malloc(sizeof(CompClientWindowRec)); 36005b261ecSmrg if (!ccw) 36135c4bbdfSmrg return BadAlloc; 36235c4bbdfSmrg ccw->id = FakeClientID(pClient->index); 36305b261ecSmrg ccw->update = update; 36405b261ecSmrg /* 36505b261ecSmrg * Now make sure there's a per-window structure to hang this from 36605b261ecSmrg */ 36735c4bbdfSmrg if (!csw) { 36835c4bbdfSmrg csw = malloc(sizeof(CompSubwindowsRec)); 36935c4bbdfSmrg if (!csw) { 37035c4bbdfSmrg free(ccw); 37135c4bbdfSmrg return BadAlloc; 37235c4bbdfSmrg } 37335c4bbdfSmrg csw->update = CompositeRedirectAutomatic; 37435c4bbdfSmrg csw->clients = 0; 37535c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw); 37605b261ecSmrg } 37705b261ecSmrg /* 37805b261ecSmrg * Redirect all existing windows 37905b261ecSmrg */ 38035c4bbdfSmrg for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) { 38135c4bbdfSmrg int ret = compRedirectWindow(pClient, pChild, update); 38235c4bbdfSmrg 38335c4bbdfSmrg if (ret != Success) { 38435c4bbdfSmrg for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib) 38535c4bbdfSmrg (void) compUnredirectWindow(pClient, pChild, update); 38635c4bbdfSmrg if (!csw->clients) { 38735c4bbdfSmrg free(csw); 38835c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0); 38935c4bbdfSmrg } 39035c4bbdfSmrg free(ccw); 39135c4bbdfSmrg return ret; 39235c4bbdfSmrg } 39305b261ecSmrg } 39405b261ecSmrg /* 39505b261ecSmrg * Hook into subwindows list 39605b261ecSmrg */ 39705b261ecSmrg ccw->next = csw->clients; 39805b261ecSmrg csw->clients = ccw; 39935c4bbdfSmrg if (!AddResource(ccw->id, CompositeClientSubwindowsType, pWin)) 40035c4bbdfSmrg return BadAlloc; 40135c4bbdfSmrg if (ccw->update == CompositeRedirectManual) { 40235c4bbdfSmrg csw->update = CompositeRedirectManual; 40335c4bbdfSmrg /* 40435c4bbdfSmrg * tell damage extension that damage events for this client are 40535c4bbdfSmrg * critical output 40635c4bbdfSmrg */ 40735c4bbdfSmrg DamageExtSetCritical(pClient, TRUE); 40835c4bbdfSmrg pWin->inhibitBGPaint = TRUE; 40905b261ecSmrg } 41005b261ecSmrg return Success; 41105b261ecSmrg} 41205b261ecSmrg 41305b261ecSmrg/* 41405b261ecSmrg * Free one of the per-client per-subwindows resources, 41505b261ecSmrg * which frees one redirect per subwindow 41605b261ecSmrg */ 41705b261ecSmrgvoid 41835c4bbdfSmrgcompFreeClientSubwindows(WindowPtr pWin, XID id) 41905b261ecSmrg{ 42035c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pWin); 42135c4bbdfSmrg CompClientWindowPtr ccw, *prev; 42235c4bbdfSmrg WindowPtr pChild; 42305b261ecSmrg 42405b261ecSmrg if (!csw) 42535c4bbdfSmrg return; 42635c4bbdfSmrg for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) { 42735c4bbdfSmrg if (ccw->id == id) { 42835c4bbdfSmrg ClientPtr pClient = clients[CLIENT_ID(id)]; 42935c4bbdfSmrg 43035c4bbdfSmrg *prev = ccw->next; 43135c4bbdfSmrg if (ccw->update == CompositeRedirectManual) { 43235c4bbdfSmrg /* 43335c4bbdfSmrg * tell damage extension that damage events for this client are 43435c4bbdfSmrg * critical output 43535c4bbdfSmrg */ 43635c4bbdfSmrg DamageExtSetCritical(pClient, FALSE); 43735c4bbdfSmrg csw->update = CompositeRedirectAutomatic; 43835c4bbdfSmrg pWin->inhibitBGPaint = FALSE; 43935c4bbdfSmrg if (pWin->mapped) 44035c4bbdfSmrg (*pWin->drawable.pScreen->ClearToBackground) (pWin, 0, 0, 0, 44135c4bbdfSmrg 0, TRUE); 44235c4bbdfSmrg } 44335c4bbdfSmrg 44435c4bbdfSmrg /* 44535c4bbdfSmrg * Unredirect all existing subwindows 44635c4bbdfSmrg */ 44735c4bbdfSmrg for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) 44835c4bbdfSmrg (void) compUnredirectWindow(pClient, pChild, ccw->update); 44935c4bbdfSmrg 45035c4bbdfSmrg free(ccw); 45135c4bbdfSmrg break; 45235c4bbdfSmrg } 45305b261ecSmrg } 45405b261ecSmrg 45505b261ecSmrg /* 45605b261ecSmrg * Check if all of the per-client records are gone 45705b261ecSmrg */ 45835c4bbdfSmrg if (!csw->clients) { 45935c4bbdfSmrg dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL); 46035c4bbdfSmrg free(csw); 46105b261ecSmrg } 46205b261ecSmrg} 46305b261ecSmrg 46405b261ecSmrg/* 46505b261ecSmrg * This is easy, just free the appropriate resource. 46605b261ecSmrg */ 46705b261ecSmrg 46805b261ecSmrgint 46935c4bbdfSmrgcompUnredirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update) 47005b261ecSmrg{ 47135c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pWin); 47235c4bbdfSmrg CompClientWindowPtr ccw; 47335c4bbdfSmrg 47405b261ecSmrg if (!csw) 47535c4bbdfSmrg return BadValue; 47605b261ecSmrg for (ccw = csw->clients; ccw; ccw = ccw->next) 47735c4bbdfSmrg if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) { 47835c4bbdfSmrg FreeResource(ccw->id, RT_NONE); 47935c4bbdfSmrg return Success; 48035c4bbdfSmrg } 48105b261ecSmrg return BadValue; 48205b261ecSmrg} 48305b261ecSmrg 48405b261ecSmrg/* 48505b261ecSmrg * Add redirection information for one subwindow (during reparent) 48605b261ecSmrg */ 48705b261ecSmrg 48805b261ecSmrgint 48935c4bbdfSmrgcompRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin) 49005b261ecSmrg{ 49135c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pParent); 49235c4bbdfSmrg CompClientWindowPtr ccw; 49305b261ecSmrg 49405b261ecSmrg if (!csw) 49535c4bbdfSmrg return Success; 49635c4bbdfSmrg for (ccw = csw->clients; ccw; ccw = ccw->next) { 49735c4bbdfSmrg int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)], 49835c4bbdfSmrg pWin, ccw->update); 49935c4bbdfSmrg 50035c4bbdfSmrg if (ret != Success) 50135c4bbdfSmrg return ret; 50205b261ecSmrg } 50305b261ecSmrg return Success; 50405b261ecSmrg} 50505b261ecSmrg 50605b261ecSmrg/* 50705b261ecSmrg * Remove redirection information for one subwindow (during reparent) 50805b261ecSmrg */ 50905b261ecSmrg 51005b261ecSmrgint 51135c4bbdfSmrgcompUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin) 51205b261ecSmrg{ 51335c4bbdfSmrg CompSubwindowsPtr csw = GetCompSubwindows(pParent); 51435c4bbdfSmrg CompClientWindowPtr ccw; 51505b261ecSmrg 51605b261ecSmrg if (!csw) 51735c4bbdfSmrg return Success; 51835c4bbdfSmrg for (ccw = csw->clients; ccw; ccw = ccw->next) { 51935c4bbdfSmrg int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)], 52035c4bbdfSmrg pWin, ccw->update); 52135c4bbdfSmrg 52235c4bbdfSmrg if (ret != Success) 52335c4bbdfSmrg return ret; 52405b261ecSmrg } 52505b261ecSmrg return Success; 52605b261ecSmrg} 52705b261ecSmrg 52805b261ecSmrgstatic PixmapPtr 52935c4bbdfSmrgcompNewPixmap(WindowPtr pWin, int x, int y, int w, int h) 53005b261ecSmrg{ 53135c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 53235c4bbdfSmrg WindowPtr pParent = pWin->parent; 53335c4bbdfSmrg PixmapPtr pPixmap; 53405b261ecSmrg 5354642e01fSmrg pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth, 53635c4bbdfSmrg CREATE_PIXMAP_USAGE_BACKING_PIXMAP); 53705b261ecSmrg 53805b261ecSmrg if (!pPixmap) 53935c4bbdfSmrg return 0; 54035c4bbdfSmrg 54105b261ecSmrg pPixmap->screen_x = x; 54205b261ecSmrg pPixmap->screen_y = y; 5439ace9065Smrg 54435c4bbdfSmrg if (pParent->drawable.depth == pWin->drawable.depth) { 54535c4bbdfSmrg GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); 54635c4bbdfSmrg 54735c4bbdfSmrg if (pGC) { 54835c4bbdfSmrg ChangeGCVal val; 54935c4bbdfSmrg 55035c4bbdfSmrg val.val = IncludeInferiors; 55135c4bbdfSmrg ChangeGC(NullClient, pGC, GCSubwindowMode, &val); 55235c4bbdfSmrg ValidateGC(&pPixmap->drawable, pGC); 55335c4bbdfSmrg (*pGC->ops->CopyArea) (&pParent->drawable, 55435c4bbdfSmrg &pPixmap->drawable, 55535c4bbdfSmrg pGC, 55635c4bbdfSmrg x - pParent->drawable.x, 55735c4bbdfSmrg y - pParent->drawable.y, w, h, 0, 0); 55835c4bbdfSmrg FreeScratchGC(pGC); 55935c4bbdfSmrg } 56005b261ecSmrg } 56135c4bbdfSmrg else { 56235c4bbdfSmrg PictFormatPtr pSrcFormat = PictureWindowFormat(pParent); 56335c4bbdfSmrg PictFormatPtr pDstFormat = PictureWindowFormat(pWin); 56435c4bbdfSmrg XID inferiors = IncludeInferiors; 56535c4bbdfSmrg int error; 56635c4bbdfSmrg 56735c4bbdfSmrg PicturePtr pSrcPicture = CreatePicture(None, 56835c4bbdfSmrg &pParent->drawable, 56935c4bbdfSmrg pSrcFormat, 57035c4bbdfSmrg CPSubwindowMode, 57135c4bbdfSmrg &inferiors, 57235c4bbdfSmrg serverClient, &error); 57335c4bbdfSmrg 57435c4bbdfSmrg PicturePtr pDstPicture = CreatePicture(None, 57535c4bbdfSmrg &pPixmap->drawable, 57635c4bbdfSmrg pDstFormat, 57735c4bbdfSmrg 0, 0, 57835c4bbdfSmrg serverClient, &error); 57935c4bbdfSmrg 58035c4bbdfSmrg if (pSrcPicture && pDstPicture) { 58135c4bbdfSmrg CompositePicture(PictOpSrc, 58235c4bbdfSmrg pSrcPicture, 58335c4bbdfSmrg NULL, 58435c4bbdfSmrg pDstPicture, 58535c4bbdfSmrg x - pParent->drawable.x, 58635c4bbdfSmrg y - pParent->drawable.y, 0, 0, 0, 0, w, h); 58735c4bbdfSmrg } 58835c4bbdfSmrg if (pSrcPicture) 58935c4bbdfSmrg FreePicture(pSrcPicture, 0); 59035c4bbdfSmrg if (pDstPicture) 59135c4bbdfSmrg FreePicture(pDstPicture, 0); 59205b261ecSmrg } 59305b261ecSmrg return pPixmap; 59405b261ecSmrg} 59505b261ecSmrg 59605b261ecSmrgBool 59735c4bbdfSmrgcompAllocPixmap(WindowPtr pWin) 59805b261ecSmrg{ 59935c4bbdfSmrg int bw = (int) pWin->borderWidth; 60035c4bbdfSmrg int x = pWin->drawable.x - bw; 60135c4bbdfSmrg int y = pWin->drawable.y - bw; 60235c4bbdfSmrg int w = pWin->drawable.width + (bw << 1); 60335c4bbdfSmrg int h = pWin->drawable.height + (bw << 1); 60435c4bbdfSmrg PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h); 60535c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 60605b261ecSmrg 60705b261ecSmrg if (!pPixmap) 60835c4bbdfSmrg return FALSE; 60905b261ecSmrg if (cw->update == CompositeRedirectAutomatic) 61035c4bbdfSmrg pWin->redirectDraw = RedirectDrawAutomatic; 61105b261ecSmrg else 61235c4bbdfSmrg pWin->redirectDraw = RedirectDrawManual; 61305b261ecSmrg 6141b5d61b8Smrg compSetPixmap(pWin, pPixmap, bw); 61505b261ecSmrg cw->oldx = COMP_ORIGIN_INVALID; 61605b261ecSmrg cw->oldy = COMP_ORIGIN_INVALID; 61705b261ecSmrg cw->damageRegistered = FALSE; 61835c4bbdfSmrg if (cw->update == CompositeRedirectAutomatic) { 61935c4bbdfSmrg DamageRegister(&pWin->drawable, cw->damage); 62035c4bbdfSmrg cw->damageRegistered = TRUE; 62105b261ecSmrg } 62235c4bbdfSmrg 62335c4bbdfSmrg /* Make sure our borderClip is up to date */ 62435c4bbdfSmrg RegionUninit(&cw->borderClip); 62535c4bbdfSmrg RegionCopy(&cw->borderClip, &pWin->borderClip); 62635c4bbdfSmrg cw->borderClipX = pWin->drawable.x; 62735c4bbdfSmrg cw->borderClipY = pWin->drawable.y; 62835c4bbdfSmrg 62905b261ecSmrg return TRUE; 63005b261ecSmrg} 63105b261ecSmrg 63205b261ecSmrgvoid 63335c4bbdfSmrgcompSetParentPixmap(WindowPtr pWin) 63405b261ecSmrg{ 63535c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 63635c4bbdfSmrg PixmapPtr pParentPixmap; 63735c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 63835c4bbdfSmrg 63935c4bbdfSmrg if (cw->damageRegistered) { 64035c4bbdfSmrg DamageUnregister(cw->damage); 64135c4bbdfSmrg cw->damageRegistered = FALSE; 64235c4bbdfSmrg DamageEmpty(cw->damage); 64305b261ecSmrg } 64405b261ecSmrg /* 64505b261ecSmrg * Move the parent-constrained border clip region back into 64605b261ecSmrg * the window so that ValidateTree will handle the unmap 64705b261ecSmrg * case correctly. Unmap adds the window borderClip to the 64805b261ecSmrg * parent exposed area; regions beyond the parent cause crashes 64905b261ecSmrg */ 6506747b715Smrg RegionCopy(&pWin->borderClip, &cw->borderClip); 65105b261ecSmrg pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); 65205b261ecSmrg pWin->redirectDraw = RedirectDrawNone; 6531b5d61b8Smrg compSetPixmap(pWin, pParentPixmap, pWin->borderWidth); 65405b261ecSmrg} 65505b261ecSmrg 65605b261ecSmrg/* 65705b261ecSmrg * Make sure the pixmap is the right size and offset. Allocate a new 65805b261ecSmrg * pixmap to change size, adjust origin to change offset, leaving the 65905b261ecSmrg * old pixmap in cw->pOldPixmap so bits can be recovered 66005b261ecSmrg */ 66105b261ecSmrgBool 66235c4bbdfSmrgcompReallocPixmap(WindowPtr pWin, int draw_x, int draw_y, 66335c4bbdfSmrg unsigned int w, unsigned int h, int bw) 66405b261ecSmrg{ 66535c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 66635c4bbdfSmrg PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin); 66735c4bbdfSmrg PixmapPtr pNew; 66835c4bbdfSmrg CompWindowPtr cw = GetCompWindow(pWin); 66935c4bbdfSmrg int pix_x, pix_y; 67035c4bbdfSmrg int pix_w, pix_h; 67135c4bbdfSmrg 67235c4bbdfSmrg assert(cw && pWin->redirectDraw != RedirectDrawNone); 67305b261ecSmrg cw->oldx = pOld->screen_x; 67405b261ecSmrg cw->oldy = pOld->screen_y; 67505b261ecSmrg pix_x = draw_x - bw; 67605b261ecSmrg pix_y = draw_y - bw; 67705b261ecSmrg pix_w = w + (bw << 1); 67805b261ecSmrg pix_h = h + (bw << 1); 67935c4bbdfSmrg if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) { 68035c4bbdfSmrg pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h); 68135c4bbdfSmrg if (!pNew) 68235c4bbdfSmrg return FALSE; 68335c4bbdfSmrg cw->pOldPixmap = pOld; 6841b5d61b8Smrg compSetPixmap(pWin, pNew, bw); 68505b261ecSmrg } 68635c4bbdfSmrg else { 68735c4bbdfSmrg pNew = pOld; 68835c4bbdfSmrg cw->pOldPixmap = 0; 68905b261ecSmrg } 69005b261ecSmrg pNew->screen_x = pix_x; 69105b261ecSmrg pNew->screen_y = pix_y; 69205b261ecSmrg return TRUE; 69305b261ecSmrg} 694