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