~ubuntu-branches/ubuntu/precise/xorg-server-lts-saucy/precise-proposed

« back to all changes in this revision

Viewing changes to miext/rootless/rootlessScreen.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2013-12-23 09:04:34 UTC
  • Revision ID: package-import@ubuntu.com-20131223090434-ov0hcp9sdd6szrwa
Tags: upstream-1.14.5
ImportĀ upstreamĀ versionĀ 1.14.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
    if (pDrawable->pScreen->SourceValidate) {
 
232
        pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h,
 
233
                                           subWindowMode);
 
234
    }
 
235
    SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
 
236
}
 
237
 
 
238
static void
 
239
RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
 
240
                  INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
 
241
                  INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
 
242
{
 
243
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
 
244
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 
245
    WindowPtr srcWin, dstWin, maskWin = NULL;
 
246
 
 
247
    if (pMask) {                // pMask can be NULL
 
248
        maskWin = (pMask->pDrawable &&
 
249
                   pMask->pDrawable->type ==
 
250
                   DRAWABLE_WINDOW) ? (WindowPtr) pMask->pDrawable : NULL;
 
251
    }
 
252
    srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
 
253
        (WindowPtr) pSrc->pDrawable : NULL;
 
254
    dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
 
255
        (WindowPtr) pDst->pDrawable : NULL;
 
256
 
 
257
    // SCREEN_UNWRAP(ps, Composite);
 
258
    ps->Composite = SCREENREC(pScreen)->Composite;
 
259
 
 
260
    if (srcWin && IsFramedWindow(srcWin))
 
261
        RootlessStartDrawing(srcWin);
 
262
    if (maskWin && IsFramedWindow(maskWin))
 
263
        RootlessStartDrawing(maskWin);
 
264
    if (dstWin && IsFramedWindow(dstWin))
 
265
        RootlessStartDrawing(dstWin);
 
266
 
 
267
    ps->Composite(op, pSrc, pMask, pDst,
 
268
                  xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
 
269
 
 
270
    if (dstWin && IsFramedWindow(dstWin)) {
 
271
        RootlessDamageRect(dstWin, xDst, yDst, width, height);
 
272
    }
 
273
 
 
274
    ps->Composite = RootlessComposite;
 
275
    // SCREEN_WRAP(ps, Composite);
 
276
}
 
277
 
 
278
static void
 
279
RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
 
280
               PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
 
281
               int nlist, GlyphListPtr list, GlyphPtr * glyphs)
 
282
{
 
283
    ScreenPtr pScreen = pDst->pDrawable->pScreen;
 
284
    PictureScreenPtr ps = GetPictureScreen(pScreen);
 
285
    int x, y;
 
286
    int n;
 
287
    GlyphPtr glyph;
 
288
    WindowPtr srcWin, dstWin;
 
289
 
 
290
    srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
 
291
        (WindowPtr) pSrc->pDrawable : NULL;
 
292
    dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
 
293
        (WindowPtr) pDst->pDrawable : NULL;
 
294
 
 
295
    if (srcWin && IsFramedWindow(srcWin))
 
296
        RootlessStartDrawing(srcWin);
 
297
    if (dstWin && IsFramedWindow(dstWin))
 
298
        RootlessStartDrawing(dstWin);
 
299
 
 
300
    //SCREEN_UNWRAP(ps, Glyphs);
 
301
    ps->Glyphs = SCREENREC(pScreen)->Glyphs;
 
302
    ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
 
303
    ps->Glyphs = RootlessGlyphs;
 
304
    //SCREEN_WRAP(ps, Glyphs);
 
305
 
 
306
    if (dstWin && IsFramedWindow(dstWin)) {
 
307
        x = xSrc;
 
308
        y = ySrc;
 
309
 
 
310
        while (nlist--) {
 
311
            x += list->xOff;
 
312
            y += list->yOff;
 
313
            n = list->len;
 
314
 
 
315
            /* Calling DamageRect for the bounding box of each glyph is
 
316
               inefficient. So compute the union of all glyphs in a list
 
317
               and damage that. */
 
318
 
 
319
            if (n > 0) {
 
320
                BoxRec box;
 
321
 
 
322
                glyph = *glyphs++;
 
323
 
 
324
                box.x1 = x - glyph->info.x;
 
325
                box.y1 = y - glyph->info.y;
 
326
                box.x2 = box.x1 + glyph->info.width;
 
327
                box.y2 = box.y1 + glyph->info.height;
 
328
 
 
329
                x += glyph->info.xOff;
 
330
                y += glyph->info.yOff;
 
331
 
 
332
                while (--n > 0) {
 
333
                    short x1, y1, x2, y2;
 
334
 
 
335
                    glyph = *glyphs++;
 
336
 
 
337
                    x1 = x - glyph->info.x;
 
338
                    y1 = y - glyph->info.y;
 
339
                    x2 = x1 + glyph->info.width;
 
340
                    y2 = y1 + glyph->info.height;
 
341
 
 
342
                    box.x1 = max(box.x1, x1);
 
343
                    box.y1 = max(box.y1, y1);
 
344
                    box.x2 = max(box.x2, x2);
 
345
                    box.y2 = max(box.y2, y2);
 
346
 
 
347
                    x += glyph->info.xOff;
 
348
                    y += glyph->info.yOff;
 
349
                }
 
350
 
 
351
                RootlessDamageBox(dstWin, &box);
 
352
            }
 
353
            list++;
 
354
        }
 
355
    }
 
356
}
 
357
 
 
358
/*
 
359
 * RootlessValidateTree
 
360
 *  ValidateTree is modified in two ways:
 
361
 *   - top-level windows don't clip each other
 
362
 *   - windows aren't clipped against root.
 
363
 *  These only matter when validating from the root.
 
364
 */
 
365
static int
 
366
RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
 
367
{
 
368
    int result;
 
369
    RegionRec saveRoot;
 
370
    ScreenPtr pScreen = pParent->drawable.pScreen;
 
371
 
 
372
    SCREEN_UNWRAP(pScreen, ValidateTree);
 
373
    RL_DEBUG_MSG("VALIDATETREE start ");
 
374
 
 
375
    // Use our custom version to validate from root
 
376
    if (IsRoot(pParent)) {
 
377
        RL_DEBUG_MSG("custom ");
 
378
        result = RootlessMiValidateTree(pParent, pChild, kind);
 
379
    }
 
380
    else {
 
381
        HUGE_ROOT(pParent);
 
382
        result = pScreen->ValidateTree(pParent, pChild, kind);
 
383
        NORMAL_ROOT(pParent);
 
384
    }
 
385
 
 
386
    SCREEN_WRAP(pScreen, ValidateTree);
 
387
    RL_DEBUG_MSG("VALIDATETREE end\n");
 
388
 
 
389
    return result;
 
390
}
 
391
 
 
392
/*
 
393
 * RootlessMarkOverlappedWindows
 
394
 *  MarkOverlappedWindows is modified to ignore overlapping
 
395
 *  top-level windows.
 
396
 */
 
397
static Bool
 
398
RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
 
399
                              WindowPtr *ppLayerWin)
 
400
{
 
401
    RegionRec saveRoot;
 
402
    Bool result;
 
403
    ScreenPtr pScreen = pWin->drawable.pScreen;
 
404
 
 
405
    SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
 
406
    RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
 
407
 
 
408
    HUGE_ROOT(pWin);
 
409
    if (IsRoot(pWin)) {
 
410
        // root - mark nothing
 
411
        RL_DEBUG_MSG("is root not marking ");
 
412
        result = FALSE;
 
413
    }
 
414
    else if (!IsTopLevel(pWin)) {
 
415
        // not top-level window - mark normally
 
416
        result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
 
417
    }
 
418
    else {
 
419
        //top-level window - mark children ONLY - NO overlaps with sibs (?)
 
420
        // This code copied from miMarkOverlappedWindows()
 
421
 
 
422
        register WindowPtr pChild;
 
423
        Bool anyMarked = FALSE;
 
424
        MarkWindowProcPtr MarkWindow = pScreen->MarkWindow;
 
425
 
 
426
        RL_DEBUG_MSG("is top level! ");
 
427
        /* single layered systems are easy */
 
428
        if (ppLayerWin)
 
429
            *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
        }
 
457
        if (anyMarked)
 
458
            (*MarkWindow) (pWin->parent);
 
459
        result = anyMarked;
 
460
    }
 
461
    NORMAL_ROOT(pWin);
 
462
    SCREEN_WRAP(pScreen, MarkOverlappedWindows);
 
463
    RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
 
464
 
 
465
    return result;
 
466
}
 
467
 
 
468
static void
 
469
expose_1(WindowPtr pWin)
 
470
{
 
471
    WindowPtr pChild;
 
472
 
 
473
    if (!pWin->realized)
 
474
        return;
 
475
 
 
476
    miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND);
 
477
 
 
478
    /* FIXME: comments in windowstr.h indicate that borderClip doesn't
 
479
       include subwindow visibility. But I'm not so sure.. so we may
 
480
       be exposing too much.. */
 
481
 
 
482
    miSendExposures(pWin, &pWin->borderClip,
 
483
                    pWin->drawable.x, pWin->drawable.y);
 
484
 
 
485
    for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib)
 
486
        expose_1(pChild);
 
487
}
 
488
 
 
489
void
 
490
RootlessScreenExpose(ScreenPtr pScreen)
 
491
{
 
492
    expose_1(pScreen->root);
 
493
}
 
494
 
 
495
ColormapPtr
 
496
RootlessGetColormap(ScreenPtr pScreen)
 
497
{
 
498
    RootlessScreenRec *s = SCREENREC(pScreen);
 
499
 
 
500
    return s->colormap;
 
501
}
 
502
 
 
503
static void
 
504
RootlessInstallColormap(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
 
 
522
static void
 
523
RootlessUninstallColormap(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
 
 
538
static void
 
539
RootlessStoreColors(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
static CARD32
 
557
RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg)
 
558
{
 
559
    RootlessScreenRec *screenRec = arg;
 
560
 
 
561
    if (!screenRec->redisplay_queued) {
 
562
        /* No update needed. Stop the timer. */
 
563
 
 
564
        screenRec->redisplay_timer_set = FALSE;
 
565
        return 0;
 
566
    }
 
567
 
 
568
    screenRec->redisplay_queued = FALSE;
 
569
 
 
570
    /* Mark that we should redisplay before waiting for I/O next time */
 
571
    screenRec->redisplay_expired = TRUE;
 
572
 
 
573
    /* Reinstall the timer immediately, so we get as close to our
 
574
       redisplay interval as possible. */
 
575
 
 
576
    return ROOTLESS_REDISPLAY_DELAY;
 
577
}
 
578
 
 
579
/*
 
580
 * RootlessQueueRedisplay
 
581
 *  Queue a redisplay after a timer delay to ensure we do not redisplay
 
582
 *  too frequently.
 
583
 */
 
584
void
 
585
RootlessQueueRedisplay(ScreenPtr pScreen)
 
586
{
 
587
    RootlessScreenRec *screenRec = SCREENREC(pScreen);
 
588
 
 
589
    screenRec->redisplay_queued = TRUE;
 
590
 
 
591
    if (screenRec->redisplay_timer_set)
 
592
        return;
 
593
 
 
594
    screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer,
 
595
                                          0, ROOTLESS_REDISPLAY_DELAY,
 
596
                                          RootlessRedisplayCallback, screenRec);
 
597
    screenRec->redisplay_timer_set = TRUE;
 
598
}
 
599
 
 
600
/*
 
601
 * RootlessBlockHandler
 
602
 *  If the redisplay timer has expired, flush drawing before blocking
 
603
 *  on select().
 
604
 */
 
605
static void
 
606
RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask)
 
607
{
 
608
    ScreenPtr pScreen = pbdata;
 
609
    RootlessScreenRec *screenRec = SCREENREC(pScreen);
 
610
 
 
611
    if (screenRec->redisplay_expired) {
 
612
        screenRec->redisplay_expired = FALSE;
 
613
 
 
614
        RootlessRedisplayScreen(pScreen);
 
615
    }
 
616
}
 
617
 
 
618
static void
 
619
RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask)
 
620
{
 
621
    // nothing here
 
622
}
 
623
 
 
624
static Bool
 
625
RootlessAllocatePrivates(ScreenPtr pScreen)
 
626
{
 
627
    RootlessScreenRec *s;
 
628
 
 
629
    if (!dixRegisterPrivateKey
 
630
        (&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec)))
 
631
        return FALSE;
 
632
    if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
 
633
        return FALSE;
 
634
    if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
 
635
        return FALSE;
 
636
    if (!dixRegisterPrivateKey
 
637
        (&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0))
 
638
        return FALSE;
 
639
 
 
640
    s = malloc(sizeof(RootlessScreenRec));
 
641
    if (!s)
 
642
        return FALSE;
 
643
    SETSCREENREC(pScreen, s);
 
644
 
 
645
    s->pixmap_data = NULL;
 
646
    s->pixmap_data_size = 0;
 
647
 
 
648
    s->redisplay_timer = NULL;
 
649
    s->redisplay_timer_set = FALSE;
 
650
 
 
651
    return TRUE;
 
652
}
 
653
 
 
654
static void
 
655
RootlessWrap(ScreenPtr pScreen)
 
656
{
 
657
    RootlessScreenRec *s = SCREENREC(pScreen);
 
658
 
 
659
#define WRAP(a) \
 
660
    if (pScreen->a) { \
 
661
        s->a = pScreen->a; \
 
662
    } else { \
 
663
        RL_DEBUG_MSG("null screen fn " #a "\n"); \
 
664
        s->a = NULL; \
 
665
    } \
 
666
    pScreen->a = Rootless##a
 
667
 
 
668
    WRAP(CreateScreenResources);
 
669
    WRAP(CloseScreen);
 
670
    WRAP(CreateGC);
 
671
    WRAP(CopyWindow);
 
672
    WRAP(GetImage);
 
673
    WRAP(SourceValidate);
 
674
    WRAP(CreateWindow);
 
675
    WRAP(DestroyWindow);
 
676
    WRAP(RealizeWindow);
 
677
    WRAP(UnrealizeWindow);
 
678
    WRAP(MoveWindow);
 
679
    WRAP(PositionWindow);
 
680
    WRAP(ResizeWindow);
 
681
    WRAP(RestackWindow);
 
682
    WRAP(ReparentWindow);
 
683
    WRAP(ChangeBorderWidth);
 
684
    WRAP(MarkOverlappedWindows);
 
685
    WRAP(ValidateTree);
 
686
    WRAP(ChangeWindowAttributes);
 
687
    WRAP(InstallColormap);
 
688
    WRAP(UninstallColormap);
 
689
    WRAP(StoreColors);
 
690
 
 
691
    WRAP(SetShape);
 
692
 
 
693
    {
 
694
        // Composite and Glyphs don't use normal screen wrapping
 
695
        PictureScreenPtr ps = GetPictureScreen(pScreen);
 
696
 
 
697
        s->Composite = ps->Composite;
 
698
        ps->Composite = RootlessComposite;
 
699
        s->Glyphs = ps->Glyphs;
 
700
        ps->Glyphs = RootlessGlyphs;
 
701
    }
 
702
 
 
703
    // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
 
704
 
 
705
#undef WRAP
 
706
}
 
707
 
 
708
/*
 
709
 * RootlessInit
 
710
 *  Called by the rootless implementation to initialize the rootless layer.
 
711
 *  Rootless wraps lots of stuff and needs a bunch of devPrivates.
 
712
 */
 
713
Bool
 
714
RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs)
 
715
{
 
716
    RootlessScreenRec *s;
 
717
 
 
718
    if (!RootlessAllocatePrivates(pScreen))
 
719
        return FALSE;
 
720
 
 
721
    s = SCREENREC(pScreen);
 
722
 
 
723
    s->imp = procs;
 
724
    s->colormap = NULL;
 
725
    s->redisplay_expired = FALSE;
 
726
 
 
727
    RootlessWrap(pScreen);
 
728
 
 
729
    if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler,
 
730
                                        RootlessWakeupHandler,
 
731
                                        (pointer) pScreen)) {
 
732
        return FALSE;
 
733
    }
 
734
 
 
735
    return TRUE;
 
736
}
 
737
 
 
738
void
 
739
RootlessUpdateRooted(Bool state)
 
740
{
 
741
    int i;
 
742
 
 
743
    if (!state) {
 
744
        for (i = 0; i < screenInfo.numScreens; i++)
 
745
            RootlessDisableRoot(screenInfo.screens[i]);
 
746
    }
 
747
    else {
 
748
        for (i = 0; i < screenInfo.numScreens; i++)
 
749
            RootlessEnableRoot(screenInfo.screens[i]);
 
750
    }
 
751
}