xserver

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

compwindow.c (25197B)


      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 #ifdef PANORAMIX
     51 #include "panoramiXsrv.h"
     52 #endif
     53 
     54 #ifdef COMPOSITE_DEBUG
     55 static int
     56 compCheckWindow(WindowPtr pWin, void *data)
     57 {
     58     ScreenPtr pScreen = pWin->drawable.pScreen;
     59     PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin);
     60     PixmapPtr pParentPixmap =
     61         pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0;
     62     PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen);
     63 
     64     if (!pWin->parent) {
     65         assert(pWin->redirectDraw == RedirectDrawNone);
     66         assert(pWinPixmap == pScreenPixmap);
     67     }
     68     else if (pWin->redirectDraw != RedirectDrawNone) {
     69         assert(pWinPixmap != pParentPixmap);
     70         assert(pWinPixmap != pScreenPixmap);
     71     }
     72     else {
     73         assert(pWinPixmap == pParentPixmap);
     74     }
     75 
     76     assert(0 < pWinPixmap->refcnt)
     77     assert(pWinPixmap->refcnt < 3);
     78 
     79     assert(0 < pScreenPixmap->refcnt);
     80     assert(pScreenPixmap->refcnt < 3);
     81 
     82     if (pParentPixmap) {
     83         assert(0 <= pParentPixmap->refcnt);
     84         assert(pParentPixmap->refcnt < 3);
     85     }
     86     return WT_WALKCHILDREN;
     87 }
     88 
     89 void
     90 compCheckTree(ScreenPtr pScreen)
     91 {
     92     WalkTree(pScreen, compCheckWindow, 0);
     93 }
     94 #endif
     95 
     96 typedef struct _compPixmapVisit {
     97     WindowPtr pWindow;
     98     PixmapPtr pPixmap;
     99     int bw;
    100 } CompPixmapVisitRec, *CompPixmapVisitPtr;
    101 
    102 static Bool
    103 compRepaintBorder(ClientPtr pClient, void *closure)
    104 {
    105     WindowPtr pWindow;
    106     int rc =
    107         dixLookupWindow(&pWindow, (XID) (intptr_t) closure, pClient,
    108                         DixWriteAccess);
    109 
    110     if (rc == Success) {
    111         RegionRec exposed;
    112 
    113         RegionNull(&exposed);
    114         RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize);
    115         pWindow->drawable.pScreen->PaintWindow(pWindow, &exposed, PW_BORDER);
    116         RegionUninit(&exposed);
    117     }
    118     return TRUE;
    119 }
    120 
    121 static int
    122 compSetPixmapVisitWindow(WindowPtr pWindow, void *data)
    123 {
    124     CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data;
    125     ScreenPtr pScreen = pWindow->drawable.pScreen;
    126 
    127     if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone)
    128         return WT_DONTWALKCHILDREN;
    129     (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap);
    130     /*
    131      * Recompute winSize and borderSize.  This is duplicate effort
    132      * when resizing pixmaps, but necessary when changing redirection.
    133      * Might be nice to fix this.
    134      */
    135     SetWinSize(pWindow);
    136     SetBorderSize(pWindow);
    137     if (pVisit->bw)
    138         QueueWorkProc(compRepaintBorder, serverClient,
    139                       (void *) (intptr_t) pWindow->drawable.id);
    140     return WT_WALKCHILDREN;
    141 }
    142 
    143 void
    144 compSetPixmap(WindowPtr pWindow, PixmapPtr pPixmap, int bw)
    145 {
    146     CompPixmapVisitRec visitRec;
    147 
    148     visitRec.pWindow = pWindow;
    149     visitRec.pPixmap = pPixmap;
    150     visitRec.bw = bw;
    151     TraverseTree(pWindow, compSetPixmapVisitWindow, (void *) &visitRec);
    152     compCheckTree(pWindow->drawable.pScreen);
    153 }
    154 
    155 Bool
    156 compCheckRedirect(WindowPtr pWin)
    157 {
    158     CompWindowPtr cw = GetCompWindow(pWin);
    159     CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
    160     Bool should;
    161 
    162     should = pWin->realized && (pWin->drawable.class != InputOnly) &&
    163         (cw != NULL) && (pWin->parent != NULL);
    164 
    165     /* Never redirect the overlay window */
    166     if (cs->pOverlayWin != NULL) {
    167         if (pWin == cs->pOverlayWin) {
    168             should = FALSE;
    169         }
    170     }
    171 
    172     if (should != (pWin->redirectDraw != RedirectDrawNone)) {
    173         if (should)
    174             return compAllocPixmap(pWin);
    175         else {
    176             ScreenPtr pScreen = pWin->drawable.pScreen;
    177             PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
    178 
    179             compSetParentPixmap(pWin);
    180             compRestoreWindow(pWin, pPixmap);
    181             (*pScreen->DestroyPixmap) (pPixmap);
    182         }
    183     }
    184     else if (should) {
    185         if (cw->update == CompositeRedirectAutomatic)
    186             pWin->redirectDraw = RedirectDrawAutomatic;
    187         else
    188             pWin->redirectDraw = RedirectDrawManual;
    189     }
    190     return TRUE;
    191 }
    192 
    193 static int
    194 updateOverlayWindow(ScreenPtr pScreen)
    195 {
    196     CompScreenPtr cs;
    197     WindowPtr pWin;             /* overlay window */
    198     XID vlist[2];
    199     int w = pScreen->width;
    200     int h = pScreen->height;
    201 
    202 #ifdef PANORAMIX
    203     if (!noPanoramiXExtension) {
    204         w = PanoramiXPixWidth;
    205         h = PanoramiXPixHeight;
    206     }
    207 #endif
    208 
    209     cs = GetCompScreen(pScreen);
    210     if ((pWin = cs->pOverlayWin) != NULL) {
    211         if ((pWin->drawable.width == w) && (pWin->drawable.height == h))
    212             return Success;
    213 
    214         /* Let's resize the overlay window. */
    215         vlist[0] = w;
    216         vlist[1] = h;
    217         return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin));
    218     }
    219 
    220     /* Let's be on the safe side and not assume an overlay window is
    221        always allocated. */
    222     return Success;
    223 }
    224 
    225 Bool
    226 compPositionWindow(WindowPtr pWin, int x, int y)
    227 {
    228     ScreenPtr pScreen = pWin->drawable.pScreen;
    229     CompScreenPtr cs = GetCompScreen(pScreen);
    230     Bool ret = TRUE;
    231 
    232     pScreen->PositionWindow = cs->PositionWindow;
    233     /*
    234      * "Shouldn't need this as all possible places should be wrapped
    235      *
    236      compCheckRedirect (pWin);
    237      */
    238 #ifdef COMPOSITE_DEBUG
    239     if ((pWin->redirectDraw != RedirectDrawNone) !=
    240         (pWin->viewable && (GetCompWindow(pWin) != NULL)))
    241         OsAbort();
    242 #endif
    243     if (pWin->redirectDraw != RedirectDrawNone) {
    244         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
    245         int bw = wBorderWidth(pWin);
    246         int nx = pWin->drawable.x - bw;
    247         int ny = pWin->drawable.y - bw;
    248 
    249         if (pPixmap->screen_x != nx || pPixmap->screen_y != ny) {
    250             pPixmap->screen_x = nx;
    251             pPixmap->screen_y = ny;
    252             pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
    253         }
    254     }
    255 
    256     if (!(*pScreen->PositionWindow) (pWin, x, y))
    257         ret = FALSE;
    258     cs->PositionWindow = pScreen->PositionWindow;
    259     pScreen->PositionWindow = compPositionWindow;
    260     compCheckTree(pWin->drawable.pScreen);
    261     if (updateOverlayWindow(pScreen) != Success)
    262         ret = FALSE;
    263     return ret;
    264 }
    265 
    266 Bool
    267 compRealizeWindow(WindowPtr pWin)
    268 {
    269     ScreenPtr pScreen = pWin->drawable.pScreen;
    270     CompScreenPtr cs = GetCompScreen(pScreen);
    271     Bool ret = TRUE;
    272 
    273     pScreen->RealizeWindow = cs->RealizeWindow;
    274     compCheckRedirect(pWin);
    275     if (!(*pScreen->RealizeWindow) (pWin))
    276         ret = FALSE;
    277     cs->RealizeWindow = pScreen->RealizeWindow;
    278     pScreen->RealizeWindow = compRealizeWindow;
    279     compCheckTree(pWin->drawable.pScreen);
    280     return ret;
    281 }
    282 
    283 Bool
    284 compUnrealizeWindow(WindowPtr pWin)
    285 {
    286     ScreenPtr pScreen = pWin->drawable.pScreen;
    287     CompScreenPtr cs = GetCompScreen(pScreen);
    288     Bool ret = TRUE;
    289 
    290     pScreen->UnrealizeWindow = cs->UnrealizeWindow;
    291     compCheckRedirect(pWin);
    292     if (!(*pScreen->UnrealizeWindow) (pWin))
    293         ret = FALSE;
    294     cs->UnrealizeWindow = pScreen->UnrealizeWindow;
    295     pScreen->UnrealizeWindow = compUnrealizeWindow;
    296     compCheckTree(pWin->drawable.pScreen);
    297     return ret;
    298 }
    299 
    300 /*
    301  * Called after the borderClip for the window has settled down
    302  * We use this to make sure our extra borderClip has the right origin
    303  */
    304 
    305 void
    306 compClipNotify(WindowPtr pWin, int dx, int dy)
    307 {
    308     ScreenPtr pScreen = pWin->drawable.pScreen;
    309     CompScreenPtr cs = GetCompScreen(pScreen);
    310     CompWindowPtr cw = GetCompWindow(pWin);
    311 
    312     if (cw) {
    313         if (cw->borderClipX != pWin->drawable.x ||
    314             cw->borderClipY != pWin->drawable.y) {
    315             RegionTranslate(&cw->borderClip,
    316                             pWin->drawable.x - cw->borderClipX,
    317                             pWin->drawable.y - cw->borderClipY);
    318             cw->borderClipX = pWin->drawable.x;
    319             cw->borderClipY = pWin->drawable.y;
    320         }
    321     }
    322     if (cs->ClipNotify) {
    323         pScreen->ClipNotify = cs->ClipNotify;
    324         (*pScreen->ClipNotify) (pWin, dx, dy);
    325         cs->ClipNotify = pScreen->ClipNotify;
    326         pScreen->ClipNotify = compClipNotify;
    327     }
    328 }
    329 
    330 Bool
    331 compIsAlternateVisual(ScreenPtr pScreen, XID visual)
    332 {
    333     CompScreenPtr cs = GetCompScreen(pScreen);
    334     int i;
    335 
    336     for (i = 0; cs && i < cs->numAlternateVisuals; i++)
    337         if (cs->alternateVisuals[i] == visual)
    338             return TRUE;
    339     return FALSE;
    340 }
    341 
    342 static Bool
    343 compIsImplicitRedirectException(ScreenPtr pScreen,
    344                                 XID parentVisual, XID winVisual)
    345 {
    346     CompScreenPtr cs = GetCompScreen(pScreen);
    347     int i;
    348 
    349     for (i = 0; i < cs->numImplicitRedirectExceptions; i++)
    350         if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual &&
    351             cs->implicitRedirectExceptions[i].winVisual == winVisual)
    352             return TRUE;
    353 
    354     return FALSE;
    355 }
    356 
    357 static Bool
    358 compImplicitRedirect(WindowPtr pWin, WindowPtr pParent)
    359 {
    360     if (pParent) {
    361         ScreenPtr pScreen = pWin->drawable.pScreen;
    362         XID winVisual = wVisual(pWin);
    363         XID parentVisual = wVisual(pParent);
    364 
    365         if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual))
    366             return FALSE;
    367 
    368         if (winVisual != parentVisual &&
    369             (compIsAlternateVisual(pScreen, winVisual) ||
    370              compIsAlternateVisual(pScreen, parentVisual)))
    371             return TRUE;
    372     }
    373     return FALSE;
    374 }
    375 
    376 static void
    377 compFreeOldPixmap(WindowPtr pWin)
    378 {
    379     ScreenPtr pScreen = pWin->drawable.pScreen;
    380 
    381     if (pWin->redirectDraw != RedirectDrawNone) {
    382         CompWindowPtr cw = GetCompWindow(pWin);
    383 
    384         if (cw->pOldPixmap) {
    385             (*pScreen->DestroyPixmap) (cw->pOldPixmap);
    386             cw->pOldPixmap = NullPixmap;
    387         }
    388     }
    389 }
    390 
    391 void
    392 compMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
    393 {
    394     ScreenPtr pScreen = pWin->drawable.pScreen;
    395     CompScreenPtr cs = GetCompScreen(pScreen);
    396 
    397     pScreen->MoveWindow = cs->MoveWindow;
    398     (*pScreen->MoveWindow) (pWin, x, y, pSib, kind);
    399     cs->MoveWindow = pScreen->MoveWindow;
    400     pScreen->MoveWindow = compMoveWindow;
    401 
    402     compFreeOldPixmap(pWin);
    403     compCheckTree(pScreen);
    404 }
    405 
    406 void
    407 compResizeWindow(WindowPtr pWin, int x, int y,
    408                  unsigned int w, unsigned int h, WindowPtr pSib)
    409 {
    410     ScreenPtr pScreen = pWin->drawable.pScreen;
    411     CompScreenPtr cs = GetCompScreen(pScreen);
    412 
    413     pScreen->ResizeWindow = cs->ResizeWindow;
    414     (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib);
    415     cs->ResizeWindow = pScreen->ResizeWindow;
    416     pScreen->ResizeWindow = compResizeWindow;
    417 
    418     compFreeOldPixmap(pWin);
    419     compCheckTree(pWin->drawable.pScreen);
    420 }
    421 
    422 void
    423 compChangeBorderWidth(WindowPtr pWin, unsigned int bw)
    424 {
    425     ScreenPtr pScreen = pWin->drawable.pScreen;
    426     CompScreenPtr cs = GetCompScreen(pScreen);
    427 
    428     pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
    429     (*pScreen->ChangeBorderWidth) (pWin, bw);
    430     cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
    431     pScreen->ChangeBorderWidth = compChangeBorderWidth;
    432 
    433     compFreeOldPixmap(pWin);
    434     compCheckTree(pWin->drawable.pScreen);
    435 }
    436 
    437 void
    438 compReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
    439 {
    440     ScreenPtr pScreen = pWin->drawable.pScreen;
    441     CompScreenPtr cs = GetCompScreen(pScreen);
    442     CompWindowPtr cw;
    443 
    444     pScreen->ReparentWindow = cs->ReparentWindow;
    445     /*
    446      * Remove any implicit redirect due to synthesized visual
    447      */
    448     if (compImplicitRedirect(pWin, pPriorParent))
    449         compUnredirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
    450     /*
    451      * Handle subwindows redirection
    452      */
    453     compUnredirectOneSubwindow(pPriorParent, pWin);
    454     compRedirectOneSubwindow(pWin->parent, pWin);
    455     /*
    456      * Add any implicit redirect due to synthesized visual
    457      */
    458     if (compImplicitRedirect(pWin, pWin->parent))
    459         compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
    460 
    461     /*
    462      * Allocate any necessary redirect pixmap
    463      * (this actually should never be true; pWin is always unmapped)
    464      */
    465     compCheckRedirect(pWin);
    466 
    467     /*
    468      * Reset pixmap pointers as appropriate
    469      */
    470     if (pWin->parent && pWin->redirectDraw == RedirectDrawNone)
    471         compSetPixmap(pWin, (*pScreen->GetWindowPixmap) (pWin->parent),
    472                       pWin->borderWidth);
    473     /*
    474      * Call down to next function
    475      */
    476     if (pScreen->ReparentWindow)
    477         (*pScreen->ReparentWindow) (pWin, pPriorParent);
    478     cs->ReparentWindow = pScreen->ReparentWindow;
    479     pScreen->ReparentWindow = compReparentWindow;
    480 
    481     cw = GetCompWindow(pWin);
    482     if (pWin->damagedDescendants || (cw && cw->damaged))
    483         compMarkAncestors(pWin);
    484 
    485     compCheckTree(pWin->drawable.pScreen);
    486 }
    487 
    488 void
    489 compCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
    490 {
    491     ScreenPtr pScreen = pWin->drawable.pScreen;
    492     CompScreenPtr cs = GetCompScreen(pScreen);
    493     int dx = 0, dy = 0;
    494 
    495     if (pWin->redirectDraw != RedirectDrawNone) {
    496         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
    497         CompWindowPtr cw = GetCompWindow(pWin);
    498 
    499         assert(cw->oldx != COMP_ORIGIN_INVALID);
    500         assert(cw->oldy != COMP_ORIGIN_INVALID);
    501         if (cw->pOldPixmap) {
    502             /*
    503              * Ok, the old bits are available in pOldPixmap and
    504              * need to be copied to pNewPixmap.
    505              */
    506             RegionRec rgnDst;
    507             GCPtr pGC;
    508 
    509             dx = ptOldOrg.x - pWin->drawable.x;
    510             dy = ptOldOrg.y - pWin->drawable.y;
    511             RegionTranslate(prgnSrc, -dx, -dy);
    512 
    513             RegionNull(&rgnDst);
    514 
    515             RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
    516 
    517             RegionTranslate(&rgnDst, -pPixmap->screen_x, -pPixmap->screen_y);
    518 
    519             dx = dx + pPixmap->screen_x - cw->oldx;
    520             dy = dy + pPixmap->screen_y - cw->oldy;
    521             pGC = GetScratchGC(pPixmap->drawable.depth, pScreen);
    522             if (pGC) {
    523                 BoxPtr pBox = RegionRects(&rgnDst);
    524                 int nBox = RegionNumRects(&rgnDst);
    525 
    526                 ValidateGC(&pPixmap->drawable, pGC);
    527                 while (nBox--) {
    528                     (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable,
    529                                                   &pPixmap->drawable,
    530                                                   pGC,
    531                                                   pBox->x1 + dx, pBox->y1 + dy,
    532                                                   pBox->x2 - pBox->x1,
    533                                                   pBox->y2 - pBox->y1,
    534                                                   pBox->x1, pBox->y1);
    535                     pBox++;
    536                 }
    537                 FreeScratchGC(pGC);
    538             }
    539             RegionUninit(&rgnDst);
    540             return;
    541         }
    542         dx = pPixmap->screen_x - cw->oldx;
    543         dy = pPixmap->screen_y - cw->oldy;
    544         ptOldOrg.x += dx;
    545         ptOldOrg.y += dy;
    546     }
    547 
    548     pScreen->CopyWindow = cs->CopyWindow;
    549     if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y) {
    550         if (dx || dy)
    551             RegionTranslate(prgnSrc, dx, dy);
    552         (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
    553         if (dx || dy)
    554             RegionTranslate(prgnSrc, -dx, -dy);
    555     }
    556     else {
    557         ptOldOrg.x -= dx;
    558         ptOldOrg.y -= dy;
    559         RegionTranslate(prgnSrc,
    560                         pWin->drawable.x - ptOldOrg.x,
    561                         pWin->drawable.y - ptOldOrg.y);
    562         DamageDamageRegion(&pWin->drawable, prgnSrc);
    563     }
    564     cs->CopyWindow = pScreen->CopyWindow;
    565     pScreen->CopyWindow = compCopyWindow;
    566     compCheckTree(pWin->drawable.pScreen);
    567 }
    568 
    569 Bool
    570 compCreateWindow(WindowPtr pWin)
    571 {
    572     ScreenPtr pScreen = pWin->drawable.pScreen;
    573     CompScreenPtr cs = GetCompScreen(pScreen);
    574     Bool ret;
    575 
    576     pScreen->CreateWindow = cs->CreateWindow;
    577     ret = (*pScreen->CreateWindow) (pWin);
    578     if (pWin->parent && ret) {
    579         CompSubwindowsPtr csw = GetCompSubwindows(pWin->parent);
    580         CompClientWindowPtr ccw;
    581         PixmapPtr parent_pixmap = (*pScreen->GetWindowPixmap)(pWin->parent);
    582         PixmapPtr window_pixmap = (*pScreen->GetWindowPixmap)(pWin);
    583 
    584         if (window_pixmap != parent_pixmap)
    585             (*pScreen->SetWindowPixmap) (pWin, parent_pixmap);
    586         if (csw)
    587             for (ccw = csw->clients; ccw; ccw = ccw->next)
    588                 compRedirectWindow(clients[CLIENT_ID(ccw->id)],
    589                                    pWin, ccw->update);
    590         if (compImplicitRedirect(pWin, pWin->parent))
    591             compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
    592     }
    593     cs->CreateWindow = pScreen->CreateWindow;
    594     pScreen->CreateWindow = compCreateWindow;
    595     compCheckTree(pWin->drawable.pScreen);
    596     return ret;
    597 }
    598 
    599 Bool
    600 compDestroyWindow(WindowPtr pWin)
    601 {
    602     ScreenPtr pScreen = pWin->drawable.pScreen;
    603     CompScreenPtr cs = GetCompScreen(pScreen);
    604     CompWindowPtr cw;
    605     CompSubwindowsPtr csw;
    606     Bool ret;
    607 
    608     pScreen->DestroyWindow = cs->DestroyWindow;
    609     while ((cw = GetCompWindow(pWin)))
    610         FreeResource(cw->clients->id, RT_NONE);
    611     while ((csw = GetCompSubwindows(pWin)))
    612         FreeResource(csw->clients->id, RT_NONE);
    613 
    614     if (pWin->redirectDraw != RedirectDrawNone) {
    615         PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
    616 
    617         compSetParentPixmap(pWin);
    618         (*pScreen->DestroyPixmap) (pPixmap);
    619     }
    620     ret = (*pScreen->DestroyWindow) (pWin);
    621     cs->DestroyWindow = pScreen->DestroyWindow;
    622     pScreen->DestroyWindow = compDestroyWindow;
    623 /*    compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
    624     return ret;
    625 }
    626 
    627 void
    628 compSetRedirectBorderClip(WindowPtr pWin, RegionPtr pRegion)
    629 {
    630     CompWindowPtr cw = GetCompWindow(pWin);
    631     RegionRec damage;
    632 
    633     RegionNull(&damage);
    634     /*
    635      * Align old border clip with new border clip
    636      */
    637     RegionTranslate(&cw->borderClip,
    638                     pWin->drawable.x - cw->borderClipX,
    639                     pWin->drawable.y - cw->borderClipY);
    640     /*
    641      * Compute newly visible portion of window for repaint
    642      */
    643     RegionSubtract(&damage, pRegion, &cw->borderClip);
    644     /*
    645      * Report that as damaged so it will be redrawn
    646      */
    647     DamageDamageRegion(&pWin->drawable, &damage);
    648     RegionUninit(&damage);
    649     /*
    650      * Save the new border clip region
    651      */
    652     RegionCopy(&cw->borderClip, pRegion);
    653     cw->borderClipX = pWin->drawable.x;
    654     cw->borderClipY = pWin->drawable.y;
    655 }
    656 
    657 RegionPtr
    658 compGetRedirectBorderClip(WindowPtr pWin)
    659 {
    660     CompWindowPtr cw = GetCompWindow(pWin);
    661 
    662     return &cw->borderClip;
    663 }
    664 
    665 static void
    666 compWindowUpdateAutomatic(WindowPtr pWin)
    667 {
    668     CompWindowPtr cw = GetCompWindow(pWin);
    669     ScreenPtr pScreen = pWin->drawable.pScreen;
    670     WindowPtr pParent = pWin->parent;
    671     PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin);
    672     PictFormatPtr pSrcFormat = PictureWindowFormat(pWin);
    673     PictFormatPtr pDstFormat = PictureWindowFormat(pWin->parent);
    674     int error;
    675     RegionPtr pRegion = DamageRegion(cw->damage);
    676     PicturePtr pSrcPicture = CreatePicture(0, &pSrcPixmap->drawable,
    677                                            pSrcFormat,
    678                                            0, 0,
    679                                            serverClient,
    680                                            &error);
    681     XID subwindowMode = IncludeInferiors;
    682     PicturePtr pDstPicture = CreatePicture(0, &pParent->drawable,
    683                                            pDstFormat,
    684                                            CPSubwindowMode,
    685                                            &subwindowMode,
    686                                            serverClient,
    687                                            &error);
    688 
    689     /*
    690      * First move the region from window to screen coordinates
    691      */
    692     RegionTranslate(pRegion, pWin->drawable.x, pWin->drawable.y);
    693 
    694     /*
    695      * Clip against the "real" border clip
    696      */
    697     RegionIntersect(pRegion, pRegion, &cw->borderClip);
    698 
    699     /*
    700      * Now translate from screen to dest coordinates
    701      */
    702     RegionTranslate(pRegion, -pParent->drawable.x, -pParent->drawable.y);
    703 
    704     /*
    705      * Clip the picture
    706      */
    707     SetPictureClipRegion(pDstPicture, 0, 0, pRegion);
    708 
    709     /*
    710      * And paint
    711      */
    712     CompositePicture(PictOpSrc, pSrcPicture, 0, pDstPicture,
    713                      0, 0,      /* src_x, src_y */
    714                      0, 0,      /* msk_x, msk_y */
    715                      pSrcPixmap->screen_x - pParent->drawable.x,
    716                      pSrcPixmap->screen_y - pParent->drawable.y,
    717                      pSrcPixmap->drawable.width, pSrcPixmap->drawable.height);
    718     FreePicture(pSrcPicture, 0);
    719     FreePicture(pDstPicture, 0);
    720     /*
    721      * Empty the damage region.  This has the nice effect of
    722      * rendering the translations above harmless
    723      */
    724     DamageEmpty(cw->damage);
    725 }
    726 
    727 static void
    728 compPaintWindowToParent(WindowPtr pWin)
    729 {
    730     compPaintChildrenToWindow(pWin);
    731 
    732     if (pWin->redirectDraw != RedirectDrawNone) {
    733         CompWindowPtr cw = GetCompWindow(pWin);
    734 
    735         if (cw->damaged) {
    736             compWindowUpdateAutomatic(pWin);
    737             cw->damaged = FALSE;
    738         }
    739     }
    740 }
    741 
    742 void
    743 compPaintChildrenToWindow(WindowPtr pWin)
    744 {
    745     WindowPtr pChild;
    746 
    747     if (!pWin->damagedDescendants)
    748         return;
    749 
    750     for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
    751         compPaintWindowToParent(pChild);
    752 
    753     pWin->damagedDescendants = FALSE;
    754 }
    755 
    756 WindowPtr
    757 CompositeRealChildHead(WindowPtr pWin)
    758 {
    759     WindowPtr pChild, pChildBefore;
    760     CompScreenPtr cs;
    761 
    762     if (!pWin->parent &&
    763         (screenIsSaved == SCREEN_SAVER_ON) &&
    764         (HasSaverWindow(pWin->drawable.pScreen))) {
    765 
    766         /* First child is the screen saver; see if next child is the overlay */
    767         pChildBefore = pWin->firstChild;
    768         pChild = pChildBefore->nextSib;
    769 
    770     }
    771     else {
    772         pChildBefore = NullWindow;
    773         pChild = pWin->firstChild;
    774     }
    775 
    776     if (!pChild) {
    777         return NullWindow;
    778     }
    779 
    780     cs = GetCompScreen(pWin->drawable.pScreen);
    781     if (pChild == cs->pOverlayWin) {
    782         return pChild;
    783     }
    784     else {
    785         return pChildBefore;
    786     }
    787 }
    788 
    789 int
    790 compConfigNotify(WindowPtr pWin, int x, int y, int w, int h,
    791                  int bw, WindowPtr pSib)
    792 {
    793     ScreenPtr pScreen = pWin->drawable.pScreen;
    794     CompScreenPtr cs = GetCompScreen(pScreen);
    795     Bool ret = 0;
    796     WindowPtr pParent = pWin->parent;
    797     int draw_x, draw_y;
    798     Bool alloc_ret;
    799 
    800     if (cs->ConfigNotify) {
    801         pScreen->ConfigNotify = cs->ConfigNotify;
    802         ret = (*pScreen->ConfigNotify) (pWin, x, y, w, h, bw, pSib);
    803         cs->ConfigNotify = pScreen->ConfigNotify;
    804         pScreen->ConfigNotify = compConfigNotify;
    805 
    806         if (ret)
    807             return ret;
    808     }
    809 
    810     if (pWin->redirectDraw == RedirectDrawNone)
    811         return Success;
    812 
    813     compCheckTree(pScreen);
    814 
    815     draw_x = pParent->drawable.x + x + bw;
    816     draw_y = pParent->drawable.y + y + bw;
    817     alloc_ret = compReallocPixmap(pWin, draw_x, draw_y, w, h, bw);
    818 
    819     if (alloc_ret == FALSE)
    820         return BadAlloc;
    821     return Success;
    822 }