1 /*
2 * Screen routines for Mac OS X rootless X server
3 *
4 * Greg Parker gparker@cs.stanford.edu
5 *
6 * February 2001 Created
7 * March 3, 2001 Restructured as generic rootless mode
8 */
9
10 /* Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
11
12 Permission is hereby granted, free of charge, to any person
13 obtaining a copy of this software and associated documentation files
14 (the "Software"), to deal in the Software without restriction,
15 including without limitation the rights to use, copy, modify, merge,
16 publish, distribute, sublicense, and/or sell copies of the Software,
17 and to permit persons to whom the Software is furnished to do so,
18 subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be
21 included in all copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
27 HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 DEALINGS IN THE SOFTWARE.
31
32 Except as contained in this notice, the name(s) of the above
33 copyright holders shall not be used in advertising or otherwise to
34 promote the sale, use or other dealings in this Software without
35 prior written authorization. */
36
37 /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessScreen.c,v 1.2 2002/04/03 00:06:32 torrey Exp $ */
38
39
40 #include "mi.h"
41 #include "scrnintstr.h"
42 #include "gcstruct.h"
43 #include "pixmapstr.h"
44 #include "windowstr.h"
45 #include "propertyst.h"
46 #include "mivalidate.h"
47 #include "picturestr.h"
48 #include "os.h"
49 #include "servermd.h"
50 #include "colormapst.h"
51
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <fcntl.h>
55
56 #include "rootless-common.h"
57 #include "rootless-window.h"
58
59 /* In milcroseconds */
60 #define REDISPLAY_DELAY 10
61 #define REDISPLAY_MAX_DELAY 60
62
63 extern int RootlessMiValidateTree(WindowPtr pRoot,
64 WindowPtr pChild, VTKind kind);
65 extern Bool RootlessCreateGC(GCPtr pGC);
66
67 int rootlessGCPrivateIndex = -1;
68 int rootlessScreenPrivateIndex = -1;
69 int rootlessWindowPrivateIndex = -1;
70
71 void
RootlessUpdateScreenPixmap(ScreenPtr pScreen)72 RootlessUpdateScreenPixmap (ScreenPtr pScreen)
73 {
74 RootlessScreenRec *s = SCREENREC(pScreen);
75 PixmapPtr pPix;
76 unsigned int rowbytes;
77
78 pPix = (*pScreen->GetScreenPixmap) (pScreen);
79 if (pPix == NULL)
80 {
81 pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth);
82 (*pScreen->SetScreenPixmap) (pPix);
83 }
84
85 rowbytes = PixmapBytePad (pScreen->width, pScreen->rootDepth);
86
87 if (s->pixmap_data_size < rowbytes)
88 {
89 if (s->pixmap_data != NULL)
90 xfree (s->pixmap_data);
91
92 s->pixmap_data_size = rowbytes;
93 s->pixmap_data = xalloc (s->pixmap_data_size);
94 if (s->pixmap_data == NULL)
95 return;
96
97 xp_fill_bytes (s->pixmap_data_size, 1, ~0,
98 s->pixmap_data, s->pixmap_data_size);
99
100 pScreen->ModifyPixmapHeader (pPix, pScreen->width, pScreen->height,
101 pScreen->rootDepth,
102 BitsPerPixel (pScreen->rootDepth),
103 0, s->pixmap_data);
104 /* ModifyPixmapHeader ignores zero arguments, so install rowbytes
105 by hand. */
106 pPix->devKind = 0;
107 }
108 }
109
110 static Bool
RootlessCreateScreenResources(ScreenPtr pScreen)111 RootlessCreateScreenResources (ScreenPtr pScreen)
112 {
113 Bool ret = TRUE;
114
115 SCREEN_UNWRAP (pScreen, CreateScreenResources);
116
117 if (pScreen->CreateScreenResources != NULL)
118 ret = (*pScreen->CreateScreenResources) (pScreen);
119
120 SCREEN_WRAP(pScreen, CreateScreenResources);
121
122 if (!ret)
123 return ret;
124
125 /* miCreateScreenResources doesn't like our null framebuffer pointer,
126 it leaves the screen pixmap with an uninitialized data pointer. So
127 we gave it depth=0,bits=0, which says, leave it the fsck alone.
128 So we have some work to do since we need the screen pixmap to be
129 valid (e.g. CopyArea from the root window) */
130
131 RootlessUpdateScreenPixmap (pScreen);
132
133 return ret;
134 }
135
136 static Bool
RootlessCloseScreen(int i,ScreenPtr pScreen)137 RootlessCloseScreen(int i, ScreenPtr pScreen)
138 {
139 RootlessScreenRec *s;
140
141 s = SCREENREC(pScreen);
142
143 /* FIXME: unwrap everything that was wrapped? */
144 pScreen->CloseScreen = s->CloseScreen;
145
146 if (s->pixmap_data != NULL)
147 {
148 xfree (s->pixmap_data);
149 s->pixmap_data = NULL;
150 s->pixmap_data_size = 0;
151 }
152
153 xfree(s);
154 return pScreen->CloseScreen(i, pScreen);
155 }
156
157 static void
RootlessGetImage(DrawablePtr pDrawable,int sx,int sy,int w,int h,unsigned int format,unsigned long planeMask,char * pdstLine)158 RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
159 unsigned int format, unsigned long planeMask, char *pdstLine)
160 {
161 ScreenPtr pScreen = pDrawable->pScreen;
162 SCREEN_UNWRAP(pScreen, GetImage);
163
164 if (pDrawable->type == DRAWABLE_WINDOW)
165 {
166 int x0, y0, x1, y1;
167
168 RootlessWindowRec *winRec;
169
170 /* Many apps use GetImage to sync with the visible frame buffer
171 FIXME: entire screen or just window or all screens? */
172 RootlessRedisplayScreen (pScreen);
173
174 /* RedisplayScreen stops drawing, so we need to start it again */
175 RootlessStartDrawing ((WindowPtr) pDrawable);
176
177 /* Check that we have some place to read from. */
178 winRec = WINREC (TopLevelParent ((WindowPtr) pDrawable));
179 if (winRec == NULL)
180 goto out;
181
182 /* Clip to top-level window bounds. */
183
184 x0 = pDrawable->x + sx;
185 y0 = pDrawable->y + sy;
186 x1 = x0 + w;
187 y1 = y0 + h;
188
189 x0 = MAX (x0, winRec->x);
190 y0 = MAX (y0, winRec->y);
191 x1 = MIN (x1, winRec->x + (int) winRec->width);
192 y1 = MIN (y1, winRec->y + (int) winRec->height);
193
194 /* FIXME: if clipped we need to adjust the data returned from
195 fbGetImage (), since it calculates the destination stride
196 from the passed in width.. */
197
198 sx = x0 - pDrawable->x;
199 sy = y0 - pDrawable->y;
200 w = x1 - x0;
201 h = y1 - y0;
202
203 if (w <= 0 || h <= 0)
204 goto out;
205 }
206
207 pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
208
209 out:
210 SCREEN_WRAP(pScreen, GetImage);
211 }
212
213 /*
214 * RootlessSourceValidate
215 * CopyArea and CopyPlane use a GC tied to the destination drawable.
216 * StartDrawing/StopDrawing wrappers won't be called if source is
217 * a visible window but the destination isn't. So, we call StartDrawing
218 * here and leave StopDrawing for the block handler.
219 */
220 static void
RootlessSourceValidate(DrawablePtr pDrawable,int x,int y,int w,int h)221 RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h)
222 {
223 SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
224 if (pDrawable->type == DRAWABLE_WINDOW) {
225 WindowPtr pWin = (WindowPtr)pDrawable;
226 RootlessStartDrawing(pWin);
227 }
228 if (pDrawable->pScreen->SourceValidate) {
229 pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h);
230 }
231 SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
232 }
233
234 #ifdef RENDER
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) {
246 maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ?
247 (WindowPtr)pMask->pDrawable : NULL;
248 }
249 srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
250 (WindowPtr)pSrc->pDrawable : NULL;
251 dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
252 (WindowPtr)pDst->pDrawable : NULL;
253
254 ps->Composite = SCREENREC(pScreen)->Composite;
255
256 if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
257 if (maskWin && IsFramedWindow(maskWin)) RootlessStartDrawing(maskWin);
258 if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);
259
260 ps->Composite(op, pSrc, pMask, pDst,
261 xSrc, ySrc, xMask, yMask,
262 xDst, yDst, width, height);
263
264 if (dstWin && IsFramedWindow(dstWin)) {
265 RootlessDamageRect(dstWin, xDst, yDst, width, height);
266 }
267
268 ps->Composite = RootlessComposite;
269 }
270
271 static void
RootlessGlyphs(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int nlist,GlyphListPtr list,GlyphPtr * glyphs)272 RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
273 PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
274 int nlist, GlyphListPtr list, GlyphPtr *glyphs)
275 {
276 ScreenPtr pScreen = pDst->pDrawable->pScreen;
277 PictureScreenPtr ps = GetPictureScreen(pScreen);
278 int x, y;
279 int n;
280 GlyphPtr glyph;
281 WindowPtr srcWin, dstWin;
282
283 srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
284 (WindowPtr)pSrc->pDrawable : NULL;
285 dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
286 (WindowPtr)pDst->pDrawable : NULL;
287
288 if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
289 if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);
290
291 ps->Glyphs = SCREENREC(pScreen)->Glyphs;
292 ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
293 ps->Glyphs = RootlessGlyphs;
294
295 if (dstWin && IsFramedWindow(dstWin))
296 {
297 x = xSrc;
298 y = ySrc;
299
300 while (nlist--)
301 {
302 /* Originally this code called DamageRect for the bounding
303 box of each glyph. But that was causing way too much
304 time to be spent in CGSBoundingRegionAddRect. So compute
305 the union of all glyphs in a list and damage that. It
306 shouldn't be very different. */
307
308 x += list->xOff;
309 y += list->yOff;
310 n = list->len;
311
312 if (n > 0)
313 {
314 BoxRec box;
315
316 glyph = *glyphs++;
317
318 box.x1 = x - glyph->info.x;
319 box.y1 = y - glyph->info.y;
320 box.x2 = box.x1 + glyph->info.width;
321 box.y2 = box.y2 + glyph->info.height;
322
323 x += glyph->info.xOff;
324 y += glyph->info.yOff;
325
326 while (--n > 0)
327 {
328 short x1, y1, x2, y2;
329
330 glyph = *glyphs++;
331
332 x1 = x - glyph->info.x;
333 y1 = y - glyph->info.y;
334 x2 = x1 + glyph->info.width;
335 y2 = y1 + glyph->info.height;
336
337 box.x1 = MAX (box.x1, x1);
338 box.y1 = MAX (box.y1, y1);
339 box.x2 = MAX (box.x2, x2);
340 box.y2 = MAX (box.y2, y2);
341
342 x += glyph->info.xOff;
343 y += glyph->info.yOff;
344 }
345
346 RootlessDamageBox (dstWin, &box);
347 }
348
349 list++;
350 }
351 }
352 }
353
354 #endif /* RENDER */
355
356 /* ValidateTree is modified in two ways:
357 - top-level windows don't clip each other
358 - windows aren't clipped against root.
359 These only matter when validating from the root. */
360 static int
RootlessValidateTree(WindowPtr pParent,WindowPtr pChild,VTKind kind)361 RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
362 {
363 int result;
364 RegionRec saveRoot;
365 ScreenPtr pScreen = pParent->drawable.pScreen;
366
367 SCREEN_UNWRAP(pScreen, ValidateTree);
368 RL_DEBUG_MSG("VALIDATETREE start ");
369
370 /* Use our custom version to validate from root */
371 if (IsRoot(pParent)) {
372 RL_DEBUG_MSG("custom ");
373 result = RootlessMiValidateTree(pParent, pChild, kind);
374 } else {
375 HUGE_ROOT(pParent);
376 result = pScreen->ValidateTree(pParent, pChild, kind);
377 NORMAL_ROOT(pParent);
378 }
379
380 SCREEN_WRAP(pScreen, ValidateTree);
381 RL_DEBUG_MSG("VALIDATETREE end\n");
382
383 return result;
384 }
385
386 /* MarkOverlappedWindows is modified to ignore overlapping top-level
387 windows. */
388 static Bool
RootlessMarkOverlappedWindows(WindowPtr pWin,WindowPtr pFirst,WindowPtr * ppLayerWin)389 RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
390 WindowPtr *ppLayerWin)
391 {
392 RegionRec saveRoot;
393 Bool result;
394 ScreenPtr pScreen = pWin->drawable.pScreen;
395 SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
396 RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
397
398 HUGE_ROOT(pWin);
399 if (IsRoot(pWin)) {
400 /* root - mark nothing */
401 RL_DEBUG_MSG("is root not marking ");
402 result = FALSE;
403 }
404 else if (! IsTopLevel(pWin)) {
405 /* not top-level window - mark normally */
406 result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
407 }
408 else {
409 /* top-level window - mark children ONLY - NO overlaps with sibs (?)
410 This code copied from miMarkOverlappedWindows() */
411
412 register WindowPtr pChild;
413 Bool anyMarked = FALSE;
414 void (* MarkWindow)() = pScreen->MarkWindow;
415
416 RL_DEBUG_MSG("is top level! ");
417 /* single layered systems are easy */
418 if (ppLayerWin) *ppLayerWin = pWin;
419
420 if (pWin == pFirst) {
421 /* Blindly mark pWin and all of its inferiors. This is a slight
422 * overkill if there are mapped windows that outside pWin's border,
423 * but it's better than wasting time on RectIn checks.
424 */
425 pChild = pWin;
426 while (1) {
427 if (pChild->viewable) {
428 if (REGION_BROKEN (pScreen, &pChild->winSize))
429 SetWinSize (pChild);
430 if (REGION_BROKEN (pScreen, &pChild->borderSize))
431 SetBorderSize (pChild);
432 (* MarkWindow)(pChild);
433 if (pChild->firstChild) {
434 pChild = pChild->firstChild;
435 continue;
436 }
437 }
438 while (!pChild->nextSib && (pChild != pWin))
439 pChild = pChild->parent;
440 if (pChild == pWin)
441 break;
442 pChild = pChild->nextSib;
443 }
444 anyMarked = TRUE;
445 pFirst = pFirst->nextSib;
446 }
447 if (anyMarked)
448 (* MarkWindow)(pWin->parent);
449 result = anyMarked;
450 }
451 NORMAL_ROOT(pWin);
452 SCREEN_WRAP(pScreen, MarkOverlappedWindows);
453 RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
454 return result;
455 }
456
457 static void
expose_1(WindowPtr pWin)458 expose_1 (WindowPtr pWin)
459 {
460 WindowPtr pChild;
461
462 if (!pWin->realized)
463 return;
464
465 (*pWin->drawable.pScreen->PaintWindowBackground) (pWin, &pWin->borderClip,
466 PW_BACKGROUND);
467
468 /* FIXME: comments in windowstr.h indicate that borderClip doesn't
469 include subwindow visibility. But I'm not so sure.. so we may
470 be exposing too much.. */
471
472 miSendExposures (pWin, &pWin->borderClip,
473 pWin->drawable.x, pWin->drawable.y);
474
475 for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib)
476 expose_1 (pChild);
477 }
478
479 void
RootlessScreenExpose(ScreenPtr pScreen)480 RootlessScreenExpose (ScreenPtr pScreen)
481 {
482 expose_1 (WindowTable[pScreen->myNum]);
483 }
484
485 ColormapPtr
RootlessGetColormap(ScreenPtr pScreen)486 RootlessGetColormap (ScreenPtr pScreen)
487 {
488 RootlessScreenRec *s = SCREENREC (pScreen);
489
490 return s->colormap;
491 }
492
493 static void
RootlessInstallColormap(ColormapPtr pMap)494 RootlessInstallColormap (ColormapPtr pMap)
495 {
496 ScreenPtr pScreen = pMap->pScreen;
497 RootlessScreenRec *s = SCREENREC (pScreen);
498
499 SCREEN_UNWRAP(pScreen, InstallColormap);
500
501 if (s->colormap != pMap)
502 {
503 s->colormap = pMap;
504 s->colormap_changed = TRUE;
505 RootlessQueueRedisplay (pScreen);
506 }
507
508 pScreen->InstallColormap (pMap);
509
510 SCREEN_WRAP (pScreen, InstallColormap);
511 }
512
513 static void
RootlessUninstallColormap(ColormapPtr pMap)514 RootlessUninstallColormap (ColormapPtr pMap)
515 {
516 ScreenPtr pScreen = pMap->pScreen;
517 RootlessScreenRec *s = SCREENREC (pScreen);
518
519 SCREEN_UNWRAP(pScreen, UninstallColormap);
520
521 if (s->colormap == pMap)
522 s->colormap = NULL;
523
524 pScreen->UninstallColormap (pMap);
525
526 SCREEN_WRAP(pScreen, UninstallColormap);
527 }
528
529 static void
RootlessStoreColors(ColormapPtr pMap,int ndef,xColorItem * pdef)530 RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
531 {
532 ScreenPtr pScreen = pMap->pScreen;
533 RootlessScreenRec *s = SCREENREC (pScreen);
534
535 SCREEN_UNWRAP(pScreen, StoreColors);
536
537 if (s->colormap == pMap && ndef > 0)
538 {
539 s->colormap_changed = TRUE;
540 RootlessQueueRedisplay (pScreen);
541 }
542
543 pScreen->StoreColors (pMap, ndef, pdef);
544
545 SCREEN_WRAP(pScreen, StoreColors);
546 }
547
548 static CARD32
redisplay_callback(OsTimerPtr timer,CARD32 time,void * arg)549 redisplay_callback (OsTimerPtr timer, CARD32 time, void *arg)
550 {
551 RootlessScreenRec *screenRec = arg;
552
553 if (!screenRec->redisplay_queued)
554 {
555 /* No update needed. Stop the timer. */
556
557 screenRec->redisplay_timer_set = FALSE;
558 return 0;
559 }
560
561 screenRec->redisplay_queued = FALSE;
562
563 /* Mark that we should redisplay before waiting for I/O next time */
564 screenRec->redisplay_expired = TRUE;
565
566 /* Reinstall the timer immediately, so we get as close to our
567 redisplay interval as possible. */
568
569 return REDISPLAY_DELAY;
570 }
571
572 void
RootlessQueueRedisplay(ScreenPtr pScreen)573 RootlessQueueRedisplay (ScreenPtr pScreen)
574 {
575 RootlessScreenRec *screenRec = SCREENREC (pScreen);
576
577 screenRec->redisplay_queued = TRUE;
578
579 if (screenRec->redisplay_timer_set)
580 return;
581
582 screenRec->redisplay_timer = TimerSet (screenRec->redisplay_timer,
583 0, REDISPLAY_DELAY,
584 redisplay_callback, screenRec);
585 screenRec->redisplay_timer_set = TRUE;
586 }
587
588 /* Call this function when it might be a good idea to flush updates.
589 Note that it will unlock window buffers! */
590 Bool
RootlessMayRedisplay(ScreenPtr pScreen)591 RootlessMayRedisplay (ScreenPtr pScreen)
592 {
593 RootlessScreenRec *screenRec = SCREENREC (pScreen);
594
595 if (!screenRec->redisplay_queued)
596 return FALSE;
597
598 /* If the timer has fired, or it's been long enough since the last
599 update, redisplay everything now. */
600
601 if (!screenRec->redisplay_expired)
602 {
603 CARD32 now = GetTimeInMillis ();
604
605 if (screenRec->last_redisplay + REDISPLAY_MAX_DELAY >= now)
606 return FALSE;
607 }
608
609 if (screenRec->redisplay_timer_set)
610 {
611 TimerCancel (screenRec->redisplay_timer);
612 screenRec->redisplay_timer_set = FALSE;
613 }
614
615 RootlessRedisplayScreen (screenRec->pScreen);
616 screenRec->redisplay_expired = FALSE;
617
618 return TRUE;
619 }
620
621 /* Flush drawing before blocking on select(). */
622 static void
RootlessBlockHandler(pointer pbdata,OSTimePtr pTimeout,pointer pReadmask)623 RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask)
624 {
625 ScreenPtr pScreen = pbdata;
626 RootlessScreenRec *screenRec = SCREENREC (pScreen);
627
628 if (screenRec->redisplay_expired)
629 {
630 screenRec->redisplay_expired = FALSE;
631
632 if (screenRec->colormap_changed)
633 {
634 RootlessFlushScreenColormaps (screenRec->pScreen);
635 screenRec->colormap_changed = FALSE;
636 }
637
638 RootlessRedisplayScreen (screenRec->pScreen);
639 }
640 }
641
642 static void
RootlessWakeupHandler(pointer data,int i,pointer LastSelectMask)643 RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask)
644 {
645 }
646
647 static Bool
RootlessAllocatePrivates(ScreenPtr pScreen)648 RootlessAllocatePrivates(ScreenPtr pScreen)
649 {
650 RootlessScreenRec *s;
651 static unsigned int rootlessGeneration = -1;
652
653 if (rootlessGeneration != serverGeneration) {
654 rootlessScreenPrivateIndex = AllocateScreenPrivateIndex();
655 if (rootlessScreenPrivateIndex == -1) return FALSE;
656 rootlessGCPrivateIndex = AllocateGCPrivateIndex();
657 if (rootlessGCPrivateIndex == -1) return FALSE;
658 rootlessWindowPrivateIndex = AllocateWindowPrivateIndex();
659 if (rootlessWindowPrivateIndex == -1) return FALSE;
660 rootlessGeneration = serverGeneration;
661 }
662
663 /* no allocation needed for screen privates */
664 if (!AllocateGCPrivate(pScreen, rootlessGCPrivateIndex,
665 sizeof(RootlessGCRec)))
666 return FALSE;
667 if (!AllocateWindowPrivate(pScreen, rootlessWindowPrivateIndex, 0))
668 return FALSE;
669
670 s = xalloc(sizeof(RootlessScreenRec));
671 if (! s) return FALSE;
672 SCREENREC(pScreen) = s;
673
674 s->pixmap_data = NULL;
675 s->pixmap_data_size = 0;
676
677 s->redisplay_timer = NULL;
678 s->redisplay_timer_set = FALSE;
679
680 return TRUE;
681 }
682
683 static void
RootlessWrap(ScreenPtr pScreen)684 RootlessWrap(ScreenPtr pScreen)
685 {
686 RootlessScreenRec *s = (RootlessScreenRec*)
687 pScreen->devPrivates[rootlessScreenPrivateIndex].ptr;
688
689 #define WRAP(a) \
690 if (pScreen->a) { \
691 s->a = pScreen->a; \
692 } else { \
693 RL_DEBUG_MSG("null screen fn " #a "\n"); \
694 s->a = NULL; \
695 } \
696 pScreen->a = Rootless##a
697
698 WRAP(CreateScreenResources);
699 WRAP(CloseScreen);
700 WRAP(CreateGC);
701 WRAP(PaintWindowBackground);
702 WRAP(PaintWindowBorder);
703 WRAP(CopyWindow);
704 WRAP(GetImage);
705 WRAP(SourceValidate);
706 WRAP(CreateWindow);
707 WRAP(DestroyWindow);
708 WRAP(RealizeWindow);
709 WRAP(UnrealizeWindow);
710 WRAP(ReparentWindow);
711 WRAP(MoveWindow);
712 WRAP(PositionWindow);
713 WRAP(ResizeWindow);
714 WRAP(RestackWindow);
715 WRAP(ChangeBorderWidth);
716 WRAP(MarkOverlappedWindows);
717 WRAP(ValidateTree);
718 WRAP(ChangeWindowAttributes);
719 WRAP(InstallColormap);
720 WRAP(UninstallColormap);
721 WRAP(StoreColors);
722
723 #ifdef SHAPE
724 WRAP(SetShape);
725 #endif
726
727 #ifdef RENDER
728 {
729 /* Composite and Glyphs don't use normal screen wrapping */
730 PictureScreenPtr ps = GetPictureScreen(pScreen);
731 s->Composite = ps->Composite;
732 ps->Composite = rootlessComposite;
733 s->Glyphs = ps->Glyphs;
734 ps->Glyphs = RootlessGlyphs;
735 }
736 #endif
737
738 // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
739 // WRAP(RestoreAreas); fixme put this back?
740
741 #undef WRAP
742 }
743
744 Bool
RootlessSetupScreen(int index,ScreenPtr pScreen)745 RootlessSetupScreen(int index, ScreenPtr pScreen)
746 {
747 RootlessScreenRec *s;
748
749 /* Add replacements for fb screen functions */
750 pScreen->PaintWindowBackground = RootlessPaintWindow;
751 pScreen->PaintWindowBorder = RootlessPaintWindow;
752
753 #ifdef RENDER
754 {
755 PictureScreenPtr ps = GetPictureScreen(pScreen);
756 ps->Composite = RootlessComposite;
757 }
758 #endif
759
760 if (!RootlessAllocatePrivates(pScreen))
761 return FALSE;
762
763 s = ((RootlessScreenRec*)
764 pScreen->devPrivates[rootlessScreenPrivateIndex].ptr);
765
766 s->pScreen = pScreen;
767 RootlessWrap(pScreen);
768
769 if (!RegisterBlockAndWakeupHandlers (RootlessBlockHandler,
770 RootlessWakeupHandler,
771 (pointer) pScreen))
772 {
773 return FALSE;
774 }
775
776 return TRUE;
777 }
778
779 void
RootlessUpdateRooted(Bool state)780 RootlessUpdateRooted (Bool state)
781 {
782 int i;
783
784 if (!state)
785 {
786 for (i = 0; i < screenInfo.numScreens; i++)
787 RootlessDisableRoot (screenInfo.screens[i]);
788 }
789 else
790 {
791 for (i = 0; i < screenInfo.numScreens; i++)
792 RootlessEnableRoot (screenInfo.screens[i]);
793 }
794 }
795