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