1706f2543Smrg/*
2706f2543Smrg * Xplugin rootless implementation frame functions
3706f2543Smrg *
4706f2543Smrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
5706f2543Smrg * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
6706f2543Smrg *
7706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8706f2543Smrg * copy of this software and associated documentation files (the "Software"),
9706f2543Smrg * to deal in the Software without restriction, including without limitation
10706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
12706f2543Smrg * Software is furnished to do so, subject to the following conditions:
13706f2543Smrg *
14706f2543Smrg * The above copyright notice and this permission notice shall be included in
15706f2543Smrg * all copies or substantial portions of the Software.
16706f2543Smrg *
17706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23706f2543Smrg * DEALINGS IN THE SOFTWARE.
24706f2543Smrg *
25706f2543Smrg * Except as contained in this notice, the name(s) of the above copyright
26706f2543Smrg * holders shall not be used in advertising or otherwise to promote the sale,
27706f2543Smrg * use or other dealings in this Software without prior written authorization.
28706f2543Smrg */
29706f2543Smrg
30706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
31706f2543Smrg#include <dix-config.h>
32706f2543Smrg#endif
33706f2543Smrg
34706f2543Smrg#include "xpr.h"
35706f2543Smrg#include "rootlessCommon.h"
36706f2543Smrg#include <Xplugin.h>
37706f2543Smrg#include "x-hash.h"
38706f2543Smrg#include "x-list.h"
39706f2543Smrg#include "applewmExt.h"
40706f2543Smrg
41706f2543Smrg#include "propertyst.h"
42706f2543Smrg#include "dix.h"
43706f2543Smrg#include <X11/Xatom.h>
44706f2543Smrg#include "windowstr.h"
45706f2543Smrg#include "quartz.h"
46706f2543Smrg
47706f2543Smrg#include "threadSafety.h"
48706f2543Smrg
49706f2543Smrg#include <pthread.h>
50706f2543Smrg
51706f2543Smrg#define DEFINE_ATOM_HELPER(func,atom_name)                      \
52706f2543Smrgstatic Atom func (void) {                                       \
53706f2543Smrg    static int generation;                                      \
54706f2543Smrg    static Atom atom;                                           \
55706f2543Smrg    if (generation != serverGeneration) {                       \
56706f2543Smrg        generation = serverGeneration;                          \
57706f2543Smrg        atom = MakeAtom (atom_name, strlen (atom_name), TRUE);  \
58706f2543Smrg    }                                                           \
59706f2543Smrg    return atom;                                                \
60706f2543Smrg}
61706f2543Smrg
62706f2543SmrgDEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
63706f2543Smrg
64706f2543Smrg/* Maps xp_window_id -> RootlessWindowRec */
65706f2543Smrgstatic x_hash_table *window_hash;
66706f2543Smrgstatic pthread_mutex_t window_hash_mutex;
67706f2543Smrg
68706f2543Smrg/* Prototypes for static functions */
69706f2543Smrgstatic Bool xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
70706f2543Smrg               int newX, int newY, RegionPtr pShape);
71706f2543Smrgstatic void xprDestroyFrame(RootlessFrameID wid);
72706f2543Smrgstatic void xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
73706f2543Smrgstatic void xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
74706f2543Smrg               int newX, int newY, unsigned int newW, unsigned int newH,
75706f2543Smrg               unsigned int gravity);
76706f2543Smrgstatic void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
77706f2543Smrgstatic void xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
78706f2543Smrgstatic void xprUnmapFrame(RootlessFrameID wid);
79706f2543Smrgstatic void xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
80706f2543Smrgstatic void xprStopDrawing(RootlessFrameID wid, Bool flush);
81706f2543Smrgstatic void xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
82706f2543Smrgstatic void xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
83706f2543Smrg               int shift_x, int shift_y);
84706f2543Smrgstatic void xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
85706f2543Smrgstatic Bool xprDoReorderWindow(RootlessWindowPtr pFrame);
86706f2543Smrgstatic void xprHideWindow(RootlessFrameID wid);
87706f2543Smrgstatic void xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
88706f2543Smrgstatic void xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
89706f2543Smrg              int dx, int dy);
90706f2543Smrg
91706f2543Smrg
92706f2543Smrgstatic inline xp_error
93706f2543SmrgxprConfigureWindow(xp_window_id id, unsigned int mask,
94706f2543Smrg                   const xp_window_changes *values)
95706f2543Smrg{
96706f2543Smrg    TA_SERVER();
97706f2543Smrg
98706f2543Smrg    return xp_configure_window(id, mask, values);
99706f2543Smrg}
100706f2543Smrg
101706f2543Smrg
102706f2543Smrgstatic void
103706f2543SmrgxprSetNativeProperty(RootlessWindowPtr pFrame)
104706f2543Smrg{
105706f2543Smrg    xp_error err;
106706f2543Smrg    unsigned int native_id;
107706f2543Smrg    long data;
108706f2543Smrg
109706f2543Smrg    TA_SERVER();
110706f2543Smrg
111706f2543Smrg    err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
112706f2543Smrg    if (err == Success)
113706f2543Smrg    {
114706f2543Smrg        /* FIXME: move this to AppleWM extension */
115706f2543Smrg
116706f2543Smrg        data = native_id;
117706f2543Smrg        dixChangeWindowProperty(serverClient, pFrame->win, xa_native_window_id(),
118706f2543Smrg				XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
119706f2543Smrg    }
120706f2543Smrg}
121706f2543Smrg
122706f2543Smrgstatic xp_error
123706f2543SmrgxprColormapCallback(void *data, int first_color, int n_colors, uint32_t *colors)
124706f2543Smrg{
125706f2543Smrg    return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch);
126706f2543Smrg}
127706f2543Smrg
128706f2543Smrg/*
129706f2543Smrg * Create and display a new frame.
130706f2543Smrg */
131706f2543Smrgstatic Bool
132706f2543SmrgxprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
133706f2543Smrg               int newX, int newY, RegionPtr pShape)
134706f2543Smrg{
135706f2543Smrg    WindowPtr pWin = pFrame->win;
136706f2543Smrg    xp_window_changes wc;
137706f2543Smrg    unsigned int mask = 0;
138706f2543Smrg    xp_error err;
139706f2543Smrg
140706f2543Smrg    TA_SERVER();
141706f2543Smrg
142706f2543Smrg    wc.x = newX;
143706f2543Smrg    wc.y = newY;
144706f2543Smrg    wc.width = pFrame->width;
145706f2543Smrg    wc.height = pFrame->height;
146706f2543Smrg    wc.bit_gravity = XP_GRAVITY_NONE;
147706f2543Smrg    mask |= XP_BOUNDS;
148706f2543Smrg
149706f2543Smrg    if (pWin->drawable.depth == 8)
150706f2543Smrg    {
151706f2543Smrg        wc.depth = XP_DEPTH_INDEX8;
152706f2543Smrg        wc.colormap = xprColormapCallback;
153706f2543Smrg        wc.colormap_data = pScreen;
154706f2543Smrg        mask |= XP_COLORMAP;
155706f2543Smrg    }
156706f2543Smrg    else if (pWin->drawable.depth == 15)
157706f2543Smrg        wc.depth = XP_DEPTH_RGB555;
158706f2543Smrg    else if (pWin->drawable.depth == 24)
159706f2543Smrg        wc.depth = XP_DEPTH_ARGB8888;
160706f2543Smrg    else
161706f2543Smrg        wc.depth = XP_DEPTH_NIL;
162706f2543Smrg    mask |= XP_DEPTH;
163706f2543Smrg
164706f2543Smrg    if (pShape != NULL)
165706f2543Smrg    {
166706f2543Smrg        wc.shape_nrects = RegionNumRects(pShape);
167706f2543Smrg        wc.shape_rects = RegionRects(pShape);
168706f2543Smrg        wc.shape_tx = wc.shape_ty = 0;
169706f2543Smrg        mask |= XP_SHAPE;
170706f2543Smrg    }
171706f2543Smrg
172706f2543Smrg    pFrame->level = !IsRoot (pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
173706f2543Smrg
174706f2543Smrg    if(XQuartzIsRootless)
175706f2543Smrg        wc.window_level = normal_window_levels[pFrame->level];
176706f2543Smrg    else if(XQuartzShieldingWindowLevel)
177706f2543Smrg        wc.window_level = XQuartzShieldingWindowLevel + 1;
178706f2543Smrg    else
179706f2543Smrg        wc.window_level = rooted_window_levels[pFrame->level];
180706f2543Smrg    mask |= XP_WINDOW_LEVEL;
181706f2543Smrg
182706f2543Smrg    err = xp_create_window(mask, &wc, (xp_window_id *) &pFrame->wid);
183706f2543Smrg
184706f2543Smrg    if (err != Success)
185706f2543Smrg    {
186706f2543Smrg        return FALSE;
187706f2543Smrg    }
188706f2543Smrg
189706f2543Smrg    if (window_hash == NULL)
190706f2543Smrg    {
191706f2543Smrg        window_hash = x_hash_table_new(NULL, NULL, NULL, NULL);
192706f2543Smrg        pthread_mutex_init(&window_hash_mutex, NULL);
193706f2543Smrg    }
194706f2543Smrg
195706f2543Smrg    pthread_mutex_lock(&window_hash_mutex);
196706f2543Smrg    x_hash_table_insert(window_hash, pFrame->wid, pFrame);
197706f2543Smrg    pthread_mutex_unlock(&window_hash_mutex);
198706f2543Smrg
199706f2543Smrg    xprSetNativeProperty(pFrame);
200706f2543Smrg
201706f2543Smrg    return TRUE;
202706f2543Smrg}
203706f2543Smrg
204706f2543Smrg
205706f2543Smrg/*
206706f2543Smrg * Destroy a frame.
207706f2543Smrg */
208706f2543Smrgstatic void
209706f2543SmrgxprDestroyFrame(RootlessFrameID wid)
210706f2543Smrg{
211706f2543Smrg    xp_error err;
212706f2543Smrg    TA_SERVER();
213706f2543Smrg
214706f2543Smrg    pthread_mutex_lock(&window_hash_mutex);
215706f2543Smrg    x_hash_table_remove(window_hash, wid);
216706f2543Smrg    pthread_mutex_unlock(&window_hash_mutex);
217706f2543Smrg
218706f2543Smrg    err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
219706f2543Smrg    if (err != Success)
220706f2543Smrg        FatalError("Could not destroy window %d (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
221706f2543Smrg}
222706f2543Smrg
223706f2543Smrg
224706f2543Smrg/*
225706f2543Smrg * Move a frame on screen.
226706f2543Smrg */
227706f2543Smrgstatic void
228706f2543SmrgxprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
229706f2543Smrg{
230706f2543Smrg    xp_window_changes wc;
231706f2543Smrg
232706f2543Smrg    TA_SERVER();
233706f2543Smrg
234706f2543Smrg    wc.x = newX;
235706f2543Smrg    wc.y = newY;
236706f2543Smrg    //    ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
237706f2543Smrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
238706f2543Smrg}
239706f2543Smrg
240706f2543Smrg
241706f2543Smrg/*
242706f2543Smrg * Resize and move a frame.
243706f2543Smrg */
244706f2543Smrgstatic void
245706f2543SmrgxprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
246706f2543Smrg               int newX, int newY, unsigned int newW, unsigned int newH,
247706f2543Smrg               unsigned int gravity)
248706f2543Smrg{
249706f2543Smrg    xp_window_changes wc;
250706f2543Smrg
251706f2543Smrg    TA_SERVER();
252706f2543Smrg
253706f2543Smrg    wc.x = newX;
254706f2543Smrg    wc.y = newY;
255706f2543Smrg    wc.width = newW;
256706f2543Smrg    wc.height = newH;
257706f2543Smrg    wc.bit_gravity = gravity;
258706f2543Smrg
259706f2543Smrg    /* It's unlikely that being async will save us anything here.
260706f2543Smrg       But it can't hurt. */
261706f2543Smrg
262706f2543Smrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
263706f2543Smrg}
264706f2543Smrg
265706f2543Smrg
266706f2543Smrg/*
267706f2543Smrg * Change frame stacking.
268706f2543Smrg */
269706f2543Smrgstatic void xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid) {
270706f2543Smrg    xp_window_changes wc;
271706f2543Smrg    unsigned int mask = XP_STACKING;
272706f2543Smrg
273706f2543Smrg    TA_SERVER();
274706f2543Smrg
275706f2543Smrg    /* Stack frame below nextWid it if it exists, or raise
276706f2543Smrg       frame above everything otherwise. */
277706f2543Smrg
278706f2543Smrg    if(nextWid == NULL) {
279706f2543Smrg        wc.stack_mode = XP_MAPPED_ABOVE;
280706f2543Smrg        wc.sibling = 0;
281706f2543Smrg    } else {
282706f2543Smrg        wc.stack_mode = XP_MAPPED_BELOW;
283706f2543Smrg        wc.sibling = x_cvt_vptr_to_uint(nextWid);
284706f2543Smrg    }
285706f2543Smrg
286706f2543Smrg    if(window_hash) {
287706f2543Smrg        RootlessWindowRec *winRec = x_hash_table_lookup(window_hash, wid, NULL);
288706f2543Smrg
289706f2543Smrg        if(winRec) {
290706f2543Smrg            if(XQuartzIsRootless)
291706f2543Smrg                wc.window_level = normal_window_levels[winRec->level];
292706f2543Smrg            else if(XQuartzShieldingWindowLevel)
293706f2543Smrg                wc.window_level = XQuartzShieldingWindowLevel + 1;
294706f2543Smrg            else
295706f2543Smrg                wc.window_level = rooted_window_levels[winRec->level];
296706f2543Smrg            mask |= XP_WINDOW_LEVEL;
297706f2543Smrg        }
298706f2543Smrg    }
299706f2543Smrg
300706f2543Smrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
301706f2543Smrg}
302706f2543Smrg
303706f2543Smrg
304706f2543Smrg/*
305706f2543Smrg * Change the frame's shape.
306706f2543Smrg */
307706f2543Smrgstatic void
308706f2543SmrgxprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
309706f2543Smrg{
310706f2543Smrg    xp_window_changes wc;
311706f2543Smrg
312706f2543Smrg    TA_SERVER();
313706f2543Smrg
314706f2543Smrg    if (pShape != NULL)
315706f2543Smrg    {
316706f2543Smrg        wc.shape_nrects = RegionNumRects(pShape);
317706f2543Smrg        wc.shape_rects = RegionRects(pShape);
318706f2543Smrg    }
319706f2543Smrg    else
320706f2543Smrg    {
321706f2543Smrg        wc.shape_nrects = -1;
322706f2543Smrg        wc.shape_rects = NULL;
323706f2543Smrg    }
324706f2543Smrg
325706f2543Smrg    wc.shape_tx = wc.shape_ty = 0;
326706f2543Smrg
327706f2543Smrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
328706f2543Smrg}
329706f2543Smrg
330706f2543Smrg
331706f2543Smrg/*
332706f2543Smrg * Unmap a frame.
333706f2543Smrg */
334706f2543Smrgstatic void
335706f2543SmrgxprUnmapFrame(RootlessFrameID wid)
336706f2543Smrg{
337706f2543Smrg    xp_window_changes wc;
338706f2543Smrg
339706f2543Smrg    TA_SERVER();
340706f2543Smrg
341706f2543Smrg    wc.stack_mode = XP_UNMAPPED;
342706f2543Smrg    wc.sibling = 0;
343706f2543Smrg
344706f2543Smrg    xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
345706f2543Smrg}
346706f2543Smrg
347706f2543Smrg
348706f2543Smrg/*
349706f2543Smrg * Start drawing to a frame.
350706f2543Smrg *  Prepare for direct access to its backing buffer.
351706f2543Smrg */
352706f2543Smrgstatic void
353706f2543SmrgxprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
354706f2543Smrg{
355706f2543Smrg    void *data[2];
356706f2543Smrg    unsigned int rowbytes[2];
357706f2543Smrg    xp_error err;
358706f2543Smrg
359706f2543Smrg    TA_SERVER();
360706f2543Smrg
361706f2543Smrg    err = xp_lock_window(x_cvt_vptr_to_uint(wid), NULL, NULL, data, rowbytes, NULL);
362706f2543Smrg    if (err != Success)
363706f2543Smrg        FatalError("Could not lock window %d for drawing (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
364706f2543Smrg
365706f2543Smrg    *pixelData = data[0];
366706f2543Smrg    *bytesPerRow = rowbytes[0];
367706f2543Smrg}
368706f2543Smrg
369706f2543Smrg
370706f2543Smrg/*
371706f2543Smrg * Stop drawing to a frame.
372706f2543Smrg */
373706f2543Smrgstatic void
374706f2543SmrgxprStopDrawing(RootlessFrameID wid, Bool flush)
375706f2543Smrg{
376706f2543Smrg    xp_error err;
377706f2543Smrg    TA_SERVER();
378706f2543Smrg
379706f2543Smrg    err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
380706f2543Smrg    /* This should be a FatalError, but we started tripping over it.  Make it a
381706f2543Smrg     * FatalError after http://xquartz.macosforge.org/trac/ticket/482 is fixed.
382706f2543Smrg     */
383706f2543Smrg    if(err != Success)
384706f2543Smrg        ErrorF("Could not unlock window %d after drawing (%d).", (int)x_cvt_vptr_to_uint(wid), (int)err);
385706f2543Smrg}
386706f2543Smrg
387706f2543Smrg
388706f2543Smrg/*
389706f2543Smrg * Flush drawing updates to the screen.
390706f2543Smrg */
391706f2543Smrgstatic void
392706f2543SmrgxprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
393706f2543Smrg{
394706f2543Smrg    TA_SERVER();
395706f2543Smrg
396706f2543Smrg    xp_flush_window(x_cvt_vptr_to_uint(wid));
397706f2543Smrg}
398706f2543Smrg
399706f2543Smrg
400706f2543Smrg/*
401706f2543Smrg * Mark damaged rectangles as requiring redisplay to screen.
402706f2543Smrg */
403706f2543Smrgstatic void
404706f2543SmrgxprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
405706f2543Smrg               int shift_x, int shift_y)
406706f2543Smrg{
407706f2543Smrg    TA_SERVER();
408706f2543Smrg
409706f2543Smrg    xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
410706f2543Smrg}
411706f2543Smrg
412706f2543Smrg
413706f2543Smrg/*
414706f2543Smrg * Called after the window associated with a frame has been switched
415706f2543Smrg * to a new top-level parent.
416706f2543Smrg */
417706f2543Smrgstatic void
418706f2543SmrgxprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
419706f2543Smrg{
420706f2543Smrg    DeleteProperty(serverClient, oldWin, xa_native_window_id());
421706f2543Smrg
422706f2543Smrg    TA_SERVER();
423706f2543Smrg
424706f2543Smrg    xprSetNativeProperty(pFrame);
425706f2543Smrg}
426706f2543Smrg
427706f2543Smrg
428706f2543Smrg/*
429706f2543Smrg * Called to check if the frame should be reordered when it is restacked.
430706f2543Smrg */
431706f2543Smrgstatic Bool xprDoReorderWindow(RootlessWindowPtr pFrame)
432706f2543Smrg{
433706f2543Smrg    WindowPtr pWin = pFrame->win;
434706f2543Smrg
435706f2543Smrg    TA_SERVER();
436706f2543Smrg
437706f2543Smrg    return AppleWMDoReorderWindow(pWin);
438706f2543Smrg}
439706f2543Smrg
440706f2543Smrg
441706f2543Smrg/*
442706f2543Smrg * Copy area in frame to another part of frame.
443706f2543Smrg *  Used to accelerate scrolling.
444706f2543Smrg */
445706f2543Smrgstatic void
446706f2543SmrgxprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
447706f2543Smrg              int dx, int dy)
448706f2543Smrg{
449706f2543Smrg    TA_SERVER();
450706f2543Smrg
451706f2543Smrg    xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
452706f2543Smrg                   dstNrects, dstRects, dx, dy);
453706f2543Smrg}
454706f2543Smrg
455706f2543Smrg
456706f2543Smrgstatic RootlessFrameProcsRec xprRootlessProcs = {
457706f2543Smrg    xprCreateFrame,
458706f2543Smrg    xprDestroyFrame,
459706f2543Smrg    xprMoveFrame,
460706f2543Smrg    xprResizeFrame,
461706f2543Smrg    xprRestackFrame,
462706f2543Smrg    xprReshapeFrame,
463706f2543Smrg    xprUnmapFrame,
464706f2543Smrg    xprStartDrawing,
465706f2543Smrg    xprStopDrawing,
466706f2543Smrg    xprUpdateRegion,
467706f2543Smrg    xprDamageRects,
468706f2543Smrg    xprSwitchWindow,
469706f2543Smrg    xprDoReorderWindow,
470706f2543Smrg    xprHideWindow,
471706f2543Smrg    xprUpdateColormap,
472706f2543Smrg    xp_copy_bytes,
473706f2543Smrg    xprCopyWindow
474706f2543Smrg};
475706f2543Smrg
476706f2543Smrg
477706f2543Smrg/*
478706f2543Smrg * Initialize XPR implementation
479706f2543Smrg */
480706f2543SmrgBool
481706f2543SmrgxprInit(ScreenPtr pScreen)
482706f2543Smrg{
483706f2543Smrg    RootlessInit(pScreen, &xprRootlessProcs);
484706f2543Smrg
485706f2543Smrg    TA_SERVER();
486706f2543Smrg
487706f2543Smrg    rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
488706f2543Smrg    rootless_CopyWindow_threshold = xp_scroll_area_threshold;
489706f2543Smrg
490706f2543Smrg    return TRUE;
491706f2543Smrg}
492706f2543Smrg
493706f2543Smrg
494706f2543Smrg/*
495706f2543Smrg * Given the id of a physical window, try to find the top-level (or root)
496706f2543Smrg * X window that it represents.
497706f2543Smrg */
498706f2543SmrgWindowPtr
499706f2543SmrgxprGetXWindow(xp_window_id wid)
500706f2543Smrg{
501706f2543Smrg    RootlessWindowRec *winRec;
502706f2543Smrg
503706f2543Smrg    if (window_hash == NULL)
504706f2543Smrg        return NULL;
505706f2543Smrg
506706f2543Smrg    winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
507706f2543Smrg
508706f2543Smrg    return winRec != NULL ? winRec->win : NULL;
509706f2543Smrg}
510706f2543Smrg
511706f2543Smrg#ifdef UNUSED_CODE
512706f2543Smrg/*
513706f2543Smrg * Given the id of a physical window, try to find the top-level (or root)
514706f2543Smrg * X window that it represents.
515706f2543Smrg */
516706f2543SmrgWindowPtr
517706f2543SmrgxprGetXWindowFromAppKit(int windowNumber)
518706f2543Smrg{
519706f2543Smrg    RootlessWindowRec *winRec;
520706f2543Smrg    Bool ret;
521706f2543Smrg    xp_window_id wid;
522706f2543Smrg
523706f2543Smrg    if (window_hash == NULL)
524706f2543Smrg        return FALSE;
525706f2543Smrg
526706f2543Smrg    /* need to lock, since this function can be called by any thread */
527706f2543Smrg
528706f2543Smrg    pthread_mutex_lock(&window_hash_mutex);
529706f2543Smrg
530706f2543Smrg    if (xp_lookup_native_window(windowNumber, &wid))
531706f2543Smrg        ret = xprGetXWindow(wid) != NULL;
532706f2543Smrg    else
533706f2543Smrg        ret = FALSE;
534706f2543Smrg
535706f2543Smrg    pthread_mutex_unlock(&window_hash_mutex);
536706f2543Smrg
537706f2543Smrg    if (!ret) return NULL;
538706f2543Smrg    winRec = x_hash_table_lookup(window_hash, x_cvt_uint_to_vptr(wid), NULL);
539706f2543Smrg
540706f2543Smrg    return winRec != NULL ? winRec->win : NULL;
541706f2543Smrg}
542706f2543Smrg#endif
543706f2543Smrg
544706f2543Smrg/*
545706f2543Smrg * The windowNumber is an AppKit window number. Returns TRUE if xpr is
546706f2543Smrg * displaying a window with that number.
547706f2543Smrg */
548706f2543SmrgBool
549706f2543SmrgxprIsX11Window(void *nsWindow, int windowNumber)
550706f2543Smrg{
551706f2543Smrg    Bool ret;
552706f2543Smrg    xp_window_id wid;
553706f2543Smrg
554706f2543Smrg    if (window_hash == NULL)
555706f2543Smrg        return FALSE;
556706f2543Smrg
557706f2543Smrg    /* need to lock, since this function can be called by any thread */
558706f2543Smrg
559706f2543Smrg    pthread_mutex_lock(&window_hash_mutex);
560706f2543Smrg
561706f2543Smrg    if (xp_lookup_native_window(windowNumber, &wid))
562706f2543Smrg        ret = xprGetXWindow(wid) != NULL;
563706f2543Smrg    else
564706f2543Smrg        ret = FALSE;
565706f2543Smrg
566706f2543Smrg    pthread_mutex_unlock(&window_hash_mutex);
567706f2543Smrg
568706f2543Smrg    return ret;
569706f2543Smrg}
570706f2543Smrg
571706f2543Smrg
572706f2543Smrg/*
573706f2543Smrg * xprHideWindows
574706f2543Smrg *  Hide or unhide all top level windows. This is called for application hide/
575706f2543Smrg *  unhide events if the window manager is not Apple-WM aware. Xplugin windows
576706f2543Smrg *  do not hide or unhide themselves.
577706f2543Smrg */
578706f2543Smrgvoid
579706f2543SmrgxprHideWindows(Bool hide)
580706f2543Smrg{
581706f2543Smrg    int screen;
582706f2543Smrg    WindowPtr pRoot, pWin;
583706f2543Smrg
584706f2543Smrg    TA_SERVER();
585706f2543Smrg
586706f2543Smrg    for (screen = 0; screen < screenInfo.numScreens; screen++) {
587706f2543Smrg        RootlessFrameID prevWid = NULL;
588706f2543Smrg        pRoot = screenInfo.screens[screen]->root;
589706f2543Smrg
590706f2543Smrg        for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
591706f2543Smrg            RootlessWindowRec *winRec = WINREC(pWin);
592706f2543Smrg
593706f2543Smrg            if (winRec != NULL) {
594706f2543Smrg                if (hide) {
595706f2543Smrg                    xprUnmapFrame(winRec->wid);
596706f2543Smrg                } else {
597706f2543Smrg                    BoxRec box;
598706f2543Smrg
599706f2543Smrg                    xprRestackFrame(winRec->wid, prevWid);
600706f2543Smrg                    prevWid = winRec->wid;
601706f2543Smrg
602706f2543Smrg                    box.x1 = 0;
603706f2543Smrg                    box.y1 = 0;
604706f2543Smrg                    box.x2 = winRec->width;
605706f2543Smrg                    box.y2 = winRec->height;
606706f2543Smrg
607706f2543Smrg                    xprDamageRects(winRec->wid, 1, &box, 0, 0);
608706f2543Smrg                    RootlessQueueRedisplay(screenInfo.screens[screen]);
609706f2543Smrg                }
610706f2543Smrg            }
611706f2543Smrg        }
612706f2543Smrg    }
613706f2543Smrg}
614706f2543Smrg
615706f2543Smrg// XXX: identical to x_cvt_vptr_to_uint ?
616706f2543Smrg#define MAKE_WINDOW_ID(x)		((xp_window_id)((size_t)(x)))
617706f2543Smrg
618706f2543SmrgBool no_configure_window;
619706f2543Smrg
620706f2543Smrgstatic inline int
621706f2543Smrgconfigure_window (xp_window_id id, unsigned int mask,
622706f2543Smrg                  const xp_window_changes *values)
623706f2543Smrg{
624706f2543Smrg  if (!no_configure_window)
625706f2543Smrg    return xp_configure_window (id, mask, values);
626706f2543Smrg  else
627706f2543Smrg    return XP_Success;
628706f2543Smrg}
629706f2543Smrg
630706f2543Smrg
631706f2543Smrgstatic
632706f2543Smrgvoid xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
633706f2543Smrg{
634706f2543Smrg  /* This is how we tell xp that the colormap may have changed. */
635706f2543Smrg  xp_window_changes wc;
636706f2543Smrg  wc.colormap = xprColormapCallback;
637706f2543Smrg  wc.colormap_data = pScreen;
638706f2543Smrg
639706f2543Smrg  configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
640706f2543Smrg}
641706f2543Smrg
642706f2543Smrgstatic
643706f2543Smrgvoid xprHideWindow(RootlessFrameID wid)
644706f2543Smrg{
645706f2543Smrg  xp_window_changes wc;
646706f2543Smrg  wc.stack_mode = XP_UNMAPPED;
647706f2543Smrg  wc.sibling = 0;
648706f2543Smrg  configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
649706f2543Smrg}
650