14642e01fSmrg/*
24642e01fSmrg * Xplugin rootless implementation frame functions
34642e01fSmrg *
435c4bbdfSmrg * Copyright (c) 2002-2012 Apple Computer, Inc. All rights reserved.
54642e01fSmrg * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
64642e01fSmrg *
74642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
84642e01fSmrg * copy of this software and associated documentation files (the "Software"),
94642e01fSmrg * to deal in the Software without restriction, including without limitation
104642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
114642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the
124642e01fSmrg * Software is furnished to do so, subject to the following conditions:
134642e01fSmrg *
144642e01fSmrg * The above copyright notice and this permission notice shall be included in
154642e01fSmrg * all copies or substantial portions of the Software.
164642e01fSmrg *
174642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
184642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
194642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
204642e01fSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
214642e01fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
224642e01fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
234642e01fSmrg * DEALINGS IN THE SOFTWARE.
244642e01fSmrg *
254642e01fSmrg * Except as contained in this notice, the name(s) of the above copyright
264642e01fSmrg * holders shall not be used in advertising or otherwise to promote the sale,
274642e01fSmrg * use or other dealings in this Software without prior written authorization.
284642e01fSmrg */
294642e01fSmrg
304642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
314642e01fSmrg#include <dix-config.h>
324642e01fSmrg#endif
334642e01fSmrg
344642e01fSmrg#include "xpr.h"
354642e01fSmrg#include "rootlessCommon.h"
364642e01fSmrg#include <Xplugin.h>
374642e01fSmrg#include "x-hash.h"
384642e01fSmrg#include "applewmExt.h"
394642e01fSmrg
404642e01fSmrg#include "propertyst.h"
414642e01fSmrg#include "dix.h"
424642e01fSmrg#include <X11/Xatom.h>
434642e01fSmrg#include "windowstr.h"
446747b715Smrg#include "quartz.h"
454642e01fSmrg
4635c4bbdfSmrg#include <dispatch/dispatch.h>
474642e01fSmrg
4835c4bbdfSmrg#define DEFINE_ATOM_HELPER(func, atom_name)                      \
4935c4bbdfSmrg    static Atom func(void) {                                       \
5035c4bbdfSmrg        static int generation;                                      \
5135c4bbdfSmrg        static Atom atom;                                           \
5235c4bbdfSmrg        if (generation != serverGeneration) {                       \
5335c4bbdfSmrg            generation = serverGeneration;                          \
5435c4bbdfSmrg            atom = MakeAtom(atom_name, strlen(atom_name), TRUE);  \
5535c4bbdfSmrg        }                                                           \
5635c4bbdfSmrg        return atom;                                                \
5735c4bbdfSmrg    }
584642e01fSmrg
594642e01fSmrgDEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
604642e01fSmrg
614642e01fSmrg/* Maps xp_window_id -> RootlessWindowRec */
6235c4bbdfSmrgstatic x_hash_table * window_hash;
6335c4bbdfSmrg
6435c4bbdfSmrg/* Need to guard window_hash since xprIsX11Window can be called from any thread. */
6535c4bbdfSmrgstatic dispatch_queue_t window_hash_serial_q;
664642e01fSmrg
674642e01fSmrg/* Prototypes for static functions */
6835c4bbdfSmrgstatic Bool
6935c4bbdfSmrgxprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX,
7035c4bbdfSmrg               int newY,
7135c4bbdfSmrg               RegionPtr pShape);
7235c4bbdfSmrgstatic void
7335c4bbdfSmrgxprDestroyFrame(RootlessFrameID wid);
7435c4bbdfSmrgstatic void
7535c4bbdfSmrgxprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
7635c4bbdfSmrgstatic void
7735c4bbdfSmrgxprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY,
7835c4bbdfSmrg               unsigned int newW, unsigned int newH,
794642e01fSmrg               unsigned int gravity);
8035c4bbdfSmrgstatic void
8135c4bbdfSmrgxprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
8235c4bbdfSmrgstatic void
8335c4bbdfSmrgxprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
8435c4bbdfSmrgstatic void
8535c4bbdfSmrgxprUnmapFrame(RootlessFrameID wid);
8635c4bbdfSmrgstatic void
8735c4bbdfSmrgxprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
8835c4bbdfSmrgstatic void
8935c4bbdfSmrgxprStopDrawing(RootlessFrameID wid, Bool flush);
9035c4bbdfSmrgstatic void
9135c4bbdfSmrgxprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
9235c4bbdfSmrgstatic void
9335c4bbdfSmrgxprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
9435c4bbdfSmrg               int shift_x,
9535c4bbdfSmrg               int shift_y);
9635c4bbdfSmrgstatic void
9735c4bbdfSmrgxprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
9835c4bbdfSmrgstatic Bool
9935c4bbdfSmrgxprDoReorderWindow(RootlessWindowPtr pFrame);
10035c4bbdfSmrgstatic void
10135c4bbdfSmrgxprHideWindow(RootlessFrameID wid);
10235c4bbdfSmrgstatic void
10335c4bbdfSmrgxprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
10435c4bbdfSmrgstatic void
10535c4bbdfSmrgxprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
10635c4bbdfSmrg              int dx,
10735c4bbdfSmrg              int dy);
1084642e01fSmrg
1094642e01fSmrgstatic inline xp_error
1104642e01fSmrgxprConfigureWindow(xp_window_id id, unsigned int mask,
1114642e01fSmrg                   const xp_window_changes *values)
1124642e01fSmrg{
1134642e01fSmrg    return xp_configure_window(id, mask, values);
1144642e01fSmrg}
1154642e01fSmrg
1164642e01fSmrgstatic void
1174642e01fSmrgxprSetNativeProperty(RootlessWindowPtr pFrame)
1184642e01fSmrg{
1194642e01fSmrg    xp_error err;
1204642e01fSmrg    unsigned int native_id;
1214642e01fSmrg    long data;
1224642e01fSmrg
1234642e01fSmrg    err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
12435c4bbdfSmrg    if (err == Success) {
1254642e01fSmrg        /* FIXME: move this to AppleWM extension */
1264642e01fSmrg
1274642e01fSmrg        data = native_id;
12835c4bbdfSmrg        dixChangeWindowProperty(serverClient, pFrame->win,
12935c4bbdfSmrg                                xa_native_window_id(),
13035c4bbdfSmrg                                XA_INTEGER, 32, PropModeReplace, 1, &data,
13135c4bbdfSmrg                                TRUE);
1324642e01fSmrg    }
1334642e01fSmrg}
1344642e01fSmrg
1356747b715Smrgstatic xp_error
13635c4bbdfSmrgxprColormapCallback(void *data, int first_color, int n_colors,
13735c4bbdfSmrg                    uint32_t *colors)
1386747b715Smrg{
13935c4bbdfSmrg    return (RootlessResolveColormap(data, first_color, n_colors,
14035c4bbdfSmrg                                    colors) ? XP_Success : XP_BadMatch);
1416747b715Smrg}
1424642e01fSmrg
1434642e01fSmrg/*
1444642e01fSmrg * Create and display a new frame.
1454642e01fSmrg */
1466747b715Smrgstatic Bool
1474642e01fSmrgxprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
1484642e01fSmrg               int newX, int newY, RegionPtr pShape)
1494642e01fSmrg{
1504642e01fSmrg    WindowPtr pWin = pFrame->win;
1514642e01fSmrg    xp_window_changes wc;
1524642e01fSmrg    unsigned int mask = 0;
1534642e01fSmrg    xp_error err;
1544642e01fSmrg
1554642e01fSmrg    wc.x = newX;
1564642e01fSmrg    wc.y = newY;
1574642e01fSmrg    wc.width = pFrame->width;
1584642e01fSmrg    wc.height = pFrame->height;
1594642e01fSmrg    wc.bit_gravity = XP_GRAVITY_NONE;
1604642e01fSmrg    mask |= XP_BOUNDS;
1614642e01fSmrg
16235c4bbdfSmrg    if (pWin->drawable.depth == 8) {
1634642e01fSmrg        wc.depth = XP_DEPTH_INDEX8;
1646747b715Smrg        wc.colormap = xprColormapCallback;
1654642e01fSmrg        wc.colormap_data = pScreen;
1664642e01fSmrg        mask |= XP_COLORMAP;
1674642e01fSmrg    }
1684642e01fSmrg    else if (pWin->drawable.depth == 15)
1694642e01fSmrg        wc.depth = XP_DEPTH_RGB555;
1704642e01fSmrg    else if (pWin->drawable.depth == 24)
1714642e01fSmrg        wc.depth = XP_DEPTH_ARGB8888;
1724642e01fSmrg    else
1734642e01fSmrg        wc.depth = XP_DEPTH_NIL;
1744642e01fSmrg    mask |= XP_DEPTH;
1754642e01fSmrg
17635c4bbdfSmrg    if (pShape != NULL) {
1776747b715Smrg        wc.shape_nrects = RegionNumRects(pShape);
1786747b715Smrg        wc.shape_rects = RegionRects(pShape);
1794642e01fSmrg        wc.shape_tx = wc.shape_ty = 0;
1804642e01fSmrg        mask |= XP_SHAPE;
1814642e01fSmrg    }
1824642e01fSmrg
18335c4bbdfSmrg    pFrame->level =
18435c4bbdfSmrg        !IsRoot(pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
1856747b715Smrg
18635c4bbdfSmrg    if (XQuartzIsRootless)
1876747b715Smrg        wc.window_level = normal_window_levels[pFrame->level];
18835c4bbdfSmrg    else if (XQuartzShieldingWindowLevel)
1898223e2f2Smrg        wc.window_level = XQuartzShieldingWindowLevel + 1;
1906747b715Smrg    else
1916747b715Smrg        wc.window_level = rooted_window_levels[pFrame->level];
1926747b715Smrg    mask |= XP_WINDOW_LEVEL;
1936747b715Smrg
19435c4bbdfSmrg    err = xp_create_window(mask, &wc, (xp_window_id *)&pFrame->wid);
1954642e01fSmrg
19635c4bbdfSmrg    if (err != Success) {
1974642e01fSmrg        return FALSE;
1984642e01fSmrg    }
1994642e01fSmrg
20035c4bbdfSmrg    dispatch_async(window_hash_serial_q, ^ {
20135c4bbdfSmrg                       x_hash_table_insert(window_hash, pFrame->wid, pFrame);
20235c4bbdfSmrg                   });
2034642e01fSmrg
2044642e01fSmrg    xprSetNativeProperty(pFrame);
2054642e01fSmrg
2064642e01fSmrg    return TRUE;
2074642e01fSmrg}
2084642e01fSmrg
2094642e01fSmrg/*
2104642e01fSmrg * Destroy a frame.
2114642e01fSmrg */
2126747b715Smrgstatic void
2134642e01fSmrgxprDestroyFrame(RootlessFrameID wid)
2144642e01fSmrg{
2156747b715Smrg    xp_error err;
21635c4bbdfSmrg
21735c4bbdfSmrg    dispatch_async(window_hash_serial_q, ^ {
21835c4bbdfSmrg                       x_hash_table_remove(window_hash, wid);
21935c4bbdfSmrg                   });
2204642e01fSmrg
2216747b715Smrg    err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
2226747b715Smrg    if (err != Success)
22335c4bbdfSmrg        FatalError("Could not destroy window %d (%d).",
22435c4bbdfSmrg                   (int)x_cvt_vptr_to_uint(
22535c4bbdfSmrg                       wid), (int)err);
2264642e01fSmrg}
2274642e01fSmrg
2284642e01fSmrg/*
2294642e01fSmrg * Move a frame on screen.
2304642e01fSmrg */
2316747b715Smrgstatic void
2324642e01fSmrgxprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
2334642e01fSmrg{
2344642e01fSmrg    xp_window_changes wc;
2354642e01fSmrg
2364642e01fSmrg    wc.x = newX;
2374642e01fSmrg    wc.y = newY;
2384642e01fSmrg    //    ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
2394642e01fSmrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
2404642e01fSmrg}
2414642e01fSmrg
2424642e01fSmrg/*
2434642e01fSmrg * Resize and move a frame.
2444642e01fSmrg */
2456747b715Smrgstatic void
2464642e01fSmrgxprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
2474642e01fSmrg               int newX, int newY, unsigned int newW, unsigned int newH,
2484642e01fSmrg               unsigned int gravity)
2494642e01fSmrg{
2504642e01fSmrg    xp_window_changes wc;
2514642e01fSmrg
2524642e01fSmrg    wc.x = newX;
2534642e01fSmrg    wc.y = newY;
2544642e01fSmrg    wc.width = newW;
2554642e01fSmrg    wc.height = newH;
2564642e01fSmrg    wc.bit_gravity = gravity;
2574642e01fSmrg
2584642e01fSmrg    /* It's unlikely that being async will save us anything here.
2594642e01fSmrg       But it can't hurt. */
2604642e01fSmrg
2614642e01fSmrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
2624642e01fSmrg}
2634642e01fSmrg
2644642e01fSmrg/*
2654642e01fSmrg * Change frame stacking.
2664642e01fSmrg */
26735c4bbdfSmrgstatic void
26835c4bbdfSmrgxprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
26935c4bbdfSmrg{
2704642e01fSmrg    xp_window_changes wc;
2716747b715Smrg    unsigned int mask = XP_STACKING;
27235c4bbdfSmrg    __block
27335c4bbdfSmrg    RootlessWindowRec * winRec;
2744642e01fSmrg
2756747b715Smrg    /* Stack frame below nextWid it if it exists, or raise
2764642e01fSmrg       frame above everything otherwise. */
2774642e01fSmrg
27835c4bbdfSmrg    if (nextWid == NULL) {
2794642e01fSmrg        wc.stack_mode = XP_MAPPED_ABOVE;
2804642e01fSmrg        wc.sibling = 0;
28135c4bbdfSmrg    }
28235c4bbdfSmrg    else {
2834642e01fSmrg        wc.stack_mode = XP_MAPPED_BELOW;
2844642e01fSmrg        wc.sibling = x_cvt_vptr_to_uint(nextWid);
2854642e01fSmrg    }
2864642e01fSmrg
28735c4bbdfSmrg    dispatch_sync(window_hash_serial_q, ^ {
28835c4bbdfSmrg                      winRec = x_hash_table_lookup(window_hash, wid, NULL);
28935c4bbdfSmrg                  });
29035c4bbdfSmrg
29135c4bbdfSmrg    if (winRec) {
29235c4bbdfSmrg        if (XQuartzIsRootless)
29335c4bbdfSmrg            wc.window_level = normal_window_levels[winRec->level];
29435c4bbdfSmrg        else if (XQuartzShieldingWindowLevel)
29535c4bbdfSmrg            wc.window_level = XQuartzShieldingWindowLevel + 1;
29635c4bbdfSmrg        else
29735c4bbdfSmrg            wc.window_level = rooted_window_levels[winRec->level];
29835c4bbdfSmrg        mask |= XP_WINDOW_LEVEL;
2996747b715Smrg    }
3006747b715Smrg
3016747b715Smrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
3024642e01fSmrg}
3034642e01fSmrg
3044642e01fSmrg/*
3054642e01fSmrg * Change the frame's shape.
3064642e01fSmrg */
3076747b715Smrgstatic void
3084642e01fSmrgxprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
3094642e01fSmrg{
3104642e01fSmrg    xp_window_changes wc;
3114642e01fSmrg
31235c4bbdfSmrg    if (pShape != NULL) {
3136747b715Smrg        wc.shape_nrects = RegionNumRects(pShape);
3146747b715Smrg        wc.shape_rects = RegionRects(pShape);
3154642e01fSmrg    }
31635c4bbdfSmrg    else {
3174642e01fSmrg        wc.shape_nrects = -1;
3184642e01fSmrg        wc.shape_rects = NULL;
3194642e01fSmrg    }
3204642e01fSmrg
3214642e01fSmrg    wc.shape_tx = wc.shape_ty = 0;
3224642e01fSmrg
3234642e01fSmrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
3244642e01fSmrg}
3254642e01fSmrg
3264642e01fSmrg/*
3274642e01fSmrg * Unmap a frame.
3284642e01fSmrg */
3296747b715Smrgstatic void
3304642e01fSmrgxprUnmapFrame(RootlessFrameID wid)
3314642e01fSmrg{
3324642e01fSmrg    xp_window_changes wc;
3334642e01fSmrg
3344642e01fSmrg    wc.stack_mode = XP_UNMAPPED;
3354642e01fSmrg    wc.sibling = 0;
3364642e01fSmrg
3374642e01fSmrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
3384642e01fSmrg}
3394642e01fSmrg
3404642e01fSmrg/*
3414642e01fSmrg * Start drawing to a frame.
3424642e01fSmrg *  Prepare for direct access to its backing buffer.
3434642e01fSmrg */
3446747b715Smrgstatic void
3454642e01fSmrgxprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
3464642e01fSmrg{
3474642e01fSmrg    void *data[2];
3484642e01fSmrg    unsigned int rowbytes[2];
3494642e01fSmrg    xp_error err;
3504642e01fSmrg
35135c4bbdfSmrg#ifdef DEBUG_XP_LOCK_WINDOW
35235c4bbdfSmrg    ErrorF("=== LOCK %d ===\n", (int)x_cvt_vptr_to_uint(wid));
353a1e1cf94Smrg    xorg_backtrace();
35435c4bbdfSmrg#endif
35535c4bbdfSmrg
35635c4bbdfSmrg    err = xp_lock_window(x_cvt_vptr_to_uint(
35735c4bbdfSmrg                             wid), NULL, NULL, data, rowbytes, NULL);
3584642e01fSmrg    if (err != Success)
35935c4bbdfSmrg        FatalError("Could not lock window %d for drawing (%d).",
36035c4bbdfSmrg                   (int)x_cvt_vptr_to_uint(
36135c4bbdfSmrg                       wid), (int)err);
3624642e01fSmrg
363a1e1cf94Smrg#ifdef DEBUG_XP_LOCK_WINDOW
364a1e1cf94Smrg    ErrorF("  bits: %p\n", *data);
365a1e1cf94Smrg#endif
366a1e1cf94Smrg
3674642e01fSmrg    *pixelData = data[0];
3684642e01fSmrg    *bytesPerRow = rowbytes[0];
3694642e01fSmrg}
3704642e01fSmrg
3714642e01fSmrg/*
3724642e01fSmrg * Stop drawing to a frame.
3734642e01fSmrg */
3746747b715Smrgstatic void
3754642e01fSmrgxprStopDrawing(RootlessFrameID wid, Bool flush)
3764642e01fSmrg{
3776747b715Smrg    xp_error err;
37835c4bbdfSmrg
37935c4bbdfSmrg#ifdef DEBUG_XP_LOCK_WINDOW
38035c4bbdfSmrg    ErrorF("=== UNLOCK %d ===\n", (int)x_cvt_vptr_to_uint(wid));
381a1e1cf94Smrg    xorg_backtrace();
38235c4bbdfSmrg#endif
38335c4bbdfSmrg
3846747b715Smrg    err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
385475c125cSmrg    /* This should be a FatalError, but we started tripping over it.  Make it a
386475c125cSmrg     * FatalError after http://xquartz.macosforge.org/trac/ticket/482 is fixed.
387475c125cSmrg     */
38835c4bbdfSmrg    if (err != Success)
38935c4bbdfSmrg        ErrorF("Could not unlock window %d after drawing (%d).",
39035c4bbdfSmrg               (int)x_cvt_vptr_to_uint(
39135c4bbdfSmrg                   wid), (int)err);
3924642e01fSmrg}
3934642e01fSmrg
3944642e01fSmrg/*
3954642e01fSmrg * Flush drawing updates to the screen.
3964642e01fSmrg */
3976747b715Smrgstatic void
3984642e01fSmrgxprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
3994642e01fSmrg{
4004642e01fSmrg    xp_flush_window(x_cvt_vptr_to_uint(wid));
4014642e01fSmrg}
4024642e01fSmrg
4034642e01fSmrg/*
4044642e01fSmrg * Mark damaged rectangles as requiring redisplay to screen.
4054642e01fSmrg */
4066747b715Smrgstatic void
4074642e01fSmrgxprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
4084642e01fSmrg               int shift_x, int shift_y)
4094642e01fSmrg{
4104642e01fSmrg    xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
4114642e01fSmrg}
4124642e01fSmrg
4134642e01fSmrg/*
4144642e01fSmrg * Called after the window associated with a frame has been switched
4154642e01fSmrg * to a new top-level parent.
4164642e01fSmrg */
4176747b715Smrgstatic void
4184642e01fSmrgxprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
4194642e01fSmrg{
4204642e01fSmrg    DeleteProperty(serverClient, oldWin, xa_native_window_id());
4214642e01fSmrg
4224642e01fSmrg    xprSetNativeProperty(pFrame);
4234642e01fSmrg}
4244642e01fSmrg
4254642e01fSmrg/*
4264642e01fSmrg * Called to check if the frame should be reordered when it is restacked.
4274642e01fSmrg */
42835c4bbdfSmrgstatic Bool
42935c4bbdfSmrgxprDoReorderWindow(RootlessWindowPtr pFrame)
4304642e01fSmrg{
4314642e01fSmrg    WindowPtr pWin = pFrame->win;
4324642e01fSmrg
4334642e01fSmrg    return AppleWMDoReorderWindow(pWin);
4344642e01fSmrg}
4354642e01fSmrg
4364642e01fSmrg/*
4374642e01fSmrg * Copy area in frame to another part of frame.
4384642e01fSmrg *  Used to accelerate scrolling.
4394642e01fSmrg */
4406747b715Smrgstatic void
4414642e01fSmrgxprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
4424642e01fSmrg              int dx, int dy)
4434642e01fSmrg{
4444642e01fSmrg    xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
4454642e01fSmrg                   dstNrects, dstRects, dx, dy);
4464642e01fSmrg}
4474642e01fSmrg
4484642e01fSmrgstatic RootlessFrameProcsRec xprRootlessProcs = {
4494642e01fSmrg    xprCreateFrame,
4504642e01fSmrg    xprDestroyFrame,
4514642e01fSmrg    xprMoveFrame,
4524642e01fSmrg    xprResizeFrame,
4534642e01fSmrg    xprRestackFrame,
4544642e01fSmrg    xprReshapeFrame,
4554642e01fSmrg    xprUnmapFrame,
4564642e01fSmrg    xprStartDrawing,
4574642e01fSmrg    xprStopDrawing,
4584642e01fSmrg    xprUpdateRegion,
4594642e01fSmrg    xprDamageRects,
4604642e01fSmrg    xprSwitchWindow,
4614642e01fSmrg    xprDoReorderWindow,
4626747b715Smrg    xprHideWindow,
4636747b715Smrg    xprUpdateColormap,
4644642e01fSmrg    xp_copy_bytes,
4654642e01fSmrg    xprCopyWindow
4664642e01fSmrg};
4674642e01fSmrg
4684642e01fSmrg/*
4694642e01fSmrg * Initialize XPR implementation
4704642e01fSmrg */
4714642e01fSmrgBool
4724642e01fSmrgxprInit(ScreenPtr pScreen)
4734642e01fSmrg{
4744642e01fSmrg    RootlessInit(pScreen, &xprRootlessProcs);
4754642e01fSmrg
4764642e01fSmrg    rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
4774642e01fSmrg    rootless_CopyWindow_threshold = xp_scroll_area_threshold;
4784642e01fSmrg
47935c4bbdfSmrg    assert((window_hash = x_hash_table_new(NULL, NULL, NULL, NULL)));
48035c4bbdfSmrg    assert((window_hash_serial_q =
48135c4bbdfSmrg                dispatch_queue_create(BUNDLE_ID_PREFIX ".X11.xpr_window_hash",
48235c4bbdfSmrg                                      NULL)));
48335c4bbdfSmrg
4844642e01fSmrg    return TRUE;
4854642e01fSmrg}
4864642e01fSmrg
4874642e01fSmrg/*
4884642e01fSmrg * Given the id of a physical window, try to find the top-level (or root)
4894642e01fSmrg * X window that it represents.
4904642e01fSmrg */
4914642e01fSmrgWindowPtr
4924642e01fSmrgxprGetXWindow(xp_window_id wid)
4934642e01fSmrg{
49435c4bbdfSmrg    RootlessWindowRec *winRec __block;
49535c4bbdfSmrg    dispatch_sync(window_hash_serial_q, ^ {
49635c4bbdfSmrg                      winRec =
49735c4bbdfSmrg                          x_hash_table_lookup(window_hash,
49835c4bbdfSmrg                                              x_cvt_uint_to_vptr(wid), NULL);
49935c4bbdfSmrg                  });
5004642e01fSmrg
5014642e01fSmrg    return winRec != NULL ? winRec->win : NULL;
5024642e01fSmrg}
5034642e01fSmrg
5044642e01fSmrg/*
5054642e01fSmrg * The windowNumber is an AppKit window number. Returns TRUE if xpr is
5064642e01fSmrg * displaying a window with that number.
5074642e01fSmrg */
5084642e01fSmrgBool
50935c4bbdfSmrgxprIsX11Window(int windowNumber)
5104642e01fSmrg{
5114642e01fSmrg    Bool ret;
5124642e01fSmrg    xp_window_id wid;
5134642e01fSmrg
5144642e01fSmrg    if (xp_lookup_native_window(windowNumber, &wid))
5154642e01fSmrg        ret = xprGetXWindow(wid) != NULL;
5164642e01fSmrg    else
5174642e01fSmrg        ret = FALSE;
5184642e01fSmrg
5194642e01fSmrg    return ret;
5204642e01fSmrg}
5214642e01fSmrg
5224642e01fSmrg/*
5234642e01fSmrg * xprHideWindows
5244642e01fSmrg *  Hide or unhide all top level windows. This is called for application hide/
5254642e01fSmrg *  unhide events if the window manager is not Apple-WM aware. Xplugin windows
5264642e01fSmrg *  do not hide or unhide themselves.
5274642e01fSmrg */
5284642e01fSmrgvoid
5294642e01fSmrgxprHideWindows(Bool hide)
5304642e01fSmrg{
5314642e01fSmrg    int screen;
5324642e01fSmrg    WindowPtr pRoot, pWin;
5334642e01fSmrg
5344642e01fSmrg    for (screen = 0; screen < screenInfo.numScreens; screen++) {
5354642e01fSmrg        RootlessFrameID prevWid = NULL;
5366747b715Smrg        pRoot = screenInfo.screens[screen]->root;
5374642e01fSmrg
5384642e01fSmrg        for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
5394642e01fSmrg            RootlessWindowRec *winRec = WINREC(pWin);
5404642e01fSmrg
5414642e01fSmrg            if (winRec != NULL) {
5424642e01fSmrg                if (hide) {
5434642e01fSmrg                    xprUnmapFrame(winRec->wid);
54435c4bbdfSmrg                }
54535c4bbdfSmrg                else {
5464642e01fSmrg                    BoxRec box;
5474642e01fSmrg
5484642e01fSmrg                    xprRestackFrame(winRec->wid, prevWid);
5494642e01fSmrg                    prevWid = winRec->wid;
5504642e01fSmrg
5514642e01fSmrg                    box.x1 = 0;
5524642e01fSmrg                    box.y1 = 0;
5534642e01fSmrg                    box.x2 = winRec->width;
5544642e01fSmrg                    box.y2 = winRec->height;
5554642e01fSmrg
5564642e01fSmrg                    xprDamageRects(winRec->wid, 1, &box, 0, 0);
5574642e01fSmrg                    RootlessQueueRedisplay(screenInfo.screens[screen]);
5584642e01fSmrg                }
5594642e01fSmrg            }
5604642e01fSmrg        }
5614642e01fSmrg    }
5624642e01fSmrg}
5636747b715Smrg
5646747b715Smrg// XXX: identical to x_cvt_vptr_to_uint ?
56535c4bbdfSmrg#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
5666747b715Smrg
5676747b715SmrgBool no_configure_window;
5686747b715Smrg
5696747b715Smrgstatic inline int
57035c4bbdfSmrgconfigure_window(xp_window_id id, unsigned int mask,
57135c4bbdfSmrg                 const xp_window_changes *values)
5726747b715Smrg{
57335c4bbdfSmrg    if (!no_configure_window)
57435c4bbdfSmrg        return xp_configure_window(id, mask, values);
57535c4bbdfSmrg    else
57635c4bbdfSmrg        return XP_Success;
5776747b715Smrg}
5786747b715Smrg
5796747b715Smrgstatic
58035c4bbdfSmrgvoid
58135c4bbdfSmrgxprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
5826747b715Smrg{
58335c4bbdfSmrg    /* This is how we tell xp that the colormap may have changed. */
58435c4bbdfSmrg    xp_window_changes wc;
58535c4bbdfSmrg    wc.colormap = xprColormapCallback;
58635c4bbdfSmrg    wc.colormap_data = pScreen;
5876747b715Smrg
58835c4bbdfSmrg    configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
5896747b715Smrg}
5906747b715Smrg
5916747b715Smrgstatic
59235c4bbdfSmrgvoid
59335c4bbdfSmrgxprHideWindow(RootlessFrameID wid)
5946747b715Smrg{
59535c4bbdfSmrg    xp_window_changes wc;
59635c4bbdfSmrg    wc.stack_mode = XP_UNMAPPED;
59735c4bbdfSmrg    wc.sibling = 0;
59835c4bbdfSmrg    configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
5996747b715Smrg}
600