rootlessScreen.c revision ed6184df
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
59extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild,
60                                  VTKind kind);
61extern Bool RootlessCreateGC(GCPtr pGC);
62
63// Initialize globals
64DevPrivateKeyRec rootlessGCPrivateKeyRec;
65DevPrivateKeyRec rootlessScreenPrivateKeyRec;
66DevPrivateKeyRec rootlessWindowPrivateKeyRec;
67DevPrivateKeyRec 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 */
78void
79RootlessUpdateScreenPixmap(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 */
118static Bool
119RootlessCreateScreenResources(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
140static Bool
141RootlessCloseScreen(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
160static void
161RootlessGetImage(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 */
221static void
222RootlessSourceValidate(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
236static void
237RootlessComposite(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
276static void
277RootlessGlyphs(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 */
363static int
364RootlessValidateTree(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 */
395static Bool
396RootlessMarkOverlappedWindows(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
466static void
467expose_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
487void
488RootlessScreenExpose(ScreenPtr pScreen)
489{
490    expose_1(pScreen->root);
491}
492
493ColormapPtr
494RootlessGetColormap(ScreenPtr pScreen)
495{
496    RootlessScreenRec *s = SCREENREC(pScreen);
497
498    return s->colormap;
499}
500
501static void
502RootlessInstallColormap(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
520static void
521RootlessUninstallColormap(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
536static void
537RootlessStoreColors(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
554static CARD32
555RootlessRedisplayCallback(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 */
582void
583RootlessQueueRedisplay(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 */
603static void
604RootlessBlockHandler(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
616static void
617RootlessWakeupHandler(void *data, int result)
618{
619    // nothing here
620}
621
622static Bool
623RootlessAllocatePrivates(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
652static void
653RootlessWrap(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 */
712Bool
713RootlessInit(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
737void
738RootlessUpdateRooted(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}
751