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