aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xquartz/xpr/xprFrame.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xquartz/xpr/xprFrame.c')
-rw-r--r--xorg-server/hw/xquartz/xpr/xprFrame.c1216
1 files changed, 608 insertions, 608 deletions
diff --git a/xorg-server/hw/xquartz/xpr/xprFrame.c b/xorg-server/hw/xquartz/xpr/xprFrame.c
index 98f1cc3ed..4214eff33 100644
--- a/xorg-server/hw/xquartz/xpr/xprFrame.c
+++ b/xorg-server/hw/xquartz/xpr/xprFrame.c
@@ -1,608 +1,608 @@
-/*
- * Xplugin rootless implementation frame functions
- *
- * Copyright (c) 2002-2011 Apple Computer, Inc. All rights reserved.
- * Copyright (c) 2003 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 "xpr.h"
-#include "rootlessCommon.h"
-#include <Xplugin.h>
-#include "x-hash.h"
-#include "applewmExt.h"
-
-#include "propertyst.h"
-#include "dix.h"
-#include <X11/Xatom.h>
-#include "windowstr.h"
-#include "quartz.h"
-
-#ifdef HAVE_LIBDISPATCH
-#include <dispatch/dispatch.h>
-#else
-#include <pthread.h>
-#endif
-
-#define DEFINE_ATOM_HELPER(func,atom_name) \
-static Atom func (void) { \
- static int generation; \
- static Atom atom; \
- if (generation != serverGeneration) { \
- generation = serverGeneration; \
- atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
- } \
- return atom; \
-}
-
-DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
-
-/* Maps xp_window_id -> RootlessWindowRec */
-static x_hash_table *window_hash;
-
-/* Need to guard window_hash since xprIsX11Window can be called from any thread. */
-#ifdef HAVE_LIBDISPATCH
-static dispatch_queue_t window_hash_serial_q;
-#else
-static pthread_rwlock_t window_hash_rwlock;
-#endif
-
-/* Prototypes for static functions */
-static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape);
-static void xprDestroyFrame(RootlessFrameID wid);
-static void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
-static void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity);
-static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
-static void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
-static void xprUnmapFrame(RootlessFrameID wid);
-static void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
-static void xprStopDrawing(RootlessFrameID wid, Bool flush);
-static void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
-static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y);
-static void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
-static Bool xprDoReorderWindow(RootlessWindowPtr pFrame);
-static void xprHideWindow(RootlessFrameID wid);
-static void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
-static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy);
-
-
-static inline xp_error
-xprConfigureWindow(xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- return xp_configure_window(id, mask, values);
-}
-
-
-static void
-xprSetNativeProperty(RootlessWindowPtr pFrame)
-{
- xp_error err;
- unsigned int native_id;
- long data;
-
- err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
- if (err == Success)
- {
- /* FIXME: move this to AppleWM extension */
-
- data = native_id;
- dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(),
- XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
- }
-}
-
-static xp_error
-xprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors)
-{
- return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch);
-}
-
-/*
- * Create and display a new frame.
- */
-static Bool
-xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
- int newX, int newY, RegionPtr pShape)
-{
- WindowPtr pWin = pFrame->win;
- xp_window_changes wc;
- unsigned int mask = 0;
- xp_error err;
-
- wc.x = newX;
- wc.y = newY;
- wc.width = pFrame->width;
- wc.height = pFrame->height;
- wc.bit_gravity = XP_GRAVITY_NONE;
- mask |= XP_BOUNDS;
-
- if (pWin->drawable.depth == 8)
- {
- wc.depth = XP_DEPTH_INDEX8;
- wc.colormap = xprColormapCallback;
- wc.colormap_data = pScreen;
- mask |= XP_COLORMAP;
- }
- else if (pWin->drawable.depth == 15)
- wc.depth = XP_DEPTH_RGB555;
- else if (pWin->drawable.depth == 24)
- wc.depth = XP_DEPTH_ARGB8888;
- else
- wc.depth = XP_DEPTH_NIL;
- mask |= XP_DEPTH;
-
- if (pShape != NULL)
- {
- wc.shape_nrects = RegionNumRects(pShape);
- wc.shape_rects = RegionRects(pShape);
- wc.shape_tx = wc.shape_ty = 0;
- mask |= XP_SHAPE;
- }
-
- pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
-
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[pFrame->level];
- else if(XQuartzShieldingWindowLevel)
- wc.window_level = XQuartzShieldingWindowLevel + 1;
- else
- wc.window_level = rooted_window_levels[pFrame->level];
- mask |= XP_WINDOW_LEVEL;
-
- err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid);
-
- if (err != Success)
- {
- return FALSE;
- }
-
-#ifdef HAVE_LIBDISPATCH
- dispatch_async(window_hash_serial_q, ^{
- x_hash_table_insert(window_hash, pFrame->wid, pFrame);
- });
-#else
- pthread_rwlock_wrlock(&window_hash_rwlock);
- x_hash_table_insert(window_hash, pFrame->wid, pFrame);
- pthread_rwlock_wrlock(&window_hash_rwlock);
-#endif
-
- xprSetNativeProperty(pFrame);
-
- return TRUE;
-}
-
-
-/*
- * Destroy a frame.
- */
-static void
-xprDestroyFrame(RootlessFrameID wid)
-{
- xp_error err;
-
-#ifdef HAVE_LIBDISPATCH
- dispatch_async(window_hash_serial_q, ^{
- x_hash_table_remove(window_hash, wid);
- });
-#else
- pthread_rwlock_wrlock(&window_hash_rwlock);
- x_hash_table_remove(window_hash, wid);
- pthread_rwlock_unlock(&window_hash_rwlock);
-#endif
-
- err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
- if (err != Success)
- FatalError("Could not destroy window %d (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
-}
-
-
-/*
- * Move a frame on screen.
- */
-static void
-xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
-{
- xp_window_changes wc;
-
- wc.x = newX;
- wc.y = newY;
- // ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
-}
-
-
-/*
- * Resize and move a frame.
- */
-static void
-xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity)
-{
- xp_window_changes wc;
-
- wc.x = newX;
- wc.y = newY;
- wc.width = newW;
- wc.height = newH;
- wc.bit_gravity = gravity;
-
- /* It's unlikely that being async will save us anything here.
- But it can't hurt. */
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
-}
-
-
-/*
- * Change frame stacking.
- */
-static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
- xp_window_changes wc;
- unsigned int mask = XP_STACKING;
-#ifdef HAVE_LIBDISPATCH
- __block
-#endif
- RootlessWindowRec *winRec;
-
- /* Stack frame below nextWid it if it exists, or raise
- frame above everything otherwise. */
-
- if(nextWid == NULL) {
- wc.stack_mode = XP_MAPPED_ABOVE;
- wc.sibling = 0;
- } else {
- wc.stack_mode = XP_MAPPED_BELOW;
- wc.sibling = x_cvt_vptr_to_uint(nextWid);
- }
-
-#ifdef HAVE_LIBDISPATCH
- dispatch_sync(window_hash_serial_q, ^{
- winRec = x_hash_table_lookup(window_hash, wid, NULL);
- });
-#else
- pthread_rwlock_rdlock(&window_hash_rwlock);
- winRec = x_hash_table_lookup(window_hash, wid, NULL);
- pthread_rwlock_unlock(&window_hash_rwlock);
-#endif
-
- if(winRec) {
- if(XQuartzIsRootless)
- wc.window_level = normal_window_levels[winRec->level];
- else if(XQuartzShieldingWindowLevel)
- wc.window_level = XQuartzShieldingWindowLevel + 1;
- else
- wc.window_level = rooted_window_levels[winRec->level];
- mask |= XP_WINDOW_LEVEL;
- }
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
-}
-
-
-/*
- * Change the frame's shape.
- */
-static void
-xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
-{
- xp_window_changes wc;
-
- if (pShape != NULL)
- {
- wc.shape_nrects = RegionNumRects(pShape);
- wc.shape_rects = RegionRects(pShape);
- }
- else
- {
- wc.shape_nrects = -1;
- wc.shape_rects = NULL;
- }
-
- wc.shape_tx = wc.shape_ty = 0;
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
-}
-
-
-/*
- * Unmap a frame.
- */
-static void
-xprUnmapFrame(RootlessFrameID wid)
-{
- xp_window_changes wc;
-
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
-
- xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
-}
-
-
-/*
- * Start drawing to a frame.
- * Prepare for direct access to its backing buffer.
- */
-static void
-xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
-{
- void *data[2];
- unsigned int rowbytes[2];
- xp_error err;
-
- err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL);
- if (err != Success)
- FatalError("Could not lock window %d for drawing (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
-
- *pixelData = data[0];
- *bytesPerRow = rowbytes[0];
-}
-
-
-/*
- * Stop drawing to a frame.
- */
-static void
-xprStopDrawing(RootlessFrameID wid, Bool flush)
-{
- xp_error err;
-
- err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
- /* This should be a FatalError, but we started tripping over it. Make it a
- * FatalError after http://xquartz.macosforge.org/trac/ticket/482 is fixed.
- */
- if(err != Success)
- ErrorF("Could not unlock window %d after drawing (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
-}
-
-
-/*
- * Flush drawing updates to the screen.
- */
-static void
-xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
-{
- xp_flush_window(x_cvt_vptr_to_uint(wid));
-}
-
-
-/*
- * Mark damaged rectangles as requiring redisplay to screen.
- */
-static void
-xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y)
-{
- xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
-}
-
-
-/*
- * Called after the window associated with a frame has been switched
- * to a new top-level parent.
- */
-static void
-xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
-{
- DeleteProperty(serverClient, oldWin, xa_native_window_id());
-
- xprSetNativeProperty(pFrame);
-}
-
-
-/*
- * Called to check if the frame should be reordered when it is restacked.
- */
-static Bool xprDoReorderWindow(RootlessWindowPtr pFrame)
-{
- WindowPtr pWin = pFrame->win;
-
- return AppleWMDoReorderWindow(pWin);
-}
-
-
-/*
- * Copy area in frame to another part of frame.
- * Used to accelerate scrolling.
- */
-static void
-xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy)
-{
- xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
- dstNrects, dstRects, dx, dy);
-}
-
-
-static RootlessFrameProcsRec xprRootlessProcs = {
- xprCreateFrame,
- xprDestroyFrame,
- xprMoveFrame,
- xprResizeFrame,
- xprRestackFrame,
- xprReshapeFrame,
- xprUnmapFrame,
- xprStartDrawing,
- xprStopDrawing,
- xprUpdateRegion,
- xprDamageRects,
- xprSwitchWindow,
- xprDoReorderWindow,
- xprHideWindow,
- xprUpdateColormap,
- xp_copy_bytes,
- xprCopyWindow
-};
-
-
-/*
- * Initialize XPR implementation
- */
-Bool
-xprInit(ScreenPtr pScreen)
-{
- RootlessInit(pScreen, &xprRootlessProcs);
-
- rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
- rootless_CopyWindow_threshold = xp_scroll_area_threshold;
-
- assert((window_hash = x_hash_table_new(NULL, NULL, NULL, NULL)));
-#ifdef HAVE_LIBDISPATCH
- assert((window_hash_serial_q = dispatch_queue_create(BUNDLE_ID_PREFIX".X11.xpr_window_hash", NULL)));
-#else
- assert(0 == pthread_rwlock_init(&window_hash_rwlock, NULL));
-#endif
-
- return TRUE;
-}
-
-
-/*
- * Given the id of a physical window, try to find the top-level (or root)
- * X window that it represents.
- */
-WindowPtr
-xprGetXWindow(xp_window_id wid)
-{
-#ifdef HAVE_LIBDISPATCH
- RootlessWindowRec *winRec __block;
- dispatch_sync(window_hash_serial_q, ^{
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
- });
-#else
- RootlessWindowRec *winRec;
- pthread_rwlock_rdlock(&window_hash_rwlock);
- winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
- pthread_rwlock_unlock(&window_hash_rwlock);
-#endif
-
- return winRec != NULL ? winRec->win : NULL;
-}
-
-/*
- * The windowNumber is an AppKit window number. Returns TRUE if xpr is
- * displaying a window with that number.
- */
-Bool
-xprIsX11Window(int windowNumber)
-{
- Bool ret;
- xp_window_id wid;
-
- if (xp_lookup_native_window(windowNumber, &wid))
- ret = xprGetXWindow(wid) != NULL;
- else
- ret = FALSE;
-
- return ret;
-}
-
-
-/*
- * xprHideWindows
- * Hide or unhide all top level windows. This is called for application hide/
- * unhide events if the window manager is not Apple-WM aware. Xplugin windows
- * do not hide or unhide themselves.
- */
-void
-xprHideWindows(Bool hide)
-{
- int screen;
- WindowPtr pRoot, pWin;
-
- for (screen = 0; screen < screenInfo.numScreens; screen++) {
- RootlessFrameID prevWid = NULL;
- pRoot = screenInfo.screens[screen]->root;
-
- for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
- RootlessWindowRec *winRec = WINREC(pWin);
-
- if (winRec != NULL) {
- if (hide) {
- xprUnmapFrame(winRec->wid);
- } else {
- BoxRec box;
-
- xprRestackFrame(winRec->wid, prevWid);
- prevWid = winRec->wid;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = winRec->width;
- box.y2 = winRec->height;
-
- xprDamageRects(winRec->wid, 1, &box, 0, 0);
- RootlessQueueRedisplay(screenInfo.screens[screen]);
- }
- }
- }
- }
-}
-
-// XXX: identical to x_cvt_vptr_to_uint ?
-#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
-
-Bool no_configure_window;
-
-static inline int
-configure_window (xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- if (!no_configure_window)
- return xp_configure_window (id, mask, values);
- else
- return XP_Success;
-}
-
-
-static
-void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
-{
- /* This is how we tell xp that the colormap may have changed. */
- xp_window_changes wc;
- wc.colormap = xprColormapCallback;
- wc.colormap_data = pScreen;
-
- configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
-}
-
-static
-void xprHideWindow(RootlessFrameID wid)
-{
- xp_window_changes wc;
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
- configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
-}
+/*
+ * Xplugin rootless implementation frame functions
+ *
+ * Copyright (c) 2002-2011 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2003 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 "xpr.h"
+#include "rootlessCommon.h"
+#include <Xplugin.h>
+#include "x-hash.h"
+#include "applewmExt.h"
+
+#include "propertyst.h"
+#include "dix.h"
+#include <X11/Xatom.h>
+#include "windowstr.h"
+#include "quartz.h"
+
+#ifdef HAVE_LIBDISPATCH
+#include <dispatch/dispatch.h>
+#else
+#include <pthread.h>
+#endif
+
+#define DEFINE_ATOM_HELPER(func,atom_name) \
+static Atom func (void) { \
+ static int generation; \
+ static Atom atom; \
+ if (generation != serverGeneration) { \
+ generation = serverGeneration; \
+ atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
+ } \
+ return atom; \
+}
+
+DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
+
+/* Maps xp_window_id -> RootlessWindowRec */
+static x_hash_table *window_hash;
+
+/* Need to guard window_hash since xprIsX11Window can be called from any thread. */
+#ifdef HAVE_LIBDISPATCH
+static dispatch_queue_t window_hash_serial_q;
+#else
+static pthread_rwlock_t window_hash_rwlock;
+#endif
+
+/* Prototypes for static functions */
+static Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
+ int newX, int newY, RegionPtr pShape);
+static void xprDestroyFrame(RootlessFrameID wid);
+static void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
+static void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
+ int newX, int newY, unsigned int newW, unsigned int newH,
+ unsigned int gravity);
+static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
+static void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
+static void xprUnmapFrame(RootlessFrameID wid);
+static void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
+static void xprStopDrawing(RootlessFrameID wid, Bool flush);
+static void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
+static void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
+ int shift_x, int shift_y);
+static void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
+static Bool xprDoReorderWindow(RootlessWindowPtr pFrame);
+static void xprHideWindow(RootlessFrameID wid);
+static void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
+static void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
+ int dx, int dy);
+
+
+static inline xp_error
+xprConfigureWindow(xp_window_id id, unsigned int mask,
+ const xp_window_changes *values)
+{
+ return xp_configure_window(id, mask, values);
+}
+
+
+static void
+xprSetNativeProperty(RootlessWindowPtr pFrame)
+{
+ xp_error err;
+ unsigned int native_id;
+ long data;
+
+ err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
+ if (err == Success)
+ {
+ /* FIXME: move this to AppleWM extension */
+
+ data = native_id;
+ dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(),
+ XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
+ }
+}
+
+static xp_error
+xprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors)
+{
+ return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch);
+}
+
+/*
+ * Create and display a new frame.
+ */
+static Bool
+xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
+ int newX, int newY, RegionPtr pShape)
+{
+ WindowPtr pWin = pFrame->win;
+ xp_window_changes wc;
+ unsigned int mask = 0;
+ xp_error err;
+
+ wc.x = newX;
+ wc.y = newY;
+ wc.width = pFrame->width;
+ wc.height = pFrame->height;
+ wc.bit_gravity = XP_GRAVITY_NONE;
+ mask |= XP_BOUNDS;
+
+ if (pWin->drawable.depth == 8)
+ {
+ wc.depth = XP_DEPTH_INDEX8;
+ wc.colormap = xprColormapCallback;
+ wc.colormap_data = pScreen;
+ mask |= XP_COLORMAP;
+ }
+ else if (pWin->drawable.depth == 15)
+ wc.depth = XP_DEPTH_RGB555;
+ else if (pWin->drawable.depth == 24)
+ wc.depth = XP_DEPTH_ARGB8888;
+ else
+ wc.depth = XP_DEPTH_NIL;
+ mask |= XP_DEPTH;
+
+ if (pShape != NULL)
+ {
+ wc.shape_nrects = RegionNumRects(pShape);
+ wc.shape_rects = RegionRects(pShape);
+ wc.shape_tx = wc.shape_ty = 0;
+ mask |= XP_SHAPE;
+ }
+
+ pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
+
+ if(XQuartzIsRootless)
+ wc.window_level = normal_window_levels[pFrame->level];
+ else if(XQuartzShieldingWindowLevel)
+ wc.window_level = XQuartzShieldingWindowLevel + 1;
+ else
+ wc.window_level = rooted_window_levels[pFrame->level];
+ mask |= XP_WINDOW_LEVEL;
+
+ err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid);
+
+ if (err != Success)
+ {
+ return FALSE;
+ }
+
+#ifdef HAVE_LIBDISPATCH
+ dispatch_async(window_hash_serial_q, ^{
+ x_hash_table_insert(window_hash, pFrame->wid, pFrame);
+ });
+#else
+ pthread_rwlock_wrlock(&window_hash_rwlock);
+ x_hash_table_insert(window_hash, pFrame->wid, pFrame);
+ pthread_rwlock_wrlock(&window_hash_rwlock);
+#endif
+
+ xprSetNativeProperty(pFrame);
+
+ return TRUE;
+}
+
+
+/*
+ * Destroy a frame.
+ */
+static void
+xprDestroyFrame(RootlessFrameID wid)
+{
+ xp_error err;
+
+#ifdef HAVE_LIBDISPATCH
+ dispatch_async(window_hash_serial_q, ^{
+ x_hash_table_remove(window_hash, wid);
+ });
+#else
+ pthread_rwlock_wrlock(&window_hash_rwlock);
+ x_hash_table_remove(window_hash, wid);
+ pthread_rwlock_unlock(&window_hash_rwlock);
+#endif
+
+ err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
+ if (err != Success)
+ FatalError("Could not destroy window %d (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
+}
+
+
+/*
+ * Move a frame on screen.
+ */
+static void
+xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
+{
+ xp_window_changes wc;
+
+ wc.x = newX;
+ wc.y = newY;
+ // ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
+}
+
+
+/*
+ * Resize and move a frame.
+ */
+static void
+xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
+ int newX, int newY, unsigned int newW, unsigned int newH,
+ unsigned int gravity)
+{
+ xp_window_changes wc;
+
+ wc.x = newX;
+ wc.y = newY;
+ wc.width = newW;
+ wc.height = newH;
+ wc.bit_gravity = gravity;
+
+ /* It's unlikely that being async will save us anything here.
+ But it can't hurt. */
+
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
+}
+
+
+/*
+ * Change frame stacking.
+ */
+static void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
+ xp_window_changes wc;
+ unsigned int mask = XP_STACKING;
+#ifdef HAVE_LIBDISPATCH
+ __block
+#endif
+ RootlessWindowRec *winRec;
+
+ /* Stack frame below nextWid it if it exists, or raise
+ frame above everything otherwise. */
+
+ if(nextWid == NULL) {
+ wc.stack_mode = XP_MAPPED_ABOVE;
+ wc.sibling = 0;
+ } else {
+ wc.stack_mode = XP_MAPPED_BELOW;
+ wc.sibling = x_cvt_vptr_to_uint(nextWid);
+ }
+
+#ifdef HAVE_LIBDISPATCH
+ dispatch_sync(window_hash_serial_q, ^{
+ winRec = x_hash_table_lookup(window_hash, wid, NULL);
+ });
+#else
+ pthread_rwlock_rdlock(&window_hash_rwlock);
+ winRec = x_hash_table_lookup(window_hash, wid, NULL);
+ pthread_rwlock_unlock(&window_hash_rwlock);
+#endif
+
+ if(winRec) {
+ if(XQuartzIsRootless)
+ wc.window_level = normal_window_levels[winRec->level];
+ else if(XQuartzShieldingWindowLevel)
+ wc.window_level = XQuartzShieldingWindowLevel + 1;
+ else
+ wc.window_level = rooted_window_levels[winRec->level];
+ mask |= XP_WINDOW_LEVEL;
+ }
+
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
+}
+
+
+/*
+ * Change the frame's shape.
+ */
+static void
+xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
+{
+ xp_window_changes wc;
+
+ if (pShape != NULL)
+ {
+ wc.shape_nrects = RegionNumRects(pShape);
+ wc.shape_rects = RegionRects(pShape);
+ }
+ else
+ {
+ wc.shape_nrects = -1;
+ wc.shape_rects = NULL;
+ }
+
+ wc.shape_tx = wc.shape_ty = 0;
+
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
+}
+
+
+/*
+ * Unmap a frame.
+ */
+static void
+xprUnmapFrame(RootlessFrameID wid)
+{
+ xp_window_changes wc;
+
+ wc.stack_mode = XP_UNMAPPED;
+ wc.sibling = 0;
+
+ xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
+}
+
+
+/*
+ * Start drawing to a frame.
+ * Prepare for direct access to its backing buffer.
+ */
+static void
+xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
+{
+ void *data[2];
+ unsigned int rowbytes[2];
+ xp_error err;
+
+ err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL);
+ if (err != Success)
+ FatalError("Could not lock window %d for drawing (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
+
+ *pixelData = data[0];
+ *bytesPerRow = rowbytes[0];
+}
+
+
+/*
+ * Stop drawing to a frame.
+ */
+static void
+xprStopDrawing(RootlessFrameID wid, Bool flush)
+{
+ xp_error err;
+
+ err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
+ /* This should be a FatalError, but we started tripping over it. Make it a
+ * FatalError after http://xquartz.macosforge.org/trac/ticket/482 is fixed.
+ */
+ if(err != Success)
+ ErrorF("Could not unlock window %d after drawing (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
+}
+
+
+/*
+ * Flush drawing updates to the screen.
+ */
+static void
+xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
+{
+ xp_flush_window(x_cvt_vptr_to_uint(wid));
+}
+
+
+/*
+ * Mark damaged rectangles as requiring redisplay to screen.
+ */
+static void
+xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
+ int shift_x, int shift_y)
+{
+ xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
+}
+
+
+/*
+ * Called after the window associated with a frame has been switched
+ * to a new top-level parent.
+ */
+static void
+xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
+{
+ DeleteProperty(serverClient, oldWin, xa_native_window_id());
+
+ xprSetNativeProperty(pFrame);
+}
+
+
+/*
+ * Called to check if the frame should be reordered when it is restacked.
+ */
+static Bool xprDoReorderWindow(RootlessWindowPtr pFrame)
+{
+ WindowPtr pWin = pFrame->win;
+
+ return AppleWMDoReorderWindow(pWin);
+}
+
+
+/*
+ * Copy area in frame to another part of frame.
+ * Used to accelerate scrolling.
+ */
+static void
+xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
+ int dx, int dy)
+{
+ xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
+ dstNrects, dstRects, dx, dy);
+}
+
+
+static RootlessFrameProcsRec xprRootlessProcs = {
+ xprCreateFrame,
+ xprDestroyFrame,
+ xprMoveFrame,
+ xprResizeFrame,
+ xprRestackFrame,
+ xprReshapeFrame,
+ xprUnmapFrame,
+ xprStartDrawing,
+ xprStopDrawing,
+ xprUpdateRegion,
+ xprDamageRects,
+ xprSwitchWindow,
+ xprDoReorderWindow,
+ xprHideWindow,
+ xprUpdateColormap,
+ xp_copy_bytes,
+ xprCopyWindow
+};
+
+
+/*
+ * Initialize XPR implementation
+ */
+Bool
+xprInit(ScreenPtr pScreen)
+{
+ RootlessInit(pScreen, &xprRootlessProcs);
+
+ rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
+ rootless_CopyWindow_threshold = xp_scroll_area_threshold;
+
+ assert((window_hash = x_hash_table_new(NULL, NULL, NULL, NULL)));
+#ifdef HAVE_LIBDISPATCH
+ assert((window_hash_serial_q = dispatch_queue_create(BUNDLE_ID_PREFIX".X11.xpr_window_hash", NULL)));
+#else
+ assert(0 == pthread_rwlock_init(&window_hash_rwlock, NULL));
+#endif
+
+ return TRUE;
+}
+
+
+/*
+ * Given the id of a physical window, try to find the top-level (or root)
+ * X window that it represents.
+ */
+WindowPtr
+xprGetXWindow(xp_window_id wid)
+{
+#ifdef HAVE_LIBDISPATCH
+ RootlessWindowRec *winRec __block;
+ dispatch_sync(window_hash_serial_q, ^{
+ winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
+ });
+#else
+ RootlessWindowRec *winRec;
+ pthread_rwlock_rdlock(&window_hash_rwlock);
+ winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
+ pthread_rwlock_unlock(&window_hash_rwlock);
+#endif
+
+ return winRec != NULL ? winRec->win : NULL;
+}
+
+/*
+ * The windowNumber is an AppKit window number. Returns TRUE if xpr is
+ * displaying a window with that number.
+ */
+Bool
+xprIsX11Window(int windowNumber)
+{
+ Bool ret;
+ xp_window_id wid;
+
+ if (xp_lookup_native_window(windowNumber, &wid))
+ ret = xprGetXWindow(wid) != NULL;
+ else
+ ret = FALSE;
+
+ return ret;
+}
+
+
+/*
+ * xprHideWindows
+ * Hide or unhide all top level windows. This is called for application hide/
+ * unhide events if the window manager is not Apple-WM aware. Xplugin windows
+ * do not hide or unhide themselves.
+ */
+void
+xprHideWindows(Bool hide)
+{
+ int screen;
+ WindowPtr pRoot, pWin;
+
+ for (screen = 0; screen < screenInfo.numScreens; screen++) {
+ RootlessFrameID prevWid = NULL;
+ pRoot = screenInfo.screens[screen]->root;
+
+ for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
+ RootlessWindowRec *winRec = WINREC(pWin);
+
+ if (winRec != NULL) {
+ if (hide) {
+ xprUnmapFrame(winRec->wid);
+ } else {
+ BoxRec box;
+
+ xprRestackFrame(winRec->wid, prevWid);
+ prevWid = winRec->wid;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = winRec->width;
+ box.y2 = winRec->height;
+
+ xprDamageRects(winRec->wid, 1, &box, 0, 0);
+ RootlessQueueRedisplay(screenInfo.screens[screen]);
+ }
+ }
+ }
+ }
+}
+
+// XXX: identical to x_cvt_vptr_to_uint ?
+#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
+
+Bool no_configure_window;
+
+static inline int
+configure_window (xp_window_id id, unsigned int mask,
+ const xp_window_changes *values)
+{
+ if (!no_configure_window)
+ return xp_configure_window (id, mask, values);
+ else
+ return XP_Success;
+}
+
+
+static
+void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
+{
+ /* This is how we tell xp that the colormap may have changed. */
+ xp_window_changes wc;
+ wc.colormap = xprColormapCallback;
+ wc.colormap_data = pScreen;
+
+ configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
+}
+
+static
+void xprHideWindow(RootlessFrameID wid)
+{
+ xp_window_changes wc;
+ wc.stack_mode = XP_UNMAPPED;
+ wc.sibling = 0;
+ configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
+}