diff options
Diffstat (limited to 'xorg-server/hw/xquartz/xpr/xprFrame.c')
-rw-r--r-- | xorg-server/hw/xquartz/xpr/xprFrame.c | 1216 |
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);
+}
|