1706f2543Smrg/* 2706f2543Smrg * Screen routines for generic rootless X server 3706f2543Smrg */ 4706f2543Smrg/* 5706f2543Smrg * Copyright (c) 2001 Greg Parker. All Rights Reserved. 6706f2543Smrg * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. 7706f2543Smrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 8706f2543Smrg * 9706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 10706f2543Smrg * copy of this software and associated documentation files (the "Software"), 11706f2543Smrg * to deal in the Software without restriction, including without limitation 12706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 14706f2543Smrg * Software is furnished to do so, subject to the following conditions: 15706f2543Smrg * 16706f2543Smrg * The above copyright notice and this permission notice shall be included in 17706f2543Smrg * all copies or substantial portions of the Software. 18706f2543Smrg * 19706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 23706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25706f2543Smrg * DEALINGS IN THE SOFTWARE. 26706f2543Smrg * 27706f2543Smrg * Except as contained in this notice, the name(s) of the above copyright 28706f2543Smrg * holders shall not be used in advertising or otherwise to promote the sale, 29706f2543Smrg * use or other dealings in this Software without prior written authorization. 30706f2543Smrg */ 31706f2543Smrg 32706f2543Smrg 33706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 34706f2543Smrg#include <dix-config.h> 35706f2543Smrg#endif 36706f2543Smrg 37706f2543Smrg#include "mi.h" 38706f2543Smrg#include "scrnintstr.h" 39706f2543Smrg#include "gcstruct.h" 40706f2543Smrg#include "pixmapstr.h" 41706f2543Smrg#include "windowstr.h" 42706f2543Smrg#include "propertyst.h" 43706f2543Smrg#include "mivalidate.h" 44706f2543Smrg#include "picturestr.h" 45706f2543Smrg#include "colormapst.h" 46706f2543Smrg 47706f2543Smrg#include <sys/types.h> 48706f2543Smrg#include <sys/stat.h> 49706f2543Smrg#include <fcntl.h> 50706f2543Smrg#include <string.h> 51706f2543Smrg 52706f2543Smrg#include "rootlessCommon.h" 53706f2543Smrg#include "rootlessWindow.h" 54706f2543Smrg 55706f2543Smrg/* In milliseconds */ 56706f2543Smrg#ifndef ROOTLESS_REDISPLAY_DELAY 57706f2543Smrg#define ROOTLESS_REDISPLAY_DELAY 10 58706f2543Smrg#endif 59706f2543Smrg 60706f2543Smrgextern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, 61706f2543Smrg VTKind kind); 62706f2543Smrgextern Bool RootlessCreateGC(GCPtr pGC); 63706f2543Smrg 64706f2543Smrg// Initialize globals 65706f2543SmrgDevPrivateKeyRec rootlessGCPrivateKeyRec; 66706f2543SmrgDevPrivateKeyRec rootlessScreenPrivateKeyRec; 67706f2543SmrgDevPrivateKeyRec rootlessWindowPrivateKeyRec; 68706f2543SmrgDevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec; 69706f2543Smrg 70706f2543Smrg/* 71706f2543Smrg * RootlessUpdateScreenPixmap 72706f2543Smrg * miCreateScreenResources does not like a null framebuffer pointer, 73706f2543Smrg * it leaves the screen pixmap with an uninitialized data pointer. 74706f2543Smrg * Thus, rootless implementations typically set the framebuffer width 75706f2543Smrg * to zero so that miCreateScreenResources does not allocate a screen 76706f2543Smrg * pixmap for us. We allocate our own screen pixmap here since we need 77706f2543Smrg * the screen pixmap to be valid (e.g. CopyArea from the root window). 78706f2543Smrg */ 79706f2543Smrgvoid 80706f2543SmrgRootlessUpdateScreenPixmap(ScreenPtr pScreen) 81706f2543Smrg{ 82706f2543Smrg RootlessScreenRec *s = SCREENREC(pScreen); 83706f2543Smrg PixmapPtr pPix; 84706f2543Smrg unsigned int rowbytes; 85706f2543Smrg 86706f2543Smrg pPix = (*pScreen->GetScreenPixmap)(pScreen); 87706f2543Smrg if (pPix == NULL) { 88706f2543Smrg pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); 89706f2543Smrg (*pScreen->SetScreenPixmap)(pPix); 90706f2543Smrg } 91706f2543Smrg 92706f2543Smrg rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); 93706f2543Smrg 94706f2543Smrg if (s->pixmap_data_size < rowbytes) { 95706f2543Smrg free(s->pixmap_data); 96706f2543Smrg 97706f2543Smrg s->pixmap_data_size = rowbytes; 98706f2543Smrg s->pixmap_data = malloc(s->pixmap_data_size); 99706f2543Smrg if (s->pixmap_data == NULL) 100706f2543Smrg return; 101706f2543Smrg 102706f2543Smrg memset(s->pixmap_data, 0xFF, s->pixmap_data_size); 103706f2543Smrg 104706f2543Smrg pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height, 105706f2543Smrg pScreen->rootDepth, 106706f2543Smrg BitsPerPixel(pScreen->rootDepth), 107706f2543Smrg 0, s->pixmap_data); 108706f2543Smrg /* ModifyPixmapHeader ignores zero arguments, so install rowbytes 109706f2543Smrg by hand. */ 110706f2543Smrg pPix->devKind = 0; 111706f2543Smrg } 112706f2543Smrg} 113706f2543Smrg 114706f2543Smrg 115706f2543Smrg/* 116706f2543Smrg * RootlessCreateScreenResources 117706f2543Smrg * Rootless implementations typically set a null framebuffer pointer, which 118706f2543Smrg * causes problems with miCreateScreenResources. We fix things up here. 119706f2543Smrg */ 120706f2543Smrgstatic Bool 121706f2543SmrgRootlessCreateScreenResources(ScreenPtr pScreen) 122706f2543Smrg{ 123706f2543Smrg Bool ret = TRUE; 124706f2543Smrg 125706f2543Smrg SCREEN_UNWRAP(pScreen, CreateScreenResources); 126706f2543Smrg 127706f2543Smrg if (pScreen->CreateScreenResources != NULL) 128706f2543Smrg ret = (*pScreen->CreateScreenResources)(pScreen); 129706f2543Smrg 130706f2543Smrg SCREEN_WRAP(pScreen, CreateScreenResources); 131706f2543Smrg 132706f2543Smrg if (!ret) 133706f2543Smrg return ret; 134706f2543Smrg 135706f2543Smrg /* Make sure we have a valid screen pixmap. */ 136706f2543Smrg 137706f2543Smrg RootlessUpdateScreenPixmap(pScreen); 138706f2543Smrg 139706f2543Smrg return ret; 140706f2543Smrg} 141706f2543Smrg 142706f2543Smrg 143706f2543Smrgstatic Bool 144706f2543SmrgRootlessCloseScreen(int i, ScreenPtr pScreen) 145706f2543Smrg{ 146706f2543Smrg RootlessScreenRec *s; 147706f2543Smrg 148706f2543Smrg s = SCREENREC(pScreen); 149706f2543Smrg 150706f2543Smrg // fixme unwrap everything that was wrapped? 151706f2543Smrg pScreen->CloseScreen = s->CloseScreen; 152706f2543Smrg 153706f2543Smrg if (s->pixmap_data != NULL) { 154706f2543Smrg free(s->pixmap_data); 155706f2543Smrg s->pixmap_data = NULL; 156706f2543Smrg s->pixmap_data_size = 0; 157706f2543Smrg } 158706f2543Smrg 159706f2543Smrg free(s); 160706f2543Smrg return pScreen->CloseScreen(i, pScreen); 161706f2543Smrg} 162706f2543Smrg 163706f2543Smrg 164706f2543Smrgstatic void 165706f2543SmrgRootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, 166706f2543Smrg unsigned int format, unsigned long planeMask, char *pdstLine) 167706f2543Smrg{ 168706f2543Smrg ScreenPtr pScreen = pDrawable->pScreen; 169706f2543Smrg SCREEN_UNWRAP(pScreen, GetImage); 170706f2543Smrg 171706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 172706f2543Smrg int x0, y0, x1, y1; 173706f2543Smrg RootlessWindowRec *winRec; 174706f2543Smrg 175706f2543Smrg // Many apps use GetImage to sync with the visible frame buffer 176706f2543Smrg // FIXME: entire screen or just window or all screens? 177706f2543Smrg RootlessRedisplayScreen(pScreen); 178706f2543Smrg 179706f2543Smrg // RedisplayScreen stops drawing, so we need to start it again 180706f2543Smrg RootlessStartDrawing((WindowPtr)pDrawable); 181706f2543Smrg 182706f2543Smrg /* Check that we have some place to read from. */ 183706f2543Smrg winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); 184706f2543Smrg if (winRec == NULL) 185706f2543Smrg goto out; 186706f2543Smrg 187706f2543Smrg /* Clip to top-level window bounds. */ 188706f2543Smrg /* FIXME: fbGetImage uses the width parameter to calculate the 189706f2543Smrg stride of the destination pixmap. If w is clipped, the data 190706f2543Smrg returned will be garbage, although we will not crash. */ 191706f2543Smrg 192706f2543Smrg x0 = pDrawable->x + sx; 193706f2543Smrg y0 = pDrawable->y + sy; 194706f2543Smrg x1 = x0 + w; 195706f2543Smrg y1 = y0 + h; 196706f2543Smrg 197706f2543Smrg x0 = max (x0, winRec->x); 198706f2543Smrg y0 = max (y0, winRec->y); 199706f2543Smrg x1 = min (x1, winRec->x + winRec->width); 200706f2543Smrg y1 = min (y1, winRec->y + winRec->height); 201706f2543Smrg 202706f2543Smrg sx = x0 - pDrawable->x; 203706f2543Smrg sy = y0 - pDrawable->y; 204706f2543Smrg w = x1 - x0; 205706f2543Smrg h = y1 - y0; 206706f2543Smrg 207706f2543Smrg if (w <= 0 || h <= 0) 208706f2543Smrg goto out; 209706f2543Smrg } 210706f2543Smrg 211706f2543Smrg pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); 212706f2543Smrg 213706f2543Smrgout: 214706f2543Smrg SCREEN_WRAP(pScreen, GetImage); 215706f2543Smrg} 216706f2543Smrg 217706f2543Smrg 218706f2543Smrg/* 219706f2543Smrg * RootlessSourceValidate 220706f2543Smrg * CopyArea and CopyPlane use a GC tied to the destination drawable. 221706f2543Smrg * StartDrawing/StopDrawing wrappers won't be called if source is 222706f2543Smrg * a visible window but the destination isn't. So, we call StartDrawing 223706f2543Smrg * here and leave StopDrawing for the block handler. 224706f2543Smrg */ 225706f2543Smrgstatic void 226706f2543SmrgRootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h, 227706f2543Smrg unsigned int subWindowMode) 228706f2543Smrg{ 229706f2543Smrg SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); 230706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 231706f2543Smrg WindowPtr pWin = (WindowPtr)pDrawable; 232706f2543Smrg RootlessStartDrawing(pWin); 233706f2543Smrg } 234706f2543Smrg if (pDrawable->pScreen->SourceValidate) { 235706f2543Smrg pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, subWindowMode); 236706f2543Smrg } 237706f2543Smrg SCREEN_WRAP(pDrawable->pScreen, SourceValidate); 238706f2543Smrg} 239706f2543Smrg 240706f2543Smrgstatic void 241706f2543SmrgRootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 242706f2543Smrg INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, 243706f2543Smrg INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 244706f2543Smrg{ 245706f2543Smrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 246706f2543Smrg PictureScreenPtr ps = GetPictureScreen(pScreen); 247706f2543Smrg WindowPtr srcWin, dstWin, maskWin = NULL; 248706f2543Smrg 249706f2543Smrg if (pMask) { // pMask can be NULL 250706f2543Smrg maskWin = (pMask->pDrawable && pMask->pDrawable->type == DRAWABLE_WINDOW) ? 251706f2543Smrg (WindowPtr)pMask->pDrawable : NULL; 252706f2543Smrg } 253706f2543Smrg srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 254706f2543Smrg (WindowPtr)pSrc->pDrawable : NULL; 255706f2543Smrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 256706f2543Smrg (WindowPtr)pDst->pDrawable : NULL; 257706f2543Smrg 258706f2543Smrg // SCREEN_UNWRAP(ps, Composite); 259706f2543Smrg ps->Composite = SCREENREC(pScreen)->Composite; 260706f2543Smrg 261706f2543Smrg if (srcWin && IsFramedWindow(srcWin)) 262706f2543Smrg RootlessStartDrawing(srcWin); 263706f2543Smrg if (maskWin && IsFramedWindow(maskWin)) 264706f2543Smrg RootlessStartDrawing(maskWin); 265706f2543Smrg if (dstWin && IsFramedWindow(dstWin)) 266706f2543Smrg RootlessStartDrawing(dstWin); 267706f2543Smrg 268706f2543Smrg ps->Composite(op, pSrc, pMask, pDst, 269706f2543Smrg xSrc, ySrc, xMask, yMask, 270706f2543Smrg xDst, yDst, width, height); 271706f2543Smrg 272706f2543Smrg if (dstWin && IsFramedWindow(dstWin)) { 273706f2543Smrg RootlessDamageRect(dstWin, xDst, yDst, width, height); 274706f2543Smrg } 275706f2543Smrg 276706f2543Smrg ps->Composite = RootlessComposite; 277706f2543Smrg // SCREEN_WRAP(ps, Composite); 278706f2543Smrg} 279706f2543Smrg 280706f2543Smrg 281706f2543Smrgstatic void 282706f2543SmrgRootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 283706f2543Smrg PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 284706f2543Smrg int nlist, GlyphListPtr list, GlyphPtr *glyphs) 285706f2543Smrg{ 286706f2543Smrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 287706f2543Smrg PictureScreenPtr ps = GetPictureScreen(pScreen); 288706f2543Smrg int x, y; 289706f2543Smrg int n; 290706f2543Smrg GlyphPtr glyph; 291706f2543Smrg WindowPtr srcWin, dstWin; 292706f2543Smrg 293706f2543Smrg srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 294706f2543Smrg (WindowPtr)pSrc->pDrawable : NULL; 295706f2543Smrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 296706f2543Smrg (WindowPtr)pDst->pDrawable : NULL; 297706f2543Smrg 298706f2543Smrg if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); 299706f2543Smrg if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); 300706f2543Smrg 301706f2543Smrg //SCREEN_UNWRAP(ps, Glyphs); 302706f2543Smrg ps->Glyphs = SCREENREC(pScreen)->Glyphs; 303706f2543Smrg ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); 304706f2543Smrg ps->Glyphs = RootlessGlyphs; 305706f2543Smrg //SCREEN_WRAP(ps, Glyphs); 306706f2543Smrg 307706f2543Smrg if (dstWin && IsFramedWindow(dstWin)) { 308706f2543Smrg x = xSrc; 309706f2543Smrg y = ySrc; 310706f2543Smrg 311706f2543Smrg while (nlist--) { 312706f2543Smrg x += list->xOff; 313706f2543Smrg y += list->yOff; 314706f2543Smrg n = list->len; 315706f2543Smrg 316706f2543Smrg /* Calling DamageRect for the bounding box of each glyph is 317706f2543Smrg inefficient. So compute the union of all glyphs in a list 318706f2543Smrg and damage that. */ 319706f2543Smrg 320706f2543Smrg if (n > 0) { 321706f2543Smrg BoxRec box; 322706f2543Smrg 323706f2543Smrg glyph = *glyphs++; 324706f2543Smrg 325706f2543Smrg box.x1 = x - glyph->info.x; 326706f2543Smrg box.y1 = y - glyph->info.y; 327706f2543Smrg box.x2 = box.x1 + glyph->info.width; 328706f2543Smrg box.y2 = box.y1 + glyph->info.height; 329706f2543Smrg 330706f2543Smrg x += glyph->info.xOff; 331706f2543Smrg y += glyph->info.yOff; 332706f2543Smrg 333706f2543Smrg while (--n > 0) { 334706f2543Smrg short x1, y1, x2, y2; 335706f2543Smrg 336706f2543Smrg glyph = *glyphs++; 337706f2543Smrg 338706f2543Smrg x1 = x - glyph->info.x; 339706f2543Smrg y1 = y - glyph->info.y; 340706f2543Smrg x2 = x1 + glyph->info.width; 341706f2543Smrg y2 = y1 + glyph->info.height; 342706f2543Smrg 343706f2543Smrg box.x1 = max (box.x1, x1); 344706f2543Smrg box.y1 = max (box.y1, y1); 345706f2543Smrg box.x2 = max (box.x2, x2); 346706f2543Smrg box.y2 = max (box.y2, y2); 347706f2543Smrg 348706f2543Smrg x += glyph->info.xOff; 349706f2543Smrg y += glyph->info.yOff; 350706f2543Smrg } 351706f2543Smrg 352706f2543Smrg RootlessDamageBox(dstWin, &box); 353706f2543Smrg } 354706f2543Smrg list++; 355706f2543Smrg } 356706f2543Smrg } 357706f2543Smrg} 358706f2543Smrg 359706f2543Smrg 360706f2543Smrg/* 361706f2543Smrg * RootlessValidateTree 362706f2543Smrg * ValidateTree is modified in two ways: 363706f2543Smrg * - top-level windows don't clip each other 364706f2543Smrg * - windows aren't clipped against root. 365706f2543Smrg * These only matter when validating from the root. 366706f2543Smrg */ 367706f2543Smrgstatic int 368706f2543SmrgRootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 369706f2543Smrg{ 370706f2543Smrg int result; 371706f2543Smrg RegionRec saveRoot; 372706f2543Smrg ScreenPtr pScreen = pParent->drawable.pScreen; 373706f2543Smrg 374706f2543Smrg SCREEN_UNWRAP(pScreen, ValidateTree); 375706f2543Smrg RL_DEBUG_MSG("VALIDATETREE start "); 376706f2543Smrg 377706f2543Smrg // Use our custom version to validate from root 378706f2543Smrg if (IsRoot(pParent)) { 379706f2543Smrg RL_DEBUG_MSG("custom "); 380706f2543Smrg result = RootlessMiValidateTree(pParent, pChild, kind); 381706f2543Smrg } else { 382706f2543Smrg HUGE_ROOT(pParent); 383706f2543Smrg result = pScreen->ValidateTree(pParent, pChild, kind); 384706f2543Smrg NORMAL_ROOT(pParent); 385706f2543Smrg } 386706f2543Smrg 387706f2543Smrg SCREEN_WRAP(pScreen, ValidateTree); 388706f2543Smrg RL_DEBUG_MSG("VALIDATETREE end\n"); 389706f2543Smrg 390706f2543Smrg return result; 391706f2543Smrg} 392706f2543Smrg 393706f2543Smrg 394706f2543Smrg/* 395706f2543Smrg * RootlessMarkOverlappedWindows 396706f2543Smrg * MarkOverlappedWindows is modified to ignore overlapping 397706f2543Smrg * top-level windows. 398706f2543Smrg */ 399706f2543Smrgstatic Bool 400706f2543SmrgRootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, 401706f2543Smrg WindowPtr *ppLayerWin) 402706f2543Smrg{ 403706f2543Smrg RegionRec saveRoot; 404706f2543Smrg Bool result; 405706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 406706f2543Smrg SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); 407706f2543Smrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); 408706f2543Smrg 409706f2543Smrg HUGE_ROOT(pWin); 410706f2543Smrg if (IsRoot(pWin)) { 411706f2543Smrg // root - mark nothing 412706f2543Smrg RL_DEBUG_MSG("is root not marking "); 413706f2543Smrg result = FALSE; 414706f2543Smrg } 415706f2543Smrg else if (! IsTopLevel(pWin)) { 416706f2543Smrg // not top-level window - mark normally 417706f2543Smrg result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); 418706f2543Smrg } 419706f2543Smrg else { 420706f2543Smrg //top-level window - mark children ONLY - NO overlaps with sibs (?) 421706f2543Smrg // This code copied from miMarkOverlappedWindows() 422706f2543Smrg 423706f2543Smrg register WindowPtr pChild; 424706f2543Smrg Bool anyMarked = FALSE; 425706f2543Smrg MarkWindowProcPtr MarkWindow = pScreen->MarkWindow; 426706f2543Smrg 427706f2543Smrg RL_DEBUG_MSG("is top level! "); 428706f2543Smrg /* single layered systems are easy */ 429706f2543Smrg if (ppLayerWin) *ppLayerWin = pWin; 430706f2543Smrg 431706f2543Smrg if (pWin == pFirst) { 432706f2543Smrg /* Blindly mark pWin and all of its inferiors. This is a slight 433706f2543Smrg * overkill if there are mapped windows that outside pWin's border, 434706f2543Smrg * but it's better than wasting time on RectIn checks. 435706f2543Smrg */ 436706f2543Smrg pChild = pWin; 437706f2543Smrg while (1) { 438706f2543Smrg if (pChild->viewable) { 439706f2543Smrg if (RegionBroken(&pChild->winSize)) 440706f2543Smrg SetWinSize (pChild); 441706f2543Smrg if (RegionBroken(&pChild->borderSize)) 442706f2543Smrg SetBorderSize (pChild); 443706f2543Smrg (* MarkWindow)(pChild); 444706f2543Smrg if (pChild->firstChild) { 445706f2543Smrg pChild = pChild->firstChild; 446706f2543Smrg continue; 447706f2543Smrg } 448706f2543Smrg } 449706f2543Smrg while (!pChild->nextSib && (pChild != pWin)) 450706f2543Smrg pChild = pChild->parent; 451706f2543Smrg if (pChild == pWin) 452706f2543Smrg break; 453706f2543Smrg pChild = pChild->nextSib; 454706f2543Smrg } 455706f2543Smrg anyMarked = TRUE; 456706f2543Smrg pFirst = pFirst->nextSib; 457706f2543Smrg } 458706f2543Smrg if (anyMarked) 459706f2543Smrg (* MarkWindow)(pWin->parent); 460706f2543Smrg result = anyMarked; 461706f2543Smrg } 462706f2543Smrg NORMAL_ROOT(pWin); 463706f2543Smrg SCREEN_WRAP(pScreen, MarkOverlappedWindows); 464706f2543Smrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); 465706f2543Smrg 466706f2543Smrg return result; 467706f2543Smrg} 468706f2543Smrg 469706f2543Smrgstatic void expose_1 (WindowPtr pWin) { 470706f2543Smrg WindowPtr pChild; 471706f2543Smrg 472706f2543Smrg if (!pWin->realized) 473706f2543Smrg return; 474706f2543Smrg 475706f2543Smrg miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); 476706f2543Smrg 477706f2543Smrg /* FIXME: comments in windowstr.h indicate that borderClip doesn't 478706f2543Smrg include subwindow visibility. But I'm not so sure.. so we may 479706f2543Smrg be exposing too much.. */ 480706f2543Smrg 481706f2543Smrg miSendExposures (pWin, &pWin->borderClip, 482706f2543Smrg pWin->drawable.x, pWin->drawable.y); 483706f2543Smrg 484706f2543Smrg for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) 485706f2543Smrg expose_1 (pChild); 486706f2543Smrg} 487706f2543Smrg 488706f2543Smrgvoid 489706f2543SmrgRootlessScreenExpose (ScreenPtr pScreen) 490706f2543Smrg{ 491706f2543Smrg expose_1 (pScreen->root); 492706f2543Smrg} 493706f2543Smrg 494706f2543Smrg 495706f2543SmrgColormapPtr 496706f2543SmrgRootlessGetColormap (ScreenPtr pScreen) 497706f2543Smrg{ 498706f2543Smrg RootlessScreenRec *s = SCREENREC (pScreen); 499706f2543Smrg 500706f2543Smrg return s->colormap; 501706f2543Smrg} 502706f2543Smrg 503706f2543Smrgstatic void 504706f2543SmrgRootlessInstallColormap (ColormapPtr pMap) 505706f2543Smrg{ 506706f2543Smrg ScreenPtr pScreen = pMap->pScreen; 507706f2543Smrg RootlessScreenRec *s = SCREENREC (pScreen); 508706f2543Smrg 509706f2543Smrg SCREEN_UNWRAP(pScreen, InstallColormap); 510706f2543Smrg 511706f2543Smrg if (s->colormap != pMap) { 512706f2543Smrg s->colormap = pMap; 513706f2543Smrg s->colormap_changed = TRUE; 514706f2543Smrg RootlessQueueRedisplay (pScreen); 515706f2543Smrg } 516706f2543Smrg 517706f2543Smrg pScreen->InstallColormap (pMap); 518706f2543Smrg 519706f2543Smrg SCREEN_WRAP (pScreen, InstallColormap); 520706f2543Smrg} 521706f2543Smrg 522706f2543Smrgstatic void 523706f2543SmrgRootlessUninstallColormap (ColormapPtr pMap) 524706f2543Smrg{ 525706f2543Smrg ScreenPtr pScreen = pMap->pScreen; 526706f2543Smrg RootlessScreenRec *s = SCREENREC (pScreen); 527706f2543Smrg 528706f2543Smrg SCREEN_UNWRAP(pScreen, UninstallColormap); 529706f2543Smrg 530706f2543Smrg if (s->colormap == pMap) 531706f2543Smrg s->colormap = NULL; 532706f2543Smrg 533706f2543Smrg pScreen->UninstallColormap (pMap); 534706f2543Smrg 535706f2543Smrg SCREEN_WRAP(pScreen, UninstallColormap); 536706f2543Smrg} 537706f2543Smrg 538706f2543Smrgstatic void 539706f2543SmrgRootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) 540706f2543Smrg{ 541706f2543Smrg ScreenPtr pScreen = pMap->pScreen; 542706f2543Smrg RootlessScreenRec *s = SCREENREC (pScreen); 543706f2543Smrg 544706f2543Smrg SCREEN_UNWRAP(pScreen, StoreColors); 545706f2543Smrg 546706f2543Smrg if (s->colormap == pMap && ndef > 0) { 547706f2543Smrg s->colormap_changed = TRUE; 548706f2543Smrg RootlessQueueRedisplay (pScreen); 549706f2543Smrg } 550706f2543Smrg 551706f2543Smrg pScreen->StoreColors (pMap, ndef, pdef); 552706f2543Smrg 553706f2543Smrg SCREEN_WRAP(pScreen, StoreColors); 554706f2543Smrg} 555706f2543Smrg 556706f2543Smrg 557706f2543Smrgstatic CARD32 558706f2543SmrgRootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) 559706f2543Smrg{ 560706f2543Smrg RootlessScreenRec *screenRec = arg; 561706f2543Smrg 562706f2543Smrg if (!screenRec->redisplay_queued) { 563706f2543Smrg /* No update needed. Stop the timer. */ 564706f2543Smrg 565706f2543Smrg screenRec->redisplay_timer_set = FALSE; 566706f2543Smrg return 0; 567706f2543Smrg } 568706f2543Smrg 569706f2543Smrg screenRec->redisplay_queued = FALSE; 570706f2543Smrg 571706f2543Smrg /* Mark that we should redisplay before waiting for I/O next time */ 572706f2543Smrg screenRec->redisplay_expired = TRUE; 573706f2543Smrg 574706f2543Smrg /* Reinstall the timer immediately, so we get as close to our 575706f2543Smrg redisplay interval as possible. */ 576706f2543Smrg 577706f2543Smrg return ROOTLESS_REDISPLAY_DELAY; 578706f2543Smrg} 579706f2543Smrg 580706f2543Smrg 581706f2543Smrg/* 582706f2543Smrg * RootlessQueueRedisplay 583706f2543Smrg * Queue a redisplay after a timer delay to ensure we do not redisplay 584706f2543Smrg * too frequently. 585706f2543Smrg */ 586706f2543Smrgvoid 587706f2543SmrgRootlessQueueRedisplay(ScreenPtr pScreen) 588706f2543Smrg{ 589706f2543Smrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 590706f2543Smrg 591706f2543Smrg screenRec->redisplay_queued = TRUE; 592706f2543Smrg 593706f2543Smrg if (screenRec->redisplay_timer_set) 594706f2543Smrg return; 595706f2543Smrg 596706f2543Smrg screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, 597706f2543Smrg 0, ROOTLESS_REDISPLAY_DELAY, 598706f2543Smrg RootlessRedisplayCallback, 599706f2543Smrg screenRec); 600706f2543Smrg screenRec->redisplay_timer_set = TRUE; 601706f2543Smrg} 602706f2543Smrg 603706f2543Smrg 604706f2543Smrg/* 605706f2543Smrg * RootlessBlockHandler 606706f2543Smrg * If the redisplay timer has expired, flush drawing before blocking 607706f2543Smrg * on select(). 608706f2543Smrg */ 609706f2543Smrgstatic void 610706f2543SmrgRootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) 611706f2543Smrg{ 612706f2543Smrg ScreenPtr pScreen = pbdata; 613706f2543Smrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 614706f2543Smrg 615706f2543Smrg if (screenRec->redisplay_expired) { 616706f2543Smrg screenRec->redisplay_expired = FALSE; 617706f2543Smrg 618706f2543Smrg RootlessRedisplayScreen(pScreen); 619706f2543Smrg } 620706f2543Smrg} 621706f2543Smrg 622706f2543Smrg 623706f2543Smrgstatic void 624706f2543SmrgRootlessWakeupHandler(pointer data, int i, pointer LastSelectMask) 625706f2543Smrg{ 626706f2543Smrg // nothing here 627706f2543Smrg} 628706f2543Smrg 629706f2543Smrg 630706f2543Smrgstatic Bool 631706f2543SmrgRootlessAllocatePrivates(ScreenPtr pScreen) 632706f2543Smrg{ 633706f2543Smrg RootlessScreenRec *s; 634706f2543Smrg 635706f2543Smrg if (!dixRegisterPrivateKey(&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec))) 636706f2543Smrg return FALSE; 637706f2543Smrg if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 638706f2543Smrg return FALSE; 639706f2543Smrg if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) 640706f2543Smrg return FALSE; 641706f2543Smrg if (!dixRegisterPrivateKey(&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0)) 642706f2543Smrg return FALSE; 643706f2543Smrg 644706f2543Smrg s = malloc(sizeof(RootlessScreenRec)); 645706f2543Smrg if (! s) return FALSE; 646706f2543Smrg SETSCREENREC(pScreen, s); 647706f2543Smrg 648706f2543Smrg s->pixmap_data = NULL; 649706f2543Smrg s->pixmap_data_size = 0; 650706f2543Smrg 651706f2543Smrg s->redisplay_timer = NULL; 652706f2543Smrg s->redisplay_timer_set = FALSE; 653706f2543Smrg 654706f2543Smrg return TRUE; 655706f2543Smrg} 656706f2543Smrg 657706f2543Smrg 658706f2543Smrgstatic void 659706f2543SmrgRootlessWrap(ScreenPtr pScreen) 660706f2543Smrg{ 661706f2543Smrg RootlessScreenRec *s = SCREENREC(pScreen); 662706f2543Smrg 663706f2543Smrg#define WRAP(a) \ 664706f2543Smrg if (pScreen->a) { \ 665706f2543Smrg s->a = pScreen->a; \ 666706f2543Smrg } else { \ 667706f2543Smrg RL_DEBUG_MSG("null screen fn " #a "\n"); \ 668706f2543Smrg s->a = NULL; \ 669706f2543Smrg } \ 670706f2543Smrg pScreen->a = Rootless##a 671706f2543Smrg 672706f2543Smrg WRAP(CreateScreenResources); 673706f2543Smrg WRAP(CloseScreen); 674706f2543Smrg WRAP(CreateGC); 675706f2543Smrg WRAP(CopyWindow); 676706f2543Smrg WRAP(GetImage); 677706f2543Smrg WRAP(SourceValidate); 678706f2543Smrg WRAP(CreateWindow); 679706f2543Smrg WRAP(DestroyWindow); 680706f2543Smrg WRAP(RealizeWindow); 681706f2543Smrg WRAP(UnrealizeWindow); 682706f2543Smrg WRAP(MoveWindow); 683706f2543Smrg WRAP(PositionWindow); 684706f2543Smrg WRAP(ResizeWindow); 685706f2543Smrg WRAP(RestackWindow); 686706f2543Smrg WRAP(ReparentWindow); 687706f2543Smrg WRAP(ChangeBorderWidth); 688706f2543Smrg WRAP(MarkOverlappedWindows); 689706f2543Smrg WRAP(ValidateTree); 690706f2543Smrg WRAP(ChangeWindowAttributes); 691706f2543Smrg WRAP(InstallColormap); 692706f2543Smrg WRAP(UninstallColormap); 693706f2543Smrg WRAP(StoreColors); 694706f2543Smrg 695706f2543Smrg WRAP(SetShape); 696706f2543Smrg 697706f2543Smrg { 698706f2543Smrg // Composite and Glyphs don't use normal screen wrapping 699706f2543Smrg PictureScreenPtr ps = GetPictureScreen(pScreen); 700706f2543Smrg s->Composite = ps->Composite; 701706f2543Smrg ps->Composite = RootlessComposite; 702706f2543Smrg s->Glyphs = ps->Glyphs; 703706f2543Smrg ps->Glyphs = RootlessGlyphs; 704706f2543Smrg } 705706f2543Smrg 706706f2543Smrg // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? 707706f2543Smrg 708706f2543Smrg#undef WRAP 709706f2543Smrg} 710706f2543Smrg 711706f2543Smrg 712706f2543Smrg/* 713706f2543Smrg * RootlessInit 714706f2543Smrg * Called by the rootless implementation to initialize the rootless layer. 715706f2543Smrg * Rootless wraps lots of stuff and needs a bunch of devPrivates. 716706f2543Smrg */ 717706f2543SmrgBool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) 718706f2543Smrg{ 719706f2543Smrg RootlessScreenRec *s; 720706f2543Smrg 721706f2543Smrg if (!RootlessAllocatePrivates(pScreen)) 722706f2543Smrg return FALSE; 723706f2543Smrg 724706f2543Smrg s = SCREENREC(pScreen); 725706f2543Smrg 726706f2543Smrg s->imp = procs; 727706f2543Smrg s->colormap = NULL; 728706f2543Smrg s->redisplay_expired = FALSE; 729706f2543Smrg 730706f2543Smrg RootlessWrap(pScreen); 731706f2543Smrg 732706f2543Smrg if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, 733706f2543Smrg RootlessWakeupHandler, 734706f2543Smrg (pointer) pScreen)) 735706f2543Smrg { 736706f2543Smrg return FALSE; 737706f2543Smrg } 738706f2543Smrg 739706f2543Smrg return TRUE; 740706f2543Smrg} 741706f2543Smrg 742706f2543Smrgvoid RootlessUpdateRooted (Bool state) { 743706f2543Smrg int i; 744706f2543Smrg 745706f2543Smrg if (!state) 746706f2543Smrg { 747706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) 748706f2543Smrg RootlessDisableRoot (screenInfo.screens[i]); 749706f2543Smrg } 750706f2543Smrg else 751706f2543Smrg { 752706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) 753706f2543Smrg RootlessEnableRoot (screenInfo.screens[i]); 754706f2543Smrg } 755706f2543Smrg} 756