rootlessScreen.c revision 1b5d61b8
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#ifdef HAVE_DIX_CONFIG_H 3305b261ecSmrg#include <dix-config.h> 3405b261ecSmrg#endif 3505b261ecSmrg 3605b261ecSmrg#include "mi.h" 3705b261ecSmrg#include "scrnintstr.h" 3805b261ecSmrg#include "gcstruct.h" 3905b261ecSmrg#include "pixmapstr.h" 4005b261ecSmrg#include "windowstr.h" 4105b261ecSmrg#include "propertyst.h" 4205b261ecSmrg#include "mivalidate.h" 4305b261ecSmrg#include "picturestr.h" 444642e01fSmrg#include "colormapst.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 646747b715SmrgDevPrivateKeyRec rootlessGCPrivateKeyRec; 656747b715SmrgDevPrivateKeyRec rootlessScreenPrivateKeyRec; 666747b715SmrgDevPrivateKeyRec rootlessWindowPrivateKeyRec; 676747b715SmrgDevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec; 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 8535c4bbdfSmrg pPix = (*pScreen->GetScreenPixmap) (pScreen); 8605b261ecSmrg if (pPix == NULL) { 8735c4bbdfSmrg pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth, 0); 8835c4bbdfSmrg (*pScreen->SetScreenPixmap) (pPix); 8905b261ecSmrg } 9005b261ecSmrg 9105b261ecSmrg rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); 9205b261ecSmrg 9305b261ecSmrg if (s->pixmap_data_size < rowbytes) { 949ace9065Smrg free(s->pixmap_data); 9505b261ecSmrg 9605b261ecSmrg s->pixmap_data_size = rowbytes; 976747b715Smrg s->pixmap_data = malloc(s->pixmap_data_size); 9805b261ecSmrg if (s->pixmap_data == NULL) 9905b261ecSmrg return; 10005b261ecSmrg 10105b261ecSmrg memset(s->pixmap_data, 0xFF, s->pixmap_data_size); 10205b261ecSmrg 10305b261ecSmrg pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height, 10405b261ecSmrg pScreen->rootDepth, 10505b261ecSmrg BitsPerPixel(pScreen->rootDepth), 10605b261ecSmrg 0, s->pixmap_data); 10705b261ecSmrg /* ModifyPixmapHeader ignores zero arguments, so install rowbytes 10805b261ecSmrg by hand. */ 10905b261ecSmrg pPix->devKind = 0; 11005b261ecSmrg } 11105b261ecSmrg} 11205b261ecSmrg 11305b261ecSmrg/* 11405b261ecSmrg * RootlessCreateScreenResources 11505b261ecSmrg * Rootless implementations typically set a null framebuffer pointer, which 11605b261ecSmrg * causes problems with miCreateScreenResources. We fix things up here. 11705b261ecSmrg */ 11805b261ecSmrgstatic Bool 11905b261ecSmrgRootlessCreateScreenResources(ScreenPtr pScreen) 12005b261ecSmrg{ 12105b261ecSmrg Bool ret = TRUE; 12205b261ecSmrg 12305b261ecSmrg SCREEN_UNWRAP(pScreen, CreateScreenResources); 12405b261ecSmrg 12505b261ecSmrg if (pScreen->CreateScreenResources != NULL) 12635c4bbdfSmrg ret = (*pScreen->CreateScreenResources) (pScreen); 12705b261ecSmrg 12805b261ecSmrg SCREEN_WRAP(pScreen, CreateScreenResources); 12905b261ecSmrg 13005b261ecSmrg if (!ret) 13105b261ecSmrg return ret; 13205b261ecSmrg 13305b261ecSmrg /* Make sure we have a valid screen pixmap. */ 13405b261ecSmrg 13505b261ecSmrg RootlessUpdateScreenPixmap(pScreen); 13605b261ecSmrg 13705b261ecSmrg return ret; 13805b261ecSmrg} 13905b261ecSmrg 14005b261ecSmrgstatic Bool 14135c4bbdfSmrgRootlessCloseScreen(ScreenPtr pScreen) 14205b261ecSmrg{ 14305b261ecSmrg RootlessScreenRec *s; 14405b261ecSmrg 14505b261ecSmrg s = SCREENREC(pScreen); 14605b261ecSmrg 14705b261ecSmrg // fixme unwrap everything that was wrapped? 14805b261ecSmrg pScreen->CloseScreen = s->CloseScreen; 14905b261ecSmrg 15005b261ecSmrg if (s->pixmap_data != NULL) { 1516747b715Smrg free(s->pixmap_data); 15205b261ecSmrg s->pixmap_data = NULL; 15305b261ecSmrg s->pixmap_data_size = 0; 15405b261ecSmrg } 15505b261ecSmrg 1566747b715Smrg free(s); 15735c4bbdfSmrg return pScreen->CloseScreen(pScreen); 15805b261ecSmrg} 15905b261ecSmrg 16005b261ecSmrgstatic void 16105b261ecSmrgRootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, 16205b261ecSmrg unsigned int format, unsigned long planeMask, char *pdstLine) 16305b261ecSmrg{ 16405b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 16535c4bbdfSmrg 16605b261ecSmrg SCREEN_UNWRAP(pScreen, GetImage); 16705b261ecSmrg 16805b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 16905b261ecSmrg int x0, y0, x1, y1; 17005b261ecSmrg RootlessWindowRec *winRec; 17105b261ecSmrg 17205b261ecSmrg // Many apps use GetImage to sync with the visible frame buffer 17305b261ecSmrg // FIXME: entire screen or just window or all screens? 17405b261ecSmrg RootlessRedisplayScreen(pScreen); 17505b261ecSmrg 17605b261ecSmrg // RedisplayScreen stops drawing, so we need to start it again 17735c4bbdfSmrg RootlessStartDrawing((WindowPtr) pDrawable); 17805b261ecSmrg 17905b261ecSmrg /* Check that we have some place to read from. */ 18005b261ecSmrg winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); 18105b261ecSmrg if (winRec == NULL) 18205b261ecSmrg goto out; 18305b261ecSmrg 18405b261ecSmrg /* Clip to top-level window bounds. */ 18505b261ecSmrg /* FIXME: fbGetImage uses the width parameter to calculate the 18605b261ecSmrg stride of the destination pixmap. If w is clipped, the data 18705b261ecSmrg returned will be garbage, although we will not crash. */ 18805b261ecSmrg 18905b261ecSmrg x0 = pDrawable->x + sx; 19005b261ecSmrg y0 = pDrawable->y + sy; 19105b261ecSmrg x1 = x0 + w; 19205b261ecSmrg y1 = y0 + h; 19305b261ecSmrg 19435c4bbdfSmrg x0 = max(x0, winRec->x); 19535c4bbdfSmrg y0 = max(y0, winRec->y); 19635c4bbdfSmrg x1 = min(x1, winRec->x + winRec->width); 19735c4bbdfSmrg y1 = min(y1, winRec->y + winRec->height); 19805b261ecSmrg 19905b261ecSmrg sx = x0 - pDrawable->x; 20005b261ecSmrg sy = y0 - pDrawable->y; 20105b261ecSmrg w = x1 - x0; 20205b261ecSmrg h = y1 - y0; 20305b261ecSmrg 20405b261ecSmrg if (w <= 0 || h <= 0) 20505b261ecSmrg goto out; 20605b261ecSmrg } 20705b261ecSmrg 20805b261ecSmrg pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); 20905b261ecSmrg 21035c4bbdfSmrg out: 21105b261ecSmrg SCREEN_WRAP(pScreen, GetImage); 21205b261ecSmrg} 21305b261ecSmrg 21405b261ecSmrg/* 21505b261ecSmrg * RootlessSourceValidate 21605b261ecSmrg * CopyArea and CopyPlane use a GC tied to the destination drawable. 21705b261ecSmrg * StartDrawing/StopDrawing wrappers won't be called if source is 21805b261ecSmrg * a visible window but the destination isn't. So, we call StartDrawing 21905b261ecSmrg * here and leave StopDrawing for the block handler. 22005b261ecSmrg */ 22105b261ecSmrgstatic void 2229ace9065SmrgRootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h, 2239ace9065Smrg unsigned int subWindowMode) 22405b261ecSmrg{ 22505b261ecSmrg SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); 22605b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 22735c4bbdfSmrg WindowPtr pWin = (WindowPtr) pDrawable; 22835c4bbdfSmrg 22905b261ecSmrg RootlessStartDrawing(pWin); 23005b261ecSmrg } 23105b261ecSmrg if (pDrawable->pScreen->SourceValidate) { 23235c4bbdfSmrg pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, 23335c4bbdfSmrg subWindowMode); 23405b261ecSmrg } 23505b261ecSmrg SCREEN_WRAP(pDrawable->pScreen, SourceValidate); 23605b261ecSmrg} 23705b261ecSmrg 23805b261ecSmrgstatic void 23905b261ecSmrgRootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 24035c4bbdfSmrg INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, 24105b261ecSmrg INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 24205b261ecSmrg{ 24305b261ecSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 24405b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 24505b261ecSmrg WindowPtr srcWin, dstWin, maskWin = NULL; 24605b261ecSmrg 24735c4bbdfSmrg if (pMask) { // pMask can be NULL 24835c4bbdfSmrg maskWin = (pMask->pDrawable && 24935c4bbdfSmrg pMask->pDrawable->type == 25035c4bbdfSmrg DRAWABLE_WINDOW) ? (WindowPtr) pMask->pDrawable : NULL; 25105b261ecSmrg } 25235c4bbdfSmrg srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 25335c4bbdfSmrg (WindowPtr) pSrc->pDrawable : NULL; 25435c4bbdfSmrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 25535c4bbdfSmrg (WindowPtr) pDst->pDrawable : NULL; 25605b261ecSmrg 25705b261ecSmrg // SCREEN_UNWRAP(ps, Composite); 25805b261ecSmrg ps->Composite = SCREENREC(pScreen)->Composite; 25905b261ecSmrg 26035c4bbdfSmrg if (srcWin && IsFramedWindow(srcWin)) 26105b261ecSmrg RootlessStartDrawing(srcWin); 26205b261ecSmrg if (maskWin && IsFramedWindow(maskWin)) 26305b261ecSmrg RootlessStartDrawing(maskWin); 26435c4bbdfSmrg if (dstWin && IsFramedWindow(dstWin)) 26505b261ecSmrg RootlessStartDrawing(dstWin); 26605b261ecSmrg 26705b261ecSmrg ps->Composite(op, pSrc, pMask, pDst, 26835c4bbdfSmrg xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); 26905b261ecSmrg 27035c4bbdfSmrg if (dstWin && IsFramedWindow(dstWin)) { 27105b261ecSmrg RootlessDamageRect(dstWin, xDst, yDst, width, height); 27205b261ecSmrg } 27305b261ecSmrg 27405b261ecSmrg ps->Composite = RootlessComposite; 27505b261ecSmrg // SCREEN_WRAP(ps, Composite); 27605b261ecSmrg} 27705b261ecSmrg 27805b261ecSmrgstatic void 27905b261ecSmrgRootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 28005b261ecSmrg PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 28135c4bbdfSmrg int nlist, GlyphListPtr list, GlyphPtr * glyphs) 28205b261ecSmrg{ 28305b261ecSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 28405b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 28505b261ecSmrg int x, y; 28605b261ecSmrg int n; 28705b261ecSmrg GlyphPtr glyph; 28805b261ecSmrg WindowPtr srcWin, dstWin; 28905b261ecSmrg 2906747b715Smrg srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 29135c4bbdfSmrg (WindowPtr) pSrc->pDrawable : NULL; 29205b261ecSmrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 29335c4bbdfSmrg (WindowPtr) pDst->pDrawable : NULL; 29405b261ecSmrg 29535c4bbdfSmrg if (srcWin && IsFramedWindow(srcWin)) 29635c4bbdfSmrg RootlessStartDrawing(srcWin); 29735c4bbdfSmrg if (dstWin && IsFramedWindow(dstWin)) 29835c4bbdfSmrg RootlessStartDrawing(dstWin); 29905b261ecSmrg 30005b261ecSmrg //SCREEN_UNWRAP(ps, Glyphs); 30105b261ecSmrg ps->Glyphs = SCREENREC(pScreen)->Glyphs; 30205b261ecSmrg ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); 30305b261ecSmrg ps->Glyphs = RootlessGlyphs; 30405b261ecSmrg //SCREEN_WRAP(ps, Glyphs); 30505b261ecSmrg 30605b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) { 30705b261ecSmrg x = xSrc; 30805b261ecSmrg y = ySrc; 30905b261ecSmrg 31005b261ecSmrg while (nlist--) { 31105b261ecSmrg x += list->xOff; 31205b261ecSmrg y += list->yOff; 31305b261ecSmrg n = list->len; 31405b261ecSmrg 31505b261ecSmrg /* Calling DamageRect for the bounding box of each glyph is 31605b261ecSmrg inefficient. So compute the union of all glyphs in a list 31705b261ecSmrg and damage that. */ 31805b261ecSmrg 31905b261ecSmrg if (n > 0) { 32005b261ecSmrg BoxRec box; 32105b261ecSmrg 32205b261ecSmrg glyph = *glyphs++; 32305b261ecSmrg 32405b261ecSmrg box.x1 = x - glyph->info.x; 32505b261ecSmrg box.y1 = y - glyph->info.y; 32605b261ecSmrg box.x2 = box.x1 + glyph->info.width; 3279ace9065Smrg box.y2 = box.y1 + glyph->info.height; 32805b261ecSmrg 32905b261ecSmrg x += glyph->info.xOff; 33005b261ecSmrg y += glyph->info.yOff; 33105b261ecSmrg 33205b261ecSmrg while (--n > 0) { 33305b261ecSmrg short x1, y1, x2, y2; 33405b261ecSmrg 33505b261ecSmrg glyph = *glyphs++; 33605b261ecSmrg 33705b261ecSmrg x1 = x - glyph->info.x; 33805b261ecSmrg y1 = y - glyph->info.y; 33905b261ecSmrg x2 = x1 + glyph->info.width; 34005b261ecSmrg y2 = y1 + glyph->info.height; 34105b261ecSmrg 34235c4bbdfSmrg box.x1 = max(box.x1, x1); 34335c4bbdfSmrg box.y1 = max(box.y1, y1); 34435c4bbdfSmrg box.x2 = max(box.x2, x2); 34535c4bbdfSmrg box.y2 = max(box.y2, y2); 34605b261ecSmrg 34705b261ecSmrg x += glyph->info.xOff; 34805b261ecSmrg y += glyph->info.yOff; 34905b261ecSmrg } 35005b261ecSmrg 35105b261ecSmrg RootlessDamageBox(dstWin, &box); 35205b261ecSmrg } 35305b261ecSmrg list++; 35405b261ecSmrg } 35505b261ecSmrg } 35605b261ecSmrg} 35705b261ecSmrg 35805b261ecSmrg/* 35905b261ecSmrg * RootlessValidateTree 36005b261ecSmrg * ValidateTree is modified in two ways: 36105b261ecSmrg * - top-level windows don't clip each other 36205b261ecSmrg * - windows aren't clipped against root. 36305b261ecSmrg * These only matter when validating from the root. 36405b261ecSmrg */ 36505b261ecSmrgstatic int 36605b261ecSmrgRootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 36705b261ecSmrg{ 36805b261ecSmrg int result; 36905b261ecSmrg RegionRec saveRoot; 37005b261ecSmrg ScreenPtr pScreen = pParent->drawable.pScreen; 37105b261ecSmrg 37205b261ecSmrg SCREEN_UNWRAP(pScreen, ValidateTree); 37305b261ecSmrg RL_DEBUG_MSG("VALIDATETREE start "); 37405b261ecSmrg 37505b261ecSmrg // Use our custom version to validate from root 37605b261ecSmrg if (IsRoot(pParent)) { 37705b261ecSmrg RL_DEBUG_MSG("custom "); 37805b261ecSmrg result = RootlessMiValidateTree(pParent, pChild, kind); 37935c4bbdfSmrg } 38035c4bbdfSmrg else { 38105b261ecSmrg HUGE_ROOT(pParent); 38205b261ecSmrg result = pScreen->ValidateTree(pParent, pChild, kind); 38305b261ecSmrg NORMAL_ROOT(pParent); 38405b261ecSmrg } 38505b261ecSmrg 38605b261ecSmrg SCREEN_WRAP(pScreen, ValidateTree); 38705b261ecSmrg RL_DEBUG_MSG("VALIDATETREE end\n"); 38805b261ecSmrg 38905b261ecSmrg return result; 39005b261ecSmrg} 39105b261ecSmrg 39205b261ecSmrg/* 39305b261ecSmrg * RootlessMarkOverlappedWindows 39405b261ecSmrg * MarkOverlappedWindows is modified to ignore overlapping 39505b261ecSmrg * top-level windows. 39605b261ecSmrg */ 39705b261ecSmrgstatic Bool 39805b261ecSmrgRootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, 39905b261ecSmrg WindowPtr *ppLayerWin) 40005b261ecSmrg{ 40105b261ecSmrg RegionRec saveRoot; 40205b261ecSmrg Bool result; 40305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 40435c4bbdfSmrg 40505b261ecSmrg SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); 40605b261ecSmrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); 40705b261ecSmrg 40805b261ecSmrg HUGE_ROOT(pWin); 40905b261ecSmrg if (IsRoot(pWin)) { 41005b261ecSmrg // root - mark nothing 41105b261ecSmrg RL_DEBUG_MSG("is root not marking "); 41205b261ecSmrg result = FALSE; 41305b261ecSmrg } 41435c4bbdfSmrg else if (!IsTopLevel(pWin)) { 41505b261ecSmrg // not top-level window - mark normally 41605b261ecSmrg result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); 41705b261ecSmrg } 41805b261ecSmrg else { 41905b261ecSmrg //top-level window - mark children ONLY - NO overlaps with sibs (?) 42005b261ecSmrg // This code copied from miMarkOverlappedWindows() 42105b261ecSmrg 42205b261ecSmrg register WindowPtr pChild; 42305b261ecSmrg Bool anyMarked = FALSE; 4246747b715Smrg MarkWindowProcPtr MarkWindow = pScreen->MarkWindow; 42505b261ecSmrg 42605b261ecSmrg RL_DEBUG_MSG("is top level! "); 42705b261ecSmrg /* single layered systems are easy */ 42835c4bbdfSmrg if (ppLayerWin) 42935c4bbdfSmrg *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)) 44035c4bbdfSmrg SetWinSize(pChild); 4416747b715Smrg if (RegionBroken(&pChild->borderSize)) 44235c4bbdfSmrg SetBorderSize(pChild); 44335c4bbdfSmrg (*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 } 45705b261ecSmrg if (anyMarked) 45835c4bbdfSmrg (*MarkWindow) (pWin->parent); 45905b261ecSmrg result = anyMarked; 46005b261ecSmrg } 46105b261ecSmrg NORMAL_ROOT(pWin); 46205b261ecSmrg SCREEN_WRAP(pScreen, MarkOverlappedWindows); 46305b261ecSmrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); 46405b261ecSmrg 46505b261ecSmrg return result; 46605b261ecSmrg} 46705b261ecSmrg 46835c4bbdfSmrgstatic void 46935c4bbdfSmrgexpose_1(WindowPtr pWin) 47035c4bbdfSmrg{ 4714642e01fSmrg WindowPtr pChild; 47235c4bbdfSmrg 4734642e01fSmrg if (!pWin->realized) 4744642e01fSmrg return; 47535c4bbdfSmrg 47635c4bbdfSmrg pWin->drawable.pScreen->PaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); 47735c4bbdfSmrg 4784642e01fSmrg /* FIXME: comments in windowstr.h indicate that borderClip doesn't 47935c4bbdfSmrg include subwindow visibility. But I'm not so sure.. so we may 48035c4bbdfSmrg be exposing too much.. */ 48135c4bbdfSmrg 48235c4bbdfSmrg miSendExposures(pWin, &pWin->borderClip, 48335c4bbdfSmrg pWin->drawable.x, pWin->drawable.y); 48435c4bbdfSmrg 4854642e01fSmrg for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) 48635c4bbdfSmrg expose_1(pChild); 4874642e01fSmrg} 4884642e01fSmrg 4894642e01fSmrgvoid 49035c4bbdfSmrgRootlessScreenExpose(ScreenPtr pScreen) 4914642e01fSmrg{ 49235c4bbdfSmrg expose_1(pScreen->root); 4934642e01fSmrg} 4944642e01fSmrg 4954642e01fSmrgColormapPtr 49635c4bbdfSmrgRootlessGetColormap(ScreenPtr pScreen) 4974642e01fSmrg{ 49835c4bbdfSmrg RootlessScreenRec *s = SCREENREC(pScreen); 4994642e01fSmrg 50035c4bbdfSmrg return s->colormap; 5014642e01fSmrg} 5024642e01fSmrg 5034642e01fSmrgstatic void 50435c4bbdfSmrgRootlessInstallColormap(ColormapPtr pMap) 5054642e01fSmrg{ 50635c4bbdfSmrg ScreenPtr pScreen = pMap->pScreen; 50735c4bbdfSmrg RootlessScreenRec *s = SCREENREC(pScreen); 5084642e01fSmrg 50935c4bbdfSmrg SCREEN_UNWRAP(pScreen, InstallColormap); 5104642e01fSmrg 51135c4bbdfSmrg if (s->colormap != pMap) { 51235c4bbdfSmrg s->colormap = pMap; 51335c4bbdfSmrg s->colormap_changed = TRUE; 51435c4bbdfSmrg RootlessQueueRedisplay(pScreen); 51535c4bbdfSmrg } 5164642e01fSmrg 51735c4bbdfSmrg pScreen->InstallColormap(pMap); 5184642e01fSmrg 51935c4bbdfSmrg SCREEN_WRAP(pScreen, InstallColormap); 5204642e01fSmrg} 5214642e01fSmrg 5224642e01fSmrgstatic void 52335c4bbdfSmrgRootlessUninstallColormap(ColormapPtr pMap) 5244642e01fSmrg{ 52535c4bbdfSmrg ScreenPtr pScreen = pMap->pScreen; 52635c4bbdfSmrg RootlessScreenRec *s = SCREENREC(pScreen); 5274642e01fSmrg 52835c4bbdfSmrg SCREEN_UNWRAP(pScreen, UninstallColormap); 5294642e01fSmrg 53035c4bbdfSmrg if (s->colormap == pMap) 53135c4bbdfSmrg s->colormap = NULL; 5324642e01fSmrg 53335c4bbdfSmrg pScreen->UninstallColormap(pMap); 5344642e01fSmrg 53535c4bbdfSmrg SCREEN_WRAP(pScreen, UninstallColormap); 5364642e01fSmrg} 5374642e01fSmrg 5384642e01fSmrgstatic void 53935c4bbdfSmrgRootlessStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef) 5404642e01fSmrg{ 54135c4bbdfSmrg ScreenPtr pScreen = pMap->pScreen; 54235c4bbdfSmrg RootlessScreenRec *s = SCREENREC(pScreen); 5434642e01fSmrg 54435c4bbdfSmrg SCREEN_UNWRAP(pScreen, StoreColors); 5454642e01fSmrg 54635c4bbdfSmrg if (s->colormap == pMap && ndef > 0) { 54735c4bbdfSmrg s->colormap_changed = TRUE; 54835c4bbdfSmrg RootlessQueueRedisplay(pScreen); 54935c4bbdfSmrg } 5504642e01fSmrg 55135c4bbdfSmrg pScreen->StoreColors(pMap, ndef, pdef); 5524642e01fSmrg 55335c4bbdfSmrg SCREEN_WRAP(pScreen, StoreColors); 5544642e01fSmrg} 5554642e01fSmrg 55605b261ecSmrgstatic CARD32 55705b261ecSmrgRootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) 55805b261ecSmrg{ 55905b261ecSmrg RootlessScreenRec *screenRec = arg; 56005b261ecSmrg 56105b261ecSmrg if (!screenRec->redisplay_queued) { 56205b261ecSmrg /* No update needed. Stop the timer. */ 56305b261ecSmrg 56405b261ecSmrg screenRec->redisplay_timer_set = FALSE; 56505b261ecSmrg return 0; 56605b261ecSmrg } 56705b261ecSmrg 56805b261ecSmrg screenRec->redisplay_queued = FALSE; 56905b261ecSmrg 57005b261ecSmrg /* Mark that we should redisplay before waiting for I/O next time */ 57105b261ecSmrg screenRec->redisplay_expired = TRUE; 57205b261ecSmrg 57305b261ecSmrg /* Reinstall the timer immediately, so we get as close to our 57405b261ecSmrg redisplay interval as possible. */ 57505b261ecSmrg 57605b261ecSmrg return ROOTLESS_REDISPLAY_DELAY; 57705b261ecSmrg} 57805b261ecSmrg 57905b261ecSmrg/* 58005b261ecSmrg * RootlessQueueRedisplay 58105b261ecSmrg * Queue a redisplay after a timer delay to ensure we do not redisplay 58205b261ecSmrg * too frequently. 58305b261ecSmrg */ 58405b261ecSmrgvoid 58505b261ecSmrgRootlessQueueRedisplay(ScreenPtr pScreen) 58605b261ecSmrg{ 58705b261ecSmrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 58805b261ecSmrg 58905b261ecSmrg screenRec->redisplay_queued = TRUE; 59005b261ecSmrg 59105b261ecSmrg if (screenRec->redisplay_timer_set) 59205b261ecSmrg return; 59305b261ecSmrg 59405b261ecSmrg screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, 59505b261ecSmrg 0, ROOTLESS_REDISPLAY_DELAY, 59635c4bbdfSmrg RootlessRedisplayCallback, screenRec); 59705b261ecSmrg screenRec->redisplay_timer_set = TRUE; 59805b261ecSmrg} 59905b261ecSmrg 60005b261ecSmrg/* 60105b261ecSmrg * RootlessBlockHandler 60205b261ecSmrg * If the redisplay timer has expired, flush drawing before blocking 60305b261ecSmrg * on select(). 60405b261ecSmrg */ 60505b261ecSmrgstatic void 6061b5d61b8SmrgRootlessBlockHandler(void *pbdata, void *ptimeout) 60705b261ecSmrg{ 60805b261ecSmrg ScreenPtr pScreen = pbdata; 60905b261ecSmrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 61005b261ecSmrg 61105b261ecSmrg if (screenRec->redisplay_expired) { 61205b261ecSmrg screenRec->redisplay_expired = FALSE; 61305b261ecSmrg 61405b261ecSmrg RootlessRedisplayScreen(pScreen); 61505b261ecSmrg } 61605b261ecSmrg} 61705b261ecSmrg 61805b261ecSmrgstatic void 6191b5d61b8SmrgRootlessWakeupHandler(void *data, int result) 62005b261ecSmrg{ 62105b261ecSmrg // nothing here 62205b261ecSmrg} 62305b261ecSmrg 62405b261ecSmrgstatic Bool 62505b261ecSmrgRootlessAllocatePrivates(ScreenPtr pScreen) 62605b261ecSmrg{ 62705b261ecSmrg RootlessScreenRec *s; 62805b261ecSmrg 62935c4bbdfSmrg if (!dixRegisterPrivateKey 63035c4bbdfSmrg (&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec))) 6316747b715Smrg return FALSE; 6326747b715Smrg if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 6336747b715Smrg return FALSE; 6346747b715Smrg if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) 6356747b715Smrg return FALSE; 63635c4bbdfSmrg if (!dixRegisterPrivateKey 63735c4bbdfSmrg (&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0)) 63805b261ecSmrg return FALSE; 63905b261ecSmrg 6406747b715Smrg s = malloc(sizeof(RootlessScreenRec)); 64135c4bbdfSmrg if (!s) 64235c4bbdfSmrg return FALSE; 6434642e01fSmrg SETSCREENREC(pScreen, s); 64405b261ecSmrg 64505b261ecSmrg s->pixmap_data = NULL; 64605b261ecSmrg s->pixmap_data_size = 0; 64705b261ecSmrg 64805b261ecSmrg s->redisplay_timer = NULL; 64905b261ecSmrg s->redisplay_timer_set = FALSE; 65005b261ecSmrg 65105b261ecSmrg return TRUE; 65205b261ecSmrg} 65305b261ecSmrg 65405b261ecSmrgstatic void 65505b261ecSmrgRootlessWrap(ScreenPtr pScreen) 65605b261ecSmrg{ 6574642e01fSmrg RootlessScreenRec *s = SCREENREC(pScreen); 65805b261ecSmrg 65905b261ecSmrg#define WRAP(a) \ 66005b261ecSmrg if (pScreen->a) { \ 66105b261ecSmrg s->a = pScreen->a; \ 66205b261ecSmrg } else { \ 66305b261ecSmrg RL_DEBUG_MSG("null screen fn " #a "\n"); \ 66405b261ecSmrg s->a = NULL; \ 66505b261ecSmrg } \ 66605b261ecSmrg pScreen->a = Rootless##a 66705b261ecSmrg 66805b261ecSmrg WRAP(CreateScreenResources); 66905b261ecSmrg WRAP(CloseScreen); 67005b261ecSmrg WRAP(CreateGC); 67105b261ecSmrg WRAP(CopyWindow); 67235c4bbdfSmrg WRAP(PaintWindow); 67305b261ecSmrg WRAP(GetImage); 67405b261ecSmrg WRAP(SourceValidate); 67505b261ecSmrg WRAP(CreateWindow); 67605b261ecSmrg WRAP(DestroyWindow); 67705b261ecSmrg WRAP(RealizeWindow); 67805b261ecSmrg WRAP(UnrealizeWindow); 67905b261ecSmrg WRAP(MoveWindow); 68005b261ecSmrg WRAP(PositionWindow); 68105b261ecSmrg WRAP(ResizeWindow); 68205b261ecSmrg WRAP(RestackWindow); 68305b261ecSmrg WRAP(ReparentWindow); 68405b261ecSmrg WRAP(ChangeBorderWidth); 68505b261ecSmrg WRAP(MarkOverlappedWindows); 68605b261ecSmrg WRAP(ValidateTree); 68705b261ecSmrg WRAP(ChangeWindowAttributes); 6884642e01fSmrg WRAP(InstallColormap); 6894642e01fSmrg WRAP(UninstallColormap); 6904642e01fSmrg WRAP(StoreColors); 69105b261ecSmrg 69205b261ecSmrg WRAP(SetShape); 69305b261ecSmrg 69405b261ecSmrg { 69505b261ecSmrg // Composite and Glyphs don't use normal screen wrapping 69605b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 69735c4bbdfSmrg 69805b261ecSmrg s->Composite = ps->Composite; 69905b261ecSmrg ps->Composite = RootlessComposite; 70005b261ecSmrg s->Glyphs = ps->Glyphs; 70105b261ecSmrg ps->Glyphs = RootlessGlyphs; 70205b261ecSmrg } 70305b261ecSmrg 70405b261ecSmrg // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? 70505b261ecSmrg 70605b261ecSmrg#undef WRAP 70705b261ecSmrg} 70805b261ecSmrg 70905b261ecSmrg/* 71005b261ecSmrg * RootlessInit 71105b261ecSmrg * Called by the rootless implementation to initialize the rootless layer. 71205b261ecSmrg * Rootless wraps lots of stuff and needs a bunch of devPrivates. 71305b261ecSmrg */ 71435c4bbdfSmrgBool 71535c4bbdfSmrgRootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) 71605b261ecSmrg{ 71705b261ecSmrg RootlessScreenRec *s; 71805b261ecSmrg 71905b261ecSmrg if (!RootlessAllocatePrivates(pScreen)) 72005b261ecSmrg return FALSE; 72105b261ecSmrg 7224642e01fSmrg s = SCREENREC(pScreen); 72305b261ecSmrg 72405b261ecSmrg s->imp = procs; 7254642e01fSmrg s->colormap = NULL; 7264642e01fSmrg s->redisplay_expired = FALSE; 72705b261ecSmrg 72805b261ecSmrg RootlessWrap(pScreen); 72905b261ecSmrg 73005b261ecSmrg if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, 73105b261ecSmrg RootlessWakeupHandler, 73235c4bbdfSmrg (void *) pScreen)) { 73305b261ecSmrg return FALSE; 73405b261ecSmrg } 73505b261ecSmrg 73605b261ecSmrg return TRUE; 73705b261ecSmrg} 7384642e01fSmrg 73935c4bbdfSmrgvoid 74035c4bbdfSmrgRootlessUpdateRooted(Bool state) 74135c4bbdfSmrg{ 7424642e01fSmrg int i; 74335c4bbdfSmrg 74435c4bbdfSmrg if (!state) { 7454642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 74635c4bbdfSmrg RootlessDisableRoot(screenInfo.screens[i]); 7474642e01fSmrg } 74835c4bbdfSmrg else { 7494642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 75035c4bbdfSmrg RootlessEnableRoot(screenInfo.screens[i]); 7514642e01fSmrg } 7524642e01fSmrg} 753