aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/miext/rootless
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-06-11 12:14:52 +0000
committermarha <marha@users.sourceforge.net>2010-06-11 12:14:52 +0000
commit4c61bf84b11e26e6f22648668c95ea760a379163 (patch)
tree0ac762ab2815eae283dded7447ad7cb5a54b926a /xorg-server/miext/rootless
parente1dabd2ce8be0d70c6c15353b58de256129dfd1f (diff)
downloadvcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.tar.gz
vcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.tar.bz2
vcxsrv-4c61bf84b11e26e6f22648668c95ea760a379163.zip
xserver git update 11/6/2010
Diffstat (limited to 'xorg-server/miext/rootless')
-rw-r--r--xorg-server/miext/rootless/rootlessCommon.c967
-rw-r--r--xorg-server/miext/rootless/rootlessCommon.h573
-rw-r--r--xorg-server/miext/rootless/rootlessGC.c2994
-rw-r--r--xorg-server/miext/rootless/rootlessScreen.c28
-rw-r--r--xorg-server/miext/rootless/rootlessValTree.c1275
-rw-r--r--xorg-server/miext/rootless/rootlessWindow.c111
-rw-r--r--xorg-server/miext/rootless/rootlessWindow.h120
7 files changed, 3032 insertions, 3036 deletions
diff --git a/xorg-server/miext/rootless/rootlessCommon.c b/xorg-server/miext/rootless/rootlessCommon.c
index 39a3eed0f..e97a53725 100644
--- a/xorg-server/miext/rootless/rootlessCommon.c
+++ b/xorg-server/miext/rootless/rootlessCommon.c
@@ -1,483 +1,484 @@
-/*
- * 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_FillBytes_threshold = 0;
-unsigned int rootless_CompositePixels_threshold = 0;
-unsigned int rootless_CopyWindow_threshold = 0;
-#ifdef ROOTLESS_GLOBAL_COORDS
-int rootlessGlobalOffsetX = 0;
-int rootlessGlobalOffsetY = 0;
-#endif
-
-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 (!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)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- 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 = REGION_EXTENTS(pScreen, &pWindow->borderClip);
- b2 = REGION_EXTENTS(pScreen, pRegion);
-
- if (EXTENTCHECK(b1, b2)) {
- /* Regions may overlap. */
-
- if (REGION_NUM_RECTS(pRegion) == 1) {
- int in;
-
- /* Damaged region only has a single rect, so we can
- just compare that against the region */
-
- in = RECT_IN_REGION(pScreen, &pWindow->borderClip,
- REGION_RECTS (pRegion));
- if (in == rgnIN) {
- /* clip totally contains pRegion */
-
-#ifdef ROOTLESS_TRACK_DAMAGE
- REGION_UNION(pScreen, &winRec->damage,
- &winRec->damage, (pRegion));
-#else
- SCREENREC(pScreen)->imp->DamageRects(winRec->wid,
- REGION_NUM_RECTS(pRegion),
- REGION_RECTS(pRegion),
- -winRec->x, -winRec->y);
-#endif
-
- RootlessQueueRedisplay(pTop->drawable.pScreen);
- goto out;
- }
- else if (in == rgnOUT) {
- /* clip doesn't contain pRegion */
-
- goto out;
- }
- }
-
- /* clip overlaps pRegion, need to intersect */
-
- REGION_NULL(pScreen, &clipped);
- REGION_INTERSECT(pScreen, &clipped, &pWindow->borderClip, pRegion);
-
-#ifdef ROOTLESS_TRACK_DAMAGE
- REGION_UNION(pScreen, &winRec->damage,
- &winRec->damage, (pRegion));
-#else
- SCREENREC(pScreen)->imp->DamageRects(winRec->wid,
- REGION_NUM_RECTS(&clipped),
- REGION_RECTS(&clipped),
- -winRec->x, -winRec->y);
-#endif
-
- REGION_UNINIT(pScreen, &clipped);
-
- RootlessQueueRedisplay(pTop->drawable.pScreen);
- }
-
-out:
-#ifdef ROOTLESSDEBUG
- {
- BoxRec *box = REGION_RECTS(pRegion), *end;
- int numBox = REGION_NUM_RECTS(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;
-
- REGION_INIT(pWindow->drawable.pScreen, &region, pBox, 1);
-
- RootlessDamageRegion(pWindow, &region);
-
- REGION_UNINIT(pWindow->drawable.pScreen, &region); /* 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;
-
- REGION_INIT(pWindow->drawable.pScreen, &region, &box, 1);
-
- RootlessDamageRegion(pWindow, &region);
-
- REGION_UNINIT(pWindow->drawable.pScreen, &region); /* no-op */
-}
-
-
-/*
- * RootlessRedisplay
- * Stop drawing and redisplay the damaged region of a window.
- */
-void
-RootlessRedisplay(WindowPtr pWindow)
-{
-#ifdef ROOTLESS_TRACK_DAMAGE
-
- RootlessWindowRec *winRec = WINREC(pWindow);
- ScreenPtr pScreen = pWindow->drawable.pScreen;
-
- RootlessStopDrawing(pWindow, FALSE);
-
- if (REGION_NOTEMPTY(pScreen, &winRec->damage)) {
- RL_DEBUG_MSG("Redisplay Win 0x%x, %i x %i @ (%i, %i)\n",
- pWindow, winRec->width, winRec->height,
- winRec->x, winRec->y);
-
- // move region to window local coords
- REGION_TRANSLATE(pScreen, &winRec->damage,
- -winRec->x, -winRec->y);
-
- SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, &winRec->damage);
-
- REGION_EMPTY(pScreen, &winRec->damage);
- }
-
-#else /* !ROOTLESS_TRACK_DAMAGE */
-
- RootlessStopDrawing(pWindow, TRUE);
-
-#endif
-}
-
-
-/*
- * RootlessRepositionWindows
- * Reposition all windows on a screen to their correct positions.
- */
-void
-RootlessRepositionWindows(ScreenPtr pScreen)
-{
- WindowPtr root = WindowTable[pScreen->myNum];
- 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 = WindowTable[pScreen->myNum];
-
- 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_FillBytes_threshold = 0;
+unsigned int rootless_CompositePixels_threshold = 0;
+unsigned int rootless_CopyWindow_threshold = 0;
+#ifdef ROOTLESS_GLOBAL_COORDS
+int rootlessGlobalOffsetX = 0;
+int rootlessGlobalOffsetY = 0;
+#endif
+
+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 (!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 */
+
+#ifdef ROOTLESS_TRACK_DAMAGE
+ RegionUnion(&winRec->damage,
+ &winRec->damage, (pRegion));
+#else
+ SCREENREC(pWindow->drawable.pScreen)->imp->
+ DamageRects(winRec->wid,
+ RegionNumRects(pRegion),
+ RegionRects(pRegion),
+ -winRec->x, -winRec->y);
+#endif
+
+ 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);
+
+#ifdef ROOTLESS_TRACK_DAMAGE
+ RegionUnion(&winRec->damage,
+ &winRec->damage, (pRegion));
+#else
+ SCREENREC(pWindow->drawable.pScreen)->imp->
+ DamageRects(winRec->wid,
+ RegionNumRects(&clipped),
+ RegionRects(&clipped),
+ -winRec->x, -winRec->y);
+#endif
+
+ 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(&region, pBox, 1);
+
+ RootlessDamageRegion(pWindow, &region);
+
+ RegionUninit(&region); /* 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(&region, &box, 1);
+
+ RootlessDamageRegion(pWindow, &region);
+
+ RegionUninit(&region); /* no-op */
+}
+
+
+/*
+ * RootlessRedisplay
+ * Stop drawing and redisplay the damaged region of a window.
+ */
+void
+RootlessRedisplay(WindowPtr pWindow)
+{
+#ifdef ROOTLESS_TRACK_DAMAGE
+
+ RootlessWindowRec *winRec = WINREC(pWindow);
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+
+ RootlessStopDrawing(pWindow, FALSE);
+
+ if (RegionNotEmpty(&winRec->damage)) {
+ RL_DEBUG_MSG("Redisplay Win 0x%x, %i x %i @ (%i, %i)\n",
+ pWindow, winRec->width, winRec->height,
+ winRec->x, winRec->y);
+
+ // move region to window local coords
+ RegionTranslate(&winRec->damage,
+ -winRec->x, -winRec->y);
+
+ SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, &winRec->damage);
+
+ RegionEmpty(&winRec->damage);
+ }
+
+#else /* !ROOTLESS_TRACK_DAMAGE */
+
+ RootlessStopDrawing(pWindow, TRUE);
+
+#endif
+}
+
+
+/*
+ * 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);
+ }
+ }
+ }
+}
diff --git a/xorg-server/miext/rootless/rootlessCommon.h b/xorg-server/miext/rootless/rootlessCommon.h
index f44c4e8cf..893ca9825 100644
--- a/xorg-server/miext/rootless/rootlessCommon.h
+++ b/xorg-server/miext/rootless/rootlessCommon.h
@@ -1,283 +1,290 @@
-/*
- * Common internal rootless definitions and code
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002-2004 Torrey T. Lyons. 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 <stdint.h>
-#ifndef _ROOTLESSCOMMON_H
-#define _ROOTLESSCOMMON_H
-
-#include "misc.h"
-#include "rootless.h"
-#include "fb.h"
-
-#include "scrnintstr.h"
-
-#include "picturestr.h"
-
-
-// Debug output, or not.
-#ifdef ROOTLESSDEBUG
-#define RL_DEBUG_MSG ErrorF
-#else
-#define RL_DEBUG_MSG(a, ...)
-#endif
-
-
-// Global variables
-extern DevPrivateKey rootlessGCPrivateKey;
-extern DevPrivateKey rootlessScreenPrivateKey;
-extern DevPrivateKey rootlessWindowPrivateKey;
-extern DevPrivateKey rootlessWindowOldPixmapPrivateKey;
-
-
-// RootlessGCRec: private per-gc data
-typedef struct {
- GCFuncs *originalFuncs;
- GCOps *originalOps;
-} RootlessGCRec;
-
-
-// RootlessScreenRec: per-screen private data
-typedef struct _RootlessScreenRec {
- // Rootless implementation functions
- RootlessFrameProcsPtr imp;
-
- // Wrapped screen functions
- CreateScreenResourcesProcPtr CreateScreenResources;
- CloseScreenProcPtr CloseScreen;
-
- CreateWindowProcPtr CreateWindow;
- DestroyWindowProcPtr DestroyWindow;
- RealizeWindowProcPtr RealizeWindow;
- UnrealizeWindowProcPtr UnrealizeWindow;
- MoveWindowProcPtr MoveWindow;
- ResizeWindowProcPtr ResizeWindow;
- RestackWindowProcPtr RestackWindow;
- ReparentWindowProcPtr ReparentWindow;
- ChangeBorderWidthProcPtr ChangeBorderWidth;
- PositionWindowProcPtr PositionWindow;
- ChangeWindowAttributesProcPtr ChangeWindowAttributes;
-
- CreateGCProcPtr CreateGC;
- CopyWindowProcPtr CopyWindow;
- GetImageProcPtr GetImage;
- SourceValidateProcPtr SourceValidate;
-
- MarkOverlappedWindowsProcPtr MarkOverlappedWindows;
- ValidateTreeProcPtr ValidateTree;
-
- SetShapeProcPtr SetShape;
-
- CompositeProcPtr Composite;
- GlyphsProcPtr Glyphs;
-
- InstallColormapProcPtr InstallColormap;
- UninstallColormapProcPtr UninstallColormap;
- StoreColorsProcPtr StoreColors;
-
- void *pixmap_data;
- unsigned int pixmap_data_size;
-
- ColormapPtr colormap;
-
- void *redisplay_timer;
- unsigned int redisplay_timer_set :1;
- unsigned int redisplay_queued :1;
- unsigned int redisplay_expired :1;
- unsigned int colormap_changed :1;
-} RootlessScreenRec, *RootlessScreenPtr;
-
-// "Definition of the Porting Layer for the X11 Sample Server" says
-// unwrap and rewrap of screen functions is unnecessary, but
-// screen->CreateGC changes after a call to cfbCreateGC.
-
-#define SCREEN_UNWRAP(screen, fn) \
- screen->fn = SCREENREC(screen)->fn;
-
-#define SCREEN_WRAP(screen, fn) \
- SCREENREC(screen)->fn = screen->fn; \
- screen->fn = Rootless##fn
-
-
-// Accessors for screen and window privates
-
-#define SCREENREC(pScreen) ((RootlessScreenRec *) \
- dixLookupPrivate(&(pScreen)->devPrivates, rootlessScreenPrivateKey))
-
-#define SETSCREENREC(pScreen, v) \
- dixSetPrivate(&(pScreen)->devPrivates, rootlessScreenPrivateKey, v)
-
-#define WINREC(pWin) ((RootlessWindowRec *) \
- dixLookupPrivate(&(pWin)->devPrivates, rootlessWindowPrivateKey))
-
-#define SETWINREC(pWin, v) \
- dixSetPrivate(&(pWin)->devPrivates, rootlessWindowPrivateKey, v)
-
-// Call a rootless implementation function.
-// Many rootless implementation functions are allowed to be NULL.
-#define CallFrameProc(pScreen, proc, params) \
- if (SCREENREC(pScreen)->frameProcs.proc) { \
- RL_DEBUG_MSG("calling frame proc " #proc " "); \
- SCREENREC(pScreen)->frameProcs.proc params; \
- }
-
-
-// BoxRec manipulators
-// Copied from shadowfb
-
-#define TRIM_BOX(box, pGC) { \
- BoxPtr extents = &pGC->pCompositeClip->extents;\
- if(box.x1 < extents->x1) box.x1 = extents->x1; \
- if(box.x2 > extents->x2) box.x2 = extents->x2; \
- if(box.y1 < extents->y1) box.y1 = extents->y1; \
- if(box.y2 > extents->y2) box.y2 = extents->y2; \
-}
-
-#define TRANSLATE_BOX(box, pDraw) { \
- box.x1 += pDraw->x; \
- box.x2 += pDraw->x; \
- box.y1 += pDraw->y; \
- box.y2 += pDraw->y; \
-}
-
-#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
- TRANSLATE_BOX(box, pDraw); \
- TRIM_BOX(box, pGC); \
-}
-
-#define BOX_NOT_EMPTY(box) \
- (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
-
-
-// HUGE_ROOT and NORMAL_ROOT
-// We don't want to clip windows to the edge of the screen.
-// HUGE_ROOT temporarily makes the root window really big.
-// This is needed as a wrapper around any function that calls
-// SetWinSize or SetBorderSize which clip a window against its
-// parents, including the root.
-
-extern RegionRec rootlessHugeRoot;
-
-#define HUGE_ROOT(pWin) \
- do { \
- WindowPtr w = pWin; \
- while (w->parent) \
- w = w->parent; \
- saveRoot = w->winSize; \
- w->winSize = rootlessHugeRoot; \
- } while (0)
-
-#define NORMAL_ROOT(pWin) \
- do { \
- WindowPtr w = pWin; \
- while (w->parent) \
- w = w->parent; \
- w->winSize = saveRoot; \
- } while (0)
-
-
-// Returns TRUE if this window is a top-level window (i.e. child of the root)
-// The root is not a top-level window.
-#define IsTopLevel(pWin) \
- ((pWin) && (pWin)->parent && !(pWin)->parent->parent)
-
-// Returns TRUE if this window is a root window
-#define IsRoot(pWin) \
- ((pWin) == WindowTable[(pWin)->drawable.pScreen->myNum])
-
-
-/*
- * SetPixmapBaseToScreen
- * Move the given pixmap's base address to where pixel (0, 0)
- * would be if the pixmap's actual data started at (x, y).
- * Can't access the bits before the first word of the drawable's data in
- * rootless mode, so make sure our base address is always 32-bit aligned.
- */
-#define SetPixmapBaseToScreen(pix, _x, _y) { \
- PixmapPtr _pPix = (PixmapPtr) (pix); \
- _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \
- ((int)(_x) * _pPix->drawable.bitsPerPixel/8 + \
- (int)(_y) * _pPix->devKind); \
- if (_pPix->drawable.bitsPerPixel != FB_UNIT) { \
- size_t _diff = ((size_t) _pPix->devPrivate.ptr) & \
- (FB_UNIT / CHAR_BIT - 1); \
- _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \
- _diff; \
- _pPix->drawable.x = _diff / \
- (_pPix->drawable.bitsPerPixel / CHAR_BIT); \
- } \
-}
-
-
-// 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);
-
-// Routines that cause regions to get redrawn.
-// DamageRegion and DamageRect are in global coordinates.
-// DamageBox is in window-local coordinates.
-void RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion);
-void RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h);
-void RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox);
-void RootlessRedisplay(WindowPtr pWindow);
-void RootlessRedisplayScreen(ScreenPtr pScreen);
-
-void RootlessQueueRedisplay(ScreenPtr pScreen);
-
-/* Return the colormap currently installed on the given screen. */
-ColormapPtr RootlessGetColormap (ScreenPtr pScreen);
-
-/* Convert colormap to ARGB. */
-Bool RootlessResolveColormap (ScreenPtr pScreen, int first_color,
- int n_colors, uint32_t *colors);
-
-void RootlessFlushWindowColormap (WindowPtr pWin);
-void RootlessFlushScreenColormaps (ScreenPtr pScreen);
-
-// Move a window to its proper location on the screen.
-void RootlessRepositionWindow(WindowPtr pWin);
-
-// Move the window to it's correct place in the physical stacking order.
-void RootlessReorderWindow(WindowPtr pWin);
-
-void RootlessScreenExpose (ScreenPtr pScreen);
-void RootlessHideAllWindows (void);
-void RootlessShowAllWindows (void);
-void RootlessUpdateRooted (Bool state);
-
-void RootlessEnableRoot (ScreenPtr pScreen);
-void RootlessDisableRoot (ScreenPtr pScreen);
-
-void RootlessSetPixmapOfAncestors(WindowPtr pWin);
-
-#endif /* _ROOTLESSCOMMON_H */
+/*
+ * Common internal rootless definitions and code
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. All Rights Reserved.
+ * Copyright (c) 2002-2004 Torrey T. Lyons. 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 <stdint.h>
+#ifndef _ROOTLESSCOMMON_H
+#define _ROOTLESSCOMMON_H
+
+#include "misc.h"
+#include "rootless.h"
+#include "fb.h"
+
+#include "scrnintstr.h"
+
+#include "picturestr.h"
+
+
+// Debug output, or not.
+#ifdef ROOTLESSDEBUG
+#define RL_DEBUG_MSG ErrorF
+#else
+#define RL_DEBUG_MSG(a, ...)
+#endif
+
+
+// Global variables
+extern DevPrivateKeyRec rootlessGCPrivateKeyRec;
+#define rootlessGCPrivateKey (&rootlessGCPrivateKeyRec)
+
+extern DevPrivateKeyRec rootlessScreenPrivateKeyRec;
+#define rootlessScreenPrivateKey (&rootlessScreenPrivateKeyRec)
+
+extern DevPrivateKeyRec rootlessWindowPrivateKeyRec;
+#define rootlessWindowPrivateKey (&rootlessWindowPrivateKeyRec)
+
+extern DevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec;
+#define rootlessWindowOldPixmapPrivateKey (&rootlessWindowOldPixmapPrivateKeyRec)
+
+
+// RootlessGCRec: private per-gc data
+typedef struct {
+ GCFuncs *originalFuncs;
+ GCOps *originalOps;
+} RootlessGCRec;
+
+
+// RootlessScreenRec: per-screen private data
+typedef struct _RootlessScreenRec {
+ // Rootless implementation functions
+ RootlessFrameProcsPtr imp;
+
+ // Wrapped screen functions
+ CreateScreenResourcesProcPtr CreateScreenResources;
+ CloseScreenProcPtr CloseScreen;
+
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ MoveWindowProcPtr MoveWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ RestackWindowProcPtr RestackWindow;
+ ReparentWindowProcPtr ReparentWindow;
+ ChangeBorderWidthProcPtr ChangeBorderWidth;
+ PositionWindowProcPtr PositionWindow;
+ ChangeWindowAttributesProcPtr ChangeWindowAttributes;
+
+ CreateGCProcPtr CreateGC;
+ CopyWindowProcPtr CopyWindow;
+ GetImageProcPtr GetImage;
+ SourceValidateProcPtr SourceValidate;
+
+ MarkOverlappedWindowsProcPtr MarkOverlappedWindows;
+ ValidateTreeProcPtr ValidateTree;
+
+ SetShapeProcPtr SetShape;
+
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+
+ InstallColormapProcPtr InstallColormap;
+ UninstallColormapProcPtr UninstallColormap;
+ StoreColorsProcPtr StoreColors;
+
+ void *pixmap_data;
+ unsigned int pixmap_data_size;
+
+ ColormapPtr colormap;
+
+ void *redisplay_timer;
+ unsigned int redisplay_timer_set :1;
+ unsigned int redisplay_queued :1;
+ unsigned int redisplay_expired :1;
+ unsigned int colormap_changed :1;
+} RootlessScreenRec, *RootlessScreenPtr;
+
+// "Definition of the Porting Layer for the X11 Sample Server" says
+// unwrap and rewrap of screen functions is unnecessary, but
+// screen->CreateGC changes after a call to cfbCreateGC.
+
+#define SCREEN_UNWRAP(screen, fn) \
+ screen->fn = SCREENREC(screen)->fn;
+
+#define SCREEN_WRAP(screen, fn) \
+ SCREENREC(screen)->fn = screen->fn; \
+ screen->fn = Rootless##fn
+
+
+// Accessors for screen and window privates
+
+#define SCREENREC(pScreen) ((RootlessScreenRec *) \
+ dixLookupPrivate(&(pScreen)->devPrivates, rootlessScreenPrivateKey))
+
+#define SETSCREENREC(pScreen, v) \
+ dixSetPrivate(&(pScreen)->devPrivates, rootlessScreenPrivateKey, v)
+
+#define WINREC(pWin) ((RootlessWindowRec *) \
+ dixLookupPrivate(&(pWin)->devPrivates, rootlessWindowPrivateKey))
+
+#define SETWINREC(pWin, v) \
+ dixSetPrivate(&(pWin)->devPrivates, rootlessWindowPrivateKey, v)
+
+// Call a rootless implementation function.
+// Many rootless implementation functions are allowed to be NULL.
+#define CallFrameProc(pScreen, proc, params) \
+ if (SCREENREC(pScreen)->frameProcs.proc) { \
+ RL_DEBUG_MSG("calling frame proc " #proc " "); \
+ SCREENREC(pScreen)->frameProcs.proc params; \
+ }
+
+
+// BoxRec manipulators
+// Copied from shadowfb
+
+#define TRIM_BOX(box, pGC) { \
+ BoxPtr extents = &pGC->pCompositeClip->extents;\
+ if(box.x1 < extents->x1) box.x1 = extents->x1; \
+ if(box.x2 > extents->x2) box.x2 = extents->x2; \
+ if(box.y1 < extents->y1) box.y1 = extents->y1; \
+ if(box.y2 > extents->y2) box.y2 = extents->y2; \
+}
+
+#define TRANSLATE_BOX(box, pDraw) { \
+ box.x1 += pDraw->x; \
+ box.x2 += pDraw->x; \
+ box.y1 += pDraw->y; \
+ box.y2 += pDraw->y; \
+}
+
+#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
+ TRANSLATE_BOX(box, pDraw); \
+ TRIM_BOX(box, pGC); \
+}
+
+#define BOX_NOT_EMPTY(box) \
+ (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
+
+
+// HUGE_ROOT and NORMAL_ROOT
+// We don't want to clip windows to the edge of the screen.
+// HUGE_ROOT temporarily makes the root window really big.
+// This is needed as a wrapper around any function that calls
+// SetWinSize or SetBorderSize which clip a window against its
+// parents, including the root.
+
+extern RegionRec rootlessHugeRoot;
+
+#define HUGE_ROOT(pWin) \
+ do { \
+ WindowPtr w = pWin; \
+ while (w->parent) \
+ w = w->parent; \
+ saveRoot = w->winSize; \
+ w->winSize = rootlessHugeRoot; \
+ } while (0)
+
+#define NORMAL_ROOT(pWin) \
+ do { \
+ WindowPtr w = pWin; \
+ while (w->parent) \
+ w = w->parent; \
+ w->winSize = saveRoot; \
+ } while (0)
+
+
+// Returns TRUE if this window is a top-level window (i.e. child of the root)
+// The root is not a top-level window.
+#define IsTopLevel(pWin) \
+ ((pWin) && (pWin)->parent && !(pWin)->parent->parent)
+
+// Returns TRUE if this window is a root window
+#define IsRoot(pWin) \
+ ((pWin) == (pWin)->drawable.pScreen->root)
+
+
+/*
+ * SetPixmapBaseToScreen
+ * Move the given pixmap's base address to where pixel (0, 0)
+ * would be if the pixmap's actual data started at (x, y).
+ * Can't access the bits before the first word of the drawable's data in
+ * rootless mode, so make sure our base address is always 32-bit aligned.
+ */
+#define SetPixmapBaseToScreen(pix, _x, _y) { \
+ PixmapPtr _pPix = (PixmapPtr) (pix); \
+ _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \
+ ((int)(_x) * _pPix->drawable.bitsPerPixel/8 + \
+ (int)(_y) * _pPix->devKind); \
+ if (_pPix->drawable.bitsPerPixel != FB_UNIT) { \
+ size_t _diff = ((size_t) _pPix->devPrivate.ptr) & \
+ (FB_UNIT / CHAR_BIT - 1); \
+ _pPix->devPrivate.ptr = (char *) (_pPix->devPrivate.ptr) - \
+ _diff; \
+ _pPix->drawable.x = _diff / \
+ (_pPix->drawable.bitsPerPixel / CHAR_BIT); \
+ } \
+}
+
+
+// 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);
+
+// Routines that cause regions to get redrawn.
+// DamageRegion and DamageRect are in global coordinates.
+// DamageBox is in window-local coordinates.
+void RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion);
+void RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h);
+void RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox);
+void RootlessRedisplay(WindowPtr pWindow);
+void RootlessRedisplayScreen(ScreenPtr pScreen);
+
+void RootlessQueueRedisplay(ScreenPtr pScreen);
+
+/* Return the colormap currently installed on the given screen. */
+ColormapPtr RootlessGetColormap (ScreenPtr pScreen);
+
+/* Convert colormap to ARGB. */
+Bool RootlessResolveColormap (ScreenPtr pScreen, int first_color,
+ int n_colors, uint32_t *colors);
+
+void RootlessFlushWindowColormap (WindowPtr pWin);
+void RootlessFlushScreenColormaps (ScreenPtr pScreen);
+
+// Move a window to its proper location on the screen.
+void RootlessRepositionWindow(WindowPtr pWin);
+
+// Move the window to it's correct place in the physical stacking order.
+void RootlessReorderWindow(WindowPtr pWin);
+
+void RootlessScreenExpose (ScreenPtr pScreen);
+void RootlessHideAllWindows (void);
+void RootlessShowAllWindows (void);
+void RootlessUpdateRooted (Bool state);
+
+void RootlessEnableRoot (ScreenPtr pScreen);
+void RootlessDisableRoot (ScreenPtr pScreen);
+
+void RootlessSetPixmapOfAncestors(WindowPtr pWin);
+
+#endif /* _ROOTLESSCOMMON_H */
diff --git a/xorg-server/miext/rootless/rootlessGC.c b/xorg-server/miext/rootless/rootlessGC.c
index 0bd314d46..444342f6a 100644
--- a/xorg-server/miext/rootless/rootlessGC.c
+++ b/xorg-server/miext/rootless/rootlessGC.c
@@ -1,1497 +1,1497 @@
-/*
- * Graphics Context support 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 <stddef.h> /* For NULL */
-#include "mi.h"
-#include "scrnintstr.h"
-#include "gcstruct.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
-#include "dixfontstr.h"
-#include "mivalidate.h"
-#include "fb.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "rootlessCommon.h"
-
-
-// GC functions
-static void RootlessValidateGC(GCPtr pGC, unsigned long changes,
- DrawablePtr pDrawable);
-static void RootlessChangeGC(GCPtr pGC, unsigned long mask);
-static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
-static void RootlessDestroyGC(GCPtr pGC);
-static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue,
- int nrects);
-static void RootlessDestroyClip(GCPtr pGC);
-static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
-
-Bool RootlessCreateGC(GCPtr pGC);
-
-GCFuncs rootlessGCFuncs = {
- RootlessValidateGC,
- RootlessChangeGC,
- RootlessCopyGC,
- RootlessDestroyGC,
- RootlessChangeClip,
- RootlessDestroyClip,
- RootlessCopyClip,
-};
-
-// GC operations
-static void RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit,
- int sorted);
-static void RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
- DDXPointPtr pptInit, int *pwidthInit,
- int nspans, int sorted);
-static void RootlessPutImage(DrawablePtr dst, GCPtr pGC,
- int depth, int x, int y, int w, int h,
- int leftPad, int format, char *pBits);
-static RegionPtr RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
- int srcx, int srcy, int w, int h,
- int dstx, int dsty);
-static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
- GCPtr pGC, int srcx, int srcy,
- int w, int h, int dstx, int dsty,
- unsigned long plane);
-static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
- int mode, int npt, DDXPointPtr pptInit);
-static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
- int mode, int npt, DDXPointPtr pptInit);
-static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
- int nseg, xSegment *pSeg);
-static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
- int nRects, xRectangle *pRects);
-static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs);
-static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
- int shape, int mode, int count,
- DDXPointPtr pptInit);
-static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
- int nRectsInit, xRectangle *pRectsInit);
-static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
- int narcsInit, xArc *parcsInit);
-static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, char *chars);
-static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, unsigned short *chars);
-static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, char *chars);
-static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, unsigned short *chars);
-static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
- int x, int y, unsigned int nglyphInit,
- CharInfoPtr *ppciInit, pointer unused);
-static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
- int x, int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase);
-static void RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
- int dx, int dy, int xOrg, int yOrg);
-
-
-static GCOps rootlessGCOps = {
- RootlessFillSpans,
- RootlessSetSpans,
- RootlessPutImage,
- RootlessCopyArea,
- RootlessCopyPlane,
- RootlessPolyPoint,
- RootlessPolylines,
- RootlessPolySegment,
- RootlessPolyRectangle,
- RootlessPolyArc,
- RootlessFillPolygon,
- RootlessPolyFillRect,
- RootlessPolyFillArc,
- RootlessPolyText8,
- RootlessPolyText16,
- RootlessImageText8,
- RootlessImageText16,
- RootlessImageGlyphBlt,
- RootlessPolyGlyphBlt,
- RootlessPushPixels
-};
-
-/*
- There are two issues we must contend with when drawing. These are
- controlled with ROOTLESS_PROTECT_ALPHA and RootlessAccelInit().
-
- If ROOTLESS_PROTECT_ALPHA is set, we have to make sure that the alpha
- channel of the on screen windows is always opaque. fb makes this harder
- than it would otherwise be by noticing that a planemask of 0x00ffffff
- includes all bits when depth==24, and so it "optimizes" the planemask to
- 0xffffffff. We work around this by temporarily setting depth=bpp while
- changing the GC.
-
- So the normal situation (in 32 bit mode) is that the planemask is
- 0x00ffffff and thus fb leaves the alpha channel alone. The rootless
- implementation is responsible for setting the alpha channel opaque
- initially.
-
- Unfortunately drawing with a planemask that doesn't have all bits set
- normally causes fb to fall off its fastest paths when blitting and
- filling. So we try to recognize when we can relax the planemask back to
- 0xffffffff, and do that for the duration of the drawing operation,
- setting the alpha channel in fg/bg pixels to opaque at the same time. We
- can do this when drawing op is GXcopy. We can also do this when copying
- from another window since its alpha channel must also be opaque.
-
- The other issue to consider is that the rootless implementation may
- provide accelerated drawing functions if RootlessAccelInit() is called.For
- some drawing primitives we swap in rootless acceleration functions, which
- use the accelerated drawing functions where possible.
-
- Where both alpha protection and acceleration is used, it is even a bigger
- win to relax the planemask to all ones because most accelerated drawing
- functions can only be used in this case. However, even if we can't set
- the planemask to all ones, we can still use the accelerated
- CompositePixels function for GXcopy if it is a forward copy. This is
- mainly intended for copying from pixmaps to windows. The CompositePixels
- operation used sets alpha to 0xFF during the copy.
-
- The three macros below are used to implement this, potentially accelerated
- drawing ops look something like this:
-
- OP {
- GC_SAVE(gc);
- GCOP_UNWRAP(gc);
-
- ...
-
- if (canAccelxxx(..) && otherwise-suitable)
- GC_UNSET_PM(gc, dst);
-
- gc->funcs->OP(gc, ...);
-
- GC_RESTORE(gc, dst);
- GCOP_WRAP(gc);
- }
-
- */
-
-#define GC_SAVE(pGC) \
- unsigned long _save_fg = (pGC)->fgPixel; \
- unsigned long _save_bg = (pGC)->bgPixel; \
- unsigned long _save_pm = (pGC)->planemask; \
- Bool _changed = FALSE
-
-#define GC_RESTORE(pGC, pDraw) \
- do { \
- if (_changed) { \
- unsigned int depth = (pDraw)->depth; \
- (pGC)->fgPixel = _save_fg; \
- (pGC)->bgPixel = _save_bg; \
- (pGC)->planemask = _save_pm; \
- (pDraw)->depth = (pDraw)->bitsPerPixel; \
- VALIDATE_GC(pGC, GCForeground | GCBackground | \
- GCPlaneMask, pDraw); \
- (pDraw)->depth = depth; \
- } \
- } while (0)
-
-#define GC_UNSET_PM(pGC, pDraw) \
- do { \
- unsigned int mask = RootlessAlphaMask ((pDraw)->bitsPerPixel); \
- if (((pGC)->planemask & mask) != mask) { \
- unsigned int depth = (pDraw)->depth; \
- (pGC)->fgPixel |= mask; \
- (pGC)->bgPixel |= mask; \
- (pGC)->planemask |= mask; \
- (pDraw)->depth = (pDraw)->bitsPerPixel; \
- VALIDATE_GC(pGC, GCForeground | \
- GCBackground | GCPlaneMask, pDraw); \
- (pDraw)->depth = depth; \
- _changed = TRUE; \
- } \
- } while (0)
-
-#define VALIDATE_GC(pGC, changes, pDrawable) \
- do { \
- pGC->funcs->ValidateGC(pGC, changes, pDrawable); \
- if (((WindowPtr) pDrawable)->viewable) { \
- gcrec->originalOps = pGC->ops; \
- } \
- } while(0)
-
-static RootlessWindowRec *
-canAccelBlit (DrawablePtr pDraw, GCPtr pGC)
-{
- WindowPtr pTop;
- RootlessWindowRec *winRec;
- unsigned int pm;
-
- if (pGC->alu != GXcopy)
- return NULL;
-
- if (pDraw->type != DRAWABLE_WINDOW)
- return NULL;
-
- pm = ~RootlessAlphaMask(pDraw->bitsPerPixel);
- if ((pGC->planemask & pm) != pm)
- return NULL;
-
- pTop = TopLevelParent((WindowPtr) pDraw);
- if (pTop == NULL)
- return NULL;
-
- winRec = WINREC(pTop);
- if (winRec == NULL)
- return NULL;
-
- return winRec;
-}
-
-static inline RootlessWindowRec *
-canAccelFill(DrawablePtr pDraw, GCPtr pGC)
-{
- if (pGC->fillStyle != FillSolid)
- return NULL;
-
- return canAccelBlit(pDraw, pGC);
-}
-
-static unsigned int
-boxBytes(DrawablePtr pDraw, BoxRec *box)
-{
- unsigned int pixels;
-
- pixels = (box->x2 - box->x1) * (box->y2 - box->y1);
-
- return pixels * (pDraw->bitsPerPixel >> 3);
-}
-
-
-/*
- * Screen function to create a graphics context
- */
-Bool
-RootlessCreateGC(GCPtr pGC)
-{
- RootlessGCRec *gcrec;
- RootlessScreenRec *s;
- Bool result;
-
- SCREEN_UNWRAP(pGC->pScreen, CreateGC);
- s = SCREENREC(pGC->pScreen);
- result = s->CreateGC(pGC);
-
- gcrec = (RootlessGCRec *)
- dixLookupPrivate(&pGC->devPrivates, rootlessGCPrivateKey);
- gcrec->originalOps = NULL; // don't wrap ops yet
- gcrec->originalFuncs = pGC->funcs;
- pGC->funcs = &rootlessGCFuncs;
-
- SCREEN_WRAP(pGC->pScreen, CreateGC);
- return result;
-}
-
-
-/*
- * GC funcs
- *
- * These wrap lower level GC funcs.
- * ValidateGC wraps the GC ops iff dest is viewable.
- * All the others just unwrap and call.
- */
-
-// GCFUNC_UNRAP assumes funcs have been wrapped and
-// does not assume ops have been wrapped
-#define GCFUNC_UNWRAP(pGC) \
- RootlessGCRec *gcrec = (RootlessGCRec *) \
- dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \
- (pGC)->funcs = gcrec->originalFuncs; \
- if (gcrec->originalOps) { \
- (pGC)->ops = gcrec->originalOps; \
-}
-
-#define GCFUNC_WRAP(pGC) \
- gcrec->originalFuncs = (pGC)->funcs; \
- (pGC)->funcs = &rootlessGCFuncs; \
- if (gcrec->originalOps) { \
- gcrec->originalOps = (pGC)->ops; \
- (pGC)->ops = &rootlessGCOps; \
-}
-
-
-static void
-RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
-{
- GCFUNC_UNWRAP(pGC);
-
- gcrec->originalOps = NULL;
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
-#ifdef ROOTLESS_PROTECT_ALPHA
- unsigned int depth = pDrawable->depth;
-
- // We force a planemask so fb doesn't overwrite the alpha channel.
- // Left to its own devices, fb will optimize away the planemask.
- pDrawable->depth = pDrawable->bitsPerPixel;
- pGC->planemask &= ~RootlessAlphaMask(pDrawable->bitsPerPixel);
- VALIDATE_GC(pGC, changes | GCPlaneMask, pDrawable);
- pDrawable->depth = depth;
-#else
- VALIDATE_GC(pGC, changes, pDrawable);
-#endif
- } else {
- pGC->funcs->ValidateGC(pGC, changes, pDrawable);
- }
-
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessChangeGC(GCPtr pGC, unsigned long mask)
-{
- GCFUNC_UNWRAP(pGC);
- pGC->funcs->ChangeGC(pGC, mask);
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
-{
- GCFUNC_UNWRAP(pGCDst);
- pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst);
- GCFUNC_WRAP(pGCDst);
-}
-
-static void RootlessDestroyGC(GCPtr pGC)
-{
- GCFUNC_UNWRAP(pGC);
- pGC->funcs->DestroyGC(pGC);
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
-{
- GCFUNC_UNWRAP(pGC);
- pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessDestroyClip(GCPtr pGC)
-{
- GCFUNC_UNWRAP(pGC);
- pGC->funcs->DestroyClip(pGC);
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
-{
- GCFUNC_UNWRAP(pgcDst);
- pgcDst->funcs->CopyClip(pgcDst, pgcSrc);
- GCFUNC_WRAP(pgcDst);
-}
-
-
-/*
- * GC ops
- *
- * We can't use shadowfb because shadowfb assumes one pixmap
- * and our root window is a special case.
- * However, much of this code is copied from shadowfb.
- */
-
-// assumes both funcs and ops are wrapped
-#define GCOP_UNWRAP(pGC) \
- RootlessGCRec *gcrec = (RootlessGCRec *) \
- dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \
- GCFuncs *saveFuncs = pGC->funcs; \
- (pGC)->funcs = gcrec->originalFuncs; \
- (pGC)->ops = gcrec->originalOps;
-
-#define GCOP_WRAP(pGC) \
- gcrec->originalOps = (pGC)->ops; \
- (pGC)->funcs = saveFuncs; \
- (pGC)->ops = &rootlessGCOps;
-
-static void
-RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit, int sorted)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("fill spans start ");
-
- if (nInit <= 0) {
- pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
- } else {
- DDXPointPtr ppt = pptInit;
- int *pwidth = pwidthInit;
- int i = nInit;
- BoxRec box;
-
- box.x1 = ppt->x;
- box.x2 = box.x1 + *pwidth;
- box.y2 = box.y1 = ppt->y;
-
- while (--i) {
- ppt++;
- pwidth++;
- if (box.x1 > ppt->x)
- box.x1 = ppt->x;
- if (box.x2 < (ppt->x + *pwidth))
- box.x2 = ppt->x + *pwidth;
- if (box.y1 > ppt->y)
- box.y1 = ppt->y;
- else if (box.y2 < ppt->y)
- box.y2 = ppt->y;
- }
-
- box.y2++;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC) &&
- boxBytes(dst, &box) >= rootless_FillBytes_threshold)
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("fill spans end\n");
-}
-
-static void
-RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
- DDXPointPtr pptInit, int *pwidthInit,
- int nspans, int sorted)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("set spans start ");
-
- if (nspans <= 0) {
- pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
- nspans, sorted);
- } else {
- DDXPointPtr ppt = pptInit;
- int *pwidth = pwidthInit;
- int i = nspans;
- BoxRec box;
-
- box.x1 = ppt->x;
- box.x2 = box.x1 + *pwidth;
- box.y2 = box.y1 = ppt->y;
-
- while (--i) {
- ppt++;
- pwidth++;
- if (box.x1 > ppt->x)
- box.x1 = ppt->x;
- if (box.x2 < (ppt->x + *pwidth))
- box.x2 = ppt->x + *pwidth;
- if (box.y1 > ppt->y)
- box.y1 = ppt->y;
- else if (box.y2 < ppt->y)
- box.y2 = ppt->y;
- }
-
- box.y2++;
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
- nspans, sorted);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("set spans end\n");
-}
-
-static void
-RootlessPutImage(DrawablePtr dst, GCPtr pGC,
- int depth, int x, int y, int w, int h,
- int leftPad, int format, char *pBits)
-{
- BoxRec box;
-
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("put image start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PutImage(dst, pGC, depth, x,y,w,h, leftPad, format, pBits);
-
- box.x1 = x + dst->x;
- box.x2 = box.x1 + w;
- box.y1 = y + dst->y;
- box.y2 = box.y1 + h;
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("put image end\n");
-}
-
-/* changed area is *dest* rect */
-static RegionPtr
-RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
- int srcx, int srcy, int w, int h,
- int dstx, int dsty)
-{
- RegionPtr result;
- BoxRec box;
-
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
-
- RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst);
-
- if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
- unsigned int bytes;
-
- /* If both source and dest are windows, and we're doing
- a simple copy operation, we can remove the alpha-protecting
- planemask (since source has opaque alpha as well) */
-
- bytes = w * h * (pSrc->depth >> 3);
-
- if (bytes >= rootless_CopyBytes_threshold && canAccelBlit(pSrc, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- RootlessStartDrawing((WindowPtr) pSrc);
- }
- RootlessStartDrawing((WindowPtr) dst);
- result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty);
-
- box.x1 = dstx + dst->x;
- box.x2 = box.x1 + w;
- box.y1 = dsty + dst->y;
- box.y2 = box.y1 + h;
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("copy area end\n");
- return result;
-}
-
-/* changed area is *dest* rect */
-static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
- GCPtr pGC, int srcx, int srcy,
- int w, int h, int dstx, int dsty,
- unsigned long plane)
-{
- RegionPtr result;
- BoxRec box;
-
- GCOP_UNWRAP(pGC);
-
- RL_DEBUG_MSG("copy plane start ");
-
- if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
- RootlessStartDrawing((WindowPtr) pSrc);
- }
- RootlessStartDrawing((WindowPtr) dst);
- result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h,
- dstx, dsty, plane);
-
- box.x1 = dstx + dst->x;
- box.x2 = box.x1 + w;
- box.y1 = dsty + dst->y;
- box.y2 = box.y1 + h;
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("copy plane end\n");
- return result;
-}
-
-// Options for size of changed area:
-// 0 = box per point
-// 1 = big box around all points
-// 2 = accumulate point in 20 pixel radius
-#define ROOTLESS_CHANGED_AREA 1
-#define abs(a) ((a) > 0 ? (a) : -(a))
-
-/* changed area is box around all points */
-static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
- int mode, int npt, DDXPointPtr pptInit)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("polypoint start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit);
-
- if (npt > 0) {
-#if ROOTLESS_CHANGED_AREA==0
- // box per point
- BoxRec box;
-
- while (npt) {
- box.x1 = pptInit->x;
- box.y1 = pptInit->y;
- box.x2 = box.x1 + 1;
- box.y2 = box.y1 + 1;
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- npt--;
- pptInit++;
- }
-
-#elif ROOTLESS_CHANGED_AREA==1
- // one big box
- BoxRec box;
-
- box.x2 = box.x1 = pptInit->x;
- box.y2 = box.y1 = pptInit->y;
- while (--npt) {
- pptInit++;
- if (box.x1 > pptInit->x)
- box.x1 = pptInit->x;
- else if (box.x2 < pptInit->x)
- box.x2 = pptInit->x;
- if (box.y1 > pptInit->y)
- box.y1 = pptInit->y;
- else if (box.y2 < pptInit->y)
- box.y2 = pptInit->y;
- }
-
- box.x2++;
- box.y2++;
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
-#elif ROOTLESS_CHANGED_AREA==2
- // clever(?) method: accumulate point in 20-pixel radius
- BoxRec box;
- int firstx, firsty;
-
- box.x2 = box.x1 = firstx = pptInit->x;
- box.y2 = box.y1 = firsty = pptInit->y;
- while (--npt) {
- pptInit++;
- if (abs(pptInit->x - firstx) > 20 ||
- abs(pptInit->y - firsty) > 20) {
- box.x2++;
- box.y2++;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- box.x2 = box.x1 = firstx = pptInit->x;
- box.y2 = box.y1 = firsty = pptInit->y;
- } else {
- if (box.x1 > pptInit->x) box.x1 = pptInit->x;
- else if (box.x2 < pptInit->x) box.x2 = pptInit->x;
- if (box.y1 > pptInit->y) box.y1 = pptInit->y;
- else if (box.y2 < pptInit->y) box.y2 = pptInit->y;
- }
- }
- box.x2++;
- box.y2++;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox((WindowPtr) dst, &box);
-#endif /* ROOTLESS_CHANGED_AREA */
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("polypoint end\n");
-}
-
-#undef ROOTLESS_CHANGED_AREA
-
-/* changed area is box around each line */
-static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
- int mode, int npt, DDXPointPtr pptInit)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("poly lines start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->Polylines(dst, pGC, mode, npt, pptInit);
-
- if (npt > 0) {
- BoxRec box;
- int extra = pGC->lineWidth >> 1;
-
- box.x2 = box.x1 = pptInit->x;
- box.y2 = box.y1 = pptInit->y;
-
- if (npt > 1) {
- if (pGC->joinStyle == JoinMiter)
- extra = 6 * pGC->lineWidth;
- else if (pGC->capStyle == CapProjecting)
- extra = pGC->lineWidth;
- }
-
- if (mode == CoordModePrevious) {
- int x = box.x1;
- int y = box.y1;
-
- while (--npt) {
- pptInit++;
- x += pptInit->x;
- y += pptInit->y;
- if (box.x1 > x)
- box.x1 = x;
- else if (box.x2 < x)
- box.x2 = x;
- if (box.y1 > y)
- box.y1 = y;
- else if (box.y2 < y)
- box.y2 = y;
- }
- } else {
- while (--npt) {
- pptInit++;
- if (box.x1 > pptInit->x)
- box.x1 = pptInit->x;
- else if (box.x2 < pptInit->x)
- box.x2 = pptInit->x;
- if (box.y1 > pptInit->y)
- box.y1 = pptInit->y;
- else if (box.y2 < pptInit->y)
- box.y2 = pptInit->y;
- }
- }
-
- box.x2++;
- box.y2++;
-
- if (extra) {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("poly lines end\n");
-}
-
-/* changed area is box around each line segment */
-static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
- int nseg, xSegment *pSeg)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("poly segment start (win 0x%x)", dst);
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolySegment(dst, pGC, nseg, pSeg);
-
- if (nseg > 0) {
- BoxRec box;
- int extra = pGC->lineWidth;
-
- if (pGC->capStyle != CapProjecting)
- extra >>= 1;
-
- if (pSeg->x2 > pSeg->x1) {
- box.x1 = pSeg->x1;
- box.x2 = pSeg->x2;
- } else {
- box.x2 = pSeg->x1;
- box.x1 = pSeg->x2;
- }
-
- if (pSeg->y2 > pSeg->y1) {
- box.y1 = pSeg->y1;
- box.y2 = pSeg->y2;
- } else {
- box.y2 = pSeg->y1;
- box.y1 = pSeg->y2;
- }
-
- while (--nseg) {
- pSeg++;
- if (pSeg->x2 > pSeg->x1) {
- if (pSeg->x1 < box.x1) box.x1 = pSeg->x1;
- if (pSeg->x2 > box.x2) box.x2 = pSeg->x2;
- } else {
- if (pSeg->x2 < box.x1) box.x1 = pSeg->x2;
- if (pSeg->x1 > box.x2) box.x2 = pSeg->x1;
- }
- if (pSeg->y2 > pSeg->y1) {
- if (pSeg->y1 < box.y1) box.y1 = pSeg->y1;
- if (pSeg->y2 > box.y2) box.y2 = pSeg->y2;
- } else {
- if (pSeg->y2 < box.y1) box.y1 = pSeg->y2;
- if (pSeg->y1 > box.y2) box.y2 = pSeg->y1;
- }
- }
-
- box.x2++;
- box.y2++;
-
- if (extra) {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("poly segment end\n");
-}
-
-/* changed area is box around each line (not entire rects) */
-static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
- int nRects, xRectangle *pRects)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("poly rectangle start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolyRectangle(dst, pGC, nRects, pRects);
-
- if (nRects > 0) {
- BoxRec box;
- int offset1, offset2, offset3;
-
- offset2 = pGC->lineWidth;
- if (!offset2) offset2 = 1;
- offset1 = offset2 >> 1;
- offset3 = offset2 - offset1;
-
- while (nRects--) {
- box.x1 = pRects->x - offset1;
- box.y1 = pRects->y - offset1;
- box.x2 = box.x1 + pRects->width + offset2;
- box.y2 = box.y1 + offset2;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- box.x1 = pRects->x - offset1;
- box.y1 = pRects->y + offset3;
- box.x2 = box.x1 + offset2;
- box.y2 = box.y1 + pRects->height - offset2;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- box.x1 = pRects->x + pRects->width - offset1;
- box.y1 = pRects->y + offset3;
- box.x2 = box.x1 + offset2;
- box.y2 = box.y1 + pRects->height - offset2;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- box.x1 = pRects->x - offset1;
- box.y1 = pRects->y + pRects->height - offset1;
- box.x2 = box.x1 + pRects->width + offset2;
- box.y2 = box.y1 + offset2;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- pRects++;
- }
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("poly rectangle end\n");
-}
-
-
-/* changed area is box around each arc (assumes all arcs are 360 degrees) */
-static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("poly arc start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolyArc(dst, pGC, narcs, parcs);
-
- if (narcs > 0) {
- int extra = pGC->lineWidth >> 1;
- BoxRec box;
-
- box.x1 = parcs->x;
- box.x2 = box.x1 + parcs->width;
- box.y1 = parcs->y;
- box.y2 = box.y1 + parcs->height;
-
- /* should I break these up instead ? */
-
- while (--narcs) {
- parcs++;
- if (box.x1 > parcs->x)
- box.x1 = parcs->x;
- if (box.x2 < (parcs->x + parcs->width))
- box.x2 = parcs->x + parcs->width;
- if (box.y1 > parcs->y)
- box.y1 = parcs->y;
- if (box.y2 < (parcs->y + parcs->height))
- box.y2 = parcs->y + parcs->height;
- }
-
- if (extra) {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- box.x2++;
- box.y2++;
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("poly arc end\n");
-}
-
-
-/* changed area is box around each poly */
-static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
- int shape, int mode, int count,
- DDXPointPtr pptInit)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)", dst,
- pGC->fillStyle);
-
- if (count <= 2) {
- pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
- } else {
- DDXPointPtr ppt = pptInit;
- int i = count;
- BoxRec box;
-
- box.x2 = box.x1 = ppt->x;
- box.y2 = box.y1 = ppt->y;
-
- if (mode != CoordModeOrigin) {
- int x = box.x1;
- int y = box.y1;
-
- while (--i) {
- ppt++;
- x += ppt->x;
- y += ppt->y;
- if (box.x1 > x)
- box.x1 = x;
- else if (box.x2 < x)
- box.x2 = x;
- if (box.y1 > y)
- box.y1 = y;
- else if (box.y2 < y)
- box.y2 = y;
- }
- } else {
- while (--i) {
- ppt++;
- if (box.x1 > ppt->x)
- box.x1 = ppt->x;
- else if (box.x2 < ppt->x)
- box.x2 = ppt->x;
- if (box.y1 > ppt->y)
- box.y1 = ppt->y;
- else if (box.y2 < ppt->y)
- box.y2 = ppt->y;
- }
- }
-
- box.x2++;
- box.y2++;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC) &&
- boxBytes(dst, &box) >= rootless_FillBytes_threshold)
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("fill poly end\n");
-}
-
-/* changed area is the rects */
-static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
- int nRectsInit, xRectangle *pRectsInit)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)", dst,
- pGC->fillStyle);
-
- if (nRectsInit <= 0) {
- pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
- } else {
- BoxRec box;
- xRectangle *pRects = pRectsInit;
- int nRects = nRectsInit;
-
- box.x1 = pRects->x;
- box.x2 = box.x1 + pRects->width;
- box.y1 = pRects->y;
- box.y2 = box.y1 + pRects->height;
-
- while (--nRects) {
- pRects++;
- if (box.x1 > pRects->x)
- box.x1 = pRects->x;
- if (box.x2 < (pRects->x + pRects->width))
- box.x2 = pRects->x + pRects->width;
- if (box.y1 > pRects->y)
- box.y1 = pRects->y;
- if (box.y2 < (pRects->y + pRects->height))
- box.y2 = pRects->y + pRects->height;
- }
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC) &&
- boxBytes(dst, &box) >= rootless_FillBytes_threshold)
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("fill rect end\n");
-}
-
-
-/* changed area is box around each arc (assuming arcs are all 360 degrees) */
-static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
- int narcsInit, xArc *parcsInit)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("fill arc start ");
-
- if (narcsInit > 0) {
- BoxRec box;
- int narcs = narcsInit;
- xArc *parcs = parcsInit;
-
- box.x1 = parcs->x;
- box.x2 = box.x1 + parcs->width;
- box.y1 = parcs->y;
- box.y2 = box.y1 + parcs->height;
-
- /* should I break these up instead ? */
-
- while (--narcs) {
- parcs++;
- if (box.x1 > parcs->x)
- box.x1 = parcs->x;
- if (box.x2 < (parcs->x + parcs->width))
- box.x2 = parcs->x + parcs->width;
- if (box.y1 > parcs->y)
- box.y1 = parcs->y;
- if (box.y2 < (parcs->y + parcs->height))
- box.y2 = parcs->y + parcs->height;
- }
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC) &&
- boxBytes(dst, &box) >= rootless_FillBytes_threshold)
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- } else {
- pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("fill arc end\n");
-}
-
-
-static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, char *chars)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("imagetext8 start ");
-
- if (count > 0) {
- int top, bot, Min, Max;
- BoxRec box;
-
- top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
- bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
- Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
- if (Min > 0) Min = 0;
- Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
- if (Max < 0) Max = 0;
-
- /* ugh */
- box.x1 = dst->x + x + Min +
- FONTMINBOUNDS(pGC->font, leftSideBearing);
- box.x2 = dst->x + x + Max +
- FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
- box.y1 = dst->y + y - top;
- box.y2 = dst->y + y + bot;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC) &&
- boxBytes(dst, &box) >= rootless_FillBytes_threshold)
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- } else {
- pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("imagetext8 end\n");
-}
-
-static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, char *chars)
-{
- int width; // the result, sorta
-
- GCOP_UNWRAP(pGC);
-
- RL_DEBUG_MSG("polytext8 start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars);
- width -= x;
-
- if (width > 0) {
- BoxRec box;
-
- /* ugh */
- box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
- box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
- if (count > 1) {
- if (width > 0) box.x2 += width;
- else box.x1 += width;
- }
-
- box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
- box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("polytext8 end\n");
- return (width + x);
-}
-
-static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, unsigned short *chars)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("imagetext16 start ");
-
- if (count > 0) {
- int top, bot, Min, Max;
- BoxRec box;
-
- top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
- bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
- Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
- if (Min > 0) Min = 0;
- Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
- if (Max < 0) Max = 0;
-
- /* ugh */
- box.x1 = dst->x + x + Min +
- FONTMINBOUNDS(pGC->font, leftSideBearing);
- box.x2 = dst->x + x + Max +
- FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
- box.y1 = dst->y + y - top;
- box.y2 = dst->y + y + bot;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC) &&
- boxBytes(dst, &box) >= rootless_FillBytes_threshold)
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- } else {
- pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("imagetext16 end\n");
-}
-
-static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, unsigned short *chars)
-{
- int width; // the result, sorta
-
- GCOP_UNWRAP(pGC);
-
- RL_DEBUG_MSG("polytext16 start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars);
- width -= x;
-
- if (width > 0) {
- BoxRec box;
-
- /* ugh */
- box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
- box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
- if (count > 1) {
- if (width > 0) box.x2 += width;
- else box.x1 += width;
- }
-
- box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
- box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("polytext16 end\n");
- return width + x;
-}
-
-static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
- int x, int y, unsigned int nglyphInit,
- CharInfoPtr *ppciInit, pointer unused)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("imageglyph start ");
-
- if (nglyphInit > 0) {
- int top, bot, width = 0;
- BoxRec box;
- unsigned int nglyph = nglyphInit;
- CharInfoPtr *ppci = ppciInit;
-
- top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
- bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
- box.x1 = ppci[0]->metrics.leftSideBearing;
- if (box.x1 > 0) box.x1 = 0;
- box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
- ppci[nglyph - 1]->metrics.characterWidth;
- if (box.x2 < 0) box.x2 = 0;
-
- box.x2 += dst->x + x;
- box.x1 += dst->x + x;
-
- while (nglyph--) {
- width += (*ppci)->metrics.characterWidth;
- ppci++;
- }
-
- if (width > 0)
- box.x2 += width;
- else
- box.x1 += width;
-
- box.y1 = dst->y + y - top;
- box.y2 = dst->y + y + bot;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC) &&
- boxBytes(dst, &box) >= rootless_FillBytes_threshold)
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- } else {
- pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("imageglyph end\n");
-}
-
-static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
- int x, int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("polyglyph start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase);
-
- if (nglyph > 0) {
- BoxRec box;
-
- /* ugh */
- box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing;
- box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
-
- if (nglyph > 1) {
- int width = 0;
-
- while (--nglyph) {
- width += (*ppci)->metrics.characterWidth;
- ppci++;
- }
-
- if (width > 0) box.x2 += width;
- else box.x1 += width;
- }
-
- box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
- box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("polyglyph end\n");
-}
-
-
-/* changed area is in dest */
-static void
-RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
- int dx, int dy, int xOrg, int yOrg)
-{
- BoxRec box;
-
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("push pixels start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg);
-
- box.x1 = xOrg + dst->x;
- box.x2 = box.x1 + dx;
- box.y1 = yOrg + dst->y;
- box.y2 = box.y1 + dy;
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("push pixels end\n");
-}
+/*
+ * Graphics Context support 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 <stddef.h> /* For NULL */
+#include "mi.h"
+#include "scrnintstr.h"
+#include "gcstruct.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "dixfontstr.h"
+#include "mivalidate.h"
+#include "fb.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "rootlessCommon.h"
+
+
+// GC functions
+static void RootlessValidateGC(GCPtr pGC, unsigned long changes,
+ DrawablePtr pDrawable);
+static void RootlessChangeGC(GCPtr pGC, unsigned long mask);
+static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void RootlessDestroyGC(GCPtr pGC);
+static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue,
+ int nrects);
+static void RootlessDestroyClip(GCPtr pGC);
+static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+
+Bool RootlessCreateGC(GCPtr pGC);
+
+GCFuncs rootlessGCFuncs = {
+ RootlessValidateGC,
+ RootlessChangeGC,
+ RootlessCopyGC,
+ RootlessDestroyGC,
+ RootlessChangeClip,
+ RootlessDestroyClip,
+ RootlessCopyClip,
+};
+
+// GC operations
+static void RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int sorted);
+static void RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int nspans, int sorted);
+static void RootlessPutImage(DrawablePtr dst, GCPtr pGC,
+ int depth, int x, int y, int w, int h,
+ int leftPad, int format, char *pBits);
+static RegionPtr RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty);
+static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
+ GCPtr pGC, int srcx, int srcy,
+ int w, int h, int dstx, int dsty,
+ unsigned long plane);
+static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit);
+static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit);
+static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
+ int nseg, xSegment *pSeg);
+static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
+ int nRects, xRectangle *pRects);
+static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs);
+static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
+ int shape, int mode, int count,
+ DDXPointPtr pptInit);
+static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
+ int nRectsInit, xRectangle *pRectsInit);
+static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
+ int narcsInit, xArc *parcsInit);
+static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars);
+static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars);
+static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars);
+static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars);
+static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyphInit,
+ CharInfoPtr *ppciInit, pointer unused);
+static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase);
+static void RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
+ int dx, int dy, int xOrg, int yOrg);
+
+
+static GCOps rootlessGCOps = {
+ RootlessFillSpans,
+ RootlessSetSpans,
+ RootlessPutImage,
+ RootlessCopyArea,
+ RootlessCopyPlane,
+ RootlessPolyPoint,
+ RootlessPolylines,
+ RootlessPolySegment,
+ RootlessPolyRectangle,
+ RootlessPolyArc,
+ RootlessFillPolygon,
+ RootlessPolyFillRect,
+ RootlessPolyFillArc,
+ RootlessPolyText8,
+ RootlessPolyText16,
+ RootlessImageText8,
+ RootlessImageText16,
+ RootlessImageGlyphBlt,
+ RootlessPolyGlyphBlt,
+ RootlessPushPixels
+};
+
+/*
+ There are two issues we must contend with when drawing. These are
+ controlled with ROOTLESS_PROTECT_ALPHA and RootlessAccelInit().
+
+ If ROOTLESS_PROTECT_ALPHA is set, we have to make sure that the alpha
+ channel of the on screen windows is always opaque. fb makes this harder
+ than it would otherwise be by noticing that a planemask of 0x00ffffff
+ includes all bits when depth==24, and so it "optimizes" the planemask to
+ 0xffffffff. We work around this by temporarily setting depth=bpp while
+ changing the GC.
+
+ So the normal situation (in 32 bit mode) is that the planemask is
+ 0x00ffffff and thus fb leaves the alpha channel alone. The rootless
+ implementation is responsible for setting the alpha channel opaque
+ initially.
+
+ Unfortunately drawing with a planemask that doesn't have all bits set
+ normally causes fb to fall off its fastest paths when blitting and
+ filling. So we try to recognize when we can relax the planemask back to
+ 0xffffffff, and do that for the duration of the drawing operation,
+ setting the alpha channel in fg/bg pixels to opaque at the same time. We
+ can do this when drawing op is GXcopy. We can also do this when copying
+ from another window since its alpha channel must also be opaque.
+
+ The other issue to consider is that the rootless implementation may
+ provide accelerated drawing functions if RootlessAccelInit() is called.For
+ some drawing primitives we swap in rootless acceleration functions, which
+ use the accelerated drawing functions where possible.
+
+ Where both alpha protection and acceleration is used, it is even a bigger
+ win to relax the planemask to all ones because most accelerated drawing
+ functions can only be used in this case. However, even if we can't set
+ the planemask to all ones, we can still use the accelerated
+ CompositePixels function for GXcopy if it is a forward copy. This is
+ mainly intended for copying from pixmaps to windows. The CompositePixels
+ operation used sets alpha to 0xFF during the copy.
+
+ The three macros below are used to implement this, potentially accelerated
+ drawing ops look something like this:
+
+ OP {
+ GC_SAVE(gc);
+ GCOP_UNWRAP(gc);
+
+ ...
+
+ if (canAccelxxx(..) && otherwise-suitable)
+ GC_UNSET_PM(gc, dst);
+
+ gc->funcs->OP(gc, ...);
+
+ GC_RESTORE(gc, dst);
+ GCOP_WRAP(gc);
+ }
+
+ */
+
+#define GC_SAVE(pGC) \
+ unsigned long _save_fg = (pGC)->fgPixel; \
+ unsigned long _save_bg = (pGC)->bgPixel; \
+ unsigned long _save_pm = (pGC)->planemask; \
+ Bool _changed = FALSE
+
+#define GC_RESTORE(pGC, pDraw) \
+ do { \
+ if (_changed) { \
+ unsigned int depth = (pDraw)->depth; \
+ (pGC)->fgPixel = _save_fg; \
+ (pGC)->bgPixel = _save_bg; \
+ (pGC)->planemask = _save_pm; \
+ (pDraw)->depth = (pDraw)->bitsPerPixel; \
+ VALIDATE_GC(pGC, GCForeground | GCBackground | \
+ GCPlaneMask, pDraw); \
+ (pDraw)->depth = depth; \
+ } \
+ } while (0)
+
+#define GC_UNSET_PM(pGC, pDraw) \
+ do { \
+ unsigned int mask = RootlessAlphaMask ((pDraw)->bitsPerPixel); \
+ if (((pGC)->planemask & mask) != mask) { \
+ unsigned int depth = (pDraw)->depth; \
+ (pGC)->fgPixel |= mask; \
+ (pGC)->bgPixel |= mask; \
+ (pGC)->planemask |= mask; \
+ (pDraw)->depth = (pDraw)->bitsPerPixel; \
+ VALIDATE_GC(pGC, GCForeground | \
+ GCBackground | GCPlaneMask, pDraw); \
+ (pDraw)->depth = depth; \
+ _changed = TRUE; \
+ } \
+ } while (0)
+
+#define VALIDATE_GC(pGC, changes, pDrawable) \
+ do { \
+ pGC->funcs->ValidateGC(pGC, changes, pDrawable); \
+ if (((WindowPtr) pDrawable)->viewable) { \
+ gcrec->originalOps = pGC->ops; \
+ } \
+ } while(0)
+
+static RootlessWindowRec *
+canAccelBlit (DrawablePtr pDraw, GCPtr pGC)
+{
+ WindowPtr pTop;
+ RootlessWindowRec *winRec;
+ unsigned int pm;
+
+ if (pGC->alu != GXcopy)
+ return NULL;
+
+ if (pDraw->type != DRAWABLE_WINDOW)
+ return NULL;
+
+ pm = ~RootlessAlphaMask(pDraw->bitsPerPixel);
+ if ((pGC->planemask & pm) != pm)
+ return NULL;
+
+ pTop = TopLevelParent((WindowPtr) pDraw);
+ if (pTop == NULL)
+ return NULL;
+
+ winRec = WINREC(pTop);
+ if (winRec == NULL)
+ return NULL;
+
+ return winRec;
+}
+
+static inline RootlessWindowRec *
+canAccelFill(DrawablePtr pDraw, GCPtr pGC)
+{
+ if (pGC->fillStyle != FillSolid)
+ return NULL;
+
+ return canAccelBlit(pDraw, pGC);
+}
+
+static unsigned int
+boxBytes(DrawablePtr pDraw, BoxRec *box)
+{
+ unsigned int pixels;
+
+ pixels = (box->x2 - box->x1) * (box->y2 - box->y1);
+
+ return pixels * (pDraw->bitsPerPixel >> 3);
+}
+
+
+/*
+ * Screen function to create a graphics context
+ */
+Bool
+RootlessCreateGC(GCPtr pGC)
+{
+ RootlessGCRec *gcrec;
+ RootlessScreenRec *s;
+ Bool result;
+
+ SCREEN_UNWRAP(pGC->pScreen, CreateGC);
+ s = SCREENREC(pGC->pScreen);
+ result = s->CreateGC(pGC);
+
+ gcrec = (RootlessGCRec *)
+ dixLookupPrivate(&pGC->devPrivates, rootlessGCPrivateKey);
+ gcrec->originalOps = NULL; // don't wrap ops yet
+ gcrec->originalFuncs = pGC->funcs;
+ pGC->funcs = &rootlessGCFuncs;
+
+ SCREEN_WRAP(pGC->pScreen, CreateGC);
+ return result;
+}
+
+
+/*
+ * GC funcs
+ *
+ * These wrap lower level GC funcs.
+ * ValidateGC wraps the GC ops iff dest is viewable.
+ * All the others just unwrap and call.
+ */
+
+// GCFUNC_UNRAP assumes funcs have been wrapped and
+// does not assume ops have been wrapped
+#define GCFUNC_UNWRAP(pGC) \
+ RootlessGCRec *gcrec = (RootlessGCRec *) \
+ dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \
+ (pGC)->funcs = gcrec->originalFuncs; \
+ if (gcrec->originalOps) { \
+ (pGC)->ops = gcrec->originalOps; \
+}
+
+#define GCFUNC_WRAP(pGC) \
+ gcrec->originalFuncs = (pGC)->funcs; \
+ (pGC)->funcs = &rootlessGCFuncs; \
+ if (gcrec->originalOps) { \
+ gcrec->originalOps = (pGC)->ops; \
+ (pGC)->ops = &rootlessGCOps; \
+}
+
+
+static void
+RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ GCFUNC_UNWRAP(pGC);
+
+ gcrec->originalOps = NULL;
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+#ifdef ROOTLESS_PROTECT_ALPHA
+ unsigned int depth = pDrawable->depth;
+
+ // We force a planemask so fb doesn't overwrite the alpha channel.
+ // Left to its own devices, fb will optimize away the planemask.
+ pDrawable->depth = pDrawable->bitsPerPixel;
+ pGC->planemask &= ~RootlessAlphaMask(pDrawable->bitsPerPixel);
+ VALIDATE_GC(pGC, changes | GCPlaneMask, pDrawable);
+ pDrawable->depth = depth;
+#else
+ VALIDATE_GC(pGC, changes, pDrawable);
+#endif
+ } else {
+ pGC->funcs->ValidateGC(pGC, changes, pDrawable);
+ }
+
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessChangeGC(GCPtr pGC, unsigned long mask)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->ChangeGC(pGC, mask);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
+{
+ GCFUNC_UNWRAP(pGCDst);
+ pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst);
+ GCFUNC_WRAP(pGCDst);
+}
+
+static void RootlessDestroyGC(GCPtr pGC)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->DestroyGC(pGC);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessDestroyClip(GCPtr pGC)
+{
+ GCFUNC_UNWRAP(pGC);
+ pGC->funcs->DestroyClip(pGC);
+ GCFUNC_WRAP(pGC);
+}
+
+static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ GCFUNC_UNWRAP(pgcDst);
+ pgcDst->funcs->CopyClip(pgcDst, pgcSrc);
+ GCFUNC_WRAP(pgcDst);
+}
+
+
+/*
+ * GC ops
+ *
+ * We can't use shadowfb because shadowfb assumes one pixmap
+ * and our root window is a special case.
+ * However, much of this code is copied from shadowfb.
+ */
+
+// assumes both funcs and ops are wrapped
+#define GCOP_UNWRAP(pGC) \
+ RootlessGCRec *gcrec = (RootlessGCRec *) \
+ dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \
+ GCFuncs *saveFuncs = pGC->funcs; \
+ (pGC)->funcs = gcrec->originalFuncs; \
+ (pGC)->ops = gcrec->originalOps;
+
+#define GCOP_WRAP(pGC) \
+ gcrec->originalOps = (pGC)->ops; \
+ (pGC)->funcs = saveFuncs; \
+ (pGC)->ops = &rootlessGCOps;
+
+static void
+RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit, int sorted)
+{
+ GC_SAVE(pGC);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill spans start ");
+
+ if (nInit <= 0) {
+ pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nInit;
+ BoxRec box;
+
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while (--i) {
+ ppt++;
+ pwidth++;
+ if (box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ if (box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if (box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if (box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (canAccelFill(dst, pGC) &&
+ boxBytes(dst, &box) >= rootless_FillBytes_threshold)
+ {
+ GC_UNSET_PM(pGC, dst);
+ }
+
+ pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GC_RESTORE(pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill spans end\n");
+}
+
+static void
+RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int nspans, int sorted)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("set spans start ");
+
+ if (nspans <= 0) {
+ pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
+ nspans, sorted);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int *pwidth = pwidthInit;
+ int i = nspans;
+ BoxRec box;
+
+ box.x1 = ppt->x;
+ box.x2 = box.x1 + *pwidth;
+ box.y2 = box.y1 = ppt->y;
+
+ while (--i) {
+ ppt++;
+ pwidth++;
+ if (box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ if (box.x2 < (ppt->x + *pwidth))
+ box.x2 = ppt->x + *pwidth;
+ if (box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if (box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
+ nspans, sorted);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("set spans end\n");
+}
+
+static void
+RootlessPutImage(DrawablePtr dst, GCPtr pGC,
+ int depth, int x, int y, int w, int h,
+ int leftPad, int format, char *pBits)
+{
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("put image start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PutImage(dst, pGC, depth, x,y,w,h, leftPad, format, pBits);
+
+ box.x1 = x + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = y + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("put image end\n");
+}
+
+/* changed area is *dest* rect */
+static RegionPtr
+RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty)
+{
+ RegionPtr result;
+ BoxRec box;
+
+ GC_SAVE(pGC);
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst);
+
+ if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
+ unsigned int bytes;
+
+ /* If both source and dest are windows, and we're doing
+ a simple copy operation, we can remove the alpha-protecting
+ planemask (since source has opaque alpha as well) */
+
+ bytes = w * h * (pSrc->depth >> 3);
+
+ if (bytes >= rootless_CopyBytes_threshold && canAccelBlit(pSrc, pGC))
+ {
+ GC_UNSET_PM(pGC, dst);
+ }
+
+ RootlessStartDrawing((WindowPtr) pSrc);
+ }
+ RootlessStartDrawing((WindowPtr) dst);
+ result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty);
+
+ box.x1 = dstx + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = dsty + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GC_RESTORE(pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("copy area end\n");
+ return result;
+}
+
+/* changed area is *dest* rect */
+static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
+ GCPtr pGC, int srcx, int srcy,
+ int w, int h, int dstx, int dsty,
+ unsigned long plane)
+{
+ RegionPtr result;
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("copy plane start ");
+
+ if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
+ RootlessStartDrawing((WindowPtr) pSrc);
+ }
+ RootlessStartDrawing((WindowPtr) dst);
+ result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h,
+ dstx, dsty, plane);
+
+ box.x1 = dstx + dst->x;
+ box.x2 = box.x1 + w;
+ box.y1 = dsty + dst->y;
+ box.y2 = box.y1 + h;
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("copy plane end\n");
+ return result;
+}
+
+// Options for size of changed area:
+// 0 = box per point
+// 1 = big box around all points
+// 2 = accumulate point in 20 pixel radius
+#define ROOTLESS_CHANGED_AREA 1
+#define abs(a) ((a) > 0 ? (a) : -(a))
+
+/* changed area is box around all points */
+static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polypoint start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit);
+
+ if (npt > 0) {
+#if ROOTLESS_CHANGED_AREA==0
+ // box per point
+ BoxRec box;
+
+ while (npt) {
+ box.x1 = pptInit->x;
+ box.y1 = pptInit->y;
+ box.x2 = box.x1 + 1;
+ box.y2 = box.y1 + 1;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ npt--;
+ pptInit++;
+ }
+
+#elif ROOTLESS_CHANGED_AREA==1
+ // one big box
+ BoxRec box;
+
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+ while (--npt) {
+ pptInit++;
+ if (box.x1 > pptInit->x)
+ box.x1 = pptInit->x;
+ else if (box.x2 < pptInit->x)
+ box.x2 = pptInit->x;
+ if (box.y1 > pptInit->y)
+ box.y1 = pptInit->y;
+ else if (box.y2 < pptInit->y)
+ box.y2 = pptInit->y;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+#elif ROOTLESS_CHANGED_AREA==2
+ // clever(?) method: accumulate point in 20-pixel radius
+ BoxRec box;
+ int firstx, firsty;
+
+ box.x2 = box.x1 = firstx = pptInit->x;
+ box.y2 = box.y1 = firsty = pptInit->y;
+ while (--npt) {
+ pptInit++;
+ if (abs(pptInit->x - firstx) > 20 ||
+ abs(pptInit->y - firsty) > 20) {
+ box.x2++;
+ box.y2++;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ box.x2 = box.x1 = firstx = pptInit->x;
+ box.y2 = box.y1 = firsty = pptInit->y;
+ } else {
+ if (box.x1 > pptInit->x) box.x1 = pptInit->x;
+ else if (box.x2 < pptInit->x) box.x2 = pptInit->x;
+ if (box.y1 > pptInit->y) box.y1 = pptInit->y;
+ else if (box.y2 < pptInit->y) box.y2 = pptInit->y;
+ }
+ }
+ box.x2++;
+ box.y2++;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox((WindowPtr) dst, &box);
+#endif /* ROOTLESS_CHANGED_AREA */
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polypoint end\n");
+}
+
+#undef ROOTLESS_CHANGED_AREA
+
+/* changed area is box around each line */
+static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("poly lines start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->Polylines(dst, pGC, mode, npt, pptInit);
+
+ if (npt > 0) {
+ BoxRec box;
+ int extra = pGC->lineWidth >> 1;
+
+ box.x2 = box.x1 = pptInit->x;
+ box.y2 = box.y1 = pptInit->y;
+
+ if (npt > 1) {
+ if (pGC->joinStyle == JoinMiter)
+ extra = 6 * pGC->lineWidth;
+ else if (pGC->capStyle == CapProjecting)
+ extra = pGC->lineWidth;
+ }
+
+ if (mode == CoordModePrevious) {
+ int x = box.x1;
+ int y = box.y1;
+
+ while (--npt) {
+ pptInit++;
+ x += pptInit->x;
+ y += pptInit->y;
+ if (box.x1 > x)
+ box.x1 = x;
+ else if (box.x2 < x)
+ box.x2 = x;
+ if (box.y1 > y)
+ box.y1 = y;
+ else if (box.y2 < y)
+ box.y2 = y;
+ }
+ } else {
+ while (--npt) {
+ pptInit++;
+ if (box.x1 > pptInit->x)
+ box.x1 = pptInit->x;
+ else if (box.x2 < pptInit->x)
+ box.x2 = pptInit->x;
+ if (box.y1 > pptInit->y)
+ box.y1 = pptInit->y;
+ else if (box.y2 < pptInit->y)
+ box.y2 = pptInit->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if (extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly lines end\n");
+}
+
+/* changed area is box around each line segment */
+static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
+ int nseg, xSegment *pSeg)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("poly segment start (win 0x%x)", dst);
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolySegment(dst, pGC, nseg, pSeg);
+
+ if (nseg > 0) {
+ BoxRec box;
+ int extra = pGC->lineWidth;
+
+ if (pGC->capStyle != CapProjecting)
+ extra >>= 1;
+
+ if (pSeg->x2 > pSeg->x1) {
+ box.x1 = pSeg->x1;
+ box.x2 = pSeg->x2;
+ } else {
+ box.x2 = pSeg->x1;
+ box.x1 = pSeg->x2;
+ }
+
+ if (pSeg->y2 > pSeg->y1) {
+ box.y1 = pSeg->y1;
+ box.y2 = pSeg->y2;
+ } else {
+ box.y2 = pSeg->y1;
+ box.y1 = pSeg->y2;
+ }
+
+ while (--nseg) {
+ pSeg++;
+ if (pSeg->x2 > pSeg->x1) {
+ if (pSeg->x1 < box.x1) box.x1 = pSeg->x1;
+ if (pSeg->x2 > box.x2) box.x2 = pSeg->x2;
+ } else {
+ if (pSeg->x2 < box.x1) box.x1 = pSeg->x2;
+ if (pSeg->x1 > box.x2) box.x2 = pSeg->x1;
+ }
+ if (pSeg->y2 > pSeg->y1) {
+ if (pSeg->y1 < box.y1) box.y1 = pSeg->y1;
+ if (pSeg->y2 > box.y2) box.y2 = pSeg->y2;
+ } else {
+ if (pSeg->y2 < box.y1) box.y1 = pSeg->y2;
+ if (pSeg->y1 > box.y2) box.y2 = pSeg->y1;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ if (extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly segment end\n");
+}
+
+/* changed area is box around each line (not entire rects) */
+static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
+ int nRects, xRectangle *pRects)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("poly rectangle start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyRectangle(dst, pGC, nRects, pRects);
+
+ if (nRects > 0) {
+ BoxRec box;
+ int offset1, offset2, offset3;
+
+ offset2 = pGC->lineWidth;
+ if (!offset2) offset2 = 1;
+ offset1 = offset2 >> 1;
+ offset3 = offset2 - offset1;
+
+ while (nRects--) {
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x + pRects->width - offset1;
+ box.y1 = pRects->y + offset3;
+ box.x2 = box.x1 + offset2;
+ box.y2 = box.y1 + pRects->height - offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ box.x1 = pRects->x - offset1;
+ box.y1 = pRects->y + pRects->height - offset1;
+ box.x2 = box.x1 + pRects->width + offset2;
+ box.y2 = box.y1 + offset2;
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ pRects++;
+ }
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly rectangle end\n");
+}
+
+
+/* changed area is box around each arc (assumes all arcs are 360 degrees) */
+static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("poly arc start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyArc(dst, pGC, narcs, parcs);
+
+ if (narcs > 0) {
+ int extra = pGC->lineWidth >> 1;
+ BoxRec box;
+
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while (--narcs) {
+ parcs++;
+ if (box.x1 > parcs->x)
+ box.x1 = parcs->x;
+ if (box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if (box.y1 > parcs->y)
+ box.y1 = parcs->y;
+ if (box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ if (extra) {
+ box.x1 -= extra;
+ box.x2 += extra;
+ box.y1 -= extra;
+ box.y2 += extra;
+ }
+
+ box.x2++;
+ box.y2++;
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("poly arc end\n");
+}
+
+
+/* changed area is box around each poly */
+static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
+ int shape, int mode, int count,
+ DDXPointPtr pptInit)
+{
+ GC_SAVE(pGC);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)", dst,
+ pGC->fillStyle);
+
+ if (count <= 2) {
+ pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
+ } else {
+ DDXPointPtr ppt = pptInit;
+ int i = count;
+ BoxRec box;
+
+ box.x2 = box.x1 = ppt->x;
+ box.y2 = box.y1 = ppt->y;
+
+ if (mode != CoordModeOrigin) {
+ int x = box.x1;
+ int y = box.y1;
+
+ while (--i) {
+ ppt++;
+ x += ppt->x;
+ y += ppt->y;
+ if (box.x1 > x)
+ box.x1 = x;
+ else if (box.x2 < x)
+ box.x2 = x;
+ if (box.y1 > y)
+ box.y1 = y;
+ else if (box.y2 < y)
+ box.y2 = y;
+ }
+ } else {
+ while (--i) {
+ ppt++;
+ if (box.x1 > ppt->x)
+ box.x1 = ppt->x;
+ else if (box.x2 < ppt->x)
+ box.x2 = ppt->x;
+ if (box.y1 > ppt->y)
+ box.y1 = ppt->y;
+ else if (box.y2 < ppt->y)
+ box.y2 = ppt->y;
+ }
+ }
+
+ box.x2++;
+ box.y2++;
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (canAccelFill(dst, pGC) &&
+ boxBytes(dst, &box) >= rootless_FillBytes_threshold)
+ {
+ GC_UNSET_PM(pGC, dst);
+ }
+
+ pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GC_RESTORE(pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill poly end\n");
+}
+
+/* changed area is the rects */
+static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
+ int nRectsInit, xRectangle *pRectsInit)
+{
+ GC_SAVE(pGC);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)", dst,
+ pGC->fillStyle);
+
+ if (nRectsInit <= 0) {
+ pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
+ } else {
+ BoxRec box;
+ xRectangle *pRects = pRectsInit;
+ int nRects = nRectsInit;
+
+ box.x1 = pRects->x;
+ box.x2 = box.x1 + pRects->width;
+ box.y1 = pRects->y;
+ box.y2 = box.y1 + pRects->height;
+
+ while (--nRects) {
+ pRects++;
+ if (box.x1 > pRects->x)
+ box.x1 = pRects->x;
+ if (box.x2 < (pRects->x + pRects->width))
+ box.x2 = pRects->x + pRects->width;
+ if (box.y1 > pRects->y)
+ box.y1 = pRects->y;
+ if (box.y2 < (pRects->y + pRects->height))
+ box.y2 = pRects->y + pRects->height;
+ }
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (canAccelFill(dst, pGC) &&
+ boxBytes(dst, &box) >= rootless_FillBytes_threshold)
+ {
+ GC_UNSET_PM(pGC, dst);
+ }
+
+ pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GC_RESTORE(pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill rect end\n");
+}
+
+
+/* changed area is box around each arc (assuming arcs are all 360 degrees) */
+static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
+ int narcsInit, xArc *parcsInit)
+{
+ GC_SAVE(pGC);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("fill arc start ");
+
+ if (narcsInit > 0) {
+ BoxRec box;
+ int narcs = narcsInit;
+ xArc *parcs = parcsInit;
+
+ box.x1 = parcs->x;
+ box.x2 = box.x1 + parcs->width;
+ box.y1 = parcs->y;
+ box.y2 = box.y1 + parcs->height;
+
+ /* should I break these up instead ? */
+
+ while (--narcs) {
+ parcs++;
+ if (box.x1 > parcs->x)
+ box.x1 = parcs->x;
+ if (box.x2 < (parcs->x + parcs->width))
+ box.x2 = parcs->x + parcs->width;
+ if (box.y1 > parcs->y)
+ box.y1 = parcs->y;
+ if (box.y2 < (parcs->y + parcs->height))
+ box.y2 = parcs->y + parcs->height;
+ }
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (canAccelFill(dst, pGC) &&
+ boxBytes(dst, &box) >= rootless_FillBytes_threshold)
+ {
+ GC_UNSET_PM(pGC, dst);
+ }
+
+ pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit);
+
+ TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ } else {
+ pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit);
+ }
+
+ GC_RESTORE(pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("fill arc end\n");
+}
+
+
+static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars)
+{
+ GC_SAVE(pGC);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imagetext8 start ");
+
+ if (count > 0) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if (Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if (Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = dst->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (canAccelFill(dst, pGC) &&
+ boxBytes(dst, &box) >= rootless_FillBytes_threshold)
+ {
+ GC_UNSET_PM(pGC, dst);
+ }
+
+ pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ } else {
+ pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
+ }
+
+ GC_RESTORE(pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imagetext8 end\n");
+}
+
+static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, char *chars)
+{
+ int width; // the result, sorta
+
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("polytext8 start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars);
+ width -= x;
+
+ if (width > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if (count > 1) {
+ if (width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polytext8 end\n");
+ return width + x;
+}
+
+static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars)
+{
+ GC_SAVE(pGC);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imagetext16 start ");
+
+ if (count > 0) {
+ int top, bot, Min, Max;
+ BoxRec box;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
+ if (Min > 0) Min = 0;
+ Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
+ if (Max < 0) Max = 0;
+
+ /* ugh */
+ box.x1 = dst->x + x + Min +
+ FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + Max +
+ FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (canAccelFill(dst, pGC) &&
+ boxBytes(dst, &box) >= rootless_FillBytes_threshold)
+ {
+ GC_UNSET_PM(pGC, dst);
+ }
+
+ pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ } else {
+ pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
+ }
+
+ GC_RESTORE(pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imagetext16 end\n");
+}
+
+static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
+ int x, int y, int count, unsigned short *chars)
+{
+ int width; // the result, sorta
+
+ GCOP_UNWRAP(pGC);
+
+ RL_DEBUG_MSG("polytext16 start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars);
+ width -= x;
+
+ if (width > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
+ box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
+
+ if (count > 1) {
+ if (width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polytext16 end\n");
+ return width + x;
+}
+
+static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyphInit,
+ CharInfoPtr *ppciInit, pointer unused)
+{
+ GC_SAVE(pGC);
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("imageglyph start ");
+
+ if (nglyphInit > 0) {
+ int top, bot, width = 0;
+ BoxRec box;
+ unsigned int nglyph = nglyphInit;
+ CharInfoPtr *ppci = ppciInit;
+
+ top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
+ bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
+
+ box.x1 = ppci[0]->metrics.leftSideBearing;
+ if (box.x1 > 0) box.x1 = 0;
+ box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
+ ppci[nglyph - 1]->metrics.characterWidth;
+ if (box.x2 < 0) box.x2 = 0;
+
+ box.x2 += dst->x + x;
+ box.x1 += dst->x + x;
+
+ while (nglyph--) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if (width > 0)
+ box.x2 += width;
+ else
+ box.x1 += width;
+
+ box.y1 = dst->y + y - top;
+ box.y2 = dst->y + y + bot;
+
+ RootlessStartDrawing((WindowPtr) dst);
+
+ if (canAccelFill(dst, pGC) &&
+ boxBytes(dst, &box) >= rootless_FillBytes_threshold)
+ {
+ GC_UNSET_PM(pGC, dst);
+ }
+
+ pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused);
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ } else {
+ pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused);
+ }
+
+ GC_RESTORE(pGC, dst);
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("imageglyph end\n");
+}
+
+static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("polyglyph start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ if (nglyph > 0) {
+ BoxRec box;
+
+ /* ugh */
+ box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing;
+ box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
+
+ if (nglyph > 1) {
+ int width = 0;
+
+ while (--nglyph) {
+ width += (*ppci)->metrics.characterWidth;
+ ppci++;
+ }
+
+ if (width > 0) box.x2 += width;
+ else box.x1 += width;
+ }
+
+ box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
+ box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+ }
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("polyglyph end\n");
+}
+
+
+/* changed area is in dest */
+static void
+RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
+ int dx, int dy, int xOrg, int yOrg)
+{
+ BoxRec box;
+
+ GCOP_UNWRAP(pGC);
+ RL_DEBUG_MSG("push pixels start ");
+
+ RootlessStartDrawing((WindowPtr) dst);
+ pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg);
+
+ box.x1 = xOrg + dst->x;
+ box.x2 = box.x1 + dx;
+ box.y1 = yOrg + dst->y;
+ box.y2 = box.y1 + dy;
+
+ TRIM_BOX(box, pGC);
+ if (BOX_NOT_EMPTY(box))
+ RootlessDamageBox ((WindowPtr) dst, &box);
+
+ GCOP_WRAP(pGC);
+ RL_DEBUG_MSG("push pixels end\n");
+}
diff --git a/xorg-server/miext/rootless/rootlessScreen.c b/xorg-server/miext/rootless/rootlessScreen.c
index 6f9341d85..fd396e464 100644
--- a/xorg-server/miext/rootless/rootlessScreen.c
+++ b/xorg-server/miext/rootless/rootlessScreen.c
@@ -62,15 +62,10 @@ extern int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild,
extern Bool RootlessCreateGC(GCPtr pGC);
// Initialize globals
-static int rootlessGCPrivateKeyIndex;
-DevPrivateKey rootlessGCPrivateKey = &rootlessGCPrivateKeyIndex;
-static int rootlessScreenPrivateKeyIndex;
-DevPrivateKey rootlessScreenPrivateKey = &rootlessScreenPrivateKeyIndex;
-static int rootlessWindowPrivateKeyIndex;
-DevPrivateKey rootlessWindowPrivateKey = &rootlessWindowPrivateKeyIndex;
-static int rootlessWindowOldPixmapPrivateKeyIndex;
-DevPrivateKey rootlessWindowOldPixmapPrivateKey = &rootlessWindowOldPixmapPrivateKeyIndex;
-
+DevPrivateKeyRec rootlessGCPrivateKeyRec;
+DevPrivateKeyRec rootlessScreenPrivateKeyRec;
+DevPrivateKeyRec rootlessWindowPrivateKeyRec;
+DevPrivateKeyRec rootlessWindowOldPixmapPrivateKeyRec;
/*
* RootlessUpdateScreenPixmap
@@ -441,9 +436,9 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst,
pChild = pWin;
while (1) {
if (pChild->viewable) {
- if (REGION_BROKEN (pScreen, &pChild->winSize))
+ if (RegionBroken(&pChild->winSize))
SetWinSize (pChild);
- if (REGION_BROKEN (pScreen, &pChild->borderSize))
+ if (RegionBroken(&pChild->borderSize))
SetBorderSize (pChild);
(* MarkWindow)(pChild);
if (pChild->firstChild) {
@@ -493,7 +488,7 @@ static void expose_1 (WindowPtr pWin) {
void
RootlessScreenExpose (ScreenPtr pScreen)
{
- expose_1 (WindowTable[pScreen->myNum]);
+ expose_1 (pScreen->root);
}
@@ -637,8 +632,13 @@ RootlessAllocatePrivates(ScreenPtr pScreen)
{
RootlessScreenRec *s;
- // no allocation needed for screen privates
- if (!dixRequestPrivate(rootlessGCPrivateKey, sizeof(RootlessGCRec)))
+ 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));
diff --git a/xorg-server/miext/rootless/rootlessValTree.c b/xorg-server/miext/rootless/rootlessValTree.c
index 0ee4919e1..6154e9d40 100644
--- a/xorg-server/miext/rootless/rootlessValTree.c
+++ b/xorg-server/miext/rootless/rootlessValTree.c
@@ -1,640 +1,635 @@
-/*
- * Calculate window clip lists for rootless mode
- *
- * This file is very closely based on mivaltree.c.
- */
-
-/*
- * mivaltree.c --
- * Functions for recalculating window clip lists. Main function
- * is miValidateTree.
- *
-
-Copyright 1987, 1988, 1989, 1998 The Open Group
-
-All Rights Reserved.
-
-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
-OPEN GROUP 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 of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
- *
- * Copyright 1987, 1988, 1989 by
- * Digital Equipment Corporation, Maynard, Massachusetts,
- *
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of Digital not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- *
- * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- *
- ******************************************************************/
-
-/* The panoramix components contained the following notice */
-/*****************************************************************
-
-Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-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.
-
-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
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 of Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-******************************************************************/
- /*
- * Aug '86: Susan Angebranndt -- original code
- * July '87: Adam de Boor -- substantially modified and commented
- * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
- * In particular, much improved code for window mapping and
- * circulating.
- * Bob Scheifler -- avoid miComputeClips for unmapped windows,
- * valdata changes
- */
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stddef.h> /* For NULL */
-#include <X11/X.h>
-#include "scrnintstr.h"
-#include "validate.h"
-#include "windowstr.h"
-#include "mi.h"
-#include "regionstr.h"
-#include "mivalidate.h"
-
-#include "globals.h"
-
-int RootlessShapedWindowIn (ScreenPtr pScreen, RegionPtr universe,
- RegionPtr bounding, BoxPtr rect, int x, int y);
-
-int RootlessMiValidateTree (WindowPtr pRoot, WindowPtr pChild, VTKind kind);
-
-/*
- * Compute the visibility of a shaped window
- */
-int
-RootlessShapedWindowIn (ScreenPtr pScreen, RegionPtr universe,
- RegionPtr bounding, BoxPtr rect, int x, int y)
-{
- BoxRec box;
- register BoxPtr boundBox;
- int nbox;
- Bool someIn, someOut;
- register int t, x1, y1, x2, y2;
-
- nbox = REGION_NUM_RECTS (bounding);
- boundBox = REGION_RECTS (bounding);
- someIn = someOut = FALSE;
- x1 = rect->x1;
- y1 = rect->y1;
- x2 = rect->x2;
- y2 = rect->y2;
- while (nbox--)
- {
- if ((t = boundBox->x1 + x) < x1)
- t = x1;
- box.x1 = t;
- if ((t = boundBox->y1 + y) < y1)
- t = y1;
- box.y1 = t;
- if ((t = boundBox->x2 + x) > x2)
- t = x2;
- box.x2 = t;
- if ((t = boundBox->y2 + y) > y2)
- t = y2;
- box.y2 = t;
- if (box.x1 > box.x2)
- box.x2 = box.x1;
- if (box.y1 > box.y2)
- box.y2 = box.y1;
- switch (RECT_IN_REGION(pScreen, universe, &box))
- {
- case rgnIN:
- if (someOut)
- return rgnPART;
- someIn = TRUE;
- break;
- case rgnOUT:
- if (someIn)
- return rgnPART;
- someOut = TRUE;
- break;
- default:
- return rgnPART;
- }
- boundBox++;
- }
- if (someIn)
- return rgnIN;
- return rgnOUT;
-}
-
-#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
- HasBorder(w) && \
- (w)->backgroundState == ParentRelative)
-
-
-/*
- *-----------------------------------------------------------------------
- * RootlessComputeClips --
- * Recompute the clipList, borderClip, exposed and borderExposed
- * regions for pParent and its children. Only viewable windows are
- * taken into account.
- *
- * Results:
- * None.
- *
- * Side Effects:
- * clipList, borderClip, exposed and borderExposed are altered.
- * A VisibilityNotify event may be generated on the parent window.
- *
- *-----------------------------------------------------------------------
- */
-static void
-RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen,
- RegionPtr universe, VTKind kind, RegionPtr exposed)
-{
- int dx,
- dy;
- RegionRec childUniverse;
- register WindowPtr pChild;
- int oldVis, newVis;
- BoxRec borderSize;
- RegionRec childUnion;
- Bool overlap;
- RegionPtr borderVisible;
- Bool resized;
- /*
- * Figure out the new visibility of this window.
- * The extent of the universe should be the same as the extent of
- * the borderSize region. If the window is unobscured, this rectangle
- * will be completely inside the universe (the universe will cover it
- * completely). If the window is completely obscured, none of the
- * universe will cover the rectangle.
- */
- borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
- borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
- dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
- if (dx > 32767)
- dx = 32767;
- borderSize.x2 = dx;
- dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
- if (dy > 32767)
- dy = 32767;
- borderSize.y2 = dy;
-
- oldVis = pParent->visibility;
- switch (RECT_IN_REGION( pScreen, universe, &borderSize))
- {
- case rgnIN:
- newVis = VisibilityUnobscured;
- break;
- case rgnPART:
- newVis = VisibilityPartiallyObscured;
- {
- RegionPtr pBounding;
-
- if ((pBounding = wBoundingShape (pParent)))
- {
- switch (RootlessShapedWindowIn (pScreen, universe,
- pBounding, &borderSize,
- pParent->drawable.x,
- pParent->drawable.y))
- {
- case rgnIN:
- newVis = VisibilityUnobscured;
- break;
- case rgnOUT:
- newVis = VisibilityFullyObscured;
- break;
- }
- }
- }
- break;
- default:
- newVis = VisibilityFullyObscured;
- break;
- }
-
- pParent->visibility = newVis;
- if (oldVis != newVis &&
- ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
- SendVisibilityNotify(pParent);
-
- dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
- dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
-
- /*
- * avoid computations when dealing with simple operations
- */
-
- switch (kind) {
- case VTMap:
- case VTStack:
- case VTUnmap:
- break;
- case VTMove:
- if ((oldVis == newVis) &&
- ((oldVis == VisibilityFullyObscured) ||
- (oldVis == VisibilityUnobscured)))
- {
- pChild = pParent;
- while (1)
- {
- if (pChild->viewable)
- {
- if (pChild->visibility != VisibilityFullyObscured)
- {
- REGION_TRANSLATE( pScreen, &pChild->borderClip,
- dx, dy);
- REGION_TRANSLATE( pScreen, &pChild->clipList,
- dx, dy);
- pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
- if (pScreen->ClipNotify)
- (* pScreen->ClipNotify) (pChild, dx, dy);
-
- }
- if (pChild->valdata)
- {
- REGION_NULL(pScreen,
- &pChild->valdata->after.borderExposed);
- if (HasParentRelativeBorder(pChild))
- {
- REGION_SUBTRACT(pScreen,
- &pChild->valdata->after.borderExposed,
- &pChild->borderClip,
- &pChild->winSize);
- }
- REGION_NULL(pScreen, &pChild->valdata->after.exposed);
- }
- if (pChild->firstChild)
- {
- pChild = pChild->firstChild;
- continue;
- }
- }
- while (!pChild->nextSib && (pChild != pParent))
- pChild = pChild->parent;
- if (pChild == pParent)
- break;
- pChild = pChild->nextSib;
- }
- return;
- }
- /* fall through */
- default:
- /*
- * To calculate exposures correctly, we have to translate the old
- * borderClip and clipList regions to the window's new location so there
- * is a correspondence between pieces of the new and old clipping regions.
- */
- if (dx || dy)
- {
- /*
- * We translate the old clipList because that will be exposed or copied
- * if gravity is right.
- */
- REGION_TRANSLATE( pScreen, &pParent->borderClip, dx, dy);
- REGION_TRANSLATE( pScreen, &pParent->clipList, dx, dy);
- }
- break;
- case VTBroken:
- REGION_EMPTY (pScreen, &pParent->borderClip);
- REGION_EMPTY (pScreen, &pParent->clipList);
- break;
- }
-
- borderVisible = pParent->valdata->before.borderVisible;
- resized = pParent->valdata->before.resized;
- REGION_NULL(pScreen, &pParent->valdata->after.borderExposed);
- REGION_NULL(pScreen, &pParent->valdata->after.exposed);
-
- /*
- * Since the borderClip must not be clipped by the children, we do
- * the border exposure first...
- *
- * 'universe' is the window's borderClip. To figure the exposures, remove
- * the area that used to be exposed from the new.
- * This leaves a region of pieces that weren't exposed before.
- */
-
- if (HasBorder (pParent))
- {
- if (borderVisible)
- {
- /*
- * when the border changes shape, the old visible portions
- * of the border will be saved by DIX in borderVisible --
- * use that region and destroy it
- */
- REGION_SUBTRACT( pScreen, exposed, universe, borderVisible);
- REGION_DESTROY( pScreen, borderVisible);
- }
- else
- {
- REGION_SUBTRACT( pScreen, exposed, universe, &pParent->borderClip);
- }
- if (HasParentRelativeBorder(pParent) && (dx || dy)) {
- REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
- universe,
- &pParent->winSize);
- } else {
- REGION_SUBTRACT( pScreen, &pParent->valdata->after.borderExposed,
- exposed, &pParent->winSize);
- }
-
- REGION_COPY( pScreen, &pParent->borderClip, universe);
-
- /*
- * To get the right clipList for the parent, and to make doubly sure
- * that no child overlaps the parent's border, we remove the parent's
- * border from the universe before proceeding.
- */
-
- REGION_INTERSECT( pScreen, universe, universe, &pParent->winSize);
- }
- else
- REGION_COPY( pScreen, &pParent->borderClip, universe);
-
- if ((pChild = pParent->firstChild) && pParent->mapped)
- {
- REGION_NULL(pScreen, &childUniverse);
- REGION_NULL(pScreen, &childUnion);
- if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
- ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
- (pChild->drawable.x < pParent->lastChild->drawable.x)))
- {
- for (; pChild; pChild = pChild->nextSib)
- {
- if (pChild->viewable)
- REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
- }
- }
- else
- {
- for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
- {
- if (pChild->viewable)
- REGION_APPEND( pScreen, &childUnion, &pChild->borderSize);
- }
- }
- REGION_VALIDATE( pScreen, &childUnion, &overlap);
-
- for (pChild = pParent->firstChild;
- pChild;
- pChild = pChild->nextSib)
- {
- if (pChild->viewable) {
- /*
- * If the child is viewable, we want to remove its extents
- * from the current universe, but we only re-clip it if
- * it's been marked.
- */
- if (pChild->valdata) {
- /*
- * Figure out the new universe from the child's
- * perspective and recurse.
- */
- REGION_INTERSECT( pScreen, &childUniverse,
- universe,
- &pChild->borderSize);
- RootlessComputeClips (pChild, pScreen, &childUniverse,
- kind, exposed);
- }
- /*
- * Once the child has been processed, we remove its extents
- * from the current universe, thus denying its space to any
- * other sibling.
- */
- if (overlap)
- REGION_SUBTRACT( pScreen, universe, universe,
- &pChild->borderSize);
- }
- }
- if (!overlap)
- REGION_SUBTRACT( pScreen, universe, universe, &childUnion);
- REGION_UNINIT( pScreen, &childUnion);
- REGION_UNINIT( pScreen, &childUniverse);
- } /* if any children */
-
- /*
- * 'universe' now contains the new clipList for the parent window.
- *
- * To figure the exposure of the window we subtract the old clip from the
- * new, just as for the border.
- */
-
- if (oldVis == VisibilityFullyObscured ||
- oldVis == VisibilityNotViewable)
- {
- REGION_COPY( pScreen, &pParent->valdata->after.exposed, universe);
- }
- else if (newVis != VisibilityFullyObscured &&
- newVis != VisibilityNotViewable)
- {
- REGION_SUBTRACT( pScreen, &pParent->valdata->after.exposed,
- universe, &pParent->clipList);
- }
-
- /*
- * One last thing: backing storage. We have to try to save what parts of
- * the window are about to be obscured. We can just subtract the universe
- * from the old clipList and get the areas that were in the old but aren't
- * in the new and, hence, are about to be obscured.
- */
- if (pParent->backStorage && !resized)
- {
- REGION_SUBTRACT( pScreen, exposed, &pParent->clipList, universe);
- (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
- }
-
- /* HACK ALERT - copying contents of regions, instead of regions */
- {
- RegionRec tmp;
-
- tmp = pParent->clipList;
- pParent->clipList = *universe;
- *universe = tmp;
- }
-
-#ifdef NOTDEF
- REGION_COPY( pScreen, &pParent->clipList, universe);
-#endif
-
- pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
-
- if (pScreen->ClipNotify)
- (* pScreen->ClipNotify) (pParent, dx, dy);
-}
-
-static void
-RootlessTreeObscured(WindowPtr pParent)
-{
- register WindowPtr pChild;
- register int oldVis;
-
- pChild = pParent;
- while (1)
- {
- if (pChild->viewable)
- {
- oldVis = pChild->visibility;
- if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
- ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
- SendVisibilityNotify(pChild);
- if (pChild->firstChild)
- {
- pChild = pChild->firstChild;
- continue;
- }
- }
- while (!pChild->nextSib && (pChild != pParent))
- pChild = pChild->parent;
- if (pChild == pParent)
- break;
- pChild = pChild->nextSib;
- }
-}
-
-/*
- *-----------------------------------------------------------------------
- * RootlessMiValidateTree --
- * Recomputes the clip list for pParent and all its inferiors.
- *
- * Results:
- * Always returns 1.
- *
- * Side Effects:
- * The clipList, borderClip, exposed, and borderExposed regions for
- * each marked window are altered.
- *
- * Notes:
- * This routine assumes that all affected windows have been marked
- * (valdata created) and their winSize and borderSize regions
- * adjusted to correspond to their new positions. The borderClip and
- * clipList regions should not have been touched.
- *
- * The top-most level is treated differently from all lower levels
- * because pParent is unchanged. For the top level, we merge the
- * regions taken up by the marked children back into the clipList
- * for pParent, thus forming a region from which the marked children
- * can claim their areas. For lower levels, where the old clipList
- * and borderClip are invalid, we can't do this and have to do the
- * extra operations done in miComputeClips, but this is much faster
- * e.g. when only one child has moved...
- *
- *-----------------------------------------------------------------------
- */
-/*
- Quartz version: used for validate from root in rootless mode.
- We need to make sure top-level windows don't clip each other,
- and that top-level windows aren't clipped to the root window.
-*/
-/*ARGSUSED*/
-// fixme this is ugly
-// Xprint/ValTree.c doesn't work, but maybe that method can?
-int
-RootlessMiValidateTree (WindowPtr pRoot, /* Parent to validate */
- WindowPtr pChild, /* First child of pRoot that was
- * affected */
- VTKind kind /* What kind of configuration caused call */)
-{
- RegionRec childClip; /* The new borderClip for the current
- * child */
- RegionRec exposed; /* For intermediate calculations */
- register ScreenPtr pScreen;
- register WindowPtr pWin;
-
- pScreen = pRoot->drawable.pScreen;
- if (pChild == NullWindow)
- pChild = pRoot->firstChild;
-
- REGION_NULL(pScreen, &childClip);
- REGION_NULL(pScreen, &exposed);
-
- if (REGION_BROKEN (pScreen, &pRoot->clipList) &&
- !REGION_BROKEN (pScreen, &pRoot->borderClip))
- {
- // fixme this might not work, but hopefully doesn't happen anyway.
- kind = VTBroken;
- REGION_EMPTY (pScreen, &pRoot->clipList);
- ErrorF("ValidateTree: BUSTED!\n");
- }
-
- /*
- * Recursively compute the clips for all children of the root.
- * They don't clip against each other or the root itself, so
- * childClip is always reset to that child's size.
- */
-
- for (pWin = pChild;
- pWin != NullWindow;
- pWin = pWin->nextSib)
- {
- if (pWin->viewable) {
- if (pWin->valdata) {
- REGION_COPY( pScreen, &childClip, &pWin->borderSize);
- RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
- } else if (pWin->visibility == VisibilityNotViewable) {
- RootlessTreeObscured(pWin);
- }
- } else {
- if (pWin->valdata) {
- REGION_EMPTY( pScreen, &pWin->clipList);
- if (pScreen->ClipNotify)
- (* pScreen->ClipNotify) (pWin, 0, 0);
- REGION_EMPTY( pScreen, &pWin->borderClip);
- pWin->valdata = NULL;
- }
- }
- }
-
- REGION_UNINIT(pScreen, &childClip);
-
- /* The root is never clipped by its children, so nothing on the root
- is ever exposed by moving or mapping its children. */
- REGION_NULL(pScreen, &pRoot->valdata->after.exposed);
- REGION_NULL(pScreen, &pRoot->valdata->after.borderExposed);
-
- return 1;
-}
+/*
+ * Calculate window clip lists for rootless mode
+ *
+ * This file is very closely based on mivaltree.c.
+ */
+
+/*
+ * mivaltree.c --
+ * Functions for recalculating window clip lists. Main function
+ * is miValidateTree.
+ *
+
+Copyright 1987, 1988, 1989, 1998 The Open Group
+
+All Rights Reserved.
+
+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
+OPEN GROUP 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 of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+ *
+ * Copyright 1987, 1988, 1989 by
+ * Digital Equipment Corporation, Maynard, Massachusetts,
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Digital not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ *
+ ******************************************************************/
+
+/* The panoramix components contained the following notice */
+/*****************************************************************
+
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+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.
+
+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
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+ /*
+ * Aug '86: Susan Angebranndt -- original code
+ * July '87: Adam de Boor -- substantially modified and commented
+ * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
+ * In particular, much improved code for window mapping and
+ * circulating.
+ * Bob Scheifler -- avoid miComputeClips for unmapped windows,
+ * valdata changes
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stddef.h> /* For NULL */
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "mi.h"
+#include "regionstr.h"
+#include "mivalidate.h"
+
+#include "globals.h"
+
+int RootlessMiValidateTree (WindowPtr pRoot, WindowPtr pChild, VTKind kind);
+
+/*
+ * Compute the visibility of a shaped window
+ */
+static int
+RootlessShapedWindowIn (RegionPtr universe,
+ RegionPtr bounding, BoxPtr rect, int x, int y)
+{
+ BoxRec box;
+ register BoxPtr boundBox;
+ int nbox;
+ Bool someIn, someOut;
+ register int t, x1, y1, x2, y2;
+
+ nbox = RegionNumRects (bounding);
+ boundBox = RegionRects (bounding);
+ someIn = someOut = FALSE;
+ x1 = rect->x1;
+ y1 = rect->y1;
+ x2 = rect->x2;
+ y2 = rect->y2;
+ while (nbox--)
+ {
+ if ((t = boundBox->x1 + x) < x1)
+ t = x1;
+ box.x1 = t;
+ if ((t = boundBox->y1 + y) < y1)
+ t = y1;
+ box.y1 = t;
+ if ((t = boundBox->x2 + x) > x2)
+ t = x2;
+ box.x2 = t;
+ if ((t = boundBox->y2 + y) > y2)
+ t = y2;
+ box.y2 = t;
+ if (box.x1 > box.x2)
+ box.x2 = box.x1;
+ if (box.y1 > box.y2)
+ box.y2 = box.y1;
+ switch (RegionContainsRect(universe, &box))
+ {
+ case rgnIN:
+ if (someOut)
+ return rgnPART;
+ someIn = TRUE;
+ break;
+ case rgnOUT:
+ if (someIn)
+ return rgnPART;
+ someOut = TRUE;
+ break;
+ default:
+ return rgnPART;
+ }
+ boundBox++;
+ }
+ if (someIn)
+ return rgnIN;
+ return rgnOUT;
+}
+
+#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
+ HasBorder(w) && \
+ (w)->backgroundState == ParentRelative)
+
+
+/*
+ *-----------------------------------------------------------------------
+ * RootlessComputeClips --
+ * Recompute the clipList, borderClip, exposed and borderExposed
+ * regions for pParent and its children. Only viewable windows are
+ * taken into account.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * clipList, borderClip, exposed and borderExposed are altered.
+ * A VisibilityNotify event may be generated on the parent window.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen,
+ RegionPtr universe, VTKind kind, RegionPtr exposed)
+{
+ int dx,
+ dy;
+ RegionRec childUniverse;
+ register WindowPtr pChild;
+ int oldVis, newVis;
+ BoxRec borderSize;
+ RegionRec childUnion;
+ Bool overlap;
+ RegionPtr borderVisible;
+ Bool resized;
+ /*
+ * Figure out the new visibility of this window.
+ * The extent of the universe should be the same as the extent of
+ * the borderSize region. If the window is unobscured, this rectangle
+ * will be completely inside the universe (the universe will cover it
+ * completely). If the window is completely obscured, none of the
+ * universe will cover the rectangle.
+ */
+ borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
+ borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
+ dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
+ if (dx > 32767)
+ dx = 32767;
+ borderSize.x2 = dx;
+ dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
+ if (dy > 32767)
+ dy = 32767;
+ borderSize.y2 = dy;
+
+ oldVis = pParent->visibility;
+ switch (RegionContainsRect(universe, &borderSize))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnPART:
+ newVis = VisibilityPartiallyObscured;
+ {
+ RegionPtr pBounding;
+
+ if ((pBounding = wBoundingShape (pParent)))
+ {
+ switch (RootlessShapedWindowIn (universe,
+ pBounding, &borderSize,
+ pParent->drawable.x,
+ pParent->drawable.y))
+ {
+ case rgnIN:
+ newVis = VisibilityUnobscured;
+ break;
+ case rgnOUT:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ newVis = VisibilityFullyObscured;
+ break;
+ }
+
+ pParent->visibility = newVis;
+ if (oldVis != newVis &&
+ ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
+ SendVisibilityNotify(pParent);
+
+ dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
+ dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
+
+ /*
+ * avoid computations when dealing with simple operations
+ */
+
+ switch (kind) {
+ case VTMap:
+ case VTStack:
+ case VTUnmap:
+ break;
+ case VTMove:
+ if ((oldVis == newVis) &&
+ ((oldVis == VisibilityFullyObscured) ||
+ (oldVis == VisibilityUnobscured)))
+ {
+ pChild = pParent;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ if (pChild->visibility != VisibilityFullyObscured)
+ {
+ RegionTranslate(&pChild->borderClip,
+ dx, dy);
+ RegionTranslate(&pChild->clipList,
+ dx, dy);
+ pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pChild, dx, dy);
+
+ }
+ if (pChild->valdata)
+ {
+ RegionNull(&pChild->valdata->after.borderExposed);
+ if (HasParentRelativeBorder(pChild))
+ {
+ RegionSubtract(&pChild->valdata->after.borderExposed,
+ &pChild->borderClip,
+ &pChild->winSize);
+ }
+ RegionNull(&pChild->valdata->after.exposed);
+ }
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pParent))
+ pChild = pChild->parent;
+ if (pChild == pParent)
+ break;
+ pChild = pChild->nextSib;
+ }
+ return;
+ }
+ /* fall through */
+ default:
+ /*
+ * To calculate exposures correctly, we have to translate the old
+ * borderClip and clipList regions to the window's new location so there
+ * is a correspondence between pieces of the new and old clipping regions.
+ */
+ if (dx || dy)
+ {
+ /*
+ * We translate the old clipList because that will be exposed or copied
+ * if gravity is right.
+ */
+ RegionTranslate(&pParent->borderClip, dx, dy);
+ RegionTranslate(&pParent->clipList, dx, dy);
+ }
+ break;
+ case VTBroken:
+ RegionEmpty(&pParent->borderClip);
+ RegionEmpty(&pParent->clipList);
+ break;
+ }
+
+ borderVisible = pParent->valdata->before.borderVisible;
+ resized = pParent->valdata->before.resized;
+ RegionNull(&pParent->valdata->after.borderExposed);
+ RegionNull(&pParent->valdata->after.exposed);
+
+ /*
+ * Since the borderClip must not be clipped by the children, we do
+ * the border exposure first...
+ *
+ * 'universe' is the window's borderClip. To figure the exposures, remove
+ * the area that used to be exposed from the new.
+ * This leaves a region of pieces that weren't exposed before.
+ */
+
+ if (HasBorder (pParent))
+ {
+ if (borderVisible)
+ {
+ /*
+ * when the border changes shape, the old visible portions
+ * of the border will be saved by DIX in borderVisible --
+ * use that region and destroy it
+ */
+ RegionSubtract(exposed, universe, borderVisible);
+ RegionDestroy(borderVisible);
+ }
+ else
+ {
+ RegionSubtract(exposed, universe, &pParent->borderClip);
+ }
+ if (HasParentRelativeBorder(pParent) && (dx || dy)) {
+ RegionSubtract(&pParent->valdata->after.borderExposed,
+ universe,
+ &pParent->winSize);
+ } else {
+ RegionSubtract(&pParent->valdata->after.borderExposed,
+ exposed, &pParent->winSize);
+ }
+
+ RegionCopy(&pParent->borderClip, universe);
+
+ /*
+ * To get the right clipList for the parent, and to make doubly sure
+ * that no child overlaps the parent's border, we remove the parent's
+ * border from the universe before proceeding.
+ */
+
+ RegionIntersect(universe, universe, &pParent->winSize);
+ }
+ else
+ RegionCopy(&pParent->borderClip, universe);
+
+ if ((pChild = pParent->firstChild) && pParent->mapped)
+ {
+ RegionNull(&childUniverse);
+ RegionNull(&childUnion);
+ if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
+ ((pChild->drawable.y == pParent->lastChild->drawable.y) &&
+ (pChild->drawable.x < pParent->lastChild->drawable.x)))
+ {
+ for (; pChild; pChild = pChild->nextSib)
+ {
+ if (pChild->viewable)
+ RegionAppend(&childUnion, &pChild->borderSize);
+ }
+ }
+ else
+ {
+ for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
+ {
+ if (pChild->viewable)
+ RegionAppend(&childUnion, &pChild->borderSize);
+ }
+ }
+ RegionValidate(&childUnion, &overlap);
+
+ for (pChild = pParent->firstChild;
+ pChild;
+ pChild = pChild->nextSib)
+ {
+ if (pChild->viewable) {
+ /*
+ * If the child is viewable, we want to remove its extents
+ * from the current universe, but we only re-clip it if
+ * it's been marked.
+ */
+ if (pChild->valdata) {
+ /*
+ * Figure out the new universe from the child's
+ * perspective and recurse.
+ */
+ RegionIntersect(&childUniverse,
+ universe,
+ &pChild->borderSize);
+ RootlessComputeClips (pChild, pScreen, &childUniverse,
+ kind, exposed);
+ }
+ /*
+ * Once the child has been processed, we remove its extents
+ * from the current universe, thus denying its space to any
+ * other sibling.
+ */
+ if (overlap)
+ RegionSubtract(universe, universe,
+ &pChild->borderSize);
+ }
+ }
+ if (!overlap)
+ RegionSubtract(universe, universe, &childUnion);
+ RegionUninit(&childUnion);
+ RegionUninit(&childUniverse);
+ } /* if any children */
+
+ /*
+ * 'universe' now contains the new clipList for the parent window.
+ *
+ * To figure the exposure of the window we subtract the old clip from the
+ * new, just as for the border.
+ */
+
+ if (oldVis == VisibilityFullyObscured ||
+ oldVis == VisibilityNotViewable)
+ {
+ RegionCopy(&pParent->valdata->after.exposed, universe);
+ }
+ else if (newVis != VisibilityFullyObscured &&
+ newVis != VisibilityNotViewable)
+ {
+ RegionSubtract(&pParent->valdata->after.exposed,
+ universe, &pParent->clipList);
+ }
+
+ /*
+ * One last thing: backing storage. We have to try to save what parts of
+ * the window are about to be obscured. We can just subtract the universe
+ * from the old clipList and get the areas that were in the old but aren't
+ * in the new and, hence, are about to be obscured.
+ */
+ if (pParent->backStorage && !resized)
+ {
+ RegionSubtract(exposed, &pParent->clipList, universe);
+ (* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
+ }
+
+ /* HACK ALERT - copying contents of regions, instead of regions */
+ {
+ RegionRec tmp;
+
+ tmp = pParent->clipList;
+ pParent->clipList = *universe;
+ *universe = tmp;
+ }
+
+#ifdef NOTDEF
+ RegionCopy(&pParent->clipList, universe);
+#endif
+
+ pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pParent, dx, dy);
+}
+
+static void
+RootlessTreeObscured(WindowPtr pParent)
+{
+ register WindowPtr pChild;
+ register int oldVis;
+
+ pChild = pParent;
+ while (1)
+ {
+ if (pChild->viewable)
+ {
+ oldVis = pChild->visibility;
+ if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
+ ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
+ SendVisibilityNotify(pChild);
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ }
+ while (!pChild->nextSib && (pChild != pParent))
+ pChild = pChild->parent;
+ if (pChild == pParent)
+ break;
+ pChild = pChild->nextSib;
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------
+ * RootlessMiValidateTree --
+ * Recomputes the clip list for pParent and all its inferiors.
+ *
+ * Results:
+ * Always returns 1.
+ *
+ * Side Effects:
+ * The clipList, borderClip, exposed, and borderExposed regions for
+ * each marked window are altered.
+ *
+ * Notes:
+ * This routine assumes that all affected windows have been marked
+ * (valdata created) and their winSize and borderSize regions
+ * adjusted to correspond to their new positions. The borderClip and
+ * clipList regions should not have been touched.
+ *
+ * The top-most level is treated differently from all lower levels
+ * because pParent is unchanged. For the top level, we merge the
+ * regions taken up by the marked children back into the clipList
+ * for pParent, thus forming a region from which the marked children
+ * can claim their areas. For lower levels, where the old clipList
+ * and borderClip are invalid, we can't do this and have to do the
+ * extra operations done in miComputeClips, but this is much faster
+ * e.g. when only one child has moved...
+ *
+ *-----------------------------------------------------------------------
+ */
+/*
+ Quartz version: used for validate from root in rootless mode.
+ We need to make sure top-level windows don't clip each other,
+ and that top-level windows aren't clipped to the root window.
+*/
+/*ARGSUSED*/
+// fixme this is ugly
+// Xprint/ValTree.c doesn't work, but maybe that method can?
+int
+RootlessMiValidateTree (WindowPtr pRoot, /* Parent to validate */
+ WindowPtr pChild, /* First child of pRoot that was
+ * affected */
+ VTKind kind /* What kind of configuration caused call */)
+{
+ RegionRec childClip; /* The new borderClip for the current
+ * child */
+ RegionRec exposed; /* For intermediate calculations */
+ register ScreenPtr pScreen;
+ register WindowPtr pWin;
+
+ pScreen = pRoot->drawable.pScreen;
+ if (pChild == NullWindow)
+ pChild = pRoot->firstChild;
+
+ RegionNull(&childClip);
+ RegionNull(&exposed);
+
+ if (RegionBroken(&pRoot->clipList) &&
+ !RegionBroken(&pRoot->borderClip))
+ {
+ // fixme this might not work, but hopefully doesn't happen anyway.
+ kind = VTBroken;
+ RegionEmpty(&pRoot->clipList);
+ ErrorF("ValidateTree: BUSTED!\n");
+ }
+
+ /*
+ * Recursively compute the clips for all children of the root.
+ * They don't clip against each other or the root itself, so
+ * childClip is always reset to that child's size.
+ */
+
+ for (pWin = pChild;
+ pWin != NullWindow;
+ pWin = pWin->nextSib)
+ {
+ if (pWin->viewable) {
+ if (pWin->valdata) {
+ RegionCopy(&childClip, &pWin->borderSize);
+ RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed);
+ } else if (pWin->visibility == VisibilityNotViewable) {
+ RootlessTreeObscured(pWin);
+ }
+ } else {
+ if (pWin->valdata) {
+ RegionEmpty(&pWin->clipList);
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify) (pWin, 0, 0);
+ RegionEmpty(&pWin->borderClip);
+ pWin->valdata = NULL;
+ }
+ }
+ }
+
+ RegionUninit(&childClip);
+
+ /* The root is never clipped by its children, so nothing on the root
+ is ever exposed by moving or mapping its children. */
+ RegionNull(&pRoot->valdata->after.exposed);
+ RegionNull(&pRoot->valdata->after.borderExposed);
+
+ return 1;
+}
diff --git a/xorg-server/miext/rootless/rootlessWindow.c b/xorg-server/miext/rootless/rootlessWindow.c
index 2f412ee43..28e412f3b 100644
--- a/xorg-server/miext/rootless/rootlessWindow.c
+++ b/xorg-server/miext/rootless/rootlessWindow.c
@@ -53,9 +53,9 @@ extern Bool no_configure_window;
#ifdef ROOTLESS_GLOBAL_COORDS
#define SCREEN_TO_GLOBAL_X \
- (dixScreenOrigins[pScreen->myNum].x + rootlessGlobalOffsetX)
+ (pScreen->x + rootlessGlobalOffsetX)
#define SCREEN_TO_GLOBAL_Y \
- (dixScreenOrigins[pScreen->myNum].y + rootlessGlobalOffsetY)
+ (pScreen->y + rootlessGlobalOffsetY)
#else
#define SCREEN_TO_GLOBAL_X 0
#define SCREEN_TO_GLOBAL_Y 0
@@ -109,8 +109,8 @@ void RootlessNativeWindowMoved (WindowPtr pWin) {
if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return;
- sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY;
+ sx = pWin->drawable.pScreen->x + darwinMainScreenX;
+ sy = pWin->drawable.pScreen->y + darwinMainScreenY;
/* Fake up a ConfigureWindow packet to resize the window to the current bounds. */
vlist[0] = (INT16) bounds.x1 - sx;
@@ -179,12 +179,10 @@ RootlessCreateWindow(WindowPtr pWin)
static void
RootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec)
{
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- SCREENREC(pScreen)->imp->DestroyFrame(winRec->wid);
+ SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid);
#ifdef ROOTLESS_TRACK_DAMAGE
- REGION_UNINIT(pScreen, &winRec->damage);
+ RegionUninit(&winRec->damage);
#endif
free(winRec);
@@ -218,23 +216,15 @@ RootlessDestroyWindow(WindowPtr pWin)
static Bool
RootlessGetShape(WindowPtr pWin, RegionPtr pShape)
{
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- /*
- * Avoid a warning.
- * REGION_NULL and the other macros don't actually seem to use pScreen.
- */
- (void)pScreen;
-
if (wBoundingShape(pWin) == NULL)
return FALSE;
/* wBoundingShape is relative to *inner* origin of window.
Translate by borderWidth to get the outside-relative position. */
- REGION_NULL(pScreen, pShape);
- REGION_COPY(pScreen, pShape, wBoundingShape(pWin));
- REGION_TRANSLATE(pScreen, pShape, pWin->borderWidth, pWin->borderWidth);
+ RegionNull(pShape);
+ RegionCopy(pShape, wBoundingShape(pWin));
+ RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth);
return TRUE;
}
@@ -247,7 +237,6 @@ RootlessGetShape(WindowPtr pWin, RegionPtr pShape)
static void RootlessReshapeFrame(WindowPtr pWin)
{
RootlessWindowRec *winRec = WINREC(pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
RegionRec newShape;
RegionPtr pShape;
@@ -266,7 +255,7 @@ static void RootlessReshapeFrame(WindowPtr pWin)
RL_DEBUG_MSG("reshaping...");
if (pShape != NULL) {
RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
- REGION_NUM_RECTS(&newShape),
+ RegionNumRects(&newShape),
newShape.extents.x1, newShape.extents.y1,
newShape.extents.x2, newShape.extents.y2);
} else {
@@ -274,10 +263,10 @@ static void RootlessReshapeFrame(WindowPtr pWin)
}
#endif
- SCREENREC(pScreen)->imp->ReshapeFrame(winRec->wid, pShape);
+ SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape);
if (pShape != NULL)
- REGION_UNINIT(pScreen, &newShape);
+ RegionUninit(&newShape);
}
@@ -288,12 +277,12 @@ static void RootlessReshapeFrame(WindowPtr pWin)
* shaped when the window is framed.
*/
void
-RootlessSetShape(WindowPtr pWin)
+RootlessSetShape(WindowPtr pWin, int kind)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
SCREEN_UNWRAP(pScreen, SetShape);
- pScreen->SetShape(pWin);
+ pScreen->SetShape(pWin, kind);
SCREEN_WRAP(pScreen, SetShape);
RootlessReshapeFrame(pWin);
@@ -355,8 +344,8 @@ RootlessPositionWindow(WindowPtr pWin, int x, int y)
#ifdef ROOTLESS_TRACK_DAMAGE
// Move damaged region to correspond to new window position
- if (REGION_NOTEMPTY(pScreen, &winRec->damage)) {
- REGION_TRANSLATE(pScreen, &winRec->damage,
+ if (RegionNotEmpty(&winRec->damage)) {
+ RegionTranslate(&winRec->damage,
x - bw - winRec->x,
y - bw - winRec->y);
}
@@ -394,7 +383,7 @@ RootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec)
winRec->borderWidth = bw;
#ifdef ROOTLESS_TRACK_DAMAGE
- REGION_NULL(pScreen, &winRec->damage);
+ RegionNull(&winRec->damage);
#endif
}
@@ -457,7 +446,7 @@ RootlessEnsureFrame(WindowPtr pWin)
RootlessFlushWindowColormap(pWin);
if (pShape != NULL)
- REGION_UNINIT(pScreen, &shape);
+ RegionUninit(&shape);
return winRec;
}
@@ -673,7 +662,7 @@ RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
- REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+ RegionTranslate(prgnSrc, -dx, -dy);
}
@@ -705,9 +694,9 @@ RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
- REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
- REGION_NULL(pScreen, &rgnDst);
- REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+ RegionTranslate(prgnSrc, -dx, -dy);
+ RegionNull(&rgnDst);
+ RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
if (gResizeDeathCount == 1) {
/* Simple case, we only have a single source pixmap. */
@@ -724,21 +713,21 @@ RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
intersect the destination with each source and copy those bits. */
for (i = 0; i < gResizeDeathCount; i++) {
- REGION_INIT(pScreen, &clip, gResizeDeathBounds + 0, 1);
- REGION_NULL(pScreen, &clipped);
- REGION_INTERSECT(pScreen, &rgnDst, &clip, &clipped);
+ RegionInit(&clip, gResizeDeathBounds + 0, 1);
+ RegionNull(&clipped);
+ RegionIntersect(&rgnDst, &clip, &clipped);
fbCopyRegion(&gResizeDeathPix[i]->drawable,
&pScreen->GetWindowPixmap(pWin)->drawable, 0,
&clipped, dx, dy, fbCopyWindowProc, 0, 0);
- REGION_UNINIT(pScreen, &clipped);
- REGION_UNINIT(pScreen, &clip);
+ RegionUninit(&clipped);
+ RegionUninit(&clip);
}
}
/* Don't update - resize will update everything */
- REGION_UNINIT(pScreen, &rgnDst);
+ RegionUninit(&rgnDst);
fbValidateDrawable(&pWin->drawable);
@@ -768,12 +757,12 @@ RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
- REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy);
+ RegionTranslate(prgnSrc, -dx, -dy);
- REGION_NULL(pScreen, &rgnDst);
- REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
+ RegionNull(&rgnDst);
+ RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
- extents = REGION_EXTENTS(pScreen, &rgnDst);
+ extents = RegionExtents(&rgnDst);
area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
/* If the area exceeds threshold, use the implementation's
@@ -797,13 +786,13 @@ RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
}
/* Move region to window local coords */
- REGION_TRANSLATE(pScreen, &rgnDst, -winRec->x, -winRec->y);
+ RegionTranslate(&rgnDst, -winRec->x, -winRec->y);
RootlessStopDrawing(pWin, FALSE);
SCREENREC(pScreen)->imp->CopyWindow(winRec->wid,
- REGION_NUM_RECTS(&rgnDst),
- REGION_RECTS(&rgnDst),
+ RegionNumRects(&rgnDst),
+ RegionRects(&rgnDst),
dx, dy);
}
else {
@@ -817,7 +806,7 @@ RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
}
out:
- REGION_UNINIT(pScreen, &rgnDst);
+ RegionUninit(&rgnDst);
fbValidateDrawable(&pWin->drawable);
SCREEN_WRAP(pScreen, CopyWindow);
@@ -1320,11 +1309,11 @@ RootlessResizeWindow(WindowPtr pWin, int x, int y,
box.x1 = x; box.y1 = y;
box.x2 = x + w; box.y2 = y + h;
- REGION_UNINIT(pScreen, &pWin->winSize);
- REGION_INIT(pScreen, &pWin->winSize, &box, 1);
- REGION_COPY(pScreen, &pWin->borderSize, &pWin->winSize);
- REGION_COPY(pScreen, &pWin->clipList, &pWin->winSize);
- REGION_COPY(pScreen, &pWin->borderClip, &pWin->winSize);
+ RegionUninit(&pWin->winSize);
+ RegionInit(&pWin->winSize, &box, 1);
+ RegionCopy(&pWin->borderSize, &pWin->winSize);
+ RegionCopy(&pWin->clipList, &pWin->winSize);
+ RegionCopy(&pWin->borderClip, &pWin->winSize);
miSendExposures(pWin, &pWin->borderClip,
pWin->drawable.x, pWin->drawable.y);
@@ -1517,7 +1506,7 @@ RootlessOrderAllWindows (void)
RL_DEBUG_MSG("RootlessOrderAllWindows() ");
for (i = 0; i < screenInfo.numScreens; i++) {
if (screenInfo.screens[i] == NULL) continue;
- pWin = WindowTable[i];
+ pWin = screenInfo.screens[i]->root;
if (pWin == NULL) continue;
for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
@@ -1533,7 +1522,7 @@ void
RootlessEnableRoot (ScreenPtr pScreen)
{
WindowPtr pRoot;
- pRoot = WindowTable[pScreen->myNum];
+ pRoot = pScreen->root;
RootlessEnsureFrame (pRoot);
(*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
@@ -1546,7 +1535,7 @@ RootlessDisableRoot (ScreenPtr pScreen)
WindowPtr pRoot;
RootlessWindowRec *winRec;
- pRoot = WindowTable[pScreen->myNum];
+ pRoot = pScreen->root;
winRec = WINREC (pRoot);
if (NULL == winRec)
@@ -1572,8 +1561,10 @@ RootlessHideAllWindows (void)
for (i = 0; i < screenInfo.numScreens; i++)
{
pScreen = screenInfo.screens[i];
- pWin = WindowTable[i];
- if (pScreen == NULL || pWin == NULL)
+ if (pScreen == NULL)
+ continue;
+ pWin = pScreen->root;
+ if (pWin == NULL)
continue;
for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
@@ -1609,8 +1600,10 @@ RootlessShowAllWindows (void)
for (i = 0; i < screenInfo.numScreens; i++)
{
pScreen = screenInfo.screens[i];
- pWin = WindowTable[i];
- if (pScreen == NULL || pWin == NULL)
+ if (pScreen == NULL)
+ continue;
+ pWin = pScreen->root;
+ if (pWin == NULL)
continue;
for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
diff --git a/xorg-server/miext/rootless/rootlessWindow.h b/xorg-server/miext/rootless/rootlessWindow.h
index ca104a4d7..2da96e661 100644
--- a/xorg-server/miext/rootless/rootlessWindow.h
+++ b/xorg-server/miext/rootless/rootlessWindow.h
@@ -1,60 +1,60 @@
-/*
- * Rootless window management
- */
-/*
- * Copyright (c) 2001 Greg Parker. 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
-
-#ifndef _ROOTLESSWINDOW_H
-#define _ROOTLESSWINDOW_H
-
-#include "rootlessCommon.h"
-
-Bool RootlessCreateWindow(WindowPtr pWin);
-Bool RootlessDestroyWindow(WindowPtr pWin);
-
-void RootlessSetShape(WindowPtr pWin);
-
-Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask);
-Bool RootlessPositionWindow(WindowPtr pWin, int x, int y);
-Bool RootlessRealizeWindow(WindowPtr pWin);
-Bool RootlessUnrealizeWindow(WindowPtr pWin);
-void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib);
-void RootlessCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc);
-void RootlessMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind);
-void RootlessResizeWindow(WindowPtr pWin, int x, int y,
- unsigned int w, unsigned int h, WindowPtr pSib);
-void RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent);
-void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width);
-#ifdef __APPLE__
-void RootlessNativeWindowMoved (WindowPtr pWin);
-void RootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state);
-#endif
-
-#endif
+/*
+ * Rootless window management
+ */
+/*
+ * Copyright (c) 2001 Greg Parker. 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
+
+#ifndef _ROOTLESSWINDOW_H
+#define _ROOTLESSWINDOW_H
+
+#include "rootlessCommon.h"
+
+Bool RootlessCreateWindow(WindowPtr pWin);
+Bool RootlessDestroyWindow(WindowPtr pWin);
+
+void RootlessSetShape(WindowPtr pWin, int kind);
+
+Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask);
+Bool RootlessPositionWindow(WindowPtr pWin, int x, int y);
+Bool RootlessRealizeWindow(WindowPtr pWin);
+Bool RootlessUnrealizeWindow(WindowPtr pWin);
+void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib);
+void RootlessCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc);
+void RootlessMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind);
+void RootlessResizeWindow(WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib);
+void RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent);
+void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width);
+#ifdef __APPLE__
+void RootlessNativeWindowMoved (WindowPtr pWin);
+void RootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state);
+#endif
+
+#endif