rootlessScreen.c revision 1b5d61b8
105b261ecSmrg/*
205b261ecSmrg * Screen routines for generic rootless X server
305b261ecSmrg */
405b261ecSmrg/*
505b261ecSmrg * Copyright (c) 2001 Greg Parker. All Rights Reserved.
605b261ecSmrg * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
705b261ecSmrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
805b261ecSmrg *
905b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
1005b261ecSmrg * copy of this software and associated documentation files (the "Software"),
1105b261ecSmrg * to deal in the Software without restriction, including without limitation
1205b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1305b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
1405b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1505b261ecSmrg *
1605b261ecSmrg * The above copyright notice and this permission notice shall be included in
1705b261ecSmrg * all copies or substantial portions of the Software.
1805b261ecSmrg *
1905b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2005b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2105b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2205b261ecSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
2305b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2405b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2505b261ecSmrg * DEALINGS IN THE SOFTWARE.
2605b261ecSmrg *
2705b261ecSmrg * Except as contained in this notice, the name(s) of the above copyright
2805b261ecSmrg * holders shall not be used in advertising or otherwise to promote the sale,
2905b261ecSmrg * use or other dealings in this Software without prior written authorization.
3005b261ecSmrg */
3105b261ecSmrg
3205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3305b261ecSmrg#include <dix-config.h>
3405b261ecSmrg#endif
3505b261ecSmrg
3605b261ecSmrg#include "mi.h"
3705b261ecSmrg#include "scrnintstr.h"
3805b261ecSmrg#include "gcstruct.h"
3905b261ecSmrg#include "pixmapstr.h"
4005b261ecSmrg#include "windowstr.h"
4105b261ecSmrg#include "propertyst.h"
4205b261ecSmrg#include "mivalidate.h"
4305b261ecSmrg#include "picturestr.h"
444642e01fSmrg#include "colormapst.h"
4505b261ecSmrg
4605b261ecSmrg#include <sys/types.h>
4705b261ecSmrg#include <sys/stat.h>
4805b261ecSmrg#include <fcntl.h>
4905b261ecSmrg#include <string.h>
5005b261ecSmrg
5105b261ecSmrg#include "rootlessCommon.h"
5205b261ecSmrg#include "rootlessWindow.h"
5305b261ecSmrg
5405b261ecSmrg/* In milliseconds */
5505b261ecSmrg#ifndef ROOTLESS_REDISPLAY_DELAY
5605b261ecSmrg#define ROOTLESS_REDISPLAY_DELAY 10
5705b261ecSmrg#endif
5805b261ecSmrg
5905b261ecSmrgextern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild,
6005b261ecSmrg                                  VTKind kind);
6105b261ecSmrgextern Bool RootlessCreateGC(GCPtr pGC);
6205b261ecSmrg
6305b261ecSmrg// Initialize globals
646747b715SmrgDevPrivateKeyRec rootlessGCPrivateKeyRec;
656747b715SmrgDevPrivateKeyRec rootlessScreenPrivateKeyRec;
666747b715SmrgDevPrivateKeyRec rootlessWindowPrivateKeyRec;
676747b715SmrgDevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec;
6805b261ecSmrg
6905b261ecSmrg/*
7005b261ecSmrg * RootlessUpdateScreenPixmap
7105b261ecSmrg *  miCreateScreenResources does not like a null framebuffer pointer,
7205b261ecSmrg *  it leaves the screen pixmap with an uninitialized data pointer.
7305b261ecSmrg *  Thus, rootless implementations typically set the framebuffer width
7405b261ecSmrg *  to zero so that miCreateScreenResources does not allocate a screen
7505b261ecSmrg *  pixmap for us. We allocate our own screen pixmap here since we need
7605b261ecSmrg *  the screen pixmap to be valid (e.g. CopyArea from the root window).
7705b261ecSmrg */
7805b261ecSmrgvoid
7905b261ecSmrgRootlessUpdateScreenPixmap(ScreenPtr pScreen)
8005b261ecSmrg{
8105b261ecSmrg    RootlessScreenRec *s = SCREENREC(pScreen);
8205b261ecSmrg    PixmapPtr pPix;
8305b261ecSmrg    unsigned int rowbytes;
8405b261ecSmrg
8535c4bbdfSmrg    pPix = (*pScreen->GetScreenPixmap) (pScreen);
8605b261ecSmrg    if (pPix == NULL) {
8735c4bbdfSmrg        pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth, 0);
8835c4bbdfSmrg        (*pScreen->SetScreenPixmap) (pPix);
8905b261ecSmrg    }
9005b261ecSmrg
9105b261ecSmrg    rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth);
9205b261ecSmrg
9305b261ecSmrg    if (s->pixmap_data_size < rowbytes) {
949ace9065Smrg        free(s->pixmap_data);
9505b261ecSmrg
9605b261ecSmrg        s->pixmap_data_size = rowbytes;
976747b715Smrg        s->pixmap_data = malloc(s->pixmap_data_size);
9805b261ecSmrg        if (s->pixmap_data == NULL)
9905b261ecSmrg            return;
10005b261ecSmrg
10105b261ecSmrg        memset(s->pixmap_data, 0xFF, s->pixmap_data_size);
10205b261ecSmrg
10305b261ecSmrg        pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height,
10405b261ecSmrg                                    pScreen->rootDepth,
10505b261ecSmrg                                    BitsPerPixel(pScreen->rootDepth),
10605b261ecSmrg                                    0, s->pixmap_data);
10705b261ecSmrg        /* ModifyPixmapHeader ignores zero arguments, so install rowbytes
10805b261ecSmrg           by hand. */
10905b261ecSmrg        pPix->devKind = 0;
11005b261ecSmrg    }
11105b261ecSmrg}
11205b261ecSmrg
11305b261ecSmrg/*
11405b261ecSmrg * RootlessCreateScreenResources
11505b261ecSmrg *  Rootless implementations typically set a null framebuffer pointer, which
11605b261ecSmrg *  causes problems with miCreateScreenResources. We fix things up here.
11705b261ecSmrg */
11805b261ecSmrgstatic Bool
11905b261ecSmrgRootlessCreateScreenResources(ScreenPtr pScreen)
12005b261ecSmrg{
12105b261ecSmrg    Bool ret = TRUE;
12205b261ecSmrg
12305b261ecSmrg    SCREEN_UNWRAP(pScreen, CreateScreenResources);
12405b261ecSmrg
12505b261ecSmrg    if (pScreen->CreateScreenResources != NULL)
12635c4bbdfSmrg        ret = (*pScreen->CreateScreenResources) (pScreen);
12705b261ecSmrg
12805b261ecSmrg    SCREEN_WRAP(pScreen, CreateScreenResources);
12905b261ecSmrg
13005b261ecSmrg    if (!ret)
13105b261ecSmrg        return ret;
13205b261ecSmrg
13305b261ecSmrg    /* Make sure we have a valid screen pixmap. */
13405b261ecSmrg
13505b261ecSmrg    RootlessUpdateScreenPixmap(pScreen);
13605b261ecSmrg
13705b261ecSmrg    return ret;
13805b261ecSmrg}
13905b261ecSmrg
14005b261ecSmrgstatic Bool
14135c4bbdfSmrgRootlessCloseScreen(ScreenPtr pScreen)
14205b261ecSmrg{
14305b261ecSmrg    RootlessScreenRec *s;
14405b261ecSmrg
14505b261ecSmrg    s = SCREENREC(pScreen);
14605b261ecSmrg
14705b261ecSmrg    // fixme unwrap everything that was wrapped?
14805b261ecSmrg    pScreen->CloseScreen = s->CloseScreen;
14905b261ecSmrg
15005b261ecSmrg    if (s->pixmap_data != NULL) {
1516747b715Smrg        free(s->pixmap_data);
15205b261ecSmrg        s->pixmap_data = NULL;
15305b261ecSmrg        s->pixmap_data_size = 0;
15405b261ecSmrg    }
15505b261ecSmrg
1566747b715Smrg    free(s);
15735c4bbdfSmrg    return pScreen->CloseScreen(pScreen);
15805b261ecSmrg}
15905b261ecSmrg
16005b261ecSmrgstatic void
16105b261ecSmrgRootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
16205b261ecSmrg                 unsigned int format, unsigned long planeMask, char *pdstLine)
16305b261ecSmrg{
16405b261ecSmrg    ScreenPtr pScreen = pDrawable->pScreen;
16535c4bbdfSmrg
16605b261ecSmrg    SCREEN_UNWRAP(pScreen, GetImage);
16705b261ecSmrg
16805b261ecSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
16905b261ecSmrg        int x0, y0, x1, y1;
17005b261ecSmrg        RootlessWindowRec *winRec;
17105b261ecSmrg
17205b261ecSmrg        // Many apps use GetImage to sync with the visible frame buffer
17305b261ecSmrg        // FIXME: entire screen or just window or all screens?
17405b261ecSmrg        RootlessRedisplayScreen(pScreen);
17505b261ecSmrg
17605b261ecSmrg        // RedisplayScreen stops drawing, so we need to start it again
17735c4bbdfSmrg        RootlessStartDrawing((WindowPtr) pDrawable);
17805b261ecSmrg
17905b261ecSmrg        /* Check that we have some place to read from. */
18005b261ecSmrg        winRec = WINREC(TopLevelParent((WindowPtr) pDrawable));
18105b261ecSmrg        if (winRec == NULL)
18205b261ecSmrg            goto out;
18305b261ecSmrg
18405b261ecSmrg        /* Clip to top-level window bounds. */
18505b261ecSmrg        /* FIXME: fbGetImage uses the width parameter to calculate the
18605b261ecSmrg           stride of the destination pixmap. If w is clipped, the data
18705b261ecSmrg           returned will be garbage, although we will not crash. */
18805b261ecSmrg
18905b261ecSmrg        x0 = pDrawable->x + sx;
19005b261ecSmrg        y0 = pDrawable->y + sy;
19105b261ecSmrg        x1 = x0 + w;
19205b261ecSmrg        y1 = y0 + h;
19305b261ecSmrg
19435c4bbdfSmrg        x0 = max(x0, winRec->x);
19535c4bbdfSmrg        y0 = max(y0, winRec->y);
19635c4bbdfSmrg        x1 = min(x1, winRec->x + winRec->width);
19735c4bbdfSmrg        y1 = min(y1, winRec->y + winRec->height);
19805b261ecSmrg
19905b261ecSmrg        sx = x0 - pDrawable->x;
20005b261ecSmrg        sy = y0 - pDrawable->y;
20105b261ecSmrg        w = x1 - x0;
20205b261ecSmrg        h = y1 - y0;
20305b261ecSmrg
20405b261ecSmrg        if (w <= 0 || h <= 0)
20505b261ecSmrg            goto out;
20605b261ecSmrg    }
20705b261ecSmrg
20805b261ecSmrg    pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
20905b261ecSmrg
21035c4bbdfSmrg out:
21105b261ecSmrg    SCREEN_WRAP(pScreen, GetImage);
21205b261ecSmrg}
21305b261ecSmrg
21405b261ecSmrg/*
21505b261ecSmrg * RootlessSourceValidate
21605b261ecSmrg *  CopyArea and CopyPlane use a GC tied to the destination drawable.
21705b261ecSmrg *  StartDrawing/StopDrawing wrappers won't be called if source is
21805b261ecSmrg *  a visible window but the destination isn't. So, we call StartDrawing
21905b261ecSmrg *  here and leave StopDrawing for the block handler.
22005b261ecSmrg */
22105b261ecSmrgstatic void
2229ace9065SmrgRootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h,
2239ace9065Smrg                       unsigned int subWindowMode)
22405b261ecSmrg{
22505b261ecSmrg    SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
22605b261ecSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
22735c4bbdfSmrg        WindowPtr pWin = (WindowPtr) pDrawable;
22835c4bbdfSmrg
22905b261ecSmrg        RootlessStartDrawing(pWin);
23005b261ecSmrg    }
23105b261ecSmrg    if (pDrawable->pScreen->SourceValidate) {
23235c4bbdfSmrg        pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h,
23335c4bbdfSmrg                                           subWindowMode);
23405b261ecSmrg    }
23505b261ecSmrg    SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
23605b261ecSmrg}
23705b261ecSmrg
23805b261ecSmrgstatic void
23905b261ecSmrgRootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
24035c4bbdfSmrg                  INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
24105b261ecSmrg                  INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
24205b261ecSmrg{
24305b261ecSmrg    ScreenPtr pScreen = pDst->pDrawable->pScreen;
24405b261ecSmrg    PictureScreenPtr ps = GetPictureScreen(pScreen);
24505b261ecSmrg    WindowPtr srcWin, dstWin, maskWin = NULL;
24605b261ecSmrg
24735c4bbdfSmrg    if (pMask) {                // pMask can be NULL
24835c4bbdfSmrg        maskWin = (pMask->pDrawable &&
24935c4bbdfSmrg                   pMask->pDrawable->type ==
25035c4bbdfSmrg                   DRAWABLE_WINDOW) ? (WindowPtr) pMask->pDrawable : NULL;
25105b261ecSmrg    }
25235c4bbdfSmrg    srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
25335c4bbdfSmrg        (WindowPtr) pSrc->pDrawable : NULL;
25435c4bbdfSmrg    dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
25535c4bbdfSmrg        (WindowPtr) pDst->pDrawable : NULL;
25605b261ecSmrg
25705b261ecSmrg    // SCREEN_UNWRAP(ps, Composite);
25805b261ecSmrg    ps->Composite = SCREENREC(pScreen)->Composite;
25905b261ecSmrg
26035c4bbdfSmrg    if (srcWin && IsFramedWindow(srcWin))
26105b261ecSmrg        RootlessStartDrawing(srcWin);
26205b261ecSmrg    if (maskWin && IsFramedWindow(maskWin))
26305b261ecSmrg        RootlessStartDrawing(maskWin);
26435c4bbdfSmrg    if (dstWin && IsFramedWindow(dstWin))
26505b261ecSmrg        RootlessStartDrawing(dstWin);
26605b261ecSmrg
26705b261ecSmrg    ps->Composite(op, pSrc, pMask, pDst,
26835c4bbdfSmrg                  xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
26905b261ecSmrg
27035c4bbdfSmrg    if (dstWin && IsFramedWindow(dstWin)) {
27105b261ecSmrg        RootlessDamageRect(dstWin, xDst, yDst, width, height);
27205b261ecSmrg    }
27305b261ecSmrg
27405b261ecSmrg    ps->Composite = RootlessComposite;
27505b261ecSmrg    // SCREEN_WRAP(ps, Composite);
27605b261ecSmrg}
27705b261ecSmrg
27805b261ecSmrgstatic void
27905b261ecSmrgRootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
28005b261ecSmrg               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
28135c4bbdfSmrg               int nlist, GlyphListPtr list, GlyphPtr * glyphs)
28205b261ecSmrg{
28305b261ecSmrg    ScreenPtr pScreen = pDst->pDrawable->pScreen;
28405b261ecSmrg    PictureScreenPtr ps = GetPictureScreen(pScreen);
28505b261ecSmrg    int x, y;
28605b261ecSmrg    int n;
28705b261ecSmrg    GlyphPtr glyph;
28805b261ecSmrg    WindowPtr srcWin, dstWin;
28905b261ecSmrg
2906747b715Smrg    srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
29135c4bbdfSmrg        (WindowPtr) pSrc->pDrawable : NULL;
29205b261ecSmrg    dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
29335c4bbdfSmrg        (WindowPtr) pDst->pDrawable : NULL;
29405b261ecSmrg
29535c4bbdfSmrg    if (srcWin && IsFramedWindow(srcWin))
29635c4bbdfSmrg        RootlessStartDrawing(srcWin);
29735c4bbdfSmrg    if (dstWin && IsFramedWindow(dstWin))
29835c4bbdfSmrg        RootlessStartDrawing(dstWin);
29905b261ecSmrg
30005b261ecSmrg    //SCREEN_UNWRAP(ps, Glyphs);
30105b261ecSmrg    ps->Glyphs = SCREENREC(pScreen)->Glyphs;
30205b261ecSmrg    ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
30305b261ecSmrg    ps->Glyphs = RootlessGlyphs;
30405b261ecSmrg    //SCREEN_WRAP(ps, Glyphs);
30505b261ecSmrg
30605b261ecSmrg    if (dstWin && IsFramedWindow(dstWin)) {
30705b261ecSmrg        x = xSrc;
30805b261ecSmrg        y = ySrc;
30905b261ecSmrg
31005b261ecSmrg        while (nlist--) {
31105b261ecSmrg            x += list->xOff;
31205b261ecSmrg            y += list->yOff;
31305b261ecSmrg            n = list->len;
31405b261ecSmrg
31505b261ecSmrg            /* Calling DamageRect for the bounding box of each glyph is
31605b261ecSmrg               inefficient. So compute the union of all glyphs in a list
31705b261ecSmrg               and damage that. */
31805b261ecSmrg
31905b261ecSmrg            if (n > 0) {
32005b261ecSmrg                BoxRec box;
32105b261ecSmrg
32205b261ecSmrg                glyph = *glyphs++;
32305b261ecSmrg
32405b261ecSmrg                box.x1 = x - glyph->info.x;
32505b261ecSmrg                box.y1 = y - glyph->info.y;
32605b261ecSmrg                box.x2 = box.x1 + glyph->info.width;
3279ace9065Smrg                box.y2 = box.y1 + glyph->info.height;
32805b261ecSmrg
32905b261ecSmrg                x += glyph->info.xOff;
33005b261ecSmrg                y += glyph->info.yOff;
33105b261ecSmrg
33205b261ecSmrg                while (--n > 0) {
33305b261ecSmrg                    short x1, y1, x2, y2;
33405b261ecSmrg
33505b261ecSmrg                    glyph = *glyphs++;
33605b261ecSmrg
33705b261ecSmrg                    x1 = x - glyph->info.x;
33805b261ecSmrg                    y1 = y - glyph->info.y;
33905b261ecSmrg                    x2 = x1 + glyph->info.width;
34005b261ecSmrg                    y2 = y1 + glyph->info.height;
34105b261ecSmrg
34235c4bbdfSmrg                    box.x1 = max(box.x1, x1);
34335c4bbdfSmrg                    box.y1 = max(box.y1, y1);
34435c4bbdfSmrg                    box.x2 = max(box.x2, x2);
34535c4bbdfSmrg                    box.y2 = max(box.y2, y2);
34605b261ecSmrg
34705b261ecSmrg                    x += glyph->info.xOff;
34805b261ecSmrg                    y += glyph->info.yOff;
34905b261ecSmrg                }
35005b261ecSmrg
35105b261ecSmrg                RootlessDamageBox(dstWin, &box);
35205b261ecSmrg            }
35305b261ecSmrg            list++;
35405b261ecSmrg        }
35505b261ecSmrg    }
35605b261ecSmrg}
35705b261ecSmrg
35805b261ecSmrg/*
35905b261ecSmrg * RootlessValidateTree
36005b261ecSmrg *  ValidateTree is modified in two ways:
36105b261ecSmrg *   - top-level windows don't clip each other
36205b261ecSmrg *   - windows aren't clipped against root.
36305b261ecSmrg *  These only matter when validating from the root.
36405b261ecSmrg */
36505b261ecSmrgstatic int
36605b261ecSmrgRootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
36705b261ecSmrg{
36805b261ecSmrg    int result;
36905b261ecSmrg    RegionRec saveRoot;
37005b261ecSmrg    ScreenPtr pScreen = pParent->drawable.pScreen;
37105b261ecSmrg
37205b261ecSmrg    SCREEN_UNWRAP(pScreen, ValidateTree);
37305b261ecSmrg    RL_DEBUG_MSG("VALIDATETREE start ");
37405b261ecSmrg
37505b261ecSmrg    // Use our custom version to validate from root
37605b261ecSmrg    if (IsRoot(pParent)) {
37705b261ecSmrg        RL_DEBUG_MSG("custom ");
37805b261ecSmrg        result = RootlessMiValidateTree(pParent, pChild, kind);
37935c4bbdfSmrg    }
38035c4bbdfSmrg    else {
38105b261ecSmrg        HUGE_ROOT(pParent);
38205b261ecSmrg        result = pScreen->ValidateTree(pParent, pChild, kind);
38305b261ecSmrg        NORMAL_ROOT(pParent);
38405b261ecSmrg    }
38505b261ecSmrg
38605b261ecSmrg    SCREEN_WRAP(pScreen, ValidateTree);
38705b261ecSmrg    RL_DEBUG_MSG("VALIDATETREE end\n");
38805b261ecSmrg
38905b261ecSmrg    return result;
39005b261ecSmrg}
39105b261ecSmrg
39205b261ecSmrg/*
39305b261ecSmrg * RootlessMarkOverlappedWindows
39405b261ecSmrg *  MarkOverlappedWindows is modified to ignore overlapping
39505b261ecSmrg *  top-level windows.
39605b261ecSmrg */
39705b261ecSmrgstatic Bool
39805b261ecSmrgRootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
39905b261ecSmrg                              WindowPtr *ppLayerWin)
40005b261ecSmrg{
40105b261ecSmrg    RegionRec saveRoot;
40205b261ecSmrg    Bool result;
40305b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
40435c4bbdfSmrg
40505b261ecSmrg    SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
40605b261ecSmrg    RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
40705b261ecSmrg
40805b261ecSmrg    HUGE_ROOT(pWin);
40905b261ecSmrg    if (IsRoot(pWin)) {
41005b261ecSmrg        // root - mark nothing
41105b261ecSmrg        RL_DEBUG_MSG("is root not marking ");
41205b261ecSmrg        result = FALSE;
41305b261ecSmrg    }
41435c4bbdfSmrg    else if (!IsTopLevel(pWin)) {
41505b261ecSmrg        // not top-level window - mark normally
41605b261ecSmrg        result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
41705b261ecSmrg    }
41805b261ecSmrg    else {
41905b261ecSmrg        //top-level window - mark children ONLY - NO overlaps with sibs (?)
42005b261ecSmrg        // This code copied from miMarkOverlappedWindows()
42105b261ecSmrg
42205b261ecSmrg        register WindowPtr pChild;
42305b261ecSmrg        Bool anyMarked = FALSE;
4246747b715Smrg        MarkWindowProcPtr MarkWindow = pScreen->MarkWindow;
42505b261ecSmrg
42605b261ecSmrg        RL_DEBUG_MSG("is top level! ");
42705b261ecSmrg        /* single layered systems are easy */
42835c4bbdfSmrg        if (ppLayerWin)
42935c4bbdfSmrg            *ppLayerWin = pWin;
43005b261ecSmrg
43105b261ecSmrg        if (pWin == pFirst) {
43205b261ecSmrg            /* Blindly mark pWin and all of its inferiors.   This is a slight
43305b261ecSmrg             * overkill if there are mapped windows that outside pWin's border,
43405b261ecSmrg             * but it's better than wasting time on RectIn checks.
43505b261ecSmrg             */
43605b261ecSmrg            pChild = pWin;
43705b261ecSmrg            while (1) {
43805b261ecSmrg                if (pChild->viewable) {
4396747b715Smrg                    if (RegionBroken(&pChild->winSize))
44035c4bbdfSmrg                        SetWinSize(pChild);
4416747b715Smrg                    if (RegionBroken(&pChild->borderSize))
44235c4bbdfSmrg                        SetBorderSize(pChild);
44335c4bbdfSmrg                    (*MarkWindow) (pChild);
44405b261ecSmrg                    if (pChild->firstChild) {
44505b261ecSmrg                        pChild = pChild->firstChild;
44605b261ecSmrg                        continue;
44705b261ecSmrg                    }
44805b261ecSmrg                }
44905b261ecSmrg                while (!pChild->nextSib && (pChild != pWin))
45005b261ecSmrg                    pChild = pChild->parent;
45105b261ecSmrg                if (pChild == pWin)
45205b261ecSmrg                    break;
45305b261ecSmrg                pChild = pChild->nextSib;
45405b261ecSmrg            }
45505b261ecSmrg            anyMarked = TRUE;
45605b261ecSmrg        }
45705b261ecSmrg        if (anyMarked)
45835c4bbdfSmrg            (*MarkWindow) (pWin->parent);
45905b261ecSmrg        result = anyMarked;
46005b261ecSmrg    }
46105b261ecSmrg    NORMAL_ROOT(pWin);
46205b261ecSmrg    SCREEN_WRAP(pScreen, MarkOverlappedWindows);
46305b261ecSmrg    RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
46405b261ecSmrg
46505b261ecSmrg    return result;
46605b261ecSmrg}
46705b261ecSmrg
46835c4bbdfSmrgstatic void
46935c4bbdfSmrgexpose_1(WindowPtr pWin)
47035c4bbdfSmrg{
4714642e01fSmrg    WindowPtr pChild;
47235c4bbdfSmrg
4734642e01fSmrg    if (!pWin->realized)
4744642e01fSmrg        return;
47535c4bbdfSmrg
47635c4bbdfSmrg    pWin->drawable.pScreen->PaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND);
47735c4bbdfSmrg
4784642e01fSmrg    /* FIXME: comments in windowstr.h indicate that borderClip doesn't
47935c4bbdfSmrg       include subwindow visibility. But I'm not so sure.. so we may
48035c4bbdfSmrg       be exposing too much.. */
48135c4bbdfSmrg
48235c4bbdfSmrg    miSendExposures(pWin, &pWin->borderClip,
48335c4bbdfSmrg                    pWin->drawable.x, pWin->drawable.y);
48435c4bbdfSmrg
4854642e01fSmrg    for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib)
48635c4bbdfSmrg        expose_1(pChild);
4874642e01fSmrg}
4884642e01fSmrg
4894642e01fSmrgvoid
49035c4bbdfSmrgRootlessScreenExpose(ScreenPtr pScreen)
4914642e01fSmrg{
49235c4bbdfSmrg    expose_1(pScreen->root);
4934642e01fSmrg}
4944642e01fSmrg
4954642e01fSmrgColormapPtr
49635c4bbdfSmrgRootlessGetColormap(ScreenPtr pScreen)
4974642e01fSmrg{
49835c4bbdfSmrg    RootlessScreenRec *s = SCREENREC(pScreen);
4994642e01fSmrg
50035c4bbdfSmrg    return s->colormap;
5014642e01fSmrg}
5024642e01fSmrg
5034642e01fSmrgstatic void
50435c4bbdfSmrgRootlessInstallColormap(ColormapPtr pMap)
5054642e01fSmrg{
50635c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
50735c4bbdfSmrg    RootlessScreenRec *s = SCREENREC(pScreen);
5084642e01fSmrg
50935c4bbdfSmrg    SCREEN_UNWRAP(pScreen, InstallColormap);
5104642e01fSmrg
51135c4bbdfSmrg    if (s->colormap != pMap) {
51235c4bbdfSmrg        s->colormap = pMap;
51335c4bbdfSmrg        s->colormap_changed = TRUE;
51435c4bbdfSmrg        RootlessQueueRedisplay(pScreen);
51535c4bbdfSmrg    }
5164642e01fSmrg
51735c4bbdfSmrg    pScreen->InstallColormap(pMap);
5184642e01fSmrg
51935c4bbdfSmrg    SCREEN_WRAP(pScreen, InstallColormap);
5204642e01fSmrg}
5214642e01fSmrg
5224642e01fSmrgstatic void
52335c4bbdfSmrgRootlessUninstallColormap(ColormapPtr pMap)
5244642e01fSmrg{
52535c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
52635c4bbdfSmrg    RootlessScreenRec *s = SCREENREC(pScreen);
5274642e01fSmrg
52835c4bbdfSmrg    SCREEN_UNWRAP(pScreen, UninstallColormap);
5294642e01fSmrg
53035c4bbdfSmrg    if (s->colormap == pMap)
53135c4bbdfSmrg        s->colormap = NULL;
5324642e01fSmrg
53335c4bbdfSmrg    pScreen->UninstallColormap(pMap);
5344642e01fSmrg
53535c4bbdfSmrg    SCREEN_WRAP(pScreen, UninstallColormap);
5364642e01fSmrg}
5374642e01fSmrg
5384642e01fSmrgstatic void
53935c4bbdfSmrgRootlessStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef)
5404642e01fSmrg{
54135c4bbdfSmrg    ScreenPtr pScreen = pMap->pScreen;
54235c4bbdfSmrg    RootlessScreenRec *s = SCREENREC(pScreen);
5434642e01fSmrg
54435c4bbdfSmrg    SCREEN_UNWRAP(pScreen, StoreColors);
5454642e01fSmrg
54635c4bbdfSmrg    if (s->colormap == pMap && ndef > 0) {
54735c4bbdfSmrg        s->colormap_changed = TRUE;
54835c4bbdfSmrg        RootlessQueueRedisplay(pScreen);
54935c4bbdfSmrg    }
5504642e01fSmrg
55135c4bbdfSmrg    pScreen->StoreColors(pMap, ndef, pdef);
5524642e01fSmrg
55335c4bbdfSmrg    SCREEN_WRAP(pScreen, StoreColors);
5544642e01fSmrg}
5554642e01fSmrg
55605b261ecSmrgstatic CARD32
55705b261ecSmrgRootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg)
55805b261ecSmrg{
55905b261ecSmrg    RootlessScreenRec *screenRec = arg;
56005b261ecSmrg
56105b261ecSmrg    if (!screenRec->redisplay_queued) {
56205b261ecSmrg        /* No update needed. Stop the timer. */
56305b261ecSmrg
56405b261ecSmrg        screenRec->redisplay_timer_set = FALSE;
56505b261ecSmrg        return 0;
56605b261ecSmrg    }
56705b261ecSmrg
56805b261ecSmrg    screenRec->redisplay_queued = FALSE;
56905b261ecSmrg
57005b261ecSmrg    /* Mark that we should redisplay before waiting for I/O next time */
57105b261ecSmrg    screenRec->redisplay_expired = TRUE;
57205b261ecSmrg
57305b261ecSmrg    /* Reinstall the timer immediately, so we get as close to our
57405b261ecSmrg       redisplay interval as possible. */
57505b261ecSmrg
57605b261ecSmrg    return ROOTLESS_REDISPLAY_DELAY;
57705b261ecSmrg}
57805b261ecSmrg
57905b261ecSmrg/*
58005b261ecSmrg * RootlessQueueRedisplay
58105b261ecSmrg *  Queue a redisplay after a timer delay to ensure we do not redisplay
58205b261ecSmrg *  too frequently.
58305b261ecSmrg */
58405b261ecSmrgvoid
58505b261ecSmrgRootlessQueueRedisplay(ScreenPtr pScreen)
58605b261ecSmrg{
58705b261ecSmrg    RootlessScreenRec *screenRec = SCREENREC(pScreen);
58805b261ecSmrg
58905b261ecSmrg    screenRec->redisplay_queued = TRUE;
59005b261ecSmrg
59105b261ecSmrg    if (screenRec->redisplay_timer_set)
59205b261ecSmrg        return;
59305b261ecSmrg
59405b261ecSmrg    screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer,
59505b261ecSmrg                                          0, ROOTLESS_REDISPLAY_DELAY,
59635c4bbdfSmrg                                          RootlessRedisplayCallback, screenRec);
59705b261ecSmrg    screenRec->redisplay_timer_set = TRUE;
59805b261ecSmrg}
59905b261ecSmrg
60005b261ecSmrg/*
60105b261ecSmrg * RootlessBlockHandler
60205b261ecSmrg *  If the redisplay timer has expired, flush drawing before blocking
60305b261ecSmrg *  on select().
60405b261ecSmrg */
60505b261ecSmrgstatic void
6061b5d61b8SmrgRootlessBlockHandler(void *pbdata, void *ptimeout)
60705b261ecSmrg{
60805b261ecSmrg    ScreenPtr pScreen = pbdata;
60905b261ecSmrg    RootlessScreenRec *screenRec = SCREENREC(pScreen);
61005b261ecSmrg
61105b261ecSmrg    if (screenRec->redisplay_expired) {
61205b261ecSmrg        screenRec->redisplay_expired = FALSE;
61305b261ecSmrg
61405b261ecSmrg        RootlessRedisplayScreen(pScreen);
61505b261ecSmrg    }
61605b261ecSmrg}
61705b261ecSmrg
61805b261ecSmrgstatic void
6191b5d61b8SmrgRootlessWakeupHandler(void *data, int result)
62005b261ecSmrg{
62105b261ecSmrg    // nothing here
62205b261ecSmrg}
62305b261ecSmrg
62405b261ecSmrgstatic Bool
62505b261ecSmrgRootlessAllocatePrivates(ScreenPtr pScreen)
62605b261ecSmrg{
62705b261ecSmrg    RootlessScreenRec *s;
62805b261ecSmrg
62935c4bbdfSmrg    if (!dixRegisterPrivateKey
63035c4bbdfSmrg        (&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec)))
6316747b715Smrg        return FALSE;
6326747b715Smrg    if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
6336747b715Smrg        return FALSE;
6346747b715Smrg    if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
6356747b715Smrg        return FALSE;
63635c4bbdfSmrg    if (!dixRegisterPrivateKey
63735c4bbdfSmrg        (&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0))
63805b261ecSmrg        return FALSE;
63905b261ecSmrg
6406747b715Smrg    s = malloc(sizeof(RootlessScreenRec));
64135c4bbdfSmrg    if (!s)
64235c4bbdfSmrg        return FALSE;
6434642e01fSmrg    SETSCREENREC(pScreen, s);
64405b261ecSmrg
64505b261ecSmrg    s->pixmap_data = NULL;
64605b261ecSmrg    s->pixmap_data_size = 0;
64705b261ecSmrg
64805b261ecSmrg    s->redisplay_timer = NULL;
64905b261ecSmrg    s->redisplay_timer_set = FALSE;
65005b261ecSmrg
65105b261ecSmrg    return TRUE;
65205b261ecSmrg}
65305b261ecSmrg
65405b261ecSmrgstatic void
65505b261ecSmrgRootlessWrap(ScreenPtr pScreen)
65605b261ecSmrg{
6574642e01fSmrg    RootlessScreenRec *s = SCREENREC(pScreen);
65805b261ecSmrg
65905b261ecSmrg#define WRAP(a) \
66005b261ecSmrg    if (pScreen->a) { \
66105b261ecSmrg        s->a = pScreen->a; \
66205b261ecSmrg    } else { \
66305b261ecSmrg        RL_DEBUG_MSG("null screen fn " #a "\n"); \
66405b261ecSmrg        s->a = NULL; \
66505b261ecSmrg    } \
66605b261ecSmrg    pScreen->a = Rootless##a
66705b261ecSmrg
66805b261ecSmrg    WRAP(CreateScreenResources);
66905b261ecSmrg    WRAP(CloseScreen);
67005b261ecSmrg    WRAP(CreateGC);
67105b261ecSmrg    WRAP(CopyWindow);
67235c4bbdfSmrg    WRAP(PaintWindow);
67305b261ecSmrg    WRAP(GetImage);
67405b261ecSmrg    WRAP(SourceValidate);
67505b261ecSmrg    WRAP(CreateWindow);
67605b261ecSmrg    WRAP(DestroyWindow);
67705b261ecSmrg    WRAP(RealizeWindow);
67805b261ecSmrg    WRAP(UnrealizeWindow);
67905b261ecSmrg    WRAP(MoveWindow);
68005b261ecSmrg    WRAP(PositionWindow);
68105b261ecSmrg    WRAP(ResizeWindow);
68205b261ecSmrg    WRAP(RestackWindow);
68305b261ecSmrg    WRAP(ReparentWindow);
68405b261ecSmrg    WRAP(ChangeBorderWidth);
68505b261ecSmrg    WRAP(MarkOverlappedWindows);
68605b261ecSmrg    WRAP(ValidateTree);
68705b261ecSmrg    WRAP(ChangeWindowAttributes);
6884642e01fSmrg    WRAP(InstallColormap);
6894642e01fSmrg    WRAP(UninstallColormap);
6904642e01fSmrg    WRAP(StoreColors);
69105b261ecSmrg
69205b261ecSmrg    WRAP(SetShape);
69305b261ecSmrg
69405b261ecSmrg    {
69505b261ecSmrg        // Composite and Glyphs don't use normal screen wrapping
69605b261ecSmrg        PictureScreenPtr ps = GetPictureScreen(pScreen);
69735c4bbdfSmrg
69805b261ecSmrg        s->Composite = ps->Composite;
69905b261ecSmrg        ps->Composite = RootlessComposite;
70005b261ecSmrg        s->Glyphs = ps->Glyphs;
70105b261ecSmrg        ps->Glyphs = RootlessGlyphs;
70205b261ecSmrg    }
70305b261ecSmrg
70405b261ecSmrg    // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
70505b261ecSmrg
70605b261ecSmrg#undef WRAP
70705b261ecSmrg}
70805b261ecSmrg
70905b261ecSmrg/*
71005b261ecSmrg * RootlessInit
71105b261ecSmrg *  Called by the rootless implementation to initialize the rootless layer.
71205b261ecSmrg *  Rootless wraps lots of stuff and needs a bunch of devPrivates.
71305b261ecSmrg */
71435c4bbdfSmrgBool
71535c4bbdfSmrgRootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs)
71605b261ecSmrg{
71705b261ecSmrg    RootlessScreenRec *s;
71805b261ecSmrg
71905b261ecSmrg    if (!RootlessAllocatePrivates(pScreen))
72005b261ecSmrg        return FALSE;
72105b261ecSmrg
7224642e01fSmrg    s = SCREENREC(pScreen);
72305b261ecSmrg
72405b261ecSmrg    s->imp = procs;
7254642e01fSmrg    s->colormap = NULL;
7264642e01fSmrg    s->redisplay_expired = FALSE;
72705b261ecSmrg
72805b261ecSmrg    RootlessWrap(pScreen);
72905b261ecSmrg
73005b261ecSmrg    if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler,
73105b261ecSmrg                                        RootlessWakeupHandler,
73235c4bbdfSmrg                                        (void *) pScreen)) {
73305b261ecSmrg        return FALSE;
73405b261ecSmrg    }
73505b261ecSmrg
73605b261ecSmrg    return TRUE;
73705b261ecSmrg}
7384642e01fSmrg
73935c4bbdfSmrgvoid
74035c4bbdfSmrgRootlessUpdateRooted(Bool state)
74135c4bbdfSmrg{
7424642e01fSmrg    int i;
74335c4bbdfSmrg
74435c4bbdfSmrg    if (!state) {
7454642e01fSmrg        for (i = 0; i < screenInfo.numScreens; i++)
74635c4bbdfSmrg            RootlessDisableRoot(screenInfo.screens[i]);
7474642e01fSmrg    }
74835c4bbdfSmrg    else {
7494642e01fSmrg        for (i = 0; i < screenInfo.numScreens; i++)
75035c4bbdfSmrg            RootlessEnableRoot(screenInfo.screens[i]);
7514642e01fSmrg    }
7524642e01fSmrg}
753