xserver

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

rootlessScreen.c (21448B)


      1 /*
      2  * Screen routines for generic rootless X server
      3  */
      4 /*
      5  * Copyright (c) 2001 Greg Parker. All Rights Reserved.
      6  * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
      7  * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
      8  *
      9  * Permission is hereby granted, free of charge, to any person obtaining a
     10  * copy of this software and associated documentation files (the "Software"),
     11  * to deal in the Software without restriction, including without limitation
     12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     13  * and/or sell copies of the Software, and to permit persons to whom the
     14  * Software is furnished to do so, subject to the following conditions:
     15  *
     16  * The above copyright notice and this permission notice shall be included in
     17  * all copies or substantial portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     22  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     23  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     24  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     25  * DEALINGS IN THE SOFTWARE.
     26  *
     27  * Except as contained in this notice, the name(s) of the above copyright
     28  * holders shall not be used in advertising or otherwise to promote the sale,
     29  * use or other dealings in this Software without prior written authorization.
     30  */
     31 
     32 #ifdef HAVE_DIX_CONFIG_H
     33 #include <dix-config.h>
     34 #endif
     35 
     36 #include "mi.h"
     37 #include "scrnintstr.h"
     38 #include "gcstruct.h"
     39 #include "pixmapstr.h"
     40 #include "windowstr.h"
     41 #include "propertyst.h"
     42 #include "mivalidate.h"
     43 #include "picturestr.h"
     44 #include "colormapst.h"
     45 
     46 #include <sys/types.h>
     47 #include <sys/stat.h>
     48 #include <fcntl.h>
     49 #include <string.h>
     50 
     51 #include "rootlessCommon.h"
     52 #include "rootlessWindow.h"
     53 
     54 /* In milliseconds */
     55 #ifndef ROOTLESS_REDISPLAY_DELAY
     56 #define ROOTLESS_REDISPLAY_DELAY 10
     57 #endif
     58 
     59 extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild,
     60                                   VTKind kind);
     61 extern Bool RootlessCreateGC(GCPtr pGC);
     62 
     63 // Initialize globals
     64 DevPrivateKeyRec rootlessGCPrivateKeyRec;
     65 DevPrivateKeyRec rootlessScreenPrivateKeyRec;
     66 DevPrivateKeyRec rootlessWindowPrivateKeyRec;
     67 DevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec;
     68 
     69 /*
     70  * RootlessUpdateScreenPixmap
     71  *  miCreateScreenResources does not like a null framebuffer pointer,
     72  *  it leaves the screen pixmap with an uninitialized data pointer.
     73  *  Thus, rootless implementations typically set the framebuffer width
     74  *  to zero so that miCreateScreenResources does not allocate a screen
     75  *  pixmap for us. We allocate our own screen pixmap here since we need
     76  *  the screen pixmap to be valid (e.g. CopyArea from the root window).
     77  */
     78 void
     79 RootlessUpdateScreenPixmap(ScreenPtr pScreen)
     80 {
     81     RootlessScreenRec *s = SCREENREC(pScreen);
     82     PixmapPtr pPix;
     83     unsigned int rowbytes;
     84 
     85     pPix = (*pScreen->GetScreenPixmap) (pScreen);
     86     if (pPix == NULL) {
     87         pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth, 0);
     88         (*pScreen->SetScreenPixmap) (pPix);
     89     }
     90 
     91     rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth);
     92 
     93     if (s->pixmap_data_size < rowbytes) {
     94         free(s->pixmap_data);
     95 
     96         s->pixmap_data_size = rowbytes;
     97         s->pixmap_data = malloc(s->pixmap_data_size);
     98         if (s->pixmap_data == NULL)
     99             return;
    100 
    101         memset(s->pixmap_data, 0xFF, s->pixmap_data_size);
    102 
    103         pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height,
    104                                     pScreen->rootDepth,
    105                                     BitsPerPixel(pScreen->rootDepth),
    106                                     0, s->pixmap_data);
    107         /* ModifyPixmapHeader ignores zero arguments, so install rowbytes
    108            by hand. */
    109         pPix->devKind = 0;
    110     }
    111 }
    112 
    113 /*
    114  * RootlessCreateScreenResources
    115  *  Rootless implementations typically set a null framebuffer pointer, which
    116  *  causes problems with miCreateScreenResources. We fix things up here.
    117  */
    118 static Bool
    119 RootlessCreateScreenResources(ScreenPtr pScreen)
    120 {
    121     Bool ret = TRUE;
    122 
    123     SCREEN_UNWRAP(pScreen, CreateScreenResources);
    124 
    125     if (pScreen->CreateScreenResources != NULL)
    126         ret = (*pScreen->CreateScreenResources) (pScreen);
    127 
    128     SCREEN_WRAP(pScreen, CreateScreenResources);
    129 
    130     if (!ret)
    131         return ret;
    132 
    133     /* Make sure we have a valid screen pixmap. */
    134 
    135     RootlessUpdateScreenPixmap(pScreen);
    136 
    137     return ret;
    138 }
    139 
    140 static Bool
    141 RootlessCloseScreen(ScreenPtr pScreen)
    142 {
    143     RootlessScreenRec *s;
    144 
    145     s = SCREENREC(pScreen);
    146 
    147     // fixme unwrap everything that was wrapped?
    148     pScreen->CloseScreen = s->CloseScreen;
    149 
    150     if (s->pixmap_data != NULL) {
    151         free(s->pixmap_data);
    152         s->pixmap_data = NULL;
    153         s->pixmap_data_size = 0;
    154     }
    155 
    156     free(s);
    157     return pScreen->CloseScreen(pScreen);
    158 }
    159 
    160 static void
    161 RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
    162                  unsigned int format, unsigned long planeMask, char *pdstLine)
    163 {
    164     ScreenPtr pScreen = pDrawable->pScreen;
    165 
    166     SCREEN_UNWRAP(pScreen, GetImage);
    167 
    168     if (pDrawable->type == DRAWABLE_WINDOW) {
    169         int x0, y0, x1, y1;
    170         RootlessWindowRec *winRec;
    171 
    172         // Many apps use GetImage to sync with the visible frame buffer
    173         // FIXME: entire screen or just window or all screens?
    174         RootlessRedisplayScreen(pScreen);
    175 
    176         // RedisplayScreen stops drawing, so we need to start it again
    177         RootlessStartDrawing((WindowPtr) pDrawable);
    178 
    179         /* Check that we have some place to read from. */
    180         winRec = WINREC(TopLevelParent((WindowPtr) pDrawable));
    181         if (winRec == NULL)
    182             goto out;
    183 
    184         /* Clip to top-level window bounds. */
    185         /* FIXME: fbGetImage uses the width parameter to calculate the
    186            stride of the destination pixmap. If w is clipped, the data
    187            returned will be garbage, although we will not crash. */
    188 
    189         x0 = pDrawable->x + sx;
    190         y0 = pDrawable->y + sy;
    191         x1 = x0 + w;
    192         y1 = y0 + h;
    193 
    194         x0 = max(x0, winRec->x);
    195         y0 = max(y0, winRec->y);
    196         x1 = min(x1, winRec->x + winRec->width);
    197         y1 = min(y1, winRec->y + winRec->height);
    198 
    199         sx = x0 - pDrawable->x;
    200         sy = y0 - pDrawable->y;
    201         w = x1 - x0;
    202         h = y1 - y0;
    203 
    204         if (w <= 0 || h <= 0)
    205             goto out;
    206     }
    207 
    208     pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
    209 
    210  out:
    211     SCREEN_WRAP(pScreen, GetImage);
    212 }
    213 
    214 /*
    215  * RootlessSourceValidate
    216  *  CopyArea and CopyPlane use a GC tied to the destination drawable.
    217  *  StartDrawing/StopDrawing wrappers won't be called if source is
    218  *  a visible window but the destination isn't. So, we call StartDrawing
    219  *  here and leave StopDrawing for the block handler.
    220  */
    221 static void
    222 RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h,
    223                        unsigned int subWindowMode)
    224 {
    225     SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
    226     if (pDrawable->type == DRAWABLE_WINDOW) {
    227         WindowPtr pWin = (WindowPtr) pDrawable;
    228 
    229         RootlessStartDrawing(pWin);
    230     }
    231     pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h,
    232                                        subWindowMode);
    233     SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
    234 }
    235 
    236 static void
    237 RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
    238                   INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
    239                   INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
    240 {
    241     ScreenPtr pScreen = pDst->pDrawable->pScreen;
    242     PictureScreenPtr ps = GetPictureScreen(pScreen);
    243     WindowPtr srcWin, dstWin, maskWin = NULL;
    244 
    245     if (pMask) {                // pMask can be NULL
    246         maskWin = (pMask->pDrawable &&
    247                    pMask->pDrawable->type ==
    248                    DRAWABLE_WINDOW) ? (WindowPtr) pMask->pDrawable : NULL;
    249     }
    250     srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
    251         (WindowPtr) pSrc->pDrawable : NULL;
    252     dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
    253         (WindowPtr) pDst->pDrawable : NULL;
    254 
    255     // SCREEN_UNWRAP(ps, Composite);
    256     ps->Composite = SCREENREC(pScreen)->Composite;
    257 
    258     if (srcWin && IsFramedWindow(srcWin))
    259         RootlessStartDrawing(srcWin);
    260     if (maskWin && IsFramedWindow(maskWin))
    261         RootlessStartDrawing(maskWin);
    262     if (dstWin && IsFramedWindow(dstWin))
    263         RootlessStartDrawing(dstWin);
    264 
    265     ps->Composite(op, pSrc, pMask, pDst,
    266                   xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
    267 
    268     if (dstWin && IsFramedWindow(dstWin)) {
    269         RootlessDamageRect(dstWin, xDst, yDst, width, height);
    270     }
    271 
    272     ps->Composite = RootlessComposite;
    273     // SCREEN_WRAP(ps, Composite);
    274 }
    275 
    276 static void
    277 RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
    278                PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
    279                int nlist, GlyphListPtr list, GlyphPtr * glyphs)
    280 {
    281     ScreenPtr pScreen = pDst->pDrawable->pScreen;
    282     PictureScreenPtr ps = GetPictureScreen(pScreen);
    283     int x, y;
    284     int n;
    285     GlyphPtr glyph;
    286     WindowPtr srcWin, dstWin;
    287 
    288     srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
    289         (WindowPtr) pSrc->pDrawable : NULL;
    290     dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
    291         (WindowPtr) pDst->pDrawable : NULL;
    292 
    293     if (srcWin && IsFramedWindow(srcWin))
    294         RootlessStartDrawing(srcWin);
    295     if (dstWin && IsFramedWindow(dstWin))
    296         RootlessStartDrawing(dstWin);
    297 
    298     //SCREEN_UNWRAP(ps, Glyphs);
    299     ps->Glyphs = SCREENREC(pScreen)->Glyphs;
    300     ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
    301     ps->Glyphs = RootlessGlyphs;
    302     //SCREEN_WRAP(ps, Glyphs);
    303 
    304     if (dstWin && IsFramedWindow(dstWin)) {
    305         x = xSrc;
    306         y = ySrc;
    307 
    308         while (nlist--) {
    309             x += list->xOff;
    310             y += list->yOff;
    311             n = list->len;
    312 
    313             /* Calling DamageRect for the bounding box of each glyph is
    314                inefficient. So compute the union of all glyphs in a list
    315                and damage that. */
    316 
    317             if (n > 0) {
    318                 BoxRec box;
    319 
    320                 glyph = *glyphs++;
    321 
    322                 box.x1 = x - glyph->info.x;
    323                 box.y1 = y - glyph->info.y;
    324                 box.x2 = box.x1 + glyph->info.width;
    325                 box.y2 = box.y1 + glyph->info.height;
    326 
    327                 x += glyph->info.xOff;
    328                 y += glyph->info.yOff;
    329 
    330                 while (--n > 0) {
    331                     short x1, y1, x2, y2;
    332 
    333                     glyph = *glyphs++;
    334 
    335                     x1 = x - glyph->info.x;
    336                     y1 = y - glyph->info.y;
    337                     x2 = x1 + glyph->info.width;
    338                     y2 = y1 + glyph->info.height;
    339 
    340                     box.x1 = max(box.x1, x1);
    341                     box.y1 = max(box.y1, y1);
    342                     box.x2 = max(box.x2, x2);
    343                     box.y2 = max(box.y2, y2);
    344 
    345                     x += glyph->info.xOff;
    346                     y += glyph->info.yOff;
    347                 }
    348 
    349                 RootlessDamageBox(dstWin, &box);
    350             }
    351             list++;
    352         }
    353     }
    354 }
    355 
    356 /*
    357  * RootlessValidateTree
    358  *  ValidateTree is modified in two ways:
    359  *   - top-level windows don't clip each other
    360  *   - windows aren't clipped against root.
    361  *  These only matter when validating from the root.
    362  */
    363 static int
    364 RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
    365 {
    366     int result;
    367     RegionRec saveRoot;
    368     ScreenPtr pScreen = pParent->drawable.pScreen;
    369 
    370     SCREEN_UNWRAP(pScreen, ValidateTree);
    371     RL_DEBUG_MSG("VALIDATETREE start ");
    372 
    373     // Use our custom version to validate from root
    374     if (IsRoot(pParent)) {
    375         RL_DEBUG_MSG("custom ");
    376         result = RootlessMiValidateTree(pParent, pChild, kind);
    377     }
    378     else {
    379         HUGE_ROOT(pParent);
    380         result = pScreen->ValidateTree(pParent, pChild, kind);
    381         NORMAL_ROOT(pParent);
    382     }
    383 
    384     SCREEN_WRAP(pScreen, ValidateTree);
    385     RL_DEBUG_MSG("VALIDATETREE end\n");
    386 
    387     return result;
    388 }
    389 
    390 /*
    391  * RootlessMarkOverlappedWindows
    392  *  MarkOverlappedWindows is modified to ignore overlapping
    393  *  top-level windows.
    394  */
    395 static Bool
    396 RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
    397                               WindowPtr *ppLayerWin)
    398 {
    399     RegionRec saveRoot;
    400     Bool result;
    401     ScreenPtr pScreen = pWin->drawable.pScreen;
    402 
    403     SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
    404     RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
    405 
    406     HUGE_ROOT(pWin);
    407     if (IsRoot(pWin)) {
    408         // root - mark nothing
    409         RL_DEBUG_MSG("is root not marking ");
    410         result = FALSE;
    411     }
    412     else if (!IsTopLevel(pWin)) {
    413         // not top-level window - mark normally
    414         result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
    415     }
    416     else {
    417         //top-level window - mark children ONLY - NO overlaps with sibs (?)
    418         // This code copied from miMarkOverlappedWindows()
    419 
    420         register WindowPtr pChild;
    421         Bool anyMarked = FALSE;
    422         MarkWindowProcPtr MarkWindow = pScreen->MarkWindow;
    423 
    424         RL_DEBUG_MSG("is top level! ");
    425         /* single layered systems are easy */
    426         if (ppLayerWin)
    427             *ppLayerWin = pWin;
    428 
    429         if (pWin == pFirst) {
    430             /* Blindly mark pWin and all of its inferiors.   This is a slight
    431              * overkill if there are mapped windows that outside pWin's border,
    432              * but it's better than wasting time on RectIn checks.
    433              */
    434             pChild = pWin;
    435             while (1) {
    436                 if (pChild->viewable) {
    437                     if (RegionBroken(&pChild->winSize))
    438                         SetWinSize(pChild);
    439                     if (RegionBroken(&pChild->borderSize))
    440                         SetBorderSize(pChild);
    441                     (*MarkWindow) (pChild);
    442                     if (pChild->firstChild) {
    443                         pChild = pChild->firstChild;
    444                         continue;
    445                     }
    446                 }
    447                 while (!pChild->nextSib && (pChild != pWin))
    448                     pChild = pChild->parent;
    449                 if (pChild == pWin)
    450                     break;
    451                 pChild = pChild->nextSib;
    452             }
    453             anyMarked = TRUE;
    454         }
    455         if (anyMarked)
    456             (*MarkWindow) (pWin->parent);
    457         result = anyMarked;
    458     }
    459     NORMAL_ROOT(pWin);
    460     SCREEN_WRAP(pScreen, MarkOverlappedWindows);
    461     RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
    462 
    463     return result;
    464 }
    465 
    466 static void
    467 expose_1(WindowPtr pWin)
    468 {
    469     WindowPtr pChild;
    470 
    471     if (!pWin->realized)
    472         return;
    473 
    474     pWin->drawable.pScreen->PaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND);
    475 
    476     /* FIXME: comments in windowstr.h indicate that borderClip doesn't
    477        include subwindow visibility. But I'm not so sure.. so we may
    478        be exposing too much.. */
    479 
    480     miSendExposures(pWin, &pWin->borderClip,
    481                     pWin->drawable.x, pWin->drawable.y);
    482 
    483     for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib)
    484         expose_1(pChild);
    485 }
    486 
    487 void
    488 RootlessScreenExpose(ScreenPtr pScreen)
    489 {
    490     expose_1(pScreen->root);
    491 }
    492 
    493 ColormapPtr
    494 RootlessGetColormap(ScreenPtr pScreen)
    495 {
    496     RootlessScreenRec *s = SCREENREC(pScreen);
    497 
    498     return s->colormap;
    499 }
    500 
    501 static void
    502 RootlessInstallColormap(ColormapPtr pMap)
    503 {
    504     ScreenPtr pScreen = pMap->pScreen;
    505     RootlessScreenRec *s = SCREENREC(pScreen);
    506 
    507     SCREEN_UNWRAP(pScreen, InstallColormap);
    508 
    509     if (s->colormap != pMap) {
    510         s->colormap = pMap;
    511         s->colormap_changed = TRUE;
    512         RootlessQueueRedisplay(pScreen);
    513     }
    514 
    515     pScreen->InstallColormap(pMap);
    516 
    517     SCREEN_WRAP(pScreen, InstallColormap);
    518 }
    519 
    520 static void
    521 RootlessUninstallColormap(ColormapPtr pMap)
    522 {
    523     ScreenPtr pScreen = pMap->pScreen;
    524     RootlessScreenRec *s = SCREENREC(pScreen);
    525 
    526     SCREEN_UNWRAP(pScreen, UninstallColormap);
    527 
    528     if (s->colormap == pMap)
    529         s->colormap = NULL;
    530 
    531     pScreen->UninstallColormap(pMap);
    532 
    533     SCREEN_WRAP(pScreen, UninstallColormap);
    534 }
    535 
    536 static void
    537 RootlessStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef)
    538 {
    539     ScreenPtr pScreen = pMap->pScreen;
    540     RootlessScreenRec *s = SCREENREC(pScreen);
    541 
    542     SCREEN_UNWRAP(pScreen, StoreColors);
    543 
    544     if (s->colormap == pMap && ndef > 0) {
    545         s->colormap_changed = TRUE;
    546         RootlessQueueRedisplay(pScreen);
    547     }
    548 
    549     pScreen->StoreColors(pMap, ndef, pdef);
    550 
    551     SCREEN_WRAP(pScreen, StoreColors);
    552 }
    553 
    554 static CARD32
    555 RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg)
    556 {
    557     RootlessScreenRec *screenRec = arg;
    558 
    559     if (!screenRec->redisplay_queued) {
    560         /* No update needed. Stop the timer. */
    561 
    562         screenRec->redisplay_timer_set = FALSE;
    563         return 0;
    564     }
    565 
    566     screenRec->redisplay_queued = FALSE;
    567 
    568     /* Mark that we should redisplay before waiting for I/O next time */
    569     screenRec->redisplay_expired = TRUE;
    570 
    571     /* Reinstall the timer immediately, so we get as close to our
    572        redisplay interval as possible. */
    573 
    574     return ROOTLESS_REDISPLAY_DELAY;
    575 }
    576 
    577 /*
    578  * RootlessQueueRedisplay
    579  *  Queue a redisplay after a timer delay to ensure we do not redisplay
    580  *  too frequently.
    581  */
    582 void
    583 RootlessQueueRedisplay(ScreenPtr pScreen)
    584 {
    585     RootlessScreenRec *screenRec = SCREENREC(pScreen);
    586 
    587     screenRec->redisplay_queued = TRUE;
    588 
    589     if (screenRec->redisplay_timer_set)
    590         return;
    591 
    592     screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer,
    593                                           0, ROOTLESS_REDISPLAY_DELAY,
    594                                           RootlessRedisplayCallback, screenRec);
    595     screenRec->redisplay_timer_set = TRUE;
    596 }
    597 
    598 /*
    599  * RootlessBlockHandler
    600  *  If the redisplay timer has expired, flush drawing before blocking
    601  *  on select().
    602  */
    603 static void
    604 RootlessBlockHandler(void *pbdata, void *ptimeout)
    605 {
    606     ScreenPtr pScreen = pbdata;
    607     RootlessScreenRec *screenRec = SCREENREC(pScreen);
    608 
    609     if (screenRec->redisplay_expired) {
    610         screenRec->redisplay_expired = FALSE;
    611 
    612         RootlessRedisplayScreen(pScreen);
    613     }
    614 }
    615 
    616 static void
    617 RootlessWakeupHandler(void *data, int result)
    618 {
    619     // nothing here
    620 }
    621 
    622 static Bool
    623 RootlessAllocatePrivates(ScreenPtr pScreen)
    624 {
    625     RootlessScreenRec *s;
    626 
    627     if (!dixRegisterPrivateKey
    628         (&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec)))
    629         return FALSE;
    630     if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
    631         return FALSE;
    632     if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
    633         return FALSE;
    634     if (!dixRegisterPrivateKey
    635         (&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0))
    636         return FALSE;
    637 
    638     s = malloc(sizeof(RootlessScreenRec));
    639     if (!s)
    640         return FALSE;
    641     SETSCREENREC(pScreen, s);
    642 
    643     s->pixmap_data = NULL;
    644     s->pixmap_data_size = 0;
    645 
    646     s->redisplay_timer = NULL;
    647     s->redisplay_timer_set = FALSE;
    648 
    649     return TRUE;
    650 }
    651 
    652 static void
    653 RootlessWrap(ScreenPtr pScreen)
    654 {
    655     RootlessScreenRec *s = SCREENREC(pScreen);
    656 
    657 #define WRAP(a) \
    658     if (pScreen->a) { \
    659         s->a = pScreen->a; \
    660     } else { \
    661         RL_DEBUG_MSG("null screen fn " #a "\n"); \
    662         s->a = NULL; \
    663     } \
    664     pScreen->a = Rootless##a
    665 
    666     WRAP(CreateScreenResources);
    667     WRAP(CloseScreen);
    668     WRAP(CreateGC);
    669     WRAP(CopyWindow);
    670     WRAP(PaintWindow);
    671     WRAP(GetImage);
    672     WRAP(SourceValidate);
    673     WRAP(CreateWindow);
    674     WRAP(DestroyWindow);
    675     WRAP(RealizeWindow);
    676     WRAP(UnrealizeWindow);
    677     WRAP(MoveWindow);
    678     WRAP(PositionWindow);
    679     WRAP(ResizeWindow);
    680     WRAP(RestackWindow);
    681     WRAP(ReparentWindow);
    682     WRAP(ChangeBorderWidth);
    683     WRAP(MarkOverlappedWindows);
    684     WRAP(ValidateTree);
    685     WRAP(ChangeWindowAttributes);
    686     WRAP(InstallColormap);
    687     WRAP(UninstallColormap);
    688     WRAP(StoreColors);
    689 
    690     WRAP(SetShape);
    691 
    692     {
    693         // Composite and Glyphs don't use normal screen wrapping
    694         PictureScreenPtr ps = GetPictureScreen(pScreen);
    695 
    696         s->Composite = ps->Composite;
    697         ps->Composite = RootlessComposite;
    698         s->Glyphs = ps->Glyphs;
    699         ps->Glyphs = RootlessGlyphs;
    700     }
    701 
    702     // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
    703 
    704 #undef WRAP
    705 }
    706 
    707 /*
    708  * RootlessInit
    709  *  Called by the rootless implementation to initialize the rootless layer.
    710  *  Rootless wraps lots of stuff and needs a bunch of devPrivates.
    711  */
    712 Bool
    713 RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs)
    714 {
    715     RootlessScreenRec *s;
    716 
    717     if (!RootlessAllocatePrivates(pScreen))
    718         return FALSE;
    719 
    720     s = SCREENREC(pScreen);
    721 
    722     s->imp = procs;
    723     s->colormap = NULL;
    724     s->redisplay_expired = FALSE;
    725 
    726     RootlessWrap(pScreen);
    727 
    728     if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler,
    729                                         RootlessWakeupHandler,
    730                                         (void *) pScreen)) {
    731         return FALSE;
    732     }
    733 
    734     return TRUE;
    735 }
    736 
    737 void
    738 RootlessUpdateRooted(Bool state)
    739 {
    740     int i;
    741 
    742     if (!state) {
    743         for (i = 0; i < screenInfo.numScreens; i++)
    744             RootlessDisableRoot(screenInfo.screens[i]);
    745     }
    746     else {
    747         for (i = 0; i < screenInfo.numScreens; i++)
    748             RootlessEnableRoot(screenInfo.screens[i]);
    749     }
    750 }