xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

compalloc.c (21172B)


      1 /*
      2  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  *
     23  * Copyright © 2003 Keith Packard
     24  *
     25  * Permission to use, copy, modify, distribute, and sell this software and its
     26  * documentation for any purpose is hereby granted without fee, provided that
     27  * the above copyright notice appear in all copies and that both that
     28  * copyright notice and this permission notice appear in supporting
     29  * documentation, and that the name of Keith Packard not be used in
     30  * advertising or publicity pertaining to distribution of the software without
     31  * specific, written prior permission.  Keith Packard makes no
     32  * representations about the suitability of this software for any purpose.  It
     33  * is provided "as is" without express or implied warranty.
     34  *
     35  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     36  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     37  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     38  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     39  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     40  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     41  * PERFORMANCE OF THIS SOFTWARE.
     42  */
     43 
     44 #ifdef HAVE_DIX_CONFIG_H
     45 #include <dix-config.h>
     46 #endif
     47 
     48 #include "compint.h"
     49 
     50 static Bool
     51 compScreenUpdate(ClientPtr pClient, void *closure)
     52 {
     53     ScreenPtr pScreen = closure;
     54     CompScreenPtr cs = GetCompScreen(pScreen);
     55 
     56     compCheckTree(pScreen);
     57     compPaintChildrenToWindow(pScreen->root);
     58 
     59     /* Next damage will restore the worker */
     60     cs->pendingScreenUpdate = FALSE;
     61     return TRUE;
     62 }
     63 
     64 void
     65 compMarkAncestors(WindowPtr pWin)
     66 {
     67     pWin = pWin->parent;
     68     while (pWin) {
     69         if (pWin->damagedDescendants)
     70             return;
     71         pWin->damagedDescendants = TRUE;
     72         pWin = pWin->parent;
     73     }
     74 }
     75 
     76 static void
     77 compReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure)
     78 {
     79     WindowPtr pWin = (WindowPtr) closure;
     80     ScreenPtr pScreen = pWin->drawable.pScreen;
     81     CompScreenPtr cs = GetCompScreen(pScreen);
     82     CompWindowPtr cw = GetCompWindow(pWin);
     83 
     84     if (!cs->pendingScreenUpdate) {
     85         QueueWorkProc(compScreenUpdate, serverClient, pScreen);
     86         cs->pendingScreenUpdate = TRUE;
     87     }
     88     cw->damaged = TRUE;
     89 
     90     compMarkAncestors(pWin);
     91 }
     92 
     93 static void
     94 compDestroyDamage(DamagePtr pDamage, void *closure)
     95 {
     96     WindowPtr pWin = (WindowPtr) closure;
     97     CompWindowPtr cw = GetCompWindow(pWin);
     98 
     99     cw->damage = 0;
    100     cw->damaged = 0;
    101     cw->damageRegistered = 0;
    102 }
    103 
    104 static Bool
    105 compMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin)
    106 {
    107     ScreenPtr pScreen = pWin->drawable.pScreen;
    108     WindowPtr pLayerWin = pWin;
    109 
    110     if (!pWin->viewable)
    111         return FALSE;
    112 
    113     (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin);
    114     (*pScreen->MarkWindow) (pLayerWin->parent);
    115 
    116     *ppLayerWin = pLayerWin;
    117 
    118     return TRUE;
    119 }
    120 
    121 static void
    122 compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin)
    123 {
    124     ScreenPtr pScreen = pWin->drawable.pScreen;
    125 
    126     (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
    127     (*pScreen->HandleExposures) (pLayerWin->parent);
    128     if (pScreen->PostValidateTree)
    129         (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther);
    130 }
    131 
    132 /*
    133  * Redirect one window for one client
    134  */
    135 int
    136 compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
    137 {
    138     CompWindowPtr cw = GetCompWindow(pWin);
    139     CompClientWindowPtr ccw;
    140     CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
    141     WindowPtr pLayerWin;
    142     Bool anyMarked = FALSE;
    143 
    144     if (pWin == cs->pOverlayWin) {
    145         return Success;
    146     }
    147 
    148     if (!pWin->parent)
    149         return BadMatch;
    150 
    151     /*
    152      * Only one Manual update is allowed
    153      */
    154     if (cw && update == CompositeRedirectManual)
    155         for (ccw = cw->clients; ccw; ccw = ccw->next)
    156             if (ccw->update == CompositeRedirectManual)
    157                 return BadAccess;
    158 
    159     /*
    160      * Allocate per-client per-window structure
    161      * The client *could* allocate multiple, but while supported,
    162      * it is not expected to be common
    163      */
    164     ccw = malloc(sizeof(CompClientWindowRec));
    165     if (!ccw)
    166         return BadAlloc;
    167     ccw->id = FakeClientID(pClient->index);
    168     ccw->update = update;
    169     /*
    170      * Now make sure there's a per-window structure to hang this from
    171      */
    172     if (!cw) {
    173         cw = malloc(sizeof(CompWindowRec));
    174         if (!cw) {
    175             free(ccw);
    176             return BadAlloc;
    177         }
    178         cw->damage = DamageCreate(compReportDamage,
    179                                   compDestroyDamage,
    180                                   DamageReportNonEmpty,
    181                                   FALSE, pWin->drawable.pScreen, pWin);
    182         if (!cw->damage) {
    183             free(ccw);
    184             free(cw);
    185             return BadAlloc;
    186         }
    187 
    188         anyMarked = compMarkWindows(pWin, &pLayerWin);
    189 
    190         RegionNull(&cw->borderClip);
    191         cw->update = CompositeRedirectAutomatic;
    192         cw->clients = 0;
    193         cw->oldx = COMP_ORIGIN_INVALID;
    194         cw->oldy = COMP_ORIGIN_INVALID;
    195         cw->damageRegistered = FALSE;
    196         cw->damaged = FALSE;
    197         cw->pOldPixmap = NullPixmap;
    198         dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, cw);
    199     }
    200     ccw->next = cw->clients;
    201     cw->clients = ccw;
    202     if (!AddResource(ccw->id, CompositeClientWindowType, pWin))
    203         return BadAlloc;
    204     if (ccw->update == CompositeRedirectManual) {
    205         if (!anyMarked)
    206             anyMarked = compMarkWindows(pWin, &pLayerWin);
    207 
    208         if (cw->damageRegistered) {
    209             DamageUnregister(cw->damage);
    210             cw->damageRegistered = FALSE;
    211         }
    212         cw->update = CompositeRedirectManual;
    213     }
    214     else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) {
    215         if (!anyMarked)
    216             anyMarked = compMarkWindows(pWin, &pLayerWin);
    217     }
    218 
    219     if (!compCheckRedirect(pWin)) {
    220         FreeResource(ccw->id, RT_NONE);
    221         return BadAlloc;
    222     }
    223 
    224     if (anyMarked)
    225         compHandleMarkedWindows(pWin, pLayerWin);
    226 
    227     return Success;
    228 }
    229 
    230 void
    231 compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap)
    232 {
    233     ScreenPtr pScreen = pWin->drawable.pScreen;
    234     WindowPtr pParent = pWin->parent;
    235 
    236     if (pParent->drawable.depth == pWin->drawable.depth) {
    237         GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
    238         int bw = (int) pWin->borderWidth;
    239         int x = bw;
    240         int y = bw;
    241         int w = pWin->drawable.width;
    242         int h = pWin->drawable.height;
    243 
    244         if (pGC) {
    245             ChangeGCVal val;
    246 
    247             val.val = IncludeInferiors;
    248             ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
    249             ValidateGC(&pWin->drawable, pGC);
    250             (*pGC->ops->CopyArea) (&pPixmap->drawable,
    251                                    &pWin->drawable, pGC, x, y, w, h, 0, 0);
    252             FreeScratchGC(pGC);
    253         }
    254     }
    255 }
    256 
    257 /*
    258  * Free one of the per-client per-window resources, clearing
    259  * redirect and the per-window pointer as appropriate
    260  */
    261 void
    262 compFreeClientWindow(WindowPtr pWin, XID id)
    263 {
    264     ScreenPtr pScreen = pWin->drawable.pScreen;
    265     CompWindowPtr cw = GetCompWindow(pWin);
    266     CompClientWindowPtr ccw, *prev;
    267     Bool anyMarked = FALSE;
    268     WindowPtr pLayerWin;
    269     PixmapPtr pPixmap = NULL;
    270 
    271     if (!cw)
    272         return;
    273     for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next) {
    274         if (ccw->id == id) {
    275             *prev = ccw->next;
    276             if (ccw->update == CompositeRedirectManual)
    277                 cw->update = CompositeRedirectAutomatic;
    278             free(ccw);
    279             break;
    280         }
    281     }
    282     if (!cw->clients) {
    283         anyMarked = compMarkWindows(pWin, &pLayerWin);
    284 
    285         if (pWin->redirectDraw != RedirectDrawNone) {
    286             pPixmap = (*pScreen->GetWindowPixmap) (pWin);
    287             compSetParentPixmap(pWin);
    288         }
    289 
    290         if (cw->damage)
    291             DamageDestroy(cw->damage);
    292 
    293         RegionUninit(&cw->borderClip);
    294 
    295         dixSetPrivate(&pWin->devPrivates, CompWindowPrivateKey, NULL);
    296         free(cw);
    297     }
    298     else if (cw->update == CompositeRedirectAutomatic &&
    299              !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) {
    300         anyMarked = compMarkWindows(pWin, &pLayerWin);
    301 
    302         DamageRegister(&pWin->drawable, cw->damage);
    303         cw->damageRegistered = TRUE;
    304         pWin->redirectDraw = RedirectDrawAutomatic;
    305         DamageDamageRegion(&pWin->drawable, &pWin->borderSize);
    306     }
    307 
    308     if (anyMarked)
    309         compHandleMarkedWindows(pWin, pLayerWin);
    310 
    311     if (pPixmap) {
    312         compRestoreWindow(pWin, pPixmap);
    313         (*pScreen->DestroyPixmap) (pPixmap);
    314     }
    315 }
    316 
    317 /*
    318  * This is easy, just free the appropriate resource.
    319  */
    320 
    321 int
    322 compUnredirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
    323 {
    324     CompWindowPtr cw = GetCompWindow(pWin);
    325     CompClientWindowPtr ccw;
    326 
    327     if (!cw)
    328         return BadValue;
    329 
    330     for (ccw = cw->clients; ccw; ccw = ccw->next)
    331         if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) {
    332             FreeResource(ccw->id, RT_NONE);
    333             return Success;
    334         }
    335     return BadValue;
    336 }
    337 
    338 /*
    339  * Redirect all subwindows for one client
    340  */
    341 
    342 int
    343 compRedirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
    344 {
    345     CompSubwindowsPtr csw = GetCompSubwindows(pWin);
    346     CompClientWindowPtr ccw;
    347     WindowPtr pChild;
    348 
    349     /*
    350      * Only one Manual update is allowed
    351      */
    352     if (csw && update == CompositeRedirectManual)
    353         for (ccw = csw->clients; ccw; ccw = ccw->next)
    354             if (ccw->update == CompositeRedirectManual)
    355                 return BadAccess;
    356     /*
    357      * Allocate per-client per-window structure
    358      * The client *could* allocate multiple, but while supported,
    359      * it is not expected to be common
    360      */
    361     ccw = malloc(sizeof(CompClientWindowRec));
    362     if (!ccw)
    363         return BadAlloc;
    364     ccw->id = FakeClientID(pClient->index);
    365     ccw->update = update;
    366     /*
    367      * Now make sure there's a per-window structure to hang this from
    368      */
    369     if (!csw) {
    370         csw = malloc(sizeof(CompSubwindowsRec));
    371         if (!csw) {
    372             free(ccw);
    373             return BadAlloc;
    374         }
    375         csw->update = CompositeRedirectAutomatic;
    376         csw->clients = 0;
    377         dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, csw);
    378     }
    379     /*
    380      * Redirect all existing windows
    381      */
    382     for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) {
    383         int ret = compRedirectWindow(pClient, pChild, update);
    384 
    385         if (ret != Success) {
    386             for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
    387                 (void) compUnredirectWindow(pClient, pChild, update);
    388             if (!csw->clients) {
    389                 free(csw);
    390                 dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, 0);
    391             }
    392             free(ccw);
    393             return ret;
    394         }
    395     }
    396     /*
    397      * Hook into subwindows list
    398      */
    399     ccw->next = csw->clients;
    400     csw->clients = ccw;
    401     if (!AddResource(ccw->id, CompositeClientSubwindowsType, pWin))
    402         return BadAlloc;
    403     if (ccw->update == CompositeRedirectManual) {
    404         csw->update = CompositeRedirectManual;
    405         /*
    406          * tell damage extension that damage events for this client are
    407          * critical output
    408          */
    409         DamageExtSetCritical(pClient, TRUE);
    410         pWin->inhibitBGPaint = TRUE;
    411     }
    412     return Success;
    413 }
    414 
    415 /*
    416  * Free one of the per-client per-subwindows resources,
    417  * which frees one redirect per subwindow
    418  */
    419 void
    420 compFreeClientSubwindows(WindowPtr pWin, XID id)
    421 {
    422     CompSubwindowsPtr csw = GetCompSubwindows(pWin);
    423     CompClientWindowPtr ccw, *prev;
    424     WindowPtr pChild;
    425 
    426     if (!csw)
    427         return;
    428     for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next) {
    429         if (ccw->id == id) {
    430             ClientPtr pClient = clients[CLIENT_ID(id)];
    431 
    432             *prev = ccw->next;
    433             if (ccw->update == CompositeRedirectManual) {
    434                 /*
    435                  * tell damage extension that damage events for this client are
    436                  * critical output
    437                  */
    438                 DamageExtSetCritical(pClient, FALSE);
    439                 csw->update = CompositeRedirectAutomatic;
    440                 pWin->inhibitBGPaint = FALSE;
    441                 if (pWin->mapped)
    442                     (*pWin->drawable.pScreen->ClearToBackground) (pWin, 0, 0, 0,
    443                                                                   0, TRUE);
    444             }
    445 
    446             /*
    447              * Unredirect all existing subwindows
    448              */
    449             for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
    450                 (void) compUnredirectWindow(pClient, pChild, ccw->update);
    451 
    452             free(ccw);
    453             break;
    454         }
    455     }
    456 
    457     /*
    458      * Check if all of the per-client records are gone
    459      */
    460     if (!csw->clients) {
    461         dixSetPrivate(&pWin->devPrivates, CompSubwindowsPrivateKey, NULL);
    462         free(csw);
    463     }
    464 }
    465 
    466 /*
    467  * This is easy, just free the appropriate resource.
    468  */
    469 
    470 int
    471 compUnredirectSubwindows(ClientPtr pClient, WindowPtr pWin, int update)
    472 {
    473     CompSubwindowsPtr csw = GetCompSubwindows(pWin);
    474     CompClientWindowPtr ccw;
    475 
    476     if (!csw)
    477         return BadValue;
    478     for (ccw = csw->clients; ccw; ccw = ccw->next)
    479         if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index) {
    480             FreeResource(ccw->id, RT_NONE);
    481             return Success;
    482         }
    483     return BadValue;
    484 }
    485 
    486 /*
    487  * Add redirection information for one subwindow (during reparent)
    488  */
    489 
    490 int
    491 compRedirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
    492 {
    493     CompSubwindowsPtr csw = GetCompSubwindows(pParent);
    494     CompClientWindowPtr ccw;
    495 
    496     if (!csw)
    497         return Success;
    498     for (ccw = csw->clients; ccw; ccw = ccw->next) {
    499         int ret = compRedirectWindow(clients[CLIENT_ID(ccw->id)],
    500                                      pWin, ccw->update);
    501 
    502         if (ret != Success)
    503             return ret;
    504     }
    505     return Success;
    506 }
    507 
    508 /*
    509  * Remove redirection information for one subwindow (during reparent)
    510  */
    511 
    512 int
    513 compUnredirectOneSubwindow(WindowPtr pParent, WindowPtr pWin)
    514 {
    515     CompSubwindowsPtr csw = GetCompSubwindows(pParent);
    516     CompClientWindowPtr ccw;
    517 
    518     if (!csw)
    519         return Success;
    520     for (ccw = csw->clients; ccw; ccw = ccw->next) {
    521         int ret = compUnredirectWindow(clients[CLIENT_ID(ccw->id)],
    522                                        pWin, ccw->update);
    523 
    524         if (ret != Success)
    525             return ret;
    526     }
    527     return Success;
    528 }
    529 
    530 static PixmapPtr
    531 compNewPixmap(WindowPtr pWin, int x, int y, int w, int h)
    532 {
    533     ScreenPtr pScreen = pWin->drawable.pScreen;
    534     WindowPtr pParent = pWin->parent;
    535     PixmapPtr pPixmap;
    536 
    537     pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth,
    538                                         CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
    539 
    540     if (!pPixmap)
    541         return 0;
    542 
    543     pPixmap->screen_x = x;
    544     pPixmap->screen_y = y;
    545 
    546     if (pParent->drawable.depth == pWin->drawable.depth) {
    547         GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen);
    548 
    549         if (pGC) {
    550             ChangeGCVal val;
    551 
    552             val.val = IncludeInferiors;
    553             ChangeGC(NullClient, pGC, GCSubwindowMode, &val);
    554             ValidateGC(&pPixmap->drawable, pGC);
    555             (*pGC->ops->CopyArea) (&pParent->drawable,
    556                                    &pPixmap->drawable,
    557                                    pGC,
    558                                    x - pParent->drawable.x,
    559                                    y - pParent->drawable.y, w, h, 0, 0);
    560             FreeScratchGC(pGC);
    561         }
    562     }
    563     else {
    564         PictFormatPtr pSrcFormat = PictureWindowFormat(pParent);
    565         PictFormatPtr pDstFormat = PictureWindowFormat(pWin);
    566         XID inferiors = IncludeInferiors;
    567         int error;
    568 
    569         PicturePtr pSrcPicture = CreatePicture(None,
    570                                                &pParent->drawable,
    571                                                pSrcFormat,
    572                                                CPSubwindowMode,
    573                                                &inferiors,
    574                                                serverClient, &error);
    575 
    576         PicturePtr pDstPicture = CreatePicture(None,
    577                                                &pPixmap->drawable,
    578                                                pDstFormat,
    579                                                0, 0,
    580                                                serverClient, &error);
    581 
    582         if (pSrcPicture && pDstPicture) {
    583             CompositePicture(PictOpSrc,
    584                              pSrcPicture,
    585                              NULL,
    586                              pDstPicture,
    587                              x - pParent->drawable.x,
    588                              y - pParent->drawable.y, 0, 0, 0, 0, w, h);
    589         }
    590         if (pSrcPicture)
    591             FreePicture(pSrcPicture, 0);
    592         if (pDstPicture)
    593             FreePicture(pDstPicture, 0);
    594     }
    595     return pPixmap;
    596 }
    597 
    598 Bool
    599 compAllocPixmap(WindowPtr pWin)
    600 {
    601     int bw = (int) pWin->borderWidth;
    602     int x = pWin->drawable.x - bw;
    603     int y = pWin->drawable.y - bw;
    604     int w = pWin->drawable.width + (bw << 1);
    605     int h = pWin->drawable.height + (bw << 1);
    606     PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h);
    607     CompWindowPtr cw = GetCompWindow(pWin);
    608 
    609     if (!pPixmap)
    610         return FALSE;
    611     if (cw->update == CompositeRedirectAutomatic)
    612         pWin->redirectDraw = RedirectDrawAutomatic;
    613     else
    614         pWin->redirectDraw = RedirectDrawManual;
    615 
    616     compSetPixmap(pWin, pPixmap, bw);
    617     cw->oldx = COMP_ORIGIN_INVALID;
    618     cw->oldy = COMP_ORIGIN_INVALID;
    619     cw->damageRegistered = FALSE;
    620     if (cw->update == CompositeRedirectAutomatic) {
    621         DamageRegister(&pWin->drawable, cw->damage);
    622         cw->damageRegistered = TRUE;
    623     }
    624 
    625     /* Make sure our borderClip is up to date */
    626     RegionUninit(&cw->borderClip);
    627     RegionCopy(&cw->borderClip, &pWin->borderClip);
    628     cw->borderClipX = pWin->drawable.x;
    629     cw->borderClipY = pWin->drawable.y;
    630 
    631     return TRUE;
    632 }
    633 
    634 void
    635 compSetParentPixmap(WindowPtr pWin)
    636 {
    637     ScreenPtr pScreen = pWin->drawable.pScreen;
    638     PixmapPtr pParentPixmap;
    639     CompWindowPtr cw = GetCompWindow(pWin);
    640 
    641     if (cw->damageRegistered) {
    642         DamageUnregister(cw->damage);
    643         cw->damageRegistered = FALSE;
    644         DamageEmpty(cw->damage);
    645     }
    646     /*
    647      * Move the parent-constrained border clip region back into
    648      * the window so that ValidateTree will handle the unmap
    649      * case correctly.  Unmap adds the window borderClip to the
    650      * parent exposed area; regions beyond the parent cause crashes
    651      */
    652     RegionCopy(&pWin->borderClip, &cw->borderClip);
    653     pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
    654     pWin->redirectDraw = RedirectDrawNone;
    655     compSetPixmap(pWin, pParentPixmap, pWin->borderWidth);
    656 }
    657 
    658 /*
    659  * Make sure the pixmap is the right size and offset.  Allocate a new
    660  * pixmap to change size, adjust origin to change offset, leaving the
    661  * old pixmap in cw->pOldPixmap so bits can be recovered
    662  */
    663 Bool
    664 compReallocPixmap(WindowPtr pWin, int draw_x, int draw_y,
    665                   unsigned int w, unsigned int h, int bw)
    666 {
    667     ScreenPtr pScreen = pWin->drawable.pScreen;
    668     PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
    669     PixmapPtr pNew;
    670     CompWindowPtr cw = GetCompWindow(pWin);
    671     int pix_x, pix_y;
    672     int pix_w, pix_h;
    673 
    674     assert(cw);
    675     assert(pWin->redirectDraw != RedirectDrawNone);
    676     cw->oldx = pOld->screen_x;
    677     cw->oldy = pOld->screen_y;
    678     pix_x = draw_x - bw;
    679     pix_y = draw_y - bw;
    680     pix_w = w + (bw << 1);
    681     pix_h = h + (bw << 1);
    682     if (pix_w != pOld->drawable.width || pix_h != pOld->drawable.height) {
    683         pNew = compNewPixmap(pWin, pix_x, pix_y, pix_w, pix_h);
    684         if (!pNew)
    685             return FALSE;
    686         cw->pOldPixmap = pOld;
    687         compSetPixmap(pWin, pNew, bw);
    688     }
    689     else {
    690         pNew = pOld;
    691         cw->pOldPixmap = 0;
    692     }
    693     pNew->screen_x = pix_x;
    694     pNew->screen_y = pix_y;
    695     return TRUE;
    696 }