diff options
Diffstat (limited to 'xorg-server/miext/rootless/rootlessScreen.c')
-rw-r--r-- | xorg-server/miext/rootless/rootlessScreen.c | 1509 |
1 files changed, 754 insertions, 755 deletions
diff --git a/xorg-server/miext/rootless/rootlessScreen.c b/xorg-server/miext/rootless/rootlessScreen.c index ca4f00c3e..0801e7206 100644 --- a/xorg-server/miext/rootless/rootlessScreen.c +++ b/xorg-server/miext/rootless/rootlessScreen.c @@ -1,755 +1,754 @@ -/*
- * Screen routines for generic rootless X server
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "mi.h"
-#include "scrnintstr.h"
-#include "gcstruct.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
-#include "propertyst.h"
-#include "mivalidate.h"
-#include "picturestr.h"
-#include "colormapst.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "rootlessCommon.h"
-#include "rootlessWindow.h"
-
-/* In milliseconds */
-#ifndef ROOTLESS_REDISPLAY_DELAY
-#define ROOTLESS_REDISPLAY_DELAY 10
-#endif
-
-extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild,
- VTKind kind);
-extern Bool RootlessCreateGC(GCPtr pGC);
-
-// Initialize globals
-DevPrivateKeyRec rootlessGCPrivateKeyRec;
-DevPrivateKeyRec rootlessScreenPrivateKeyRec;
-DevPrivateKeyRec rootlessWindowPrivateKeyRec;
-DevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec;
-
-/*
- * RootlessUpdateScreenPixmap
- * miCreateScreenResources does not like a null framebuffer pointer,
- * it leaves the screen pixmap with an uninitialized data pointer.
- * Thus, rootless implementations typically set the framebuffer width
- * to zero so that miCreateScreenResources does not allocate a screen
- * pixmap for us. We allocate our own screen pixmap here since we need
- * the screen pixmap to be valid (e.g. CopyArea from the root window).
- */
-void
-RootlessUpdateScreenPixmap(ScreenPtr pScreen)
-{
- RootlessScreenRec *s = SCREENREC(pScreen);
- PixmapPtr pPix;
- unsigned int rowbytes;
-
- pPix = (*pScreen->GetScreenPixmap)(pScreen);
- if (pPix == NULL) {
- pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0);
- (*pScreen->SetScreenPixmap)(pPix);
- }
-
- rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth);
-
- if (s->pixmap_data_size < rowbytes) {
- free(s->pixmap_data);
-
- s->pixmap_data_size = rowbytes;
- s->pixmap_data = malloc(s->pixmap_data_size);
- if (s->pixmap_data == NULL)
- return;
-
- memset(s->pixmap_data, 0xFF, s->pixmap_data_size);
-
- pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height,
- pScreen->rootDepth,
- BitsPerPixel(pScreen->rootDepth),
- 0, s->pixmap_data);
- /* ModifyPixmapHeader ignores zero arguments, so install rowbytes
- by hand. */
- pPix->devKind = 0;
- }
-}
-
-
-/*
- * RootlessCreateScreenResources
- * Rootless implementations typically set a null framebuffer pointer, which
- * causes problems with miCreateScreenResources. We fix things up here.
- */
-static Bool
-RootlessCreateScreenResources(ScreenPtr pScreen)
-{
- Bool ret = TRUE;
-
- SCREEN_UNWRAP(pScreen, CreateScreenResources);
-
- if (pScreen->CreateScreenResources != NULL)
- ret = (*pScreen->CreateScreenResources)(pScreen);
-
- SCREEN_WRAP(pScreen, CreateScreenResources);
-
- if (!ret)
- return ret;
-
- /* Make sure we have a valid screen pixmap. */
-
- RootlessUpdateScreenPixmap(pScreen);
-
- return ret;
-}
-
-
-static Bool
-RootlessCloseScreen(int i, ScreenPtr pScreen)
-{
- RootlessScreenRec *s;
-
- s = SCREENREC(pScreen);
-
- // fixme unwrap everything that was wrapped?
- pScreen->CloseScreen = s->CloseScreen;
-
- if (s->pixmap_data != NULL) {
- free(s->pixmap_data);
- s->pixmap_data = NULL;
- s->pixmap_data_size = 0;
- }
-
- free(s);
- return pScreen->CloseScreen(i, pScreen);
-}
-
-
-static void
-RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
- unsigned int format, unsigned long planeMask, char *pdstLine)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- SCREEN_UNWRAP(pScreen, GetImage);
-
- if (pDrawable->type == DRAWABLE_WINDOW) {
- int x0, y0, x1, y1;
- RootlessWindowRec *winRec;
-
- // Many apps use GetImage to sync with the visible frame buffer
- // FIXME: entire screen or just window or all screens?
- RootlessRedisplayScreen(pScreen);
-
- // RedisplayScreen stops drawing, so we need to start it again
- RootlessStartDrawing((WindowPtr)pDrawable);
-
- /* Check that we have some place to read from. */
- winRec = WINREC(TopLevelParent((WindowPtr) pDrawable));
- if (winRec == NULL)
- goto out;
-
- /* Clip to top-level window bounds. */
- /* FIXME: fbGetImage uses the width parameter to calculate the
- stride of the destination pixmap. If w is clipped, the data
- returned will be garbage, although we will not crash. */
-
- x0 = pDrawable->x + sx;
- y0 = pDrawable->y + sy;
- x1 = x0 + w;
- y1 = y0 + h;
-
- x0 = max (x0, winRec->x);
- y0 = max (y0, winRec->y);
- x1 = min (x1, winRec->x + winRec->width);
- y1 = min (y1, winRec->y + winRec->height);
-
- sx = x0 - pDrawable->x;
- sy = y0 - pDrawable->y;
- w = x1 - x0;
- h = y1 - y0;
-
- if (w <= 0 || h <= 0)
- goto out;
- }
-
- pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
-
-out:
- SCREEN_WRAP(pScreen, GetImage);
-}
-
-
-/*
- * RootlessSourceValidate
- * CopyArea and CopyPlane use a GC tied to the destination drawable.
- * StartDrawing/StopDrawing wrappers won't be called if source is
- * a visible window but the destination isn't. So, we call StartDrawing
- * here and leave StopDrawing for the block handler.
- */
-static void
-RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h,
- unsigned int subWindowMode)
-{
- SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
- if (pDrawable->type == DRAWABLE_WINDOW) {
- WindowPtr pWin = (WindowPtr)pDrawable;
- RootlessStartDrawing(pWin);
- }
- if (pDrawable->pScreen->SourceValidate) {
- pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, subWindowMode);
- }
- SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
-}
-
-static void
-RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
- INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
- INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- WindowPtr srcWin, dstWin, maskWin = NULL;
-
- if (pMask) { // pMask can be NULL
- maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ?
- (WindowPtr)pMask->pDrawable : NULL;
- }
- srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
- (WindowPtr)pSrc->pDrawable : NULL;
- dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
- (WindowPtr)pDst->pDrawable : NULL;
-
- // SCREEN_UNWRAP(ps, Composite);
- ps->Composite = SCREENREC(pScreen)->Composite;
-
- if (srcWin && IsFramedWindow(srcWin))
- RootlessStartDrawing(srcWin);
- if (maskWin && IsFramedWindow(maskWin))
- RootlessStartDrawing(maskWin);
- if (dstWin && IsFramedWindow(dstWin))
- RootlessStartDrawing(dstWin);
-
- ps->Composite(op, pSrc, pMask, pDst,
- xSrc, ySrc, xMask, yMask,
- xDst, yDst, width, height);
-
- if (dstWin && IsFramedWindow(dstWin)) {
- RootlessDamageRect(dstWin, xDst, yDst, width, height);
- }
-
- ps->Composite = RootlessComposite;
- // SCREEN_WRAP(ps, Composite);
-}
-
-
-static void
-RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
- int nlist, GlyphListPtr list, GlyphPtr *glyphs)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- int x, y;
- int n;
- GlyphPtr glyph;
- WindowPtr srcWin, dstWin;
-
- srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
- (WindowPtr)pSrc->pDrawable : NULL;
- dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
- (WindowPtr)pDst->pDrawable : NULL;
-
- if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
- if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);
-
- //SCREEN_UNWRAP(ps, Glyphs);
- ps->Glyphs = SCREENREC(pScreen)->Glyphs;
- ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
- ps->Glyphs = RootlessGlyphs;
- //SCREEN_WRAP(ps, Glyphs);
-
- if (dstWin && IsFramedWindow(dstWin)) {
- x = xSrc;
- y = ySrc;
-
- while (nlist--) {
- x += list->xOff;
- y += list->yOff;
- n = list->len;
-
- /* Calling DamageRect for the bounding box of each glyph is
- inefficient. So compute the union of all glyphs in a list
- and damage that. */
-
- if (n > 0) {
- BoxRec box;
-
- glyph = *glyphs++;
-
- box.x1 = x - glyph->info.x;
- box.y1 = y - glyph->info.y;
- box.x2 = box.x1 + glyph->info.width;
- box.y2 = box.y2 + glyph->info.height;
-
- x += glyph->info.xOff;
- y += glyph->info.yOff;
-
- while (--n > 0) {
- short x1, y1, x2, y2;
-
- glyph = *glyphs++;
-
- x1 = x - glyph->info.x;
- y1 = y - glyph->info.y;
- x2 = x1 + glyph->info.width;
- y2 = y1 + glyph->info.height;
-
- box.x1 = max (box.x1, x1);
- box.y1 = max (box.y1, y1);
- box.x2 = max (box.x2, x2);
- box.y2 = max (box.y2, y2);
-
- x += glyph->info.xOff;
- y += glyph->info.yOff;
- }
-
- RootlessDamageBox(dstWin, &box);
- }
- list++;
- }
- }
-}
-
-
-/*
- * RootlessValidateTree
- * ValidateTree is modified in two ways:
- * - top-level windows don't clip each other
- * - windows aren't clipped against root.
- * These only matter when validating from the root.
- */
-static int
-RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
-{
- int result;
- RegionRec saveRoot;
- ScreenPtr pScreen = pParent->drawable.pScreen;
-
- SCREEN_UNWRAP(pScreen, ValidateTree);
- RL_DEBUG_MSG("VALIDATETREE start ");
-
- // Use our custom version to validate from root
- if (IsRoot(pParent)) {
- RL_DEBUG_MSG("custom ");
- result = RootlessMiValidateTree(pParent, pChild, kind);
- } else {
- HUGE_ROOT(pParent);
- result = pScreen->ValidateTree(pParent, pChild, kind);
- NORMAL_ROOT(pParent);
- }
-
- SCREEN_WRAP(pScreen, ValidateTree);
- RL_DEBUG_MSG("VALIDATETREE end\n");
-
- return result;
-}
-
-
-/*
- * RootlessMarkOverlappedWindows
- * MarkOverlappedWindows is modified to ignore overlapping
- * top-level windows.
- */
-static Bool
-RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
- WindowPtr *ppLayerWin)
-{
- RegionRec saveRoot;
- Bool result;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- SCREEN_UNWRAP(pScreen, MarkOverlappedWindows);
- RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start ");
-
- HUGE_ROOT(pWin);
- if (IsRoot(pWin)) {
- // root - mark nothing
- RL_DEBUG_MSG("is root not marking ");
- result = FALSE;
- }
- else if (! IsTopLevel(pWin)) {
- // not top-level window - mark normally
- result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin);
- }
- else {
- //top-level window - mark children ONLY - NO overlaps with sibs (?)
- // This code copied from miMarkOverlappedWindows()
-
- register WindowPtr pChild;
- Bool anyMarked = FALSE;
- MarkWindowProcPtr MarkWindow = pScreen->MarkWindow;
-
- RL_DEBUG_MSG("is top level! ");
- /* single layered systems are easy */
- if (ppLayerWin) *ppLayerWin = pWin;
-
- if (pWin == pFirst) {
- /* Blindly mark pWin and all of its inferiors. This is a slight
- * overkill if there are mapped windows that outside pWin's border,
- * but it's better than wasting time on RectIn checks.
- */
- pChild = pWin;
- while (1) {
- if (pChild->viewable) {
- if (RegionBroken(&pChild->winSize))
- SetWinSize (pChild);
- if (RegionBroken(&pChild->borderSize))
- SetBorderSize (pChild);
- (* MarkWindow)(pChild);
- if (pChild->firstChild) {
- pChild = pChild->firstChild;
- continue;
- }
- }
- while (!pChild->nextSib && (pChild != pWin))
- pChild = pChild->parent;
- if (pChild == pWin)
- break;
- pChild = pChild->nextSib;
- }
- anyMarked = TRUE;
- pFirst = pFirst->nextSib;
- }
- if (anyMarked)
- (* MarkWindow)(pWin->parent);
- result = anyMarked;
- }
- NORMAL_ROOT(pWin);
- SCREEN_WRAP(pScreen, MarkOverlappedWindows);
- RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n");
-
- return result;
-}
-
-static void expose_1 (WindowPtr pWin) {
- WindowPtr pChild;
-
- if (!pWin->realized)
- return;
-
- miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND);
-
- /* FIXME: comments in windowstr.h indicate that borderClip doesn't
- include subwindow visibility. But I'm not so sure.. so we may
- be exposing too much.. */
-
- miSendExposures (pWin, &pWin->borderClip,
- pWin->drawable.x, pWin->drawable.y);
-
- for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib)
- expose_1 (pChild);
-}
-
-void
-RootlessScreenExpose (ScreenPtr pScreen)
-{
- expose_1 (pScreen->root);
-}
-
-
-ColormapPtr
-RootlessGetColormap (ScreenPtr pScreen)
-{
- RootlessScreenRec *s = SCREENREC (pScreen);
-
- return s->colormap;
-}
-
-static void
-RootlessInstallColormap (ColormapPtr pMap)
-{
- ScreenPtr pScreen = pMap->pScreen;
- RootlessScreenRec *s = SCREENREC (pScreen);
-
- SCREEN_UNWRAP(pScreen, InstallColormap);
-
- if (s->colormap != pMap) {
- s->colormap = pMap;
- s->colormap_changed = TRUE;
- RootlessQueueRedisplay (pScreen);
- }
-
- pScreen->InstallColormap (pMap);
-
- SCREEN_WRAP (pScreen, InstallColormap);
-}
-
-static void
-RootlessUninstallColormap (ColormapPtr pMap)
-{
- ScreenPtr pScreen = pMap->pScreen;
- RootlessScreenRec *s = SCREENREC (pScreen);
-
- SCREEN_UNWRAP(pScreen, UninstallColormap);
-
- if (s->colormap == pMap)
- s->colormap = NULL;
-
- pScreen->UninstallColormap (pMap);
-
- SCREEN_WRAP(pScreen, UninstallColormap);
-}
-
-static void
-RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
-{
- ScreenPtr pScreen = pMap->pScreen;
- RootlessScreenRec *s = SCREENREC (pScreen);
-
- SCREEN_UNWRAP(pScreen, StoreColors);
-
- if (s->colormap == pMap && ndef > 0) {
- s->colormap_changed = TRUE;
- RootlessQueueRedisplay (pScreen);
- }
-
- pScreen->StoreColors (pMap, ndef, pdef);
-
- SCREEN_WRAP(pScreen, StoreColors);
-}
-
-
-static CARD32
-RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg)
-{
- RootlessScreenRec *screenRec = arg;
-
- if (!screenRec->redisplay_queued) {
- /* No update needed. Stop the timer. */
-
- screenRec->redisplay_timer_set = FALSE;
- return 0;
- }
-
- screenRec->redisplay_queued = FALSE;
-
- /* Mark that we should redisplay before waiting for I/O next time */
- screenRec->redisplay_expired = TRUE;
-
- /* Reinstall the timer immediately, so we get as close to our
- redisplay interval as possible. */
-
- return ROOTLESS_REDISPLAY_DELAY;
-}
-
-
-/*
- * RootlessQueueRedisplay
- * Queue a redisplay after a timer delay to ensure we do not redisplay
- * too frequently.
- */
-void
-RootlessQueueRedisplay(ScreenPtr pScreen)
-{
- RootlessScreenRec *screenRec = SCREENREC(pScreen);
-
- screenRec->redisplay_queued = TRUE;
-
- if (screenRec->redisplay_timer_set)
- return;
-
- screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer,
- 0, ROOTLESS_REDISPLAY_DELAY,
- RootlessRedisplayCallback,
- screenRec);
- screenRec->redisplay_timer_set = TRUE;
-}
-
-
-/*
- * RootlessBlockHandler
- * If the redisplay timer has expired, flush drawing before blocking
- * on select().
- */
-static void
-RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask)
-{
- ScreenPtr pScreen = pbdata;
- RootlessScreenRec *screenRec = SCREENREC(pScreen);
-
- if (screenRec->redisplay_expired) {
- screenRec->redisplay_expired = FALSE;
-
- RootlessRedisplayScreen(pScreen);
- }
-}
-
-
-static void
-RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask)
-{
- // nothing here
-}
-
-
-static Bool
-RootlessAllocatePrivates(ScreenPtr pScreen)
-{
- RootlessScreenRec *s;
-
- if (!dixRegisterPrivateKey(&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec)))
- return FALSE;
- if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
- if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
- return FALSE;
- if (!dixRegisterPrivateKey(&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0))
- return FALSE;
-
- s = malloc(sizeof(RootlessScreenRec));
- if (! s) return FALSE;
- SETSCREENREC(pScreen, s);
-
- s->pixmap_data = NULL;
- s->pixmap_data_size = 0;
-
- s->redisplay_timer = NULL;
- s->redisplay_timer_set = FALSE;
-
- return TRUE;
-}
-
-
-static void
-RootlessWrap(ScreenPtr pScreen)
-{
- RootlessScreenRec *s = SCREENREC(pScreen);
-
-#define WRAP(a) \
- if (pScreen->a) { \
- s->a = pScreen->a; \
- } else { \
- RL_DEBUG_MSG("null screen fn " #a "\n"); \
- s->a = NULL; \
- } \
- pScreen->a = Rootless##a
-
- WRAP(CreateScreenResources);
- WRAP(CloseScreen);
- WRAP(CreateGC);
- WRAP(CopyWindow);
- WRAP(GetImage);
- WRAP(SourceValidate);
- WRAP(CreateWindow);
- WRAP(DestroyWindow);
- WRAP(RealizeWindow);
- WRAP(UnrealizeWindow);
- WRAP(MoveWindow);
- WRAP(PositionWindow);
- WRAP(ResizeWindow);
- WRAP(RestackWindow);
- WRAP(ReparentWindow);
- WRAP(ChangeBorderWidth);
- WRAP(MarkOverlappedWindows);
- WRAP(ValidateTree);
- WRAP(ChangeWindowAttributes);
- WRAP(InstallColormap);
- WRAP(UninstallColormap);
- WRAP(StoreColors);
-
- WRAP(SetShape);
-
- {
- // Composite and Glyphs don't use normal screen wrapping
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- s->Composite = ps->Composite;
- ps->Composite = RootlessComposite;
- s->Glyphs = ps->Glyphs;
- ps->Glyphs = RootlessGlyphs;
- }
-
- // WRAP(ClearToBackground); fixme put this back? useful for shaped wins?
-
-#undef WRAP
-}
-
-
-/*
- * RootlessInit
- * Called by the rootless implementation to initialize the rootless layer.
- * Rootless wraps lots of stuff and needs a bunch of devPrivates.
- */
-Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs)
-{
- RootlessScreenRec *s;
-
- if (!RootlessAllocatePrivates(pScreen))
- return FALSE;
-
- s = SCREENREC(pScreen);
-
- s->imp = procs;
- s->colormap = NULL;
- s->redisplay_expired = FALSE;
-
- RootlessWrap(pScreen);
-
- if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler,
- RootlessWakeupHandler,
- (pointer) pScreen))
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-void RootlessUpdateRooted (Bool state) {
- int i;
-
- if (!state)
- {
- for (i = 0; i < screenInfo.numScreens; i++)
- RootlessDisableRoot (screenInfo.screens[i]);
- }
- else
- {
- for (i = 0; i < screenInfo.numScreens; i++)
- RootlessEnableRoot (screenInfo.screens[i]);
- }
-}
+/* + * Screen routines for generic rootless X server + */ +/* + * Copyright (c) 2001 Greg Parker. All Rights Reserved. + * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "mi.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "mivalidate.h" +#include "picturestr.h" +#include "colormapst.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> + +#include "rootlessCommon.h" +#include "rootlessWindow.h" + +/* In milliseconds */ +#ifndef ROOTLESS_REDISPLAY_DELAY +#define ROOTLESS_REDISPLAY_DELAY 10 +#endif + +extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, + VTKind kind); +extern Bool RootlessCreateGC(GCPtr pGC); + +// Initialize globals +DevPrivateKeyRec rootlessGCPrivateKeyRec; +DevPrivateKeyRec rootlessScreenPrivateKeyRec; +DevPrivateKeyRec rootlessWindowPrivateKeyRec; +DevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec; + +/* + * RootlessUpdateScreenPixmap + * miCreateScreenResources does not like a null framebuffer pointer, + * it leaves the screen pixmap with an uninitialized data pointer. + * Thus, rootless implementations typically set the framebuffer width + * to zero so that miCreateScreenResources does not allocate a screen + * pixmap for us. We allocate our own screen pixmap here since we need + * the screen pixmap to be valid (e.g. CopyArea from the root window). + */ +void +RootlessUpdateScreenPixmap(ScreenPtr pScreen) +{ + RootlessScreenRec *s = SCREENREC(pScreen); + PixmapPtr pPix; + unsigned int rowbytes; + + pPix = (*pScreen->GetScreenPixmap)(pScreen); + if (pPix == NULL) { + pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); + (*pScreen->SetScreenPixmap)(pPix); + } + + rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); + + if (s->pixmap_data_size < rowbytes) { + free(s->pixmap_data); + + s->pixmap_data_size = rowbytes; + s->pixmap_data = malloc(s->pixmap_data_size); + if (s->pixmap_data == NULL) + return; + + memset(s->pixmap_data, 0xFF, s->pixmap_data_size); + + pScreen->ModifyPixmapHeader(pPix, pScreen->width, pScreen->height, + pScreen->rootDepth, + BitsPerPixel(pScreen->rootDepth), + 0, s->pixmap_data); + /* ModifyPixmapHeader ignores zero arguments, so install rowbytes + by hand. */ + pPix->devKind = 0; + } +} + + +/* + * RootlessCreateScreenResources + * Rootless implementations typically set a null framebuffer pointer, which + * causes problems with miCreateScreenResources. We fix things up here. + */ +static Bool +RootlessCreateScreenResources(ScreenPtr pScreen) +{ + Bool ret = TRUE; + + SCREEN_UNWRAP(pScreen, CreateScreenResources); + + if (pScreen->CreateScreenResources != NULL) + ret = (*pScreen->CreateScreenResources)(pScreen); + + SCREEN_WRAP(pScreen, CreateScreenResources); + + if (!ret) + return ret; + + /* Make sure we have a valid screen pixmap. */ + + RootlessUpdateScreenPixmap(pScreen); + + return ret; +} + + +static Bool +RootlessCloseScreen(int i, ScreenPtr pScreen) +{ + RootlessScreenRec *s; + + s = SCREENREC(pScreen); + + // fixme unwrap everything that was wrapped? + pScreen->CloseScreen = s->CloseScreen; + + if (s->pixmap_data != NULL) { + free(s->pixmap_data); + s->pixmap_data = NULL; + s->pixmap_data_size = 0; + } + + free(s); + return pScreen->CloseScreen(i, pScreen); +} + + +static void +RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planeMask, char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + SCREEN_UNWRAP(pScreen, GetImage); + + if (pDrawable->type == DRAWABLE_WINDOW) { + int x0, y0, x1, y1; + RootlessWindowRec *winRec; + + // Many apps use GetImage to sync with the visible frame buffer + // FIXME: entire screen or just window or all screens? + RootlessRedisplayScreen(pScreen); + + // RedisplayScreen stops drawing, so we need to start it again + RootlessStartDrawing((WindowPtr)pDrawable); + + /* Check that we have some place to read from. */ + winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); + if (winRec == NULL) + goto out; + + /* Clip to top-level window bounds. */ + /* FIXME: fbGetImage uses the width parameter to calculate the + stride of the destination pixmap. If w is clipped, the data + returned will be garbage, although we will not crash. */ + + x0 = pDrawable->x + sx; + y0 = pDrawable->y + sy; + x1 = x0 + w; + y1 = y0 + h; + + x0 = max (x0, winRec->x); + y0 = max (y0, winRec->y); + x1 = min (x1, winRec->x + winRec->width); + y1 = min (y1, winRec->y + winRec->height); + + sx = x0 - pDrawable->x; + sy = y0 - pDrawable->y; + w = x1 - x0; + h = y1 - y0; + + if (w <= 0 || h <= 0) + goto out; + } + + pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); + +out: + SCREEN_WRAP(pScreen, GetImage); +} + + +/* + * RootlessSourceValidate + * CopyArea and CopyPlane use a GC tied to the destination drawable. + * StartDrawing/StopDrawing wrappers won't be called if source is + * a visible window but the destination isn't. So, we call StartDrawing + * here and leave StopDrawing for the block handler. + */ +static void +RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h, + unsigned int subWindowMode) +{ + SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); + if (pDrawable->type == DRAWABLE_WINDOW) { + WindowPtr pWin = (WindowPtr)pDrawable; + RootlessStartDrawing(pWin); + } + if (pDrawable->pScreen->SourceValidate) { + pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, subWindowMode); + } + SCREEN_WRAP(pDrawable->pScreen, SourceValidate); +} + +static void +RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, + INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, + INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + WindowPtr srcWin, dstWin, maskWin = NULL; + + if (pMask) { // pMask can be NULL + maskWin = (pMask->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pMask->pDrawable : NULL; + } + srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pSrc->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pDst->pDrawable : NULL; + + // SCREEN_UNWRAP(ps, Composite); + ps->Composite = SCREENREC(pScreen)->Composite; + + if (srcWin && IsFramedWindow(srcWin)) + RootlessStartDrawing(srcWin); + if (maskWin && IsFramedWindow(maskWin)) + RootlessStartDrawing(maskWin); + if (dstWin && IsFramedWindow(dstWin)) + RootlessStartDrawing(dstWin); + + ps->Composite(op, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, + xDst, yDst, width, height); + + if (dstWin && IsFramedWindow(dstWin)) { + RootlessDamageRect(dstWin, xDst, yDst, width, height); + } + + ps->Composite = RootlessComposite; + // SCREEN_WRAP(ps, Composite); +} + + +static void +RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, + int nlist, GlyphListPtr list, GlyphPtr *glyphs) +{ + ScreenPtr pScreen = pDst->pDrawable->pScreen; + PictureScreenPtr ps = GetPictureScreen(pScreen); + int x, y; + int n; + GlyphPtr glyph; + WindowPtr srcWin, dstWin; + + srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pSrc->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr)pDst->pDrawable : NULL; + + if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); + if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); + + //SCREEN_UNWRAP(ps, Glyphs); + ps->Glyphs = SCREENREC(pScreen)->Glyphs; + ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); + ps->Glyphs = RootlessGlyphs; + //SCREEN_WRAP(ps, Glyphs); + + if (dstWin && IsFramedWindow(dstWin)) { + x = xSrc; + y = ySrc; + + while (nlist--) { + x += list->xOff; + y += list->yOff; + n = list->len; + + /* Calling DamageRect for the bounding box of each glyph is + inefficient. So compute the union of all glyphs in a list + and damage that. */ + + if (n > 0) { + BoxRec box; + + glyph = *glyphs++; + + box.x1 = x - glyph->info.x; + box.y1 = y - glyph->info.y; + box.x2 = box.x1 + glyph->info.width; + box.y2 = box.y1 + glyph->info.height; + + x += glyph->info.xOff; + y += glyph->info.yOff; + + while (--n > 0) { + short x1, y1, x2, y2; + + glyph = *glyphs++; + + x1 = x - glyph->info.x; + y1 = y - glyph->info.y; + x2 = x1 + glyph->info.width; + y2 = y1 + glyph->info.height; + + box.x1 = max (box.x1, x1); + box.y1 = max (box.y1, y1); + box.x2 = max (box.x2, x2); + box.y2 = max (box.y2, y2); + + x += glyph->info.xOff; + y += glyph->info.yOff; + } + + RootlessDamageBox(dstWin, &box); + } + list++; + } + } +} + + +/* + * RootlessValidateTree + * ValidateTree is modified in two ways: + * - top-level windows don't clip each other + * - windows aren't clipped against root. + * These only matter when validating from the root. + */ +static int +RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) +{ + int result; + RegionRec saveRoot; + ScreenPtr pScreen = pParent->drawable.pScreen; + + SCREEN_UNWRAP(pScreen, ValidateTree); + RL_DEBUG_MSG("VALIDATETREE start "); + + // Use our custom version to validate from root + if (IsRoot(pParent)) { + RL_DEBUG_MSG("custom "); + result = RootlessMiValidateTree(pParent, pChild, kind); + } else { + HUGE_ROOT(pParent); + result = pScreen->ValidateTree(pParent, pChild, kind); + NORMAL_ROOT(pParent); + } + + SCREEN_WRAP(pScreen, ValidateTree); + RL_DEBUG_MSG("VALIDATETREE end\n"); + + return result; +} + + +/* + * RootlessMarkOverlappedWindows + * MarkOverlappedWindows is modified to ignore overlapping + * top-level windows. + */ +static Bool +RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, + WindowPtr *ppLayerWin) +{ + RegionRec saveRoot; + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); + RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); + + HUGE_ROOT(pWin); + if (IsRoot(pWin)) { + // root - mark nothing + RL_DEBUG_MSG("is root not marking "); + result = FALSE; + } + else if (! IsTopLevel(pWin)) { + // not top-level window - mark normally + result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); + } + else { + //top-level window - mark children ONLY - NO overlaps with sibs (?) + // This code copied from miMarkOverlappedWindows() + + register WindowPtr pChild; + Bool anyMarked = FALSE; + MarkWindowProcPtr MarkWindow = pScreen->MarkWindow; + + RL_DEBUG_MSG("is top level! "); + /* single layered systems are easy */ + if (ppLayerWin) *ppLayerWin = pWin; + + if (pWin == pFirst) { + /* Blindly mark pWin and all of its inferiors. This is a slight + * overkill if there are mapped windows that outside pWin's border, + * but it's better than wasting time on RectIn checks. + */ + pChild = pWin; + while (1) { + if (pChild->viewable) { + if (RegionBroken(&pChild->winSize)) + SetWinSize (pChild); + if (RegionBroken(&pChild->borderSize)) + SetBorderSize (pChild); + (* MarkWindow)(pChild); + if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pWin)) + pChild = pChild->parent; + if (pChild == pWin) + break; + pChild = pChild->nextSib; + } + anyMarked = TRUE; + } + if (anyMarked) + (* MarkWindow)(pWin->parent); + result = anyMarked; + } + NORMAL_ROOT(pWin); + SCREEN_WRAP(pScreen, MarkOverlappedWindows); + RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS end\n"); + + return result; +} + +static void expose_1 (WindowPtr pWin) { + WindowPtr pChild; + + if (!pWin->realized) + return; + + miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); + + /* FIXME: comments in windowstr.h indicate that borderClip doesn't + include subwindow visibility. But I'm not so sure.. so we may + be exposing too much.. */ + + miSendExposures (pWin, &pWin->borderClip, + pWin->drawable.x, pWin->drawable.y); + + for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) + expose_1 (pChild); +} + +void +RootlessScreenExpose (ScreenPtr pScreen) +{ + expose_1 (pScreen->root); +} + + +ColormapPtr +RootlessGetColormap (ScreenPtr pScreen) +{ + RootlessScreenRec *s = SCREENREC (pScreen); + + return s->colormap; +} + +static void +RootlessInstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, InstallColormap); + + if (s->colormap != pMap) { + s->colormap = pMap; + s->colormap_changed = TRUE; + RootlessQueueRedisplay (pScreen); + } + + pScreen->InstallColormap (pMap); + + SCREEN_WRAP (pScreen, InstallColormap); +} + +static void +RootlessUninstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, UninstallColormap); + + if (s->colormap == pMap) + s->colormap = NULL; + + pScreen->UninstallColormap (pMap); + + SCREEN_WRAP(pScreen, UninstallColormap); +} + +static void +RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC (pScreen); + + SCREEN_UNWRAP(pScreen, StoreColors); + + if (s->colormap == pMap && ndef > 0) { + s->colormap_changed = TRUE; + RootlessQueueRedisplay (pScreen); + } + + pScreen->StoreColors (pMap, ndef, pdef); + + SCREEN_WRAP(pScreen, StoreColors); +} + + +static CARD32 +RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) +{ + RootlessScreenRec *screenRec = arg; + + if (!screenRec->redisplay_queued) { + /* No update needed. Stop the timer. */ + + screenRec->redisplay_timer_set = FALSE; + return 0; + } + + screenRec->redisplay_queued = FALSE; + + /* Mark that we should redisplay before waiting for I/O next time */ + screenRec->redisplay_expired = TRUE; + + /* Reinstall the timer immediately, so we get as close to our + redisplay interval as possible. */ + + return ROOTLESS_REDISPLAY_DELAY; +} + + +/* + * RootlessQueueRedisplay + * Queue a redisplay after a timer delay to ensure we do not redisplay + * too frequently. + */ +void +RootlessQueueRedisplay(ScreenPtr pScreen) +{ + RootlessScreenRec *screenRec = SCREENREC(pScreen); + + screenRec->redisplay_queued = TRUE; + + if (screenRec->redisplay_timer_set) + return; + + screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, + 0, ROOTLESS_REDISPLAY_DELAY, + RootlessRedisplayCallback, + screenRec); + screenRec->redisplay_timer_set = TRUE; +} + + +/* + * RootlessBlockHandler + * If the redisplay timer has expired, flush drawing before blocking + * on select(). + */ +static void +RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) +{ + ScreenPtr pScreen = pbdata; + RootlessScreenRec *screenRec = SCREENREC(pScreen); + + if (screenRec->redisplay_expired) { + screenRec->redisplay_expired = FALSE; + + RootlessRedisplayScreen(pScreen); + } +} + + +static void +RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask) +{ + // nothing here +} + + +static Bool +RootlessAllocatePrivates(ScreenPtr pScreen) +{ + RootlessScreenRec *s; + + if (!dixRegisterPrivateKey(&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec))) + return FALSE; + if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + + s = malloc(sizeof(RootlessScreenRec)); + if (! s) return FALSE; + SETSCREENREC(pScreen, s); + + s->pixmap_data = NULL; + s->pixmap_data_size = 0; + + s->redisplay_timer = NULL; + s->redisplay_timer_set = FALSE; + + return TRUE; +} + + +static void +RootlessWrap(ScreenPtr pScreen) +{ + RootlessScreenRec *s = SCREENREC(pScreen); + +#define WRAP(a) \ + if (pScreen->a) { \ + s->a = pScreen->a; \ + } else { \ + RL_DEBUG_MSG("null screen fn " #a "\n"); \ + s->a = NULL; \ + } \ + pScreen->a = Rootless##a + + WRAP(CreateScreenResources); + WRAP(CloseScreen); + WRAP(CreateGC); + WRAP(CopyWindow); + WRAP(GetImage); + WRAP(SourceValidate); + WRAP(CreateWindow); + WRAP(DestroyWindow); + WRAP(RealizeWindow); + WRAP(UnrealizeWindow); + WRAP(MoveWindow); + WRAP(PositionWindow); + WRAP(ResizeWindow); + WRAP(RestackWindow); + WRAP(ReparentWindow); + WRAP(ChangeBorderWidth); + WRAP(MarkOverlappedWindows); + WRAP(ValidateTree); + WRAP(ChangeWindowAttributes); + WRAP(InstallColormap); + WRAP(UninstallColormap); + WRAP(StoreColors); + + WRAP(SetShape); + + { + // Composite and Glyphs don't use normal screen wrapping + PictureScreenPtr ps = GetPictureScreen(pScreen); + s->Composite = ps->Composite; + ps->Composite = RootlessComposite; + s->Glyphs = ps->Glyphs; + ps->Glyphs = RootlessGlyphs; + } + + // WRAP(ClearToBackground); fixme put this back? useful for shaped wins? + +#undef WRAP +} + + +/* + * RootlessInit + * Called by the rootless implementation to initialize the rootless layer. + * Rootless wraps lots of stuff and needs a bunch of devPrivates. + */ +Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) +{ + RootlessScreenRec *s; + + if (!RootlessAllocatePrivates(pScreen)) + return FALSE; + + s = SCREENREC(pScreen); + + s->imp = procs; + s->colormap = NULL; + s->redisplay_expired = FALSE; + + RootlessWrap(pScreen); + + if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, + RootlessWakeupHandler, + (pointer) pScreen)) + { + return FALSE; + } + + return TRUE; +} + +void RootlessUpdateRooted (Bool state) { + int i; + + if (!state) + { + for (i = 0; i < screenInfo.numScreens; i++) + RootlessDisableRoot (screenInfo.screens[i]); + } + else + { + for (i = 0; i < screenInfo.numScreens; i++) + RootlessEnableRoot (screenInfo.screens[i]); + } +} |