diff options
Diffstat (limited to 'xorg-server/miext/rootless/rootlessCommon.c')
-rw-r--r-- | xorg-server/miext/rootless/rootlessCommon.c | 908 |
1 files changed, 460 insertions, 448 deletions
diff --git a/xorg-server/miext/rootless/rootlessCommon.c b/xorg-server/miext/rootless/rootlessCommon.c index 3ea3e5970..d8f43bd1b 100644 --- a/xorg-server/miext/rootless/rootlessCommon.c +++ b/xorg-server/miext/rootless/rootlessCommon.c @@ -1,448 +1,460 @@ -/*
- * Common rootless definitions and code
- */
-/*
- * 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 <stddef.h> /* For NULL */
-#include <limits.h> /* For CHAR_BIT */
-
-#include "rootlessCommon.h"
-#include "colormapst.h"
-
-unsigned int rootless_CopyBytes_threshold = 0;
-unsigned int rootless_CopyWindow_threshold = 0;
-int rootlessGlobalOffsetX = 0;
-int rootlessGlobalOffsetY = 0;
-
-RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL};
-
-/* Following macro from miregion.c */
-
-/* true iff two Boxes overlap */
-#define EXTENTCHECK(r1,r2) \
- (!( ((r1)->x2 <= (r2)->x1) || \
- ((r1)->x1 >= (r2)->x2) || \
- ((r1)->y2 <= (r2)->y1) || \
- ((r1)->y1 >= (r2)->y2) ) )
-
-
-/*
- * TopLevelParent
- * Returns the top-level parent of pWindow.
- * The root is the top-level parent of itself, even though the root is
- * not otherwise considered to be a top-level window.
- */
-WindowPtr
-TopLevelParent(WindowPtr pWindow)
-{
- WindowPtr top;
-
- if (IsRoot(pWindow))
- return pWindow;
-
- top = pWindow;
- while (top && ! IsTopLevel(top))
- top = top->parent;
-
- return top;
-}
-
-
-/*
- * IsFramedWindow
- * Returns TRUE if this window is visible inside a frame
- * (e.g. it is visible and has a top-level or root parent)
- */
-Bool
-IsFramedWindow(WindowPtr pWin)
-{
- WindowPtr top;
-
- if (!dixPrivateKeyRegistered(&rootlessWindowPrivateKeyRec))
- return FALSE;
-
- if (!pWin->realized)
- return FALSE;
- top = TopLevelParent(pWin);
-
- return (top && WINREC(top));
-}
-
-Bool
-RootlessResolveColormap (ScreenPtr pScreen, int first_color,
- int n_colors, uint32_t *colors)
-{
- int last, i;
- ColormapPtr map;
-
- map = RootlessGetColormap (pScreen);
- if (map == NULL || map->class != PseudoColor) return FALSE;
-
- last = min (map->pVisual->ColormapEntries, first_color + n_colors);
- for (i = max (0, first_color); i < last; i++) {
- Entry *ent = map->red + i;
- uint16_t red, green, blue;
-
- if (!ent->refcnt) continue;
- if (ent->fShared) {
- red = ent->co.shco.red->color;
- green = ent->co.shco.green->color;
- blue = ent->co.shco.blue->color;
- } else {
- red = ent->co.local.red;
- green = ent->co.local.green;
- blue = ent->co.local.blue;
- }
-
- colors[i - first_color] = (0xFF000000UL
- | ((uint32_t) red & 0xff00) << 8
- | (green & 0xff00)
- | (blue >> 8));
- }
-
- return TRUE;
-}
-
-
-/*
- * RootlessStartDrawing
- * Prepare a window for direct access to its backing buffer.
- * Each top-level parent has a Pixmap representing its backing buffer,
- * which all of its children inherit.
- */
-void RootlessStartDrawing(WindowPtr pWindow)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- WindowPtr top = TopLevelParent(pWindow);
- RootlessWindowRec *winRec;
- PixmapPtr curPixmap;
-
- if (top == NULL)
- return;
- winRec = WINREC(top);
- if (winRec == NULL)
- return;
-
- // Make sure the window's top-level parent is prepared for drawing.
- if (!winRec->is_drawing) {
- int bw = wBorderWidth(top);
-
- SCREENREC(pScreen)->imp->StartDrawing(winRec->wid, &winRec->pixelData,
- &winRec->bytesPerRow);
-
- winRec->pixmap =
- GetScratchPixmapHeader(pScreen, winRec->width, winRec->height,
- top->drawable.depth,
- top->drawable.bitsPerPixel,
- winRec->bytesPerRow,
- winRec->pixelData);
- SetPixmapBaseToScreen(winRec->pixmap,
- top->drawable.x - bw, top->drawable.y - bw);
-
- winRec->is_drawing = TRUE;
- }
-
- curPixmap = pScreen->GetWindowPixmap(pWindow);
- if (curPixmap == winRec->pixmap)
- {
- RL_DEBUG_MSG("Window %p already has winRec->pixmap %p; not pushing\n", pWindow, winRec->pixmap);
- }
- else
- {
- PixmapPtr oldPixmap = dixLookupPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey);
- if (oldPixmap != NULL)
- {
- if (oldPixmap == curPixmap)
- RL_DEBUG_MSG("Window %p's curPixmap %p is the same as its oldPixmap; strange\n", pWindow, curPixmap);
- else
- RL_DEBUG_MSG("Window %p's existing oldPixmap %p being lost!\n", pWindow, oldPixmap);
- }
- dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, curPixmap);
- pScreen->SetWindowPixmap(pWindow, winRec->pixmap);
- }
-}
-
-
-/*
- * RootlessStopDrawing
- * Stop drawing to a window's backing buffer. If flush is true,
- * damaged regions are flushed to the screen.
- */
-static int RestorePreDrawingPixmapVisitor(WindowPtr pWindow, pointer data)
-{
- RootlessWindowRec *winRec = (RootlessWindowRec*)data;
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- PixmapPtr exPixmap = pScreen->GetWindowPixmap(pWindow);
- PixmapPtr oldPixmap = dixLookupPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey);
- if (oldPixmap == NULL)
- {
- if (exPixmap == winRec->pixmap)
- RL_DEBUG_MSG("Window %p appears to be in drawing mode (ex-pixmap %p equals winRec->pixmap, which is being freed) but has no oldPixmap!\n", pWindow, exPixmap);
- }
- else
- {
- if (exPixmap != winRec->pixmap)
- RL_DEBUG_MSG("Window %p appears to be in drawing mode (oldPixmap %p) but ex-pixmap %p not winRec->pixmap %p!\n", pWindow, oldPixmap, exPixmap, winRec->pixmap);
- if (oldPixmap == winRec->pixmap)
- RL_DEBUG_MSG("Window %p's oldPixmap %p is winRec->pixmap, which has just been freed!\n", pWindow, oldPixmap);
- pScreen->SetWindowPixmap(pWindow, oldPixmap);
- dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
- }
- return WT_WALKCHILDREN;
-}
-
-void RootlessStopDrawing(WindowPtr pWindow, Bool flush)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- WindowPtr top = TopLevelParent(pWindow);
- RootlessWindowRec *winRec;
-
- if (top == NULL)
- return;
- winRec = WINREC(top);
- if (winRec == NULL)
- return;
-
- if (winRec->is_drawing) {
- SCREENREC(pScreen)->imp->StopDrawing(winRec->wid, flush);
-
- FreeScratchPixmapHeader(winRec->pixmap);
- TraverseTree(top, RestorePreDrawingPixmapVisitor, (pointer)winRec);
- winRec->pixmap = NULL;
-
- winRec->is_drawing = FALSE;
- }
- else if (flush) {
- SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, NULL);
- }
-
- if (flush && winRec->is_reorder_pending) {
- winRec->is_reorder_pending = FALSE;
- RootlessReorderWindow(pWindow);
- }
-}
-
-
-/*
- * RootlessDamageRegion
- * Mark a damaged region as requiring redisplay to screen.
- * pRegion is in GLOBAL coordinates.
- */
-void
-RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion)
-{
- RootlessWindowRec *winRec;
- RegionRec clipped;
- WindowPtr pTop;
- BoxPtr b1, b2;
-
- RL_DEBUG_MSG("Damaged win 0x%x ", pWindow);
-
- pTop = TopLevelParent(pWindow);
- if (pTop == NULL)
- return;
-
- winRec = WINREC(pTop);
- if (winRec == NULL)
- return;
-
- /* We need to intersect the drawn region with the clip of the window
- to avoid marking places we didn't actually draw (which can cause
- problems when the window has an extra client-side backing store)
-
- But this is a costly operation and since we'll normally just be
- drawing inside the clip, go to some lengths to avoid the general
- case intersection. */
-
- b1 = RegionExtents(&pWindow->borderClip);
- b2 = RegionExtents(pRegion);
-
- if (EXTENTCHECK(b1, b2)) {
- /* Regions may overlap. */
-
- if (RegionNumRects(pRegion) == 1) {
- int in;
-
- /* Damaged region only has a single rect, so we can
- just compare that against the region */
-
- in = RegionContainsRect(&pWindow->borderClip,
- RegionRects (pRegion));
- if (in == rgnIN) {
- /* clip totally contains pRegion */
-
- SCREENREC(pWindow->drawable.pScreen)->imp->
- DamageRects(winRec->wid,
- RegionNumRects(pRegion),
- RegionRects(pRegion),
- -winRec->x, -winRec->y);
-
- RootlessQueueRedisplay(pTop->drawable.pScreen);
- goto out;
- }
- else if (in == rgnOUT) {
- /* clip doesn't contain pRegion */
-
- goto out;
- }
- }
-
- /* clip overlaps pRegion, need to intersect */
-
- RegionNull(&clipped);
- RegionIntersect(&clipped, &pWindow->borderClip, pRegion);
-
- SCREENREC(pWindow->drawable.pScreen)->imp->
- DamageRects(winRec->wid,
- RegionNumRects(&clipped),
- RegionRects(&clipped),
- -winRec->x, -winRec->y);
-
- RegionUninit(&clipped);
-
- RootlessQueueRedisplay(pTop->drawable.pScreen);
- }
-
-out:
-#ifdef ROOTLESSDEBUG
- {
- BoxRec *box = RegionRects(pRegion), *end;
- int numBox = RegionNumRects(pRegion);
-
- for (end = box+numBox; box < end; box++) {
- RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n",
- box->x1, box->x2, box->y1, box->y2);
- }
- }
-#endif
- return;
-}
-
-
-/*
- * RootlessDamageBox
- * Mark a damaged box as requiring redisplay to screen.
- * pRegion is in GLOBAL coordinates.
- */
-void
-RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox)
-{
- RegionRec region;
-
- RegionInit(®ion, pBox, 1);
-
- RootlessDamageRegion(pWindow, ®ion);
-
- RegionUninit(®ion); /* no-op */
-}
-
-
-/*
- * RootlessDamageRect
- * Mark a damaged rectangle as requiring redisplay to screen.
- * (x, y, w, h) is in window-local coordinates.
- */
-void
-RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h)
-{
- BoxRec box;
- RegionRec region;
-
- x += pWindow->drawable.x;
- y += pWindow->drawable.y;
-
- box.x1 = x;
- box.x2 = x + w;
- box.y1 = y;
- box.y2 = y + h;
-
- RegionInit(®ion, &box, 1);
-
- RootlessDamageRegion(pWindow, ®ion);
-
- RegionUninit(®ion); /* no-op */
-}
-
-
-/*
- * RootlessRedisplay
- * Stop drawing and redisplay the damaged region of a window.
- */
-void
-RootlessRedisplay(WindowPtr pWindow)
-{
- RootlessStopDrawing(pWindow, TRUE);
-}
-
-
-/*
- * RootlessRepositionWindows
- * Reposition all windows on a screen to their correct positions.
- */
-void
-RootlessRepositionWindows(ScreenPtr pScreen)
-{
- WindowPtr root = pScreen->root;
- WindowPtr win;
-
- if (root != NULL) {
- RootlessRepositionWindow(root);
-
- for (win = root->firstChild; win; win = win->nextSib) {
- if (WINREC(win) != NULL)
- RootlessRepositionWindow(win);
- }
- }
-}
-
-
-/*
- * RootlessRedisplayScreen
- * Walk every window on a screen and redisplay the damaged regions.
- */
-void
-RootlessRedisplayScreen(ScreenPtr pScreen)
-{
- WindowPtr root = pScreen->root;
-
- if (root != NULL) {
- WindowPtr win;
-
- RootlessRedisplay(root);
- for (win = root->firstChild; win; win = win->nextSib) {
- if (WINREC(win) != NULL) {
- RootlessRedisplay(win);
- }
- }
- }
-}
+/* + * Common rootless definitions and code + */ +/* + * 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 <stddef.h> /* For NULL */ +#include <limits.h> /* For CHAR_BIT */ + +#include "rootlessCommon.h" +#include "colormapst.h" + +unsigned int rootless_CopyBytes_threshold = 0; +unsigned int rootless_CopyWindow_threshold = 0; +int rootlessGlobalOffsetX = 0; +int rootlessGlobalOffsetY = 0; + +RegionRec rootlessHugeRoot = { {-32767, -32767, 32767, 32767}, NULL }; + +/* Following macro from miregion.c */ + +/* true iff two Boxes overlap */ +#define EXTENTCHECK(r1,r2) \ + (!( ((r1)->x2 <= (r2)->x1) || \ + ((r1)->x1 >= (r2)->x2) || \ + ((r1)->y2 <= (r2)->y1) || \ + ((r1)->y1 >= (r2)->y2) ) ) + +/* + * TopLevelParent + * Returns the top-level parent of pWindow. + * The root is the top-level parent of itself, even though the root is + * not otherwise considered to be a top-level window. + */ +WindowPtr +TopLevelParent(WindowPtr pWindow) +{ + WindowPtr top; + + if (IsRoot(pWindow)) + return pWindow; + + top = pWindow; + while (top && !IsTopLevel(top)) + top = top->parent; + + return top; +} + +/* + * IsFramedWindow + * Returns TRUE if this window is visible inside a frame + * (e.g. it is visible and has a top-level or root parent) + */ +Bool +IsFramedWindow(WindowPtr pWin) +{ + WindowPtr top; + + if (!dixPrivateKeyRegistered(&rootlessWindowPrivateKeyRec)) + return FALSE; + + if (!pWin->realized) + return FALSE; + top = TopLevelParent(pWin); + + return (top && WINREC(top)); +} + +Bool +RootlessResolveColormap(ScreenPtr pScreen, int first_color, + int n_colors, uint32_t * colors) +{ + int last, i; + ColormapPtr map; + + map = RootlessGetColormap(pScreen); + if (map == NULL || map->class != PseudoColor) + return FALSE; + + last = min(map->pVisual->ColormapEntries, first_color + n_colors); + for (i = max(0, first_color); i < last; i++) { + Entry *ent = map->red + i; + uint16_t red, green, blue; + + if (!ent->refcnt) + continue; + if (ent->fShared) { + red = ent->co.shco.red->color; + green = ent->co.shco.green->color; + blue = ent->co.shco.blue->color; + } + else { + red = ent->co.local.red; + green = ent->co.local.green; + blue = ent->co.local.blue; + } + + colors[i - first_color] = (0xFF000000UL + | ((uint32_t) red & 0xff00) << 8 + | (green & 0xff00) + | (blue >> 8)); + } + + return TRUE; +} + +/* + * RootlessStartDrawing + * Prepare a window for direct access to its backing buffer. + * Each top-level parent has a Pixmap representing its backing buffer, + * which all of its children inherit. + */ +void +RootlessStartDrawing(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + WindowPtr top = TopLevelParent(pWindow); + RootlessWindowRec *winRec; + PixmapPtr curPixmap; + + if (top == NULL) + return; + winRec = WINREC(top); + if (winRec == NULL) + return; + + // Make sure the window's top-level parent is prepared for drawing. + if (!winRec->is_drawing) { + int bw = wBorderWidth(top); + + SCREENREC(pScreen)->imp->StartDrawing(winRec->wid, &winRec->pixelData, + &winRec->bytesPerRow); + + winRec->pixmap = + GetScratchPixmapHeader(pScreen, winRec->width, winRec->height, + top->drawable.depth, + top->drawable.bitsPerPixel, + winRec->bytesPerRow, winRec->pixelData); + SetPixmapBaseToScreen(winRec->pixmap, + top->drawable.x - bw, top->drawable.y - bw); + + winRec->is_drawing = TRUE; + } + + curPixmap = pScreen->GetWindowPixmap(pWindow); + if (curPixmap == winRec->pixmap) { + RL_DEBUG_MSG("Window %p already has winRec->pixmap %p; not pushing\n", + pWindow, winRec->pixmap); + } + else { + PixmapPtr oldPixmap = + dixLookupPrivate(&pWindow->devPrivates, + rootlessWindowOldPixmapPrivateKey); + if (oldPixmap != NULL) { + if (oldPixmap == curPixmap) + RL_DEBUG_MSG + ("Window %p's curPixmap %p is the same as its oldPixmap; strange\n", + pWindow, curPixmap); + else + RL_DEBUG_MSG("Window %p's existing oldPixmap %p being lost!\n", + pWindow, oldPixmap); + } + dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, + curPixmap); + pScreen->SetWindowPixmap(pWindow, winRec->pixmap); + } +} + +/* + * RootlessStopDrawing + * Stop drawing to a window's backing buffer. If flush is true, + * damaged regions are flushed to the screen. + */ +static int +RestorePreDrawingPixmapVisitor(WindowPtr pWindow, pointer data) +{ + RootlessWindowRec *winRec = (RootlessWindowRec *) data; + ScreenPtr pScreen = pWindow->drawable.pScreen; + PixmapPtr exPixmap = pScreen->GetWindowPixmap(pWindow); + PixmapPtr oldPixmap = + dixLookupPrivate(&pWindow->devPrivates, + rootlessWindowOldPixmapPrivateKey); + if (oldPixmap == NULL) { + if (exPixmap == winRec->pixmap) + RL_DEBUG_MSG + ("Window %p appears to be in drawing mode (ex-pixmap %p equals winRec->pixmap, which is being freed) but has no oldPixmap!\n", + pWindow, exPixmap); + } + else { + if (exPixmap != winRec->pixmap) + RL_DEBUG_MSG + ("Window %p appears to be in drawing mode (oldPixmap %p) but ex-pixmap %p not winRec->pixmap %p!\n", + pWindow, oldPixmap, exPixmap, winRec->pixmap); + if (oldPixmap == winRec->pixmap) + RL_DEBUG_MSG + ("Window %p's oldPixmap %p is winRec->pixmap, which has just been freed!\n", + pWindow, oldPixmap); + pScreen->SetWindowPixmap(pWindow, oldPixmap); + dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, + NULL); + } + return WT_WALKCHILDREN; +} + +void +RootlessStopDrawing(WindowPtr pWindow, Bool flush) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + WindowPtr top = TopLevelParent(pWindow); + RootlessWindowRec *winRec; + + if (top == NULL) + return; + winRec = WINREC(top); + if (winRec == NULL) + return; + + if (winRec->is_drawing) { + SCREENREC(pScreen)->imp->StopDrawing(winRec->wid, flush); + + FreeScratchPixmapHeader(winRec->pixmap); + TraverseTree(top, RestorePreDrawingPixmapVisitor, (pointer) winRec); + winRec->pixmap = NULL; + + winRec->is_drawing = FALSE; + } + else if (flush) { + SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, NULL); + } + + if (flush && winRec->is_reorder_pending) { + winRec->is_reorder_pending = FALSE; + RootlessReorderWindow(pWindow); + } +} + +/* + * RootlessDamageRegion + * Mark a damaged region as requiring redisplay to screen. + * pRegion is in GLOBAL coordinates. + */ +void +RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion) +{ + RootlessWindowRec *winRec; + RegionRec clipped; + WindowPtr pTop; + BoxPtr b1, b2; + + RL_DEBUG_MSG("Damaged win 0x%x ", pWindow); + + pTop = TopLevelParent(pWindow); + if (pTop == NULL) + return; + + winRec = WINREC(pTop); + if (winRec == NULL) + return; + + /* We need to intersect the drawn region with the clip of the window + to avoid marking places we didn't actually draw (which can cause + problems when the window has an extra client-side backing store) + + But this is a costly operation and since we'll normally just be + drawing inside the clip, go to some lengths to avoid the general + case intersection. */ + + b1 = RegionExtents(&pWindow->borderClip); + b2 = RegionExtents(pRegion); + + if (EXTENTCHECK(b1, b2)) { + /* Regions may overlap. */ + + if (RegionNumRects(pRegion) == 1) { + int in; + + /* Damaged region only has a single rect, so we can + just compare that against the region */ + + in = RegionContainsRect(&pWindow->borderClip, RegionRects(pRegion)); + if (in == rgnIN) { + /* clip totally contains pRegion */ + + SCREENREC(pWindow->drawable.pScreen)->imp->DamageRects(winRec-> + wid, + RegionNumRects + (pRegion), + RegionRects + (pRegion), + -winRec-> + x, + -winRec-> + y); + + RootlessQueueRedisplay(pTop->drawable.pScreen); + goto out; + } + else if (in == rgnOUT) { + /* clip doesn't contain pRegion */ + + goto out; + } + } + + /* clip overlaps pRegion, need to intersect */ + + RegionNull(&clipped); + RegionIntersect(&clipped, &pWindow->borderClip, pRegion); + + SCREENREC(pWindow->drawable.pScreen)->imp->DamageRects(winRec->wid, + RegionNumRects + (&clipped), + RegionRects + (&clipped), + -winRec->x, + -winRec->y); + + RegionUninit(&clipped); + + RootlessQueueRedisplay(pTop->drawable.pScreen); + } + + out: +#ifdef ROOTLESSDEBUG + { + BoxRec *box = RegionRects(pRegion), *end; + int numBox = RegionNumRects(pRegion); + + for (end = box + numBox; box < end; box++) { + RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n", + box->x1, box->x2, box->y1, box->y2); + } + } +#endif + return; +} + +/* + * RootlessDamageBox + * Mark a damaged box as requiring redisplay to screen. + * pRegion is in GLOBAL coordinates. + */ +void +RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox) +{ + RegionRec region; + + RegionInit(®ion, pBox, 1); + + RootlessDamageRegion(pWindow, ®ion); + + RegionUninit(®ion); /* no-op */ +} + +/* + * RootlessDamageRect + * Mark a damaged rectangle as requiring redisplay to screen. + * (x, y, w, h) is in window-local coordinates. + */ +void +RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h) +{ + BoxRec box; + RegionRec region; + + x += pWindow->drawable.x; + y += pWindow->drawable.y; + + box.x1 = x; + box.x2 = x + w; + box.y1 = y; + box.y2 = y + h; + + RegionInit(®ion, &box, 1); + + RootlessDamageRegion(pWindow, ®ion); + + RegionUninit(®ion); /* no-op */ +} + +/* + * RootlessRedisplay + * Stop drawing and redisplay the damaged region of a window. + */ +void +RootlessRedisplay(WindowPtr pWindow) +{ + RootlessStopDrawing(pWindow, TRUE); +} + +/* + * RootlessRepositionWindows + * Reposition all windows on a screen to their correct positions. + */ +void +RootlessRepositionWindows(ScreenPtr pScreen) +{ + WindowPtr root = pScreen->root; + WindowPtr win; + + if (root != NULL) { + RootlessRepositionWindow(root); + + for (win = root->firstChild; win; win = win->nextSib) { + if (WINREC(win) != NULL) + RootlessRepositionWindow(win); + } + } +} + +/* + * RootlessRedisplayScreen + * Walk every window on a screen and redisplay the damaged regions. + */ +void +RootlessRedisplayScreen(ScreenPtr pScreen) +{ + WindowPtr root = pScreen->root; + + if (root != NULL) { + WindowPtr win; + + RootlessRedisplay(root); + for (win = root->firstChild; win; win = win->nextSib) { + if (WINREC(win) != NULL) { + RootlessRedisplay(win); + } + } + } +} |