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 5405b261ecSmrgextern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, 5505b261ecSmrg VTKind kind); 5605b261ecSmrgextern Bool RootlessCreateGC(GCPtr pGC); 5705b261ecSmrg 5805b261ecSmrg// Initialize globals 596747b715SmrgDevPrivateKeyRec rootlessGCPrivateKeyRec; 606747b715SmrgDevPrivateKeyRec rootlessScreenPrivateKeyRec; 616747b715SmrgDevPrivateKeyRec rootlessWindowPrivateKeyRec; 626747b715SmrgDevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec; 6305b261ecSmrg 6405b261ecSmrg/* 6505b261ecSmrg * RootlessUpdateScreenPixmap 6605b261ecSmrg * miCreateScreenResources does not like a null framebuffer pointer, 6705b261ecSmrg * it leaves the screen pixmap with an uninitialized data pointer. 6805b261ecSmrg * Thus, rootless implementations typically set the framebuffer width 6905b261ecSmrg * to zero so that miCreateScreenResources does not allocate a screen 7005b261ecSmrg * pixmap for us. We allocate our own screen pixmap here since we need 7105b261ecSmrg * the screen pixmap to be valid (e.g. CopyArea from the root window). 7205b261ecSmrg */ 7305b261ecSmrgvoid 7405b261ecSmrgRootlessUpdateScreenPixmap(ScreenPtr pScreen) 7505b261ecSmrg{ 7605b261ecSmrg RootlessScreenRec *s = SCREENREC(pScreen); 7705b261ecSmrg PixmapPtr pPix; 7805b261ecSmrg unsigned int rowbytes; 7905b261ecSmrg 8035c4bbdfSmrg pPix = (*pScreen->GetScreenPixmap) (pScreen); 8105b261ecSmrg if (pPix == NULL) { 8235c4bbdfSmrg pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth, 0); 8335c4bbdfSmrg (*pScreen->SetScreenPixmap) (pPix); 8405b261ecSmrg } 8505b261ecSmrg 8605b261ecSmrg rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); 8705b261ecSmrg 8805b261ecSmrg if (s->pixmap_data_size < rowbytes) { 899ace9065Smrg free(s->pixmap_data); 9005b261ecSmrg 9105b261ecSmrg s->pixmap_data_size = rowbytes; 926747b715Smrg s->pixmap_data = malloc(s->pixmap_data_size); 9305b261ecSmrg if (s->pixmap_data == NULL) 9405b261ecSmrg return; 9505b261ecSmrg 9605b261ecSmrg memset(s->pixmap_data, 0xFF, s->pixmap_data_size); 9705b261ecSmrg 9805b261ecSmrg pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height, 9905b261ecSmrg pScreen->rootDepth, 10005b261ecSmrg BitsPerPixel(pScreen->rootDepth), 10105b261ecSmrg 0, s->pixmap_data); 10205b261ecSmrg /* ModifyPixmapHeader ignores zero arguments, so install rowbytes 10305b261ecSmrg by hand. */ 10405b261ecSmrg pPix->devKind = 0; 10505b261ecSmrg } 10605b261ecSmrg} 10705b261ecSmrg 10805b261ecSmrg/* 10905b261ecSmrg * RootlessCreateScreenResources 11005b261ecSmrg * Rootless implementations typically set a null framebuffer pointer, which 11105b261ecSmrg * causes problems with miCreateScreenResources. We fix things up here. 11205b261ecSmrg */ 11305b261ecSmrgstatic Bool 11405b261ecSmrgRootlessCreateScreenResources(ScreenPtr pScreen) 11505b261ecSmrg{ 11605b261ecSmrg Bool ret = TRUE; 11705b261ecSmrg 11805b261ecSmrg SCREEN_UNWRAP(pScreen, CreateScreenResources); 11905b261ecSmrg 12005b261ecSmrg if (pScreen->CreateScreenResources != NULL) 12135c4bbdfSmrg ret = (*pScreen->CreateScreenResources) (pScreen); 12205b261ecSmrg 12305b261ecSmrg SCREEN_WRAP(pScreen, CreateScreenResources); 12405b261ecSmrg 12505b261ecSmrg if (!ret) 12605b261ecSmrg return ret; 12705b261ecSmrg 12805b261ecSmrg /* Make sure we have a valid screen pixmap. */ 12905b261ecSmrg 13005b261ecSmrg RootlessUpdateScreenPixmap(pScreen); 13105b261ecSmrg 13205b261ecSmrg return ret; 13305b261ecSmrg} 13405b261ecSmrg 13505b261ecSmrgstatic Bool 13635c4bbdfSmrgRootlessCloseScreen(ScreenPtr pScreen) 13705b261ecSmrg{ 13805b261ecSmrg RootlessScreenRec *s; 13905b261ecSmrg 14005b261ecSmrg s = SCREENREC(pScreen); 14105b261ecSmrg 14205b261ecSmrg // fixme unwrap everything that was wrapped? 14305b261ecSmrg pScreen->CloseScreen = s->CloseScreen; 14405b261ecSmrg 14505b261ecSmrg if (s->pixmap_data != NULL) { 1466747b715Smrg free(s->pixmap_data); 14705b261ecSmrg s->pixmap_data = NULL; 14805b261ecSmrg s->pixmap_data_size = 0; 14905b261ecSmrg } 15005b261ecSmrg 1516747b715Smrg free(s); 15235c4bbdfSmrg return pScreen->CloseScreen(pScreen); 15305b261ecSmrg} 15405b261ecSmrg 15505b261ecSmrgstatic void 15605b261ecSmrgRootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, 15705b261ecSmrg unsigned int format, unsigned long planeMask, char *pdstLine) 15805b261ecSmrg{ 15905b261ecSmrg ScreenPtr pScreen = pDrawable->pScreen; 16035c4bbdfSmrg 16105b261ecSmrg SCREEN_UNWRAP(pScreen, GetImage); 16205b261ecSmrg 16305b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 16405b261ecSmrg int x0, y0, x1, y1; 16505b261ecSmrg RootlessWindowRec *winRec; 16605b261ecSmrg 16705b261ecSmrg // Many apps use GetImage to sync with the visible frame buffer 16805b261ecSmrg // FIXME: entire screen or just window or all screens? 16905b261ecSmrg RootlessRedisplayScreen(pScreen); 17005b261ecSmrg 17105b261ecSmrg // RedisplayScreen stops drawing, so we need to start it again 17235c4bbdfSmrg RootlessStartDrawing((WindowPtr) pDrawable); 17305b261ecSmrg 17405b261ecSmrg /* Check that we have some place to read from. */ 17505b261ecSmrg winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); 17605b261ecSmrg if (winRec == NULL) 17705b261ecSmrg goto out; 17805b261ecSmrg 17905b261ecSmrg /* Clip to top-level window bounds. */ 18005b261ecSmrg /* FIXME: fbGetImage uses the width parameter to calculate the 18105b261ecSmrg stride of the destination pixmap. If w is clipped, the data 18205b261ecSmrg returned will be garbage, although we will not crash. */ 18305b261ecSmrg 18405b261ecSmrg x0 = pDrawable->x + sx; 18505b261ecSmrg y0 = pDrawable->y + sy; 18605b261ecSmrg x1 = x0 + w; 18705b261ecSmrg y1 = y0 + h; 18805b261ecSmrg 18935c4bbdfSmrg x0 = max(x0, winRec->x); 19035c4bbdfSmrg y0 = max(y0, winRec->y); 19135c4bbdfSmrg x1 = min(x1, winRec->x + winRec->width); 19235c4bbdfSmrg y1 = min(y1, winRec->y + winRec->height); 19305b261ecSmrg 19405b261ecSmrg sx = x0 - pDrawable->x; 19505b261ecSmrg sy = y0 - pDrawable->y; 19605b261ecSmrg w = x1 - x0; 19705b261ecSmrg h = y1 - y0; 19805b261ecSmrg 19905b261ecSmrg if (w <= 0 || h <= 0) 20005b261ecSmrg goto out; 20105b261ecSmrg } 20205b261ecSmrg 20305b261ecSmrg pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); 20405b261ecSmrg 20535c4bbdfSmrg out: 20605b261ecSmrg SCREEN_WRAP(pScreen, GetImage); 20705b261ecSmrg} 20805b261ecSmrg 20905b261ecSmrg/* 21005b261ecSmrg * RootlessSourceValidate 21105b261ecSmrg * CopyArea and CopyPlane use a GC tied to the destination drawable. 21205b261ecSmrg * StartDrawing/StopDrawing wrappers won't be called if source is 21305b261ecSmrg * a visible window but the destination isn't. So, we call StartDrawing 21405b261ecSmrg * here and leave StopDrawing for the block handler. 21505b261ecSmrg */ 21605b261ecSmrgstatic void 2179ace9065SmrgRootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h, 2189ace9065Smrg unsigned int subWindowMode) 21905b261ecSmrg{ 22005b261ecSmrg SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); 22105b261ecSmrg if (pDrawable->type == DRAWABLE_WINDOW) { 22235c4bbdfSmrg WindowPtr pWin = (WindowPtr) pDrawable; 22335c4bbdfSmrg 22405b261ecSmrg RootlessStartDrawing(pWin); 22505b261ecSmrg } 226ed6184dfSmrg pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, 227ed6184dfSmrg subWindowMode); 22805b261ecSmrg SCREEN_WRAP(pDrawable->pScreen, SourceValidate); 22905b261ecSmrg} 23005b261ecSmrg 23105b261ecSmrgstatic void 23205b261ecSmrgRootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, 23335c4bbdfSmrg INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, 23405b261ecSmrg INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) 23505b261ecSmrg{ 23605b261ecSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 23705b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 23805b261ecSmrg WindowPtr srcWin, dstWin, maskWin = NULL; 23905b261ecSmrg 24035c4bbdfSmrg if (pMask) { // pMask can be NULL 24135c4bbdfSmrg maskWin = (pMask->pDrawable && 24235c4bbdfSmrg pMask->pDrawable->type == 24335c4bbdfSmrg DRAWABLE_WINDOW) ? (WindowPtr) pMask->pDrawable : NULL; 24405b261ecSmrg } 24535c4bbdfSmrg srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 24635c4bbdfSmrg (WindowPtr) pSrc->pDrawable : NULL; 24735c4bbdfSmrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 24835c4bbdfSmrg (WindowPtr) pDst->pDrawable : NULL; 24905b261ecSmrg 25005b261ecSmrg // SCREEN_UNWRAP(ps, Composite); 25105b261ecSmrg ps->Composite = SCREENREC(pScreen)->Composite; 25205b261ecSmrg 25335c4bbdfSmrg if (srcWin && IsFramedWindow(srcWin)) 25405b261ecSmrg RootlessStartDrawing(srcWin); 25505b261ecSmrg if (maskWin && IsFramedWindow(maskWin)) 25605b261ecSmrg RootlessStartDrawing(maskWin); 25735c4bbdfSmrg if (dstWin && IsFramedWindow(dstWin)) 25805b261ecSmrg RootlessStartDrawing(dstWin); 25905b261ecSmrg 26005b261ecSmrg ps->Composite(op, pSrc, pMask, pDst, 26135c4bbdfSmrg xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); 26205b261ecSmrg 26335c4bbdfSmrg if (dstWin && IsFramedWindow(dstWin)) { 26405b261ecSmrg RootlessDamageRect(dstWin, xDst, yDst, width, height); 26505b261ecSmrg } 26605b261ecSmrg 26705b261ecSmrg ps->Composite = RootlessComposite; 26805b261ecSmrg // SCREEN_WRAP(ps, Composite); 26905b261ecSmrg} 27005b261ecSmrg 27105b261ecSmrgstatic void 27205b261ecSmrgRootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, 27305b261ecSmrg PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, 27435c4bbdfSmrg int nlist, GlyphListPtr list, GlyphPtr * glyphs) 27505b261ecSmrg{ 27605b261ecSmrg ScreenPtr pScreen = pDst->pDrawable->pScreen; 27705b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 27805b261ecSmrg int x, y; 27905b261ecSmrg int n; 28005b261ecSmrg GlyphPtr glyph; 28105b261ecSmrg WindowPtr srcWin, dstWin; 28205b261ecSmrg 2836747b715Smrg srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? 28435c4bbdfSmrg (WindowPtr) pSrc->pDrawable : NULL; 28505b261ecSmrg dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? 28635c4bbdfSmrg (WindowPtr) pDst->pDrawable : NULL; 28705b261ecSmrg 28835c4bbdfSmrg if (srcWin && IsFramedWindow(srcWin)) 28935c4bbdfSmrg RootlessStartDrawing(srcWin); 29035c4bbdfSmrg if (dstWin && IsFramedWindow(dstWin)) 29135c4bbdfSmrg RootlessStartDrawing(dstWin); 29205b261ecSmrg 29305b261ecSmrg //SCREEN_UNWRAP(ps, Glyphs); 29405b261ecSmrg ps->Glyphs = SCREENREC(pScreen)->Glyphs; 29505b261ecSmrg ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); 29605b261ecSmrg ps->Glyphs = RootlessGlyphs; 29705b261ecSmrg //SCREEN_WRAP(ps, Glyphs); 29805b261ecSmrg 29905b261ecSmrg if (dstWin && IsFramedWindow(dstWin)) { 30005b261ecSmrg x = xSrc; 30105b261ecSmrg y = ySrc; 30205b261ecSmrg 30305b261ecSmrg while (nlist--) { 30405b261ecSmrg x += list->xOff; 30505b261ecSmrg y += list->yOff; 30605b261ecSmrg n = list->len; 30705b261ecSmrg 30805b261ecSmrg /* Calling DamageRect for the bounding box of each glyph is 30905b261ecSmrg inefficient. So compute the union of all glyphs in a list 31005b261ecSmrg and damage that. */ 31105b261ecSmrg 31205b261ecSmrg if (n > 0) { 31305b261ecSmrg BoxRec box; 31405b261ecSmrg 31505b261ecSmrg glyph = *glyphs++; 31605b261ecSmrg 31705b261ecSmrg box.x1 = x - glyph->info.x; 31805b261ecSmrg box.y1 = y - glyph->info.y; 31905b261ecSmrg box.x2 = box.x1 + glyph->info.width; 3209ace9065Smrg box.y2 = box.y1 + glyph->info.height; 32105b261ecSmrg 32205b261ecSmrg x += glyph->info.xOff; 32305b261ecSmrg y += glyph->info.yOff; 32405b261ecSmrg 32505b261ecSmrg while (--n > 0) { 32605b261ecSmrg short x1, y1, x2, y2; 32705b261ecSmrg 32805b261ecSmrg glyph = *glyphs++; 32905b261ecSmrg 33005b261ecSmrg x1 = x - glyph->info.x; 33105b261ecSmrg y1 = y - glyph->info.y; 33205b261ecSmrg x2 = x1 + glyph->info.width; 33305b261ecSmrg y2 = y1 + glyph->info.height; 33405b261ecSmrg 33535c4bbdfSmrg box.x1 = max(box.x1, x1); 33635c4bbdfSmrg box.y1 = max(box.y1, y1); 33735c4bbdfSmrg box.x2 = max(box.x2, x2); 33835c4bbdfSmrg box.y2 = max(box.y2, y2); 33905b261ecSmrg 34005b261ecSmrg x += glyph->info.xOff; 34105b261ecSmrg y += glyph->info.yOff; 34205b261ecSmrg } 34305b261ecSmrg 34405b261ecSmrg RootlessDamageBox(dstWin, &box); 34505b261ecSmrg } 34605b261ecSmrg list++; 34705b261ecSmrg } 34805b261ecSmrg } 34905b261ecSmrg} 35005b261ecSmrg 35105b261ecSmrg/* 35205b261ecSmrg * RootlessValidateTree 35305b261ecSmrg * ValidateTree is modified in two ways: 35405b261ecSmrg * - top-level windows don't clip each other 35505b261ecSmrg * - windows aren't clipped against root. 35605b261ecSmrg * These only matter when validating from the root. 35705b261ecSmrg */ 35805b261ecSmrgstatic int 35905b261ecSmrgRootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) 36005b261ecSmrg{ 36105b261ecSmrg int result; 36205b261ecSmrg RegionRec saveRoot; 36305b261ecSmrg ScreenPtr pScreen = pParent->drawable.pScreen; 36405b261ecSmrg 36505b261ecSmrg SCREEN_UNWRAP(pScreen, ValidateTree); 36605b261ecSmrg RL_DEBUG_MSG("VALIDATETREE start "); 36705b261ecSmrg 36805b261ecSmrg // Use our custom version to validate from root 36905b261ecSmrg if (IsRoot(pParent)) { 37005b261ecSmrg RL_DEBUG_MSG("custom "); 37105b261ecSmrg result = RootlessMiValidateTree(pParent, pChild, kind); 37235c4bbdfSmrg } 37335c4bbdfSmrg else { 37405b261ecSmrg HUGE_ROOT(pParent); 37505b261ecSmrg result = pScreen->ValidateTree(pParent, pChild, kind); 37605b261ecSmrg NORMAL_ROOT(pParent); 37705b261ecSmrg } 37805b261ecSmrg 37905b261ecSmrg SCREEN_WRAP(pScreen, ValidateTree); 38005b261ecSmrg RL_DEBUG_MSG("VALIDATETREE end\n"); 38105b261ecSmrg 38205b261ecSmrg return result; 38305b261ecSmrg} 38405b261ecSmrg 38505b261ecSmrg/* 38605b261ecSmrg * RootlessMarkOverlappedWindows 38705b261ecSmrg * MarkOverlappedWindows is modified to ignore overlapping 38805b261ecSmrg * top-level windows. 38905b261ecSmrg */ 39005b261ecSmrgstatic Bool 39105b261ecSmrgRootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, 39205b261ecSmrg WindowPtr *ppLayerWin) 39305b261ecSmrg{ 39405b261ecSmrg RegionRec saveRoot; 39505b261ecSmrg Bool result; 39605b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 39735c4bbdfSmrg 39805b261ecSmrg SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); 39905b261ecSmrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); 40005b261ecSmrg 40105b261ecSmrg HUGE_ROOT(pWin); 40205b261ecSmrg if (IsRoot(pWin)) { 40305b261ecSmrg // root - mark nothing 40405b261ecSmrg RL_DEBUG_MSG("is root not marking "); 40505b261ecSmrg result = FALSE; 40605b261ecSmrg } 40735c4bbdfSmrg else if (!IsTopLevel(pWin)) { 40805b261ecSmrg // not top-level window - mark normally 40905b261ecSmrg result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); 41005b261ecSmrg } 41105b261ecSmrg else { 41205b261ecSmrg //top-level window - mark children ONLY - NO overlaps with sibs (?) 41305b261ecSmrg // This code copied from miMarkOverlappedWindows() 41405b261ecSmrg 41505b261ecSmrg register WindowPtr pChild; 41605b261ecSmrg Bool anyMarked = FALSE; 4176747b715Smrg MarkWindowProcPtr MarkWindow = pScreen->MarkWindow; 41805b261ecSmrg 41905b261ecSmrg RL_DEBUG_MSG("is top level! "); 42005b261ecSmrg /* single layered systems are easy */ 42135c4bbdfSmrg if (ppLayerWin) 42235c4bbdfSmrg *ppLayerWin = pWin; 42305b261ecSmrg 42405b261ecSmrg if (pWin == pFirst) { 42505b261ecSmrg /* Blindly mark pWin and all of its inferiors. This is a slight 42605b261ecSmrg * overkill if there are mapped windows that outside pWin's border, 42705b261ecSmrg * but it's better than wasting time on RectIn checks. 42805b261ecSmrg */ 42905b261ecSmrg pChild = pWin; 43005b261ecSmrg while (1) { 43105b261ecSmrg if (pChild->viewable) { 4326747b715Smrg if (RegionBroken(&pChild->winSize)) 43335c4bbdfSmrg SetWinSize(pChild); 4346747b715Smrg if (RegionBroken(&pChild->borderSize)) 43535c4bbdfSmrg SetBorderSize(pChild); 43635c4bbdfSmrg (*MarkWindow) (pChild); 43705b261ecSmrg if (pChild->firstChild) { 43805b261ecSmrg pChild = pChild->firstChild; 43905b261ecSmrg continue; 44005b261ecSmrg } 44105b261ecSmrg } 44205b261ecSmrg while (!pChild->nextSib && (pChild != pWin)) 44305b261ecSmrg pChild = pChild->parent; 44405b261ecSmrg if (pChild == pWin) 44505b261ecSmrg break; 44605b261ecSmrg pChild = pChild->nextSib; 44705b261ecSmrg } 44805b261ecSmrg anyMarked = TRUE; 44905b261ecSmrg } 45005b261ecSmrg if (anyMarked) 45135c4bbdfSmrg (*MarkWindow) (pWin->parent); 45205b261ecSmrg result = anyMarked; 45305b261ecSmrg } 45405b261ecSmrg NORMAL_ROOT(pWin); 45505b261ecSmrg SCREEN_WRAP(pScreen, MarkOverlappedWindows); 45605b261ecSmrg RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); 45705b261ecSmrg 45805b261ecSmrg return result; 45905b261ecSmrg} 46005b261ecSmrg 46135c4bbdfSmrgstatic void 46235c4bbdfSmrgexpose_1(WindowPtr pWin) 46335c4bbdfSmrg{ 4644642e01fSmrg WindowPtr pChild; 46535c4bbdfSmrg 4664642e01fSmrg if (!pWin->realized) 4674642e01fSmrg return; 46835c4bbdfSmrg 46935c4bbdfSmrg pWin->drawable.pScreen->PaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); 47035c4bbdfSmrg 4714642e01fSmrg /* FIXME: comments in windowstr.h indicate that borderClip doesn't 47235c4bbdfSmrg include subwindow visibility. But I'm not so sure.. so we may 47335c4bbdfSmrg be exposing too much.. */ 47435c4bbdfSmrg 47535c4bbdfSmrg miSendExposures(pWin, &pWin->borderClip, 47635c4bbdfSmrg pWin->drawable.x, pWin->drawable.y); 47735c4bbdfSmrg 4784642e01fSmrg for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) 47935c4bbdfSmrg expose_1(pChild); 4804642e01fSmrg} 4814642e01fSmrg 4824642e01fSmrgvoid 48335c4bbdfSmrgRootlessScreenExpose(ScreenPtr pScreen) 4844642e01fSmrg{ 48535c4bbdfSmrg expose_1(pScreen->root); 4864642e01fSmrg} 4874642e01fSmrg 4884642e01fSmrgColormapPtr 48935c4bbdfSmrgRootlessGetColormap(ScreenPtr pScreen) 4904642e01fSmrg{ 49135c4bbdfSmrg RootlessScreenRec *s = SCREENREC(pScreen); 4924642e01fSmrg 49335c4bbdfSmrg return s->colormap; 4944642e01fSmrg} 4954642e01fSmrg 4964642e01fSmrgstatic void 49735c4bbdfSmrgRootlessInstallColormap(ColormapPtr pMap) 4984642e01fSmrg{ 49935c4bbdfSmrg ScreenPtr pScreen = pMap->pScreen; 50035c4bbdfSmrg RootlessScreenRec *s = SCREENREC(pScreen); 5014642e01fSmrg 50235c4bbdfSmrg SCREEN_UNWRAP(pScreen, InstallColormap); 5034642e01fSmrg 50435c4bbdfSmrg if (s->colormap != pMap) { 50535c4bbdfSmrg s->colormap = pMap; 50635c4bbdfSmrg s->colormap_changed = TRUE; 50735c4bbdfSmrg RootlessQueueRedisplay(pScreen); 50835c4bbdfSmrg } 5094642e01fSmrg 51035c4bbdfSmrg pScreen->InstallColormap(pMap); 5114642e01fSmrg 51235c4bbdfSmrg SCREEN_WRAP(pScreen, InstallColormap); 5134642e01fSmrg} 5144642e01fSmrg 5154642e01fSmrgstatic void 51635c4bbdfSmrgRootlessUninstallColormap(ColormapPtr pMap) 5174642e01fSmrg{ 51835c4bbdfSmrg ScreenPtr pScreen = pMap->pScreen; 51935c4bbdfSmrg RootlessScreenRec *s = SCREENREC(pScreen); 5204642e01fSmrg 52135c4bbdfSmrg SCREEN_UNWRAP(pScreen, UninstallColormap); 5224642e01fSmrg 52335c4bbdfSmrg if (s->colormap == pMap) 52435c4bbdfSmrg s->colormap = NULL; 5254642e01fSmrg 52635c4bbdfSmrg pScreen->UninstallColormap(pMap); 5274642e01fSmrg 52835c4bbdfSmrg SCREEN_WRAP(pScreen, UninstallColormap); 5294642e01fSmrg} 5304642e01fSmrg 5314642e01fSmrgstatic void 53235c4bbdfSmrgRootlessStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef) 5334642e01fSmrg{ 53435c4bbdfSmrg ScreenPtr pScreen = pMap->pScreen; 53535c4bbdfSmrg RootlessScreenRec *s = SCREENREC(pScreen); 5364642e01fSmrg 53735c4bbdfSmrg SCREEN_UNWRAP(pScreen, StoreColors); 5384642e01fSmrg 53935c4bbdfSmrg if (s->colormap == pMap && ndef > 0) { 54035c4bbdfSmrg s->colormap_changed = TRUE; 54135c4bbdfSmrg RootlessQueueRedisplay(pScreen); 54235c4bbdfSmrg } 5434642e01fSmrg 54435c4bbdfSmrg pScreen->StoreColors(pMap, ndef, pdef); 5454642e01fSmrg 54635c4bbdfSmrg SCREEN_WRAP(pScreen, StoreColors); 5474642e01fSmrg} 5484642e01fSmrg 54905b261ecSmrgstatic CARD32 55005b261ecSmrgRootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) 55105b261ecSmrg{ 55205b261ecSmrg RootlessScreenRec *screenRec = arg; 55305b261ecSmrg 55405b261ecSmrg if (!screenRec->redisplay_queued) { 55505b261ecSmrg /* No update needed. Stop the timer. */ 55605b261ecSmrg 55705b261ecSmrg screenRec->redisplay_timer_set = FALSE; 55805b261ecSmrg return 0; 55905b261ecSmrg } 56005b261ecSmrg 56105b261ecSmrg screenRec->redisplay_queued = FALSE; 56205b261ecSmrg 56305b261ecSmrg /* Mark that we should redisplay before waiting for I/O next time */ 56405b261ecSmrg screenRec->redisplay_expired = TRUE; 56505b261ecSmrg 56605b261ecSmrg /* Reinstall the timer immediately, so we get as close to our 56705b261ecSmrg redisplay interval as possible. */ 56805b261ecSmrg 56905b261ecSmrg return ROOTLESS_REDISPLAY_DELAY; 57005b261ecSmrg} 57105b261ecSmrg 57205b261ecSmrg/* 57305b261ecSmrg * RootlessQueueRedisplay 57405b261ecSmrg * Queue a redisplay after a timer delay to ensure we do not redisplay 57505b261ecSmrg * too frequently. 57605b261ecSmrg */ 57705b261ecSmrgvoid 57805b261ecSmrgRootlessQueueRedisplay(ScreenPtr pScreen) 57905b261ecSmrg{ 58005b261ecSmrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 58105b261ecSmrg 58205b261ecSmrg screenRec->redisplay_queued = TRUE; 58305b261ecSmrg 58405b261ecSmrg if (screenRec->redisplay_timer_set) 58505b261ecSmrg return; 58605b261ecSmrg 58705b261ecSmrg screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, 58805b261ecSmrg 0, ROOTLESS_REDISPLAY_DELAY, 58935c4bbdfSmrg RootlessRedisplayCallback, screenRec); 59005b261ecSmrg screenRec->redisplay_timer_set = TRUE; 59105b261ecSmrg} 59205b261ecSmrg 59305b261ecSmrg/* 59405b261ecSmrg * RootlessBlockHandler 59505b261ecSmrg * If the redisplay timer has expired, flush drawing before blocking 59605b261ecSmrg * on select(). 59705b261ecSmrg */ 59805b261ecSmrgstatic void 5991b5d61b8SmrgRootlessBlockHandler(void *pbdata, void *ptimeout) 60005b261ecSmrg{ 60105b261ecSmrg ScreenPtr pScreen = pbdata; 60205b261ecSmrg RootlessScreenRec *screenRec = SCREENREC(pScreen); 60305b261ecSmrg 60405b261ecSmrg if (screenRec->redisplay_expired) { 60505b261ecSmrg screenRec->redisplay_expired = FALSE; 60605b261ecSmrg 60705b261ecSmrg RootlessRedisplayScreen(pScreen); 60805b261ecSmrg } 60905b261ecSmrg} 61005b261ecSmrg 61105b261ecSmrgstatic void 6121b5d61b8SmrgRootlessWakeupHandler(void *data, int result) 61305b261ecSmrg{ 61405b261ecSmrg // nothing here 61505b261ecSmrg} 61605b261ecSmrg 61705b261ecSmrgstatic Bool 61805b261ecSmrgRootlessAllocatePrivates(ScreenPtr pScreen) 61905b261ecSmrg{ 62005b261ecSmrg RootlessScreenRec *s; 62105b261ecSmrg 62235c4bbdfSmrg if (!dixRegisterPrivateKey 62335c4bbdfSmrg (&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec))) 6246747b715Smrg return FALSE; 6256747b715Smrg if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 6266747b715Smrg return FALSE; 6276747b715Smrg if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) 6286747b715Smrg return FALSE; 62935c4bbdfSmrg if (!dixRegisterPrivateKey 63035c4bbdfSmrg (&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0)) 63105b261ecSmrg return FALSE; 63205b261ecSmrg 6336747b715Smrg s = malloc(sizeof(RootlessScreenRec)); 63435c4bbdfSmrg if (!s) 63535c4bbdfSmrg return FALSE; 6364642e01fSmrg SETSCREENREC(pScreen, s); 63705b261ecSmrg 63805b261ecSmrg s->pixmap_data = NULL; 63905b261ecSmrg s->pixmap_data_size = 0; 64005b261ecSmrg 64105b261ecSmrg s->redisplay_timer = NULL; 64205b261ecSmrg s->redisplay_timer_set = FALSE; 64305b261ecSmrg 64405b261ecSmrg return TRUE; 64505b261ecSmrg} 64605b261ecSmrg 64705b261ecSmrgstatic void 64805b261ecSmrgRootlessWrap(ScreenPtr pScreen) 64905b261ecSmrg{ 6504642e01fSmrg RootlessScreenRec *s = SCREENREC(pScreen); 65105b261ecSmrg 65205b261ecSmrg#define WRAP(a) \ 65305b261ecSmrg if (pScreen->a) { \ 65405b261ecSmrg s->a = pScreen->a; \ 65505b261ecSmrg } else { \ 65605b261ecSmrg RL_DEBUG_MSG("null screen fn " #a "\n"); \ 65705b261ecSmrg s->a = NULL; \ 65805b261ecSmrg } \ 65905b261ecSmrg pScreen->a = Rootless##a 66005b261ecSmrg 66105b261ecSmrg WRAP(CreateScreenResources); 66205b261ecSmrg WRAP(CloseScreen); 66305b261ecSmrg WRAP(CreateGC); 66405b261ecSmrg WRAP(CopyWindow); 66535c4bbdfSmrg WRAP(PaintWindow); 66605b261ecSmrg WRAP(GetImage); 66705b261ecSmrg WRAP(SourceValidate); 66805b261ecSmrg WRAP(CreateWindow); 66905b261ecSmrg WRAP(DestroyWindow); 67005b261ecSmrg WRAP(RealizeWindow); 67105b261ecSmrg WRAP(UnrealizeWindow); 67205b261ecSmrg WRAP(MoveWindow); 67305b261ecSmrg WRAP(PositionWindow); 67405b261ecSmrg WRAP(ResizeWindow); 67505b261ecSmrg WRAP(RestackWindow); 67605b261ecSmrg WRAP(ReparentWindow); 67705b261ecSmrg WRAP(ChangeBorderWidth); 67805b261ecSmrg WRAP(MarkOverlappedWindows); 67905b261ecSmrg WRAP(ValidateTree); 68005b261ecSmrg WRAP(ChangeWindowAttributes); 6814642e01fSmrg WRAP(InstallColormap); 6824642e01fSmrg WRAP(UninstallColormap); 6834642e01fSmrg WRAP(StoreColors); 68405b261ecSmrg 68505b261ecSmrg WRAP(SetShape); 68605b261ecSmrg 68705b261ecSmrg { 68805b261ecSmrg // Composite and Glyphs don't use normal screen wrapping 68905b261ecSmrg PictureScreenPtr ps = GetPictureScreen(pScreen); 69035c4bbdfSmrg 69105b261ecSmrg s->Composite = ps->Composite; 69205b261ecSmrg ps->Composite = RootlessComposite; 69305b261ecSmrg s->Glyphs = ps->Glyphs; 69405b261ecSmrg ps->Glyphs = RootlessGlyphs; 69505b261ecSmrg } 69605b261ecSmrg 69705b261ecSmrg // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? 69805b261ecSmrg 69905b261ecSmrg#undef WRAP 70005b261ecSmrg} 70105b261ecSmrg 70205b261ecSmrg/* 70305b261ecSmrg * RootlessInit 70405b261ecSmrg * Called by the rootless implementation to initialize the rootless layer. 70505b261ecSmrg * Rootless wraps lots of stuff and needs a bunch of devPrivates. 70605b261ecSmrg */ 70735c4bbdfSmrgBool 70835c4bbdfSmrgRootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) 70905b261ecSmrg{ 71005b261ecSmrg RootlessScreenRec *s; 71105b261ecSmrg 71205b261ecSmrg if (!RootlessAllocatePrivates(pScreen)) 71305b261ecSmrg return FALSE; 71405b261ecSmrg 7154642e01fSmrg s = SCREENREC(pScreen); 71605b261ecSmrg 71705b261ecSmrg s->imp = procs; 7184642e01fSmrg s->colormap = NULL; 7194642e01fSmrg s->redisplay_expired = FALSE; 72005b261ecSmrg 72105b261ecSmrg RootlessWrap(pScreen); 72205b261ecSmrg 72305b261ecSmrg if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, 72405b261ecSmrg RootlessWakeupHandler, 72535c4bbdfSmrg (void *) pScreen)) { 72605b261ecSmrg return FALSE; 72705b261ecSmrg } 72805b261ecSmrg 72905b261ecSmrg return TRUE; 73005b261ecSmrg} 7314642e01fSmrg 73235c4bbdfSmrgvoid 73335c4bbdfSmrgRootlessUpdateRooted(Bool state) 73435c4bbdfSmrg{ 7354642e01fSmrg int i; 73635c4bbdfSmrg 73735c4bbdfSmrg if (!state) { 7384642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 73935c4bbdfSmrg RootlessDisableRoot(screenInfo.screens[i]); 7404642e01fSmrg } 74135c4bbdfSmrg else { 7424642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 74335c4bbdfSmrg RootlessEnableRoot(screenInfo.screens[i]); 7444642e01fSmrg } 7454642e01fSmrg} 746