rootlessScreen.c revision 9ace9065
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" 454642e01fSmrg#include "colormapst.h" 4605b261ecSmrg 4705b261ecSmrg#include <sys/types.h> 4805b261ecSmrg#include <sys/stat.h> 4905b261ecSmrg#include <fcntl.h> 5005b261ecSmrg#include <string.h> 5105b261ecSmrg 5205b261ecSmrg#include "rootlessCommon.h" 5305b261ecSmrg#include "rootlessWindow.h" 5405b261ecSmrg 5505b261ecSmrg/* In milliseconds */ 5605b261ecSmrg#ifndef ROOTLESS_REDISPLAY_DELAY 5705b261ecSmrg#define ROOTLESS_REDISPLAY_DELAY 10 5805b261ecSmrg#endif 5905b261ecSmrg 6005b261ecSmrgextern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, 6105b261ecSmrg VTKind kind); 6205b261ecSmrgextern Bool RootlessCreateGC(GCPtr pGC); 6305b261ecSmrg 6405b261ecSmrg// Initialize globals 656747b715SmrgDevPrivateKeyRec rootlessGCPrivateKeyRec; 666747b715SmrgDevPrivateKeyRec rootlessScreenPrivateKeyRec; 676747b715SmrgDevPrivateKeyRec rootlessWindowPrivateKeyRec; 686747b715SmrgDevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec; 6905b261ecSmrg 7005b261ecSmrg/* 7105b261ecSmrg * RootlessUpdateScreenPixmap 7205b261ecSmrg * miCreateScreenResources does not like a null framebuffer pointer, 7305b261ecSmrg * it leaves the screen pixmap with an uninitialized data pointer. 7405b261ecSmrg * Thus, rootless implementations typically set the framebuffer width 7505b261ecSmrg * to zero so that miCreateScreenResources does not allocate a screen 7605b261ecSmrg * pixmap for us. We allocate our own screen pixmap here since we need 7705b261ecSmrg * the screen pixmap to be valid (e.g. CopyArea from the root window). 7805b261ecSmrg */ 7905b261ecSmrgvoid 8005b261ecSmrgRootlessUpdateScreenPixmap(ScreenPtr pScreen) 8105b261ecSmrg{ 8205b261ecSmrg RootlessScreenRec *s = SCREENREC(pScreen); 8305b261ecSmrg PixmapPtr pPix; 8405b261ecSmrg unsigned int rowbytes; 8505b261ecSmrg 8605b261ecSmrg pPix = (*pScreen->GetScreenPixmap)(pScreen); 8705b261ecSmrg if (pPix == NULL) { 884642e01fSmrg pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); 8905b261ecSmrg (*pScreen->SetScreenPixmap)(pPix); 9005b261ecSmrg } 9105b261ecSmrg 9205b261ecSmrg rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); 9305b261ecSmrg 9405b261ecSmrg if (s->pixmap_data_size < rowbytes) { 959ace9065Smrg free(s->pixmap_data); 9605b261ecSmrg 9705b261ecSmrg s->pixmap_data_size = rowbytes; 986747b715Smrg s->pixmap_data = malloc(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) { 1546747b715Smrg free(s->pixmap_data); 15505b261ecSmrg s->pixmap_data = NULL; 15605b261ecSmrg s->pixmap_data_size = 0; 15705b261ecSmrg } 15805b261ecSmrg 1596747b715Smrg free(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 1976747b715Smrg x0 = max (x0, winRec->x); 1986747b715Smrg y0 = max (y0, winRec->y); 1996747b715Smrg x1 = min (x1, winRec->x + winRec->width); 2006747b715Smrg 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 2269ace9065SmrgRootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h, 2279ace9065Smrg unsigned int subWindowMode) 22805b261ecSmrg{ 22905b261ecSmrg SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); 23005b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 23105b261ecSmrg WindowPtr pWin = (WindowPtr)pDrawable; 23205b261ecSmrg RootlessStartDrawing(pWin); 23305b261ecSmrg } 23405b261ecSmrg if (pDrawable->pScreen->SourceValidate) { 2359ace9065Smrg pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, subWindowMode); 23605b261ecSmrg } 23705b261ecSmrg SCREEN_WRAP(pDrawable->pScreen, SourceValidate); 23805b261ecSmrg} 23905b261ecSmrg 24005b261ecSmrgstatic void 24105b261ecSmrgRootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 24205b261ecSmrg INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, 24305b261ecSmrg INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 24405b261ecSmrg{ 24505b261ecSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 24605b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 24705b261ecSmrg WindowPtr srcWin, dstWin, maskWin = NULL; 24805b261ecSmrg 24905b261ecSmrg if (pMask) { // pMask can be NULL 25005b261ecSmrg maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ? 25105b261ecSmrg (WindowPtr)pMask->pDrawable : NULL; 25205b261ecSmrg } 2536747b715Smrg srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 25405b261ecSmrg (WindowPtr)pSrc->pDrawable : NULL; 25505b261ecSmrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 25605b261ecSmrg (WindowPtr)pDst->pDrawable : NULL; 25705b261ecSmrg 25805b261ecSmrg // SCREEN_UNWRAP(ps, Composite); 25905b261ecSmrg ps->Composite = SCREENREC(pScreen)->Composite; 26005b261ecSmrg 26105b261ecSmrg if (srcWin && IsFramedWindow(srcWin)) 26205b261ecSmrg RootlessStartDrawing(srcWin); 26305b261ecSmrg if (maskWin && IsFramedWindow(maskWin)) 26405b261ecSmrg RootlessStartDrawing(maskWin); 26505b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) 26605b261ecSmrg RootlessStartDrawing(dstWin); 26705b261ecSmrg 26805b261ecSmrg ps->Composite(op, pSrc, pMask, pDst, 26905b261ecSmrg xSrc, ySrc, xMask, yMask, 27005b261ecSmrg xDst, yDst, width, height); 27105b261ecSmrg 27205b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) { 27305b261ecSmrg RootlessDamageRect(dstWin, xDst, yDst, width, height); 27405b261ecSmrg } 27505b261ecSmrg 27605b261ecSmrg ps->Composite = RootlessComposite; 27705b261ecSmrg // SCREEN_WRAP(ps, Composite); 27805b261ecSmrg} 27905b261ecSmrg 28005b261ecSmrg 28105b261ecSmrgstatic void 28205b261ecSmrgRootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 28305b261ecSmrg PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 28405b261ecSmrg int nlist, GlyphListPtr list, GlyphPtr *glyphs) 28505b261ecSmrg{ 28605b261ecSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 28705b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 28805b261ecSmrg int x, y; 28905b261ecSmrg int n; 29005b261ecSmrg GlyphPtr glyph; 29105b261ecSmrg WindowPtr srcWin, dstWin; 29205b261ecSmrg 2936747b715Smrg srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 29405b261ecSmrg (WindowPtr)pSrc->pDrawable : NULL; 29505b261ecSmrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 29605b261ecSmrg (WindowPtr)pDst->pDrawable : NULL; 29705b261ecSmrg 29805b261ecSmrg if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); 29905b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); 30005b261ecSmrg 30105b261ecSmrg //SCREEN_UNWRAP(ps, Glyphs); 30205b261ecSmrg ps->Glyphs = SCREENREC(pScreen)->Glyphs; 30305b261ecSmrg ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); 30405b261ecSmrg ps->Glyphs = RootlessGlyphs; 30505b261ecSmrg //SCREEN_WRAP(ps, Glyphs); 30605b261ecSmrg 30705b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) { 30805b261ecSmrg x = xSrc; 30905b261ecSmrg y = ySrc; 31005b261ecSmrg 31105b261ecSmrg while (nlist--) { 31205b261ecSmrg x += list->xOff; 31305b261ecSmrg y += list->yOff; 31405b261ecSmrg n = list->len; 31505b261ecSmrg 31605b261ecSmrg /* Calling DamageRect for the bounding box of each glyph is 31705b261ecSmrg inefficient. So compute the union of all glyphs in a list 31805b261ecSmrg and damage that. */ 31905b261ecSmrg 32005b261ecSmrg if (n > 0) { 32105b261ecSmrg BoxRec box; 32205b261ecSmrg 32305b261ecSmrg glyph = *glyphs++; 32405b261ecSmrg 32505b261ecSmrg box.x1 = x - glyph->info.x; 32605b261ecSmrg box.y1 = y - glyph->info.y; 32705b261ecSmrg box.x2 = box.x1 + glyph->info.width; 3289ace9065Smrg box.y2 = box.y1 + glyph->info.height; 32905b261ecSmrg 33005b261ecSmrg x += glyph->info.xOff; 33105b261ecSmrg y += glyph->info.yOff; 33205b261ecSmrg 33305b261ecSmrg while (--n > 0) { 33405b261ecSmrg short x1, y1, x2, y2; 33505b261ecSmrg 33605b261ecSmrg glyph = *glyphs++; 33705b261ecSmrg 33805b261ecSmrg x1 = x - glyph->info.x; 33905b261ecSmrg y1 = y - glyph->info.y; 34005b261ecSmrg x2 = x1 + glyph->info.width; 34105b261ecSmrg y2 = y1 + glyph->info.height; 34205b261ecSmrg 3436747b715Smrg box.x1 = max (box.x1, x1); 3446747b715Smrg box.y1 = max (box.y1, y1); 3456747b715Smrg box.x2 = max (box.x2, x2); 3466747b715Smrg box.y2 = max (box.y2, y2); 34705b261ecSmrg 34805b261ecSmrg x += glyph->info.xOff; 34905b261ecSmrg y += glyph->info.yOff; 35005b261ecSmrg } 35105b261ecSmrg 35205b261ecSmrg RootlessDamageBox(dstWin, &box); 35305b261ecSmrg } 35405b261ecSmrg list++; 35505b261ecSmrg } 35605b261ecSmrg } 35705b261ecSmrg} 35805b261ecSmrg 35905b261ecSmrg 36005b261ecSmrg/* 36105b261ecSmrg * RootlessValidateTree 36205b261ecSmrg * ValidateTree is modified in two ways: 36305b261ecSmrg * - top-level windows don't clip each other 36405b261ecSmrg * - windows aren't clipped against root. 36505b261ecSmrg * These only matter when validating from the root. 36605b261ecSmrg */ 36705b261ecSmrgstatic int 36805b261ecSmrgRootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 36905b261ecSmrg{ 37005b261ecSmrg int result; 37105b261ecSmrg RegionRec saveRoot; 37205b261ecSmrg ScreenPtr pScreen = pParent->drawable.pScreen; 37305b261ecSmrg 37405b261ecSmrg SCREEN_UNWRAP(pScreen, ValidateTree); 37505b261ecSmrg RL_DEBUG_MSG("VALIDATETREE start "); 37605b261ecSmrg 37705b261ecSmrg // Use our custom version to validate from root 37805b261ecSmrg if (IsRoot(pParent)) { 37905b261ecSmrg RL_DEBUG_MSG("custom "); 38005b261ecSmrg result = RootlessMiValidateTree(pParent, pChild, kind); 38105b261ecSmrg } else { 38205b261ecSmrg HUGE_ROOT(pParent); 38305b261ecSmrg result = pScreen->ValidateTree(pParent, pChild, kind); 38405b261ecSmrg NORMAL_ROOT(pParent); 38505b261ecSmrg } 38605b261ecSmrg 38705b261ecSmrg SCREEN_WRAP(pScreen, ValidateTree); 38805b261ecSmrg RL_DEBUG_MSG("VALIDATETREE end\n"); 38905b261ecSmrg 39005b261ecSmrg return result; 39105b261ecSmrg} 39205b261ecSmrg 39305b261ecSmrg 39405b261ecSmrg/* 39505b261ecSmrg * RootlessMarkOverlappedWindows 39605b261ecSmrg * MarkOverlappedWindows is modified to ignore overlapping 39705b261ecSmrg * top-level windows. 39805b261ecSmrg */ 39905b261ecSmrgstatic Bool 40005b261ecSmrgRootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, 40105b261ecSmrg WindowPtr *ppLayerWin) 40205b261ecSmrg{ 40305b261ecSmrg RegionRec saveRoot; 40405b261ecSmrg Bool result; 40505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 40605b261ecSmrg SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); 40705b261ecSmrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); 40805b261ecSmrg 40905b261ecSmrg HUGE_ROOT(pWin); 41005b261ecSmrg if (IsRoot(pWin)) { 41105b261ecSmrg // root - mark nothing 41205b261ecSmrg RL_DEBUG_MSG("is root not marking "); 41305b261ecSmrg result = FALSE; 41405b261ecSmrg } 41505b261ecSmrg else if (! IsTopLevel(pWin)) { 41605b261ecSmrg // not top-level window - mark normally 41705b261ecSmrg result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); 41805b261ecSmrg } 41905b261ecSmrg else { 42005b261ecSmrg //top-level window - mark children ONLY - NO overlaps with sibs (?) 42105b261ecSmrg // This code copied from miMarkOverlappedWindows() 42205b261ecSmrg 42305b261ecSmrg register WindowPtr pChild; 42405b261ecSmrg Bool anyMarked = FALSE; 4256747b715Smrg MarkWindowProcPtr MarkWindow = pScreen->MarkWindow; 42605b261ecSmrg 42705b261ecSmrg RL_DEBUG_MSG("is top level! "); 42805b261ecSmrg /* single layered systems are easy */ 42905b261ecSmrg if (ppLayerWin) *ppLayerWin = pWin; 43005b261ecSmrg 43105b261ecSmrg if (pWin == pFirst) { 43205b261ecSmrg /* Blindly mark pWin and all of its inferiors. This is a slight 43305b261ecSmrg * overkill if there are mapped windows that outside pWin's border, 43405b261ecSmrg * but it's better than wasting time on RectIn checks. 43505b261ecSmrg */ 43605b261ecSmrg pChild = pWin; 43705b261ecSmrg while (1) { 43805b261ecSmrg if (pChild->viewable) { 4396747b715Smrg if (RegionBroken(&pChild->winSize)) 44005b261ecSmrg SetWinSize (pChild); 4416747b715Smrg if (RegionBroken(&pChild->borderSize)) 44205b261ecSmrg SetBorderSize (pChild); 44305b261ecSmrg (* MarkWindow)(pChild); 44405b261ecSmrg if (pChild->firstChild) { 44505b261ecSmrg pChild = pChild->firstChild; 44605b261ecSmrg continue; 44705b261ecSmrg } 44805b261ecSmrg } 44905b261ecSmrg while (!pChild->nextSib && (pChild != pWin)) 45005b261ecSmrg pChild = pChild->parent; 45105b261ecSmrg if (pChild == pWin) 45205b261ecSmrg break; 45305b261ecSmrg pChild = pChild->nextSib; 45405b261ecSmrg } 45505b261ecSmrg anyMarked = TRUE; 45605b261ecSmrg pFirst = pFirst->nextSib; 45705b261ecSmrg } 45805b261ecSmrg if (anyMarked) 45905b261ecSmrg (* MarkWindow)(pWin->parent); 46005b261ecSmrg result = anyMarked; 46105b261ecSmrg } 46205b261ecSmrg NORMAL_ROOT(pWin); 46305b261ecSmrg SCREEN_WRAP(pScreen, MarkOverlappedWindows); 46405b261ecSmrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); 46505b261ecSmrg 46605b261ecSmrg return result; 46705b261ecSmrg} 46805b261ecSmrg 4696747b715Smrgstatic void expose_1 (WindowPtr pWin) { 4704642e01fSmrg WindowPtr pChild; 4714642e01fSmrg 4724642e01fSmrg if (!pWin->realized) 4734642e01fSmrg return; 4744642e01fSmrg 4756747b715Smrg miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); 4764642e01fSmrg 4774642e01fSmrg /* FIXME: comments in windowstr.h indicate that borderClip doesn't 4784642e01fSmrg include subwindow visibility. But I'm not so sure.. so we may 4794642e01fSmrg be exposing too much.. */ 4804642e01fSmrg 4814642e01fSmrg miSendExposures (pWin, &pWin->borderClip, 4824642e01fSmrg pWin->drawable.x, pWin->drawable.y); 4834642e01fSmrg 4844642e01fSmrg for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) 4854642e01fSmrg expose_1 (pChild); 4864642e01fSmrg} 4874642e01fSmrg 4884642e01fSmrgvoid 4894642e01fSmrgRootlessScreenExpose (ScreenPtr pScreen) 4904642e01fSmrg{ 4916747b715Smrg expose_1 (pScreen->root); 4924642e01fSmrg} 4934642e01fSmrg 4944642e01fSmrg 4954642e01fSmrgColormapPtr 4964642e01fSmrgRootlessGetColormap (ScreenPtr pScreen) 4974642e01fSmrg{ 4984642e01fSmrg RootlessScreenRec *s = SCREENREC (pScreen); 4994642e01fSmrg 5004642e01fSmrg return s->colormap; 5014642e01fSmrg} 5024642e01fSmrg 5034642e01fSmrgstatic void 5044642e01fSmrgRootlessInstallColormap (ColormapPtr pMap) 5054642e01fSmrg{ 5064642e01fSmrg ScreenPtr pScreen = pMap->pScreen; 5074642e01fSmrg RootlessScreenRec *s = SCREENREC (pScreen); 5084642e01fSmrg 5094642e01fSmrg SCREEN_UNWRAP(pScreen, InstallColormap); 5104642e01fSmrg 5114642e01fSmrg if (s->colormap != pMap) { 5124642e01fSmrg s->colormap = pMap; 5134642e01fSmrg s->colormap_changed = TRUE; 5144642e01fSmrg RootlessQueueRedisplay (pScreen); 5154642e01fSmrg } 5164642e01fSmrg 5174642e01fSmrg pScreen->InstallColormap (pMap); 5184642e01fSmrg 5194642e01fSmrg SCREEN_WRAP (pScreen, InstallColormap); 5204642e01fSmrg} 5214642e01fSmrg 5224642e01fSmrgstatic void 5234642e01fSmrgRootlessUninstallColormap (ColormapPtr pMap) 5244642e01fSmrg{ 5254642e01fSmrg ScreenPtr pScreen = pMap->pScreen; 5264642e01fSmrg RootlessScreenRec *s = SCREENREC (pScreen); 5274642e01fSmrg 5284642e01fSmrg SCREEN_UNWRAP(pScreen, UninstallColormap); 5294642e01fSmrg 5304642e01fSmrg if (s->colormap == pMap) 5314642e01fSmrg s->colormap = NULL; 5324642e01fSmrg 5334642e01fSmrg pScreen->UninstallColormap (pMap); 5344642e01fSmrg 5354642e01fSmrg SCREEN_WRAP(pScreen, UninstallColormap); 5364642e01fSmrg} 5374642e01fSmrg 5384642e01fSmrgstatic void 5394642e01fSmrgRootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) 5404642e01fSmrg{ 5414642e01fSmrg ScreenPtr pScreen = pMap->pScreen; 5424642e01fSmrg RootlessScreenRec *s = SCREENREC (pScreen); 5434642e01fSmrg 5444642e01fSmrg SCREEN_UNWRAP(pScreen, StoreColors); 5454642e01fSmrg 5464642e01fSmrg if (s->colormap == pMap && ndef > 0) { 5474642e01fSmrg s->colormap_changed = TRUE; 5484642e01fSmrg RootlessQueueRedisplay (pScreen); 5494642e01fSmrg } 5504642e01fSmrg 5514642e01fSmrg pScreen->StoreColors (pMap, ndef, pdef); 5524642e01fSmrg 5534642e01fSmrg SCREEN_WRAP(pScreen, StoreColors); 5544642e01fSmrg} 5554642e01fSmrg 55605b261ecSmrg 55705b261ecSmrgstatic CARD32 55805b261ecSmrgRootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) 55905b261ecSmrg{ 56005b261ecSmrg RootlessScreenRec *screenRec = arg; 56105b261ecSmrg 56205b261ecSmrg if (!screenRec->redisplay_queued) { 56305b261ecSmrg /* No update needed. Stop the timer. */ 56405b261ecSmrg 56505b261ecSmrg screenRec->redisplay_timer_set = FALSE; 56605b261ecSmrg return 0; 56705b261ecSmrg } 56805b261ecSmrg 56905b261ecSmrg screenRec->redisplay_queued = FALSE; 57005b261ecSmrg 57105b261ecSmrg /* Mark that we should redisplay before waiting for I/O next time */ 57205b261ecSmrg screenRec->redisplay_expired = TRUE; 57305b261ecSmrg 57405b261ecSmrg /* Reinstall the timer immediately, so we get as close to our 57505b261ecSmrg redisplay interval as possible. */ 57605b261ecSmrg 57705b261ecSmrg return ROOTLESS_REDISPLAY_DELAY; 57805b261ecSmrg} 57905b261ecSmrg 58005b261ecSmrg 58105b261ecSmrg/* 58205b261ecSmrg * RootlessQueueRedisplay 58305b261ecSmrg * Queue a redisplay after a timer delay to ensure we do not redisplay 58405b261ecSmrg * too frequently. 58505b261ecSmrg */ 58605b261ecSmrgvoid 58705b261ecSmrgRootlessQueueRedisplay(ScreenPtr pScreen) 58805b261ecSmrg{ 58905b261ecSmrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 59005b261ecSmrg 59105b261ecSmrg screenRec->redisplay_queued = TRUE; 59205b261ecSmrg 59305b261ecSmrg if (screenRec->redisplay_timer_set) 59405b261ecSmrg return; 59505b261ecSmrg 59605b261ecSmrg screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, 59705b261ecSmrg 0, ROOTLESS_REDISPLAY_DELAY, 59805b261ecSmrg RootlessRedisplayCallback, 59905b261ecSmrg screenRec); 60005b261ecSmrg screenRec->redisplay_timer_set = TRUE; 60105b261ecSmrg} 60205b261ecSmrg 60305b261ecSmrg 60405b261ecSmrg/* 60505b261ecSmrg * RootlessBlockHandler 60605b261ecSmrg * If the redisplay timer has expired, flush drawing before blocking 60705b261ecSmrg * on select(). 60805b261ecSmrg */ 60905b261ecSmrgstatic void 61005b261ecSmrgRootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) 61105b261ecSmrg{ 61205b261ecSmrg ScreenPtr pScreen = pbdata; 61305b261ecSmrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 61405b261ecSmrg 61505b261ecSmrg if (screenRec->redisplay_expired) { 61605b261ecSmrg screenRec->redisplay_expired = FALSE; 61705b261ecSmrg 61805b261ecSmrg RootlessRedisplayScreen(pScreen); 61905b261ecSmrg } 62005b261ecSmrg} 62105b261ecSmrg 62205b261ecSmrg 62305b261ecSmrgstatic void 62405b261ecSmrgRootlessWakeupHandler(pointer data, int i, pointer LastSelectMask) 62505b261ecSmrg{ 62605b261ecSmrg // nothing here 62705b261ecSmrg} 62805b261ecSmrg 62905b261ecSmrg 63005b261ecSmrgstatic Bool 63105b261ecSmrgRootlessAllocatePrivates(ScreenPtr pScreen) 63205b261ecSmrg{ 63305b261ecSmrg RootlessScreenRec *s; 63405b261ecSmrg 6356747b715Smrg if (!dixRegisterPrivateKey(&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec))) 6366747b715Smrg return FALSE; 6376747b715Smrg if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 6386747b715Smrg return FALSE; 6396747b715Smrg if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) 6406747b715Smrg return FALSE; 6416747b715Smrg if (!dixRegisterPrivateKey(&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0)) 64205b261ecSmrg return FALSE; 64305b261ecSmrg 6446747b715Smrg s = malloc(sizeof(RootlessScreenRec)); 64505b261ecSmrg if (! s) return FALSE; 6464642e01fSmrg SETSCREENREC(pScreen, s); 64705b261ecSmrg 64805b261ecSmrg s->pixmap_data = NULL; 64905b261ecSmrg s->pixmap_data_size = 0; 65005b261ecSmrg 65105b261ecSmrg s->redisplay_timer = NULL; 65205b261ecSmrg s->redisplay_timer_set = FALSE; 65305b261ecSmrg 65405b261ecSmrg return TRUE; 65505b261ecSmrg} 65605b261ecSmrg 65705b261ecSmrg 65805b261ecSmrgstatic void 65905b261ecSmrgRootlessWrap(ScreenPtr pScreen) 66005b261ecSmrg{ 6614642e01fSmrg RootlessScreenRec *s = SCREENREC(pScreen); 66205b261ecSmrg 66305b261ecSmrg#define WRAP(a) \ 66405b261ecSmrg if (pScreen->a) { \ 66505b261ecSmrg s->a = pScreen->a; \ 66605b261ecSmrg } else { \ 66705b261ecSmrg RL_DEBUG_MSG("null screen fn " #a "\n"); \ 66805b261ecSmrg s->a = NULL; \ 66905b261ecSmrg } \ 67005b261ecSmrg pScreen->a = Rootless##a 67105b261ecSmrg 67205b261ecSmrg WRAP(CreateScreenResources); 67305b261ecSmrg WRAP(CloseScreen); 67405b261ecSmrg WRAP(CreateGC); 67505b261ecSmrg WRAP(CopyWindow); 67605b261ecSmrg WRAP(GetImage); 67705b261ecSmrg WRAP(SourceValidate); 67805b261ecSmrg WRAP(CreateWindow); 67905b261ecSmrg WRAP(DestroyWindow); 68005b261ecSmrg WRAP(RealizeWindow); 68105b261ecSmrg WRAP(UnrealizeWindow); 68205b261ecSmrg WRAP(MoveWindow); 68305b261ecSmrg WRAP(PositionWindow); 68405b261ecSmrg WRAP(ResizeWindow); 68505b261ecSmrg WRAP(RestackWindow); 68605b261ecSmrg WRAP(ReparentWindow); 68705b261ecSmrg WRAP(ChangeBorderWidth); 68805b261ecSmrg WRAP(MarkOverlappedWindows); 68905b261ecSmrg WRAP(ValidateTree); 69005b261ecSmrg WRAP(ChangeWindowAttributes); 6914642e01fSmrg WRAP(InstallColormap); 6924642e01fSmrg WRAP(UninstallColormap); 6934642e01fSmrg WRAP(StoreColors); 69405b261ecSmrg 69505b261ecSmrg WRAP(SetShape); 69605b261ecSmrg 69705b261ecSmrg { 69805b261ecSmrg // Composite and Glyphs don't use normal screen wrapping 69905b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 70005b261ecSmrg s->Composite = ps->Composite; 70105b261ecSmrg ps->Composite = RootlessComposite; 70205b261ecSmrg s->Glyphs = ps->Glyphs; 70305b261ecSmrg ps->Glyphs = RootlessGlyphs; 70405b261ecSmrg } 70505b261ecSmrg 70605b261ecSmrg // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? 70705b261ecSmrg 70805b261ecSmrg#undef WRAP 70905b261ecSmrg} 71005b261ecSmrg 71105b261ecSmrg 71205b261ecSmrg/* 71305b261ecSmrg * RootlessInit 71405b261ecSmrg * Called by the rootless implementation to initialize the rootless layer. 71505b261ecSmrg * Rootless wraps lots of stuff and needs a bunch of devPrivates. 71605b261ecSmrg */ 71705b261ecSmrgBool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) 71805b261ecSmrg{ 71905b261ecSmrg RootlessScreenRec *s; 72005b261ecSmrg 72105b261ecSmrg if (!RootlessAllocatePrivates(pScreen)) 72205b261ecSmrg return FALSE; 72305b261ecSmrg 7244642e01fSmrg s = SCREENREC(pScreen); 72505b261ecSmrg 72605b261ecSmrg s->imp = procs; 7274642e01fSmrg s->colormap = NULL; 7284642e01fSmrg s->redisplay_expired = FALSE; 72905b261ecSmrg 73005b261ecSmrg RootlessWrap(pScreen); 73105b261ecSmrg 73205b261ecSmrg if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, 73305b261ecSmrg RootlessWakeupHandler, 73405b261ecSmrg (pointer) pScreen)) 73505b261ecSmrg { 73605b261ecSmrg return FALSE; 73705b261ecSmrg } 73805b261ecSmrg 73905b261ecSmrg return TRUE; 74005b261ecSmrg} 7414642e01fSmrg 7424642e01fSmrgvoid RootlessUpdateRooted (Bool state) { 7434642e01fSmrg int i; 7444642e01fSmrg 7454642e01fSmrg if (!state) 7464642e01fSmrg { 7474642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 7484642e01fSmrg RootlessDisableRoot (screenInfo.screens[i]); 7494642e01fSmrg } 7504642e01fSmrg else 7514642e01fSmrg { 7524642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 7534642e01fSmrg RootlessEnableRoot (screenInfo.screens[i]); 7544642e01fSmrg } 7554642e01fSmrg} 756