rootlessScreen.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg * Screen routines for generic rootless X server 305b261ecSmrg */ 405b261ecSmrg/* 505b261ecSmrg * Copyright (c) 2001 Greg Parker. All Rights Reserved. 605b261ecSmrg * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. 705b261ecSmrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 805b261ecSmrg * 905b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 1005b261ecSmrg * copy of this software and associated documentation files (the "Software"), 1105b261ecSmrg * to deal in the Software without restriction, including without limitation 1205b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1305b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 1405b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1505b261ecSmrg * 1605b261ecSmrg * The above copyright notice and this permission notice shall be included in 1705b261ecSmrg * all copies or substantial portions of the Software. 1805b261ecSmrg * 1905b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2005b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2105b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2205b261ecSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2305b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2405b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2505b261ecSmrg * DEALINGS IN THE SOFTWARE. 2605b261ecSmrg * 2705b261ecSmrg * Except as contained in this notice, the name(s) of the above copyright 2805b261ecSmrg * holders shall not be used in advertising or otherwise to promote the sale, 2905b261ecSmrg * use or other dealings in this Software without prior written authorization. 3005b261ecSmrg */ 3105b261ecSmrg 3205b261ecSmrg 3305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3405b261ecSmrg#include <dix-config.h> 3505b261ecSmrg#endif 3605b261ecSmrg 3705b261ecSmrg#include "mi.h" 3805b261ecSmrg#include "scrnintstr.h" 3905b261ecSmrg#include "gcstruct.h" 4005b261ecSmrg#include "pixmapstr.h" 4105b261ecSmrg#include "windowstr.h" 4205b261ecSmrg#include "propertyst.h" 4305b261ecSmrg#include "mivalidate.h" 4405b261ecSmrg#include "picturestr.h" 4505b261ecSmrg 4605b261ecSmrg#include <sys/types.h> 4705b261ecSmrg#include <sys/stat.h> 4805b261ecSmrg#include <fcntl.h> 4905b261ecSmrg#include <string.h> 5005b261ecSmrg 5105b261ecSmrg#include "rootlessCommon.h" 5205b261ecSmrg#include "rootlessWindow.h" 5305b261ecSmrg 5405b261ecSmrg/* In milliseconds */ 5505b261ecSmrg#ifndef ROOTLESS_REDISPLAY_DELAY 5605b261ecSmrg#define ROOTLESS_REDISPLAY_DELAY 10 5705b261ecSmrg#endif 5805b261ecSmrg 5905b261ecSmrgextern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, 6005b261ecSmrg VTKind kind); 6105b261ecSmrgextern Bool RootlessCreateGC(GCPtr pGC); 6205b261ecSmrg 6305b261ecSmrg// Initialize globals 6405b261ecSmrgint rootlessGCPrivateIndex = -1; 6505b261ecSmrgint rootlessScreenPrivateIndex = -1; 6605b261ecSmrgint rootlessWindowPrivateIndex = -1; 6705b261ecSmrg 6805b261ecSmrg 6905b261ecSmrg/* 7005b261ecSmrg * RootlessUpdateScreenPixmap 7105b261ecSmrg * miCreateScreenResources does not like a null framebuffer pointer, 7205b261ecSmrg * it leaves the screen pixmap with an uninitialized data pointer. 7305b261ecSmrg * Thus, rootless implementations typically set the framebuffer width 7405b261ecSmrg * to zero so that miCreateScreenResources does not allocate a screen 7505b261ecSmrg * pixmap for us. We allocate our own screen pixmap here since we need 7605b261ecSmrg * the screen pixmap to be valid (e.g. CopyArea from the root window). 7705b261ecSmrg */ 7805b261ecSmrgvoid 7905b261ecSmrgRootlessUpdateScreenPixmap(ScreenPtr pScreen) 8005b261ecSmrg{ 8105b261ecSmrg RootlessScreenRec *s = SCREENREC(pScreen); 8205b261ecSmrg PixmapPtr pPix; 8305b261ecSmrg unsigned int rowbytes; 8405b261ecSmrg 8505b261ecSmrg pPix = (*pScreen->GetScreenPixmap)(pScreen); 8605b261ecSmrg if (pPix == NULL) { 8705b261ecSmrg pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth); 8805b261ecSmrg (*pScreen->SetScreenPixmap)(pPix); 8905b261ecSmrg } 9005b261ecSmrg 9105b261ecSmrg rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); 9205b261ecSmrg 9305b261ecSmrg if (s->pixmap_data_size < rowbytes) { 9405b261ecSmrg if (s->pixmap_data != NULL) 9505b261ecSmrg xfree(s->pixmap_data); 9605b261ecSmrg 9705b261ecSmrg s->pixmap_data_size = rowbytes; 9805b261ecSmrg s->pixmap_data = xalloc(s->pixmap_data_size); 9905b261ecSmrg if (s->pixmap_data == NULL) 10005b261ecSmrg return; 10105b261ecSmrg 10205b261ecSmrg memset(s->pixmap_data, 0xFF, s->pixmap_data_size); 10305b261ecSmrg 10405b261ecSmrg pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height, 10505b261ecSmrg pScreen->rootDepth, 10605b261ecSmrg BitsPerPixel(pScreen->rootDepth), 10705b261ecSmrg 0, s->pixmap_data); 10805b261ecSmrg /* ModifyPixmapHeader ignores zero arguments, so install rowbytes 10905b261ecSmrg by hand. */ 11005b261ecSmrg pPix->devKind = 0; 11105b261ecSmrg } 11205b261ecSmrg} 11305b261ecSmrg 11405b261ecSmrg 11505b261ecSmrg/* 11605b261ecSmrg * RootlessCreateScreenResources 11705b261ecSmrg * Rootless implementations typically set a null framebuffer pointer, which 11805b261ecSmrg * causes problems with miCreateScreenResources. We fix things up here. 11905b261ecSmrg */ 12005b261ecSmrgstatic Bool 12105b261ecSmrgRootlessCreateScreenResources(ScreenPtr pScreen) 12205b261ecSmrg{ 12305b261ecSmrg Bool ret = TRUE; 12405b261ecSmrg 12505b261ecSmrg SCREEN_UNWRAP(pScreen, CreateScreenResources); 12605b261ecSmrg 12705b261ecSmrg if (pScreen->CreateScreenResources != NULL) 12805b261ecSmrg ret = (*pScreen->CreateScreenResources)(pScreen); 12905b261ecSmrg 13005b261ecSmrg SCREEN_WRAP(pScreen, CreateScreenResources); 13105b261ecSmrg 13205b261ecSmrg if (!ret) 13305b261ecSmrg return ret; 13405b261ecSmrg 13505b261ecSmrg /* Make sure we have a valid screen pixmap. */ 13605b261ecSmrg 13705b261ecSmrg RootlessUpdateScreenPixmap(pScreen); 13805b261ecSmrg 13905b261ecSmrg return ret; 14005b261ecSmrg} 14105b261ecSmrg 14205b261ecSmrg 14305b261ecSmrgstatic Bool 14405b261ecSmrgRootlessCloseScreen(int i, ScreenPtr pScreen) 14505b261ecSmrg{ 14605b261ecSmrg RootlessScreenRec *s; 14705b261ecSmrg 14805b261ecSmrg s = SCREENREC(pScreen); 14905b261ecSmrg 15005b261ecSmrg // fixme unwrap everything that was wrapped? 15105b261ecSmrg pScreen->CloseScreen = s->CloseScreen; 15205b261ecSmrg 15305b261ecSmrg if (s->pixmap_data != NULL) { 15405b261ecSmrg xfree (s->pixmap_data); 15505b261ecSmrg s->pixmap_data = NULL; 15605b261ecSmrg s->pixmap_data_size = 0; 15705b261ecSmrg } 15805b261ecSmrg 15905b261ecSmrg xfree(s); 16005b261ecSmrg return pScreen->CloseScreen(i, pScreen); 16105b261ecSmrg} 16205b261ecSmrg 16305b261ecSmrg 16405b261ecSmrgstatic void 16505b261ecSmrgRootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, 16605b261ecSmrg unsigned int format, unsigned long planeMask, char *pdstLine) 16705b261ecSmrg{ 16805b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 16905b261ecSmrg SCREEN_UNWRAP(pScreen, GetImage); 17005b261ecSmrg 17105b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 17205b261ecSmrg int x0, y0, x1, y1; 17305b261ecSmrg RootlessWindowRec *winRec; 17405b261ecSmrg 17505b261ecSmrg // Many apps use GetImage to sync with the visible frame buffer 17605b261ecSmrg // FIXME: entire screen or just window or all screens? 17705b261ecSmrg RootlessRedisplayScreen(pScreen); 17805b261ecSmrg 17905b261ecSmrg // RedisplayScreen stops drawing, so we need to start it again 18005b261ecSmrg RootlessStartDrawing((WindowPtr)pDrawable); 18105b261ecSmrg 18205b261ecSmrg /* Check that we have some place to read from. */ 18305b261ecSmrg winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); 18405b261ecSmrg if (winRec == NULL) 18505b261ecSmrg goto out; 18605b261ecSmrg 18705b261ecSmrg /* Clip to top-level window bounds. */ 18805b261ecSmrg /* FIXME: fbGetImage uses the width parameter to calculate the 18905b261ecSmrg stride of the destination pixmap. If w is clipped, the data 19005b261ecSmrg returned will be garbage, although we will not crash. */ 19105b261ecSmrg 19205b261ecSmrg x0 = pDrawable->x + sx; 19305b261ecSmrg y0 = pDrawable->y + sy; 19405b261ecSmrg x1 = x0 + w; 19505b261ecSmrg y1 = y0 + h; 19605b261ecSmrg 19705b261ecSmrg x0 = MAX (x0, winRec->x); 19805b261ecSmrg y0 = MAX (y0, winRec->y); 19905b261ecSmrg x1 = MIN (x1, winRec->x + winRec->width); 20005b261ecSmrg y1 = MIN (y1, winRec->y + winRec->height); 20105b261ecSmrg 20205b261ecSmrg sx = x0 - pDrawable->x; 20305b261ecSmrg sy = y0 - pDrawable->y; 20405b261ecSmrg w = x1 - x0; 20505b261ecSmrg h = y1 - y0; 20605b261ecSmrg 20705b261ecSmrg if (w <= 0 || h <= 0) 20805b261ecSmrg goto out; 20905b261ecSmrg } 21005b261ecSmrg 21105b261ecSmrg pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); 21205b261ecSmrg 21305b261ecSmrgout: 21405b261ecSmrg SCREEN_WRAP(pScreen, GetImage); 21505b261ecSmrg} 21605b261ecSmrg 21705b261ecSmrg 21805b261ecSmrg/* 21905b261ecSmrg * RootlessSourceValidate 22005b261ecSmrg * CopyArea and CopyPlane use a GC tied to the destination drawable. 22105b261ecSmrg * StartDrawing/StopDrawing wrappers won't be called if source is 22205b261ecSmrg * a visible window but the destination isn't. So, we call StartDrawing 22305b261ecSmrg * here and leave StopDrawing for the block handler. 22405b261ecSmrg */ 22505b261ecSmrgstatic void 22605b261ecSmrgRootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h) 22705b261ecSmrg{ 22805b261ecSmrg SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); 22905b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 23005b261ecSmrg WindowPtr pWin = (WindowPtr)pDrawable; 23105b261ecSmrg RootlessStartDrawing(pWin); 23205b261ecSmrg } 23305b261ecSmrg if (pDrawable->pScreen->SourceValidate) { 23405b261ecSmrg pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h); 23505b261ecSmrg } 23605b261ecSmrg SCREEN_WRAP(pDrawable->pScreen, SourceValidate); 23705b261ecSmrg} 23805b261ecSmrg 23905b261ecSmrg#ifdef RENDER 24005b261ecSmrg 24105b261ecSmrgstatic void 24205b261ecSmrgRootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 24305b261ecSmrg INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, 24405b261ecSmrg INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 24505b261ecSmrg{ 24605b261ecSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 24705b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 24805b261ecSmrg WindowPtr srcWin, dstWin, maskWin = NULL; 24905b261ecSmrg 25005b261ecSmrg if (pMask) { // pMask can be NULL 25105b261ecSmrg maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ? 25205b261ecSmrg (WindowPtr)pMask->pDrawable : NULL; 25305b261ecSmrg } 25405b261ecSmrg srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 25505b261ecSmrg (WindowPtr)pSrc->pDrawable : NULL; 25605b261ecSmrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 25705b261ecSmrg (WindowPtr)pDst->pDrawable : NULL; 25805b261ecSmrg 25905b261ecSmrg // SCREEN_UNWRAP(ps, Composite); 26005b261ecSmrg ps->Composite = SCREENREC(pScreen)->Composite; 26105b261ecSmrg 26205b261ecSmrg if (srcWin && IsFramedWindow(srcWin)) 26305b261ecSmrg RootlessStartDrawing(srcWin); 26405b261ecSmrg if (maskWin && IsFramedWindow(maskWin)) 26505b261ecSmrg RootlessStartDrawing(maskWin); 26605b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) 26705b261ecSmrg RootlessStartDrawing(dstWin); 26805b261ecSmrg 26905b261ecSmrg ps->Composite(op, pSrc, pMask, pDst, 27005b261ecSmrg xSrc, ySrc, xMask, yMask, 27105b261ecSmrg xDst, yDst, width, height); 27205b261ecSmrg 27305b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) { 27405b261ecSmrg RootlessDamageRect(dstWin, xDst, yDst, width, height); 27505b261ecSmrg } 27605b261ecSmrg 27705b261ecSmrg ps->Composite = RootlessComposite; 27805b261ecSmrg // SCREEN_WRAP(ps, Composite); 27905b261ecSmrg} 28005b261ecSmrg 28105b261ecSmrg 28205b261ecSmrgstatic void 28305b261ecSmrgRootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 28405b261ecSmrg PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 28505b261ecSmrg int nlist, GlyphListPtr list, GlyphPtr *glyphs) 28605b261ecSmrg{ 28705b261ecSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 28805b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 28905b261ecSmrg int x, y; 29005b261ecSmrg int n; 29105b261ecSmrg GlyphPtr glyph; 29205b261ecSmrg WindowPtr srcWin, dstWin; 29305b261ecSmrg 29405b261ecSmrg srcWin = (pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 29505b261ecSmrg (WindowPtr)pSrc->pDrawable : NULL; 29605b261ecSmrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 29705b261ecSmrg (WindowPtr)pDst->pDrawable : NULL; 29805b261ecSmrg 29905b261ecSmrg if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); 30005b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); 30105b261ecSmrg 30205b261ecSmrg //SCREEN_UNWRAP(ps, Glyphs); 30305b261ecSmrg ps->Glyphs = SCREENREC(pScreen)->Glyphs; 30405b261ecSmrg ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); 30505b261ecSmrg ps->Glyphs = RootlessGlyphs; 30605b261ecSmrg //SCREEN_WRAP(ps, Glyphs); 30705b261ecSmrg 30805b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) { 30905b261ecSmrg x = xSrc; 31005b261ecSmrg y = ySrc; 31105b261ecSmrg 31205b261ecSmrg while (nlist--) { 31305b261ecSmrg x += list->xOff; 31405b261ecSmrg y += list->yOff; 31505b261ecSmrg n = list->len; 31605b261ecSmrg 31705b261ecSmrg /* Calling DamageRect for the bounding box of each glyph is 31805b261ecSmrg inefficient. So compute the union of all glyphs in a list 31905b261ecSmrg and damage that. */ 32005b261ecSmrg 32105b261ecSmrg if (n > 0) { 32205b261ecSmrg BoxRec box; 32305b261ecSmrg 32405b261ecSmrg glyph = *glyphs++; 32505b261ecSmrg 32605b261ecSmrg box.x1 = x - glyph->info.x; 32705b261ecSmrg box.y1 = y - glyph->info.y; 32805b261ecSmrg box.x2 = box.x1 + glyph->info.width; 32905b261ecSmrg box.y2 = box.y2 + glyph->info.height; 33005b261ecSmrg 33105b261ecSmrg x += glyph->info.xOff; 33205b261ecSmrg y += glyph->info.yOff; 33305b261ecSmrg 33405b261ecSmrg while (--n > 0) { 33505b261ecSmrg short x1, y1, x2, y2; 33605b261ecSmrg 33705b261ecSmrg glyph = *glyphs++; 33805b261ecSmrg 33905b261ecSmrg x1 = x - glyph->info.x; 34005b261ecSmrg y1 = y - glyph->info.y; 34105b261ecSmrg x2 = x1 + glyph->info.width; 34205b261ecSmrg y2 = y1 + glyph->info.height; 34305b261ecSmrg 34405b261ecSmrg box.x1 = MAX (box.x1, x1); 34505b261ecSmrg box.y1 = MAX (box.y1, y1); 34605b261ecSmrg box.x2 = MAX (box.x2, x2); 34705b261ecSmrg box.y2 = MAX (box.y2, y2); 34805b261ecSmrg 34905b261ecSmrg x += glyph->info.xOff; 35005b261ecSmrg y += glyph->info.yOff; 35105b261ecSmrg } 35205b261ecSmrg 35305b261ecSmrg RootlessDamageBox(dstWin, &box); 35405b261ecSmrg } 35505b261ecSmrg list++; 35605b261ecSmrg } 35705b261ecSmrg } 35805b261ecSmrg} 35905b261ecSmrg 36005b261ecSmrg#endif // RENDER 36105b261ecSmrg 36205b261ecSmrg 36305b261ecSmrg/* 36405b261ecSmrg * RootlessValidateTree 36505b261ecSmrg * ValidateTree is modified in two ways: 36605b261ecSmrg * - top-level windows don't clip each other 36705b261ecSmrg * - windows aren't clipped against root. 36805b261ecSmrg * These only matter when validating from the root. 36905b261ecSmrg */ 37005b261ecSmrgstatic int 37105b261ecSmrgRootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 37205b261ecSmrg{ 37305b261ecSmrg int result; 37405b261ecSmrg RegionRec saveRoot; 37505b261ecSmrg ScreenPtr pScreen = pParent->drawable.pScreen; 37605b261ecSmrg 37705b261ecSmrg SCREEN_UNWRAP(pScreen, ValidateTree); 37805b261ecSmrg RL_DEBUG_MSG("VALIDATETREE start "); 37905b261ecSmrg 38005b261ecSmrg // Use our custom version to validate from root 38105b261ecSmrg if (IsRoot(pParent)) { 38205b261ecSmrg RL_DEBUG_MSG("custom "); 38305b261ecSmrg result = RootlessMiValidateTree(pParent, pChild, kind); 38405b261ecSmrg } else { 38505b261ecSmrg HUGE_ROOT(pParent); 38605b261ecSmrg result = pScreen->ValidateTree(pParent, pChild, kind); 38705b261ecSmrg NORMAL_ROOT(pParent); 38805b261ecSmrg } 38905b261ecSmrg 39005b261ecSmrg SCREEN_WRAP(pScreen, ValidateTree); 39105b261ecSmrg RL_DEBUG_MSG("VALIDATETREE end\n"); 39205b261ecSmrg 39305b261ecSmrg return result; 39405b261ecSmrg} 39505b261ecSmrg 39605b261ecSmrg 39705b261ecSmrg/* 39805b261ecSmrg * RootlessMarkOverlappedWindows 39905b261ecSmrg * MarkOverlappedWindows is modified to ignore overlapping 40005b261ecSmrg * top-level windows. 40105b261ecSmrg */ 40205b261ecSmrgstatic Bool 40305b261ecSmrgRootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, 40405b261ecSmrg WindowPtr *ppLayerWin) 40505b261ecSmrg{ 40605b261ecSmrg RegionRec saveRoot; 40705b261ecSmrg Bool result; 40805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 40905b261ecSmrg SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); 41005b261ecSmrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); 41105b261ecSmrg 41205b261ecSmrg HUGE_ROOT(pWin); 41305b261ecSmrg if (IsRoot(pWin)) { 41405b261ecSmrg // root - mark nothing 41505b261ecSmrg RL_DEBUG_MSG("is root not marking "); 41605b261ecSmrg result = FALSE; 41705b261ecSmrg } 41805b261ecSmrg else if (! IsTopLevel(pWin)) { 41905b261ecSmrg // not top-level window - mark normally 42005b261ecSmrg result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); 42105b261ecSmrg } 42205b261ecSmrg else { 42305b261ecSmrg //top-level window - mark children ONLY - NO overlaps with sibs (?) 42405b261ecSmrg // This code copied from miMarkOverlappedWindows() 42505b261ecSmrg 42605b261ecSmrg register WindowPtr pChild; 42705b261ecSmrg Bool anyMarked = FALSE; 42805b261ecSmrg void (* MarkWindow)() = pScreen->MarkWindow; 42905b261ecSmrg 43005b261ecSmrg RL_DEBUG_MSG("is top level! "); 43105b261ecSmrg /* single layered systems are easy */ 43205b261ecSmrg if (ppLayerWin) *ppLayerWin = pWin; 43305b261ecSmrg 43405b261ecSmrg if (pWin == pFirst) { 43505b261ecSmrg /* Blindly mark pWin and all of its inferiors. This is a slight 43605b261ecSmrg * overkill if there are mapped windows that outside pWin's border, 43705b261ecSmrg * but it's better than wasting time on RectIn checks. 43805b261ecSmrg */ 43905b261ecSmrg pChild = pWin; 44005b261ecSmrg while (1) { 44105b261ecSmrg if (pChild->viewable) { 44205b261ecSmrg if (REGION_BROKEN (pScreen, &pChild->winSize)) 44305b261ecSmrg SetWinSize (pChild); 44405b261ecSmrg if (REGION_BROKEN (pScreen, &pChild->borderSize)) 44505b261ecSmrg SetBorderSize (pChild); 44605b261ecSmrg (* MarkWindow)(pChild); 44705b261ecSmrg if (pChild->firstChild) { 44805b261ecSmrg pChild = pChild->firstChild; 44905b261ecSmrg continue; 45005b261ecSmrg } 45105b261ecSmrg } 45205b261ecSmrg while (!pChild->nextSib && (pChild != pWin)) 45305b261ecSmrg pChild = pChild->parent; 45405b261ecSmrg if (pChild == pWin) 45505b261ecSmrg break; 45605b261ecSmrg pChild = pChild->nextSib; 45705b261ecSmrg } 45805b261ecSmrg anyMarked = TRUE; 45905b261ecSmrg pFirst = pFirst->nextSib; 46005b261ecSmrg } 46105b261ecSmrg if (anyMarked) 46205b261ecSmrg (* MarkWindow)(pWin->parent); 46305b261ecSmrg result = anyMarked; 46405b261ecSmrg } 46505b261ecSmrg NORMAL_ROOT(pWin); 46605b261ecSmrg SCREEN_WRAP(pScreen, MarkOverlappedWindows); 46705b261ecSmrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); 46805b261ecSmrg 46905b261ecSmrg return result; 47005b261ecSmrg} 47105b261ecSmrg 47205b261ecSmrg 47305b261ecSmrgstatic CARD32 47405b261ecSmrgRootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) 47505b261ecSmrg{ 47605b261ecSmrg RootlessScreenRec *screenRec = arg; 47705b261ecSmrg 47805b261ecSmrg if (!screenRec->redisplay_queued) { 47905b261ecSmrg /* No update needed. Stop the timer. */ 48005b261ecSmrg 48105b261ecSmrg screenRec->redisplay_timer_set = FALSE; 48205b261ecSmrg return 0; 48305b261ecSmrg } 48405b261ecSmrg 48505b261ecSmrg screenRec->redisplay_queued = FALSE; 48605b261ecSmrg 48705b261ecSmrg /* Mark that we should redisplay before waiting for I/O next time */ 48805b261ecSmrg screenRec->redisplay_expired = TRUE; 48905b261ecSmrg 49005b261ecSmrg /* Reinstall the timer immediately, so we get as close to our 49105b261ecSmrg redisplay interval as possible. */ 49205b261ecSmrg 49305b261ecSmrg return ROOTLESS_REDISPLAY_DELAY; 49405b261ecSmrg} 49505b261ecSmrg 49605b261ecSmrg 49705b261ecSmrg/* 49805b261ecSmrg * RootlessQueueRedisplay 49905b261ecSmrg * Queue a redisplay after a timer delay to ensure we do not redisplay 50005b261ecSmrg * too frequently. 50105b261ecSmrg */ 50205b261ecSmrgvoid 50305b261ecSmrgRootlessQueueRedisplay(ScreenPtr pScreen) 50405b261ecSmrg{ 50505b261ecSmrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 50605b261ecSmrg 50705b261ecSmrg screenRec->redisplay_queued = TRUE; 50805b261ecSmrg 50905b261ecSmrg if (screenRec->redisplay_timer_set) 51005b261ecSmrg return; 51105b261ecSmrg 51205b261ecSmrg screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, 51305b261ecSmrg 0, ROOTLESS_REDISPLAY_DELAY, 51405b261ecSmrg RootlessRedisplayCallback, 51505b261ecSmrg screenRec); 51605b261ecSmrg screenRec->redisplay_timer_set = TRUE; 51705b261ecSmrg} 51805b261ecSmrg 51905b261ecSmrg 52005b261ecSmrg/* 52105b261ecSmrg * RootlessBlockHandler 52205b261ecSmrg * If the redisplay timer has expired, flush drawing before blocking 52305b261ecSmrg * on select(). 52405b261ecSmrg */ 52505b261ecSmrgstatic void 52605b261ecSmrgRootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) 52705b261ecSmrg{ 52805b261ecSmrg ScreenPtr pScreen = pbdata; 52905b261ecSmrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 53005b261ecSmrg 53105b261ecSmrg if (screenRec->redisplay_expired) { 53205b261ecSmrg screenRec->redisplay_expired = FALSE; 53305b261ecSmrg 53405b261ecSmrg RootlessRedisplayScreen(pScreen); 53505b261ecSmrg } 53605b261ecSmrg} 53705b261ecSmrg 53805b261ecSmrg 53905b261ecSmrgstatic void 54005b261ecSmrgRootlessWakeupHandler(pointer data, int i, pointer LastSelectMask) 54105b261ecSmrg{ 54205b261ecSmrg // nothing here 54305b261ecSmrg} 54405b261ecSmrg 54505b261ecSmrg 54605b261ecSmrgstatic Bool 54705b261ecSmrgRootlessAllocatePrivates(ScreenPtr pScreen) 54805b261ecSmrg{ 54905b261ecSmrg RootlessScreenRec *s; 55005b261ecSmrg static unsigned long rootlessGeneration = 0; 55105b261ecSmrg 55205b261ecSmrg if (rootlessGeneration != serverGeneration) { 55305b261ecSmrg rootlessScreenPrivateIndex = AllocateScreenPrivateIndex(); 55405b261ecSmrg if (rootlessScreenPrivateIndex == -1) return FALSE; 55505b261ecSmrg rootlessGCPrivateIndex = AllocateGCPrivateIndex(); 55605b261ecSmrg if (rootlessGCPrivateIndex == -1) return FALSE; 55705b261ecSmrg rootlessWindowPrivateIndex = AllocateWindowPrivateIndex(); 55805b261ecSmrg if (rootlessWindowPrivateIndex == -1) return FALSE; 55905b261ecSmrg rootlessGeneration = serverGeneration; 56005b261ecSmrg } 56105b261ecSmrg 56205b261ecSmrg // no allocation needed for screen privates 56305b261ecSmrg if (!AllocateGCPrivate(pScreen, rootlessGCPrivateIndex, 56405b261ecSmrg sizeof(RootlessGCRec))) 56505b261ecSmrg return FALSE; 56605b261ecSmrg if (!AllocateWindowPrivate(pScreen, rootlessWindowPrivateIndex, 0)) 56705b261ecSmrg return FALSE; 56805b261ecSmrg 56905b261ecSmrg s = xalloc(sizeof(RootlessScreenRec)); 57005b261ecSmrg if (! s) return FALSE; 57105b261ecSmrg SCREENREC(pScreen) = s; 57205b261ecSmrg 57305b261ecSmrg s->pixmap_data = NULL; 57405b261ecSmrg s->pixmap_data_size = 0; 57505b261ecSmrg 57605b261ecSmrg s->redisplay_timer = NULL; 57705b261ecSmrg s->redisplay_timer_set = FALSE; 57805b261ecSmrg 57905b261ecSmrg return TRUE; 58005b261ecSmrg} 58105b261ecSmrg 58205b261ecSmrg 58305b261ecSmrgstatic void 58405b261ecSmrgRootlessWrap(ScreenPtr pScreen) 58505b261ecSmrg{ 58605b261ecSmrg RootlessScreenRec *s = (RootlessScreenRec*) 58705b261ecSmrg pScreen->devPrivates[rootlessScreenPrivateIndex].ptr; 58805b261ecSmrg 58905b261ecSmrg#define WRAP(a) \ 59005b261ecSmrg if (pScreen->a) { \ 59105b261ecSmrg s->a = pScreen->a; \ 59205b261ecSmrg } else { \ 59305b261ecSmrg RL_DEBUG_MSG("null screen fn " #a "\n"); \ 59405b261ecSmrg s->a = NULL; \ 59505b261ecSmrg } \ 59605b261ecSmrg pScreen->a = Rootless##a 59705b261ecSmrg 59805b261ecSmrg WRAP(CreateScreenResources); 59905b261ecSmrg WRAP(CloseScreen); 60005b261ecSmrg WRAP(CreateGC); 60105b261ecSmrg WRAP(PaintWindowBackground); 60205b261ecSmrg WRAP(PaintWindowBorder); 60305b261ecSmrg WRAP(CopyWindow); 60405b261ecSmrg WRAP(GetImage); 60505b261ecSmrg WRAP(SourceValidate); 60605b261ecSmrg WRAP(CreateWindow); 60705b261ecSmrg WRAP(DestroyWindow); 60805b261ecSmrg WRAP(RealizeWindow); 60905b261ecSmrg WRAP(UnrealizeWindow); 61005b261ecSmrg WRAP(MoveWindow); 61105b261ecSmrg WRAP(PositionWindow); 61205b261ecSmrg WRAP(ResizeWindow); 61305b261ecSmrg WRAP(RestackWindow); 61405b261ecSmrg WRAP(ReparentWindow); 61505b261ecSmrg WRAP(ChangeBorderWidth); 61605b261ecSmrg WRAP(MarkOverlappedWindows); 61705b261ecSmrg WRAP(ValidateTree); 61805b261ecSmrg WRAP(ChangeWindowAttributes); 61905b261ecSmrg 62005b261ecSmrg#ifdef SHAPE 62105b261ecSmrg WRAP(SetShape); 62205b261ecSmrg#endif 62305b261ecSmrg 62405b261ecSmrg#ifdef RENDER 62505b261ecSmrg { 62605b261ecSmrg // Composite and Glyphs don't use normal screen wrapping 62705b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 62805b261ecSmrg s->Composite = ps->Composite; 62905b261ecSmrg ps->Composite = RootlessComposite; 63005b261ecSmrg s->Glyphs = ps->Glyphs; 63105b261ecSmrg ps->Glyphs = RootlessGlyphs; 63205b261ecSmrg } 63305b261ecSmrg#endif 63405b261ecSmrg 63505b261ecSmrg // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? 63605b261ecSmrg // WRAP(RestoreAreas); fixme put this back? 63705b261ecSmrg 63805b261ecSmrg#undef WRAP 63905b261ecSmrg} 64005b261ecSmrg 64105b261ecSmrg 64205b261ecSmrg/* 64305b261ecSmrg * RootlessInit 64405b261ecSmrg * Called by the rootless implementation to initialize the rootless layer. 64505b261ecSmrg * Rootless wraps lots of stuff and needs a bunch of devPrivates. 64605b261ecSmrg */ 64705b261ecSmrgBool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) 64805b261ecSmrg{ 64905b261ecSmrg RootlessScreenRec *s; 65005b261ecSmrg 65105b261ecSmrg if (!RootlessAllocatePrivates(pScreen)) 65205b261ecSmrg return FALSE; 65305b261ecSmrg 65405b261ecSmrg s = (RootlessScreenRec*) 65505b261ecSmrg pScreen->devPrivates[rootlessScreenPrivateIndex].ptr; 65605b261ecSmrg 65705b261ecSmrg s->imp = procs; 65805b261ecSmrg 65905b261ecSmrg RootlessWrap(pScreen); 66005b261ecSmrg 66105b261ecSmrg if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, 66205b261ecSmrg RootlessWakeupHandler, 66305b261ecSmrg (pointer) pScreen)) 66405b261ecSmrg { 66505b261ecSmrg return FALSE; 66605b261ecSmrg } 66705b261ecSmrg 66805b261ecSmrg return TRUE; 66905b261ecSmrg} 670