xref: /OK3568_Linux_fs/external/xserver/hw/xquartz/xpr/xprFrame.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Xplugin rootless implementation frame functions
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (c) 2002-2012 Apple Computer, Inc. All rights reserved.
5*4882a593Smuzhiyun  * Copyright (c) 2003 Torrey T. Lyons. All Rights Reserved.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
8*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
9*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
10*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
12*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * The above copyright notice and this permission notice shall be included in
15*4882a593Smuzhiyun  * all copies or substantial portions of the Software.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20*4882a593Smuzhiyun  * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21*4882a593Smuzhiyun  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22*4882a593Smuzhiyun  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Except as contained in this notice, the name(s) of the above copyright
26*4882a593Smuzhiyun  * holders shall not be used in advertising or otherwise to promote the sale,
27*4882a593Smuzhiyun  * use or other dealings in this Software without prior written authorization.
28*4882a593Smuzhiyun  */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
31*4882a593Smuzhiyun #include <dix-config.h>
32*4882a593Smuzhiyun #endif
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include "xpr.h"
35*4882a593Smuzhiyun #include "rootlessCommon.h"
36*4882a593Smuzhiyun #include <Xplugin.h>
37*4882a593Smuzhiyun #include "x-hash.h"
38*4882a593Smuzhiyun #include "applewmExt.h"
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #include "propertyst.h"
41*4882a593Smuzhiyun #include "dix.h"
42*4882a593Smuzhiyun #include <X11/Xatom.h>
43*4882a593Smuzhiyun #include "windowstr.h"
44*4882a593Smuzhiyun #include "quartz.h"
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #include <dispatch/dispatch.h>
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #ifdef DEBUG_XP_LOCK_WINDOW
49*4882a593Smuzhiyun #include <execinfo.h>
50*4882a593Smuzhiyun #endif
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #define DEFINE_ATOM_HELPER(func, atom_name)                      \
53*4882a593Smuzhiyun     static Atom func(void) {                                       \
54*4882a593Smuzhiyun         static int generation;                                      \
55*4882a593Smuzhiyun         static Atom atom;                                           \
56*4882a593Smuzhiyun         if (generation != serverGeneration) {                       \
57*4882a593Smuzhiyun             generation = serverGeneration;                          \
58*4882a593Smuzhiyun             atom = MakeAtom(atom_name, strlen(atom_name), TRUE);  \
59*4882a593Smuzhiyun         }                                                           \
60*4882a593Smuzhiyun         return atom;                                                \
61*4882a593Smuzhiyun     }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID")
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /* Maps xp_window_id -> RootlessWindowRec */
66*4882a593Smuzhiyun static x_hash_table * window_hash;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun /* Need to guard window_hash since xprIsX11Window can be called from any thread. */
69*4882a593Smuzhiyun static dispatch_queue_t window_hash_serial_q;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /* Prototypes for static functions */
72*4882a593Smuzhiyun static Bool
73*4882a593Smuzhiyun xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX,
74*4882a593Smuzhiyun                int newY,
75*4882a593Smuzhiyun                RegionPtr pShape);
76*4882a593Smuzhiyun static void
77*4882a593Smuzhiyun xprDestroyFrame(RootlessFrameID wid);
78*4882a593Smuzhiyun static void
79*4882a593Smuzhiyun xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
80*4882a593Smuzhiyun static void
81*4882a593Smuzhiyun xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY,
82*4882a593Smuzhiyun                unsigned int newW, unsigned int newH,
83*4882a593Smuzhiyun                unsigned int gravity);
84*4882a593Smuzhiyun static void
85*4882a593Smuzhiyun xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid);
86*4882a593Smuzhiyun static void
87*4882a593Smuzhiyun xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape);
88*4882a593Smuzhiyun static void
89*4882a593Smuzhiyun xprUnmapFrame(RootlessFrameID wid);
90*4882a593Smuzhiyun static void
91*4882a593Smuzhiyun xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow);
92*4882a593Smuzhiyun static void
93*4882a593Smuzhiyun xprStopDrawing(RootlessFrameID wid, Bool flush);
94*4882a593Smuzhiyun static void
95*4882a593Smuzhiyun xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage);
96*4882a593Smuzhiyun static void
97*4882a593Smuzhiyun xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
98*4882a593Smuzhiyun                int shift_x,
99*4882a593Smuzhiyun                int shift_y);
100*4882a593Smuzhiyun static void
101*4882a593Smuzhiyun xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin);
102*4882a593Smuzhiyun static Bool
103*4882a593Smuzhiyun xprDoReorderWindow(RootlessWindowPtr pFrame);
104*4882a593Smuzhiyun static void
105*4882a593Smuzhiyun xprHideWindow(RootlessFrameID wid);
106*4882a593Smuzhiyun static void
107*4882a593Smuzhiyun xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen);
108*4882a593Smuzhiyun static void
109*4882a593Smuzhiyun xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
110*4882a593Smuzhiyun               int dx,
111*4882a593Smuzhiyun               int dy);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun static inline xp_error
xprConfigureWindow(xp_window_id id,unsigned int mask,const xp_window_changes * values)114*4882a593Smuzhiyun xprConfigureWindow(xp_window_id id, unsigned int mask,
115*4882a593Smuzhiyun                    const xp_window_changes *values)
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun     return xp_configure_window(id, mask, values);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun static void
xprSetNativeProperty(RootlessWindowPtr pFrame)121*4882a593Smuzhiyun xprSetNativeProperty(RootlessWindowPtr pFrame)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun     xp_error err;
124*4882a593Smuzhiyun     unsigned int native_id;
125*4882a593Smuzhiyun     long data;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun     err = xp_get_native_window(x_cvt_vptr_to_uint(pFrame->wid), &native_id);
128*4882a593Smuzhiyun     if (err == Success) {
129*4882a593Smuzhiyun         /* FIXME: move this to AppleWM extension */
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun         data = native_id;
132*4882a593Smuzhiyun         dixChangeWindowProperty(serverClient, pFrame->win,
133*4882a593Smuzhiyun                                 xa_native_window_id(),
134*4882a593Smuzhiyun                                 XA_INTEGER, 32, PropModeReplace, 1, &data,
135*4882a593Smuzhiyun                                 TRUE);
136*4882a593Smuzhiyun     }
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun static xp_error
xprColormapCallback(void * data,int first_color,int n_colors,uint32_t * colors)140*4882a593Smuzhiyun xprColormapCallback(void *data, int first_color, int n_colors,
141*4882a593Smuzhiyun                     uint32_t *colors)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun     return (RootlessResolveColormap(data, first_color, n_colors,
144*4882a593Smuzhiyun                                     colors) ? XP_Success : XP_BadMatch);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun /*
148*4882a593Smuzhiyun  * Create and display a new frame.
149*4882a593Smuzhiyun  */
150*4882a593Smuzhiyun static Bool
xprCreateFrame(RootlessWindowPtr pFrame,ScreenPtr pScreen,int newX,int newY,RegionPtr pShape)151*4882a593Smuzhiyun xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen,
152*4882a593Smuzhiyun                int newX, int newY, RegionPtr pShape)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun     WindowPtr pWin = pFrame->win;
155*4882a593Smuzhiyun     xp_window_changes wc;
156*4882a593Smuzhiyun     unsigned int mask = 0;
157*4882a593Smuzhiyun     xp_error err;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun     wc.x = newX;
160*4882a593Smuzhiyun     wc.y = newY;
161*4882a593Smuzhiyun     wc.width = pFrame->width;
162*4882a593Smuzhiyun     wc.height = pFrame->height;
163*4882a593Smuzhiyun     wc.bit_gravity = XP_GRAVITY_NONE;
164*4882a593Smuzhiyun     mask |= XP_BOUNDS;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun     if (pWin->drawable.depth == 8) {
167*4882a593Smuzhiyun         wc.depth = XP_DEPTH_INDEX8;
168*4882a593Smuzhiyun         wc.colormap = xprColormapCallback;
169*4882a593Smuzhiyun         wc.colormap_data = pScreen;
170*4882a593Smuzhiyun         mask |= XP_COLORMAP;
171*4882a593Smuzhiyun     }
172*4882a593Smuzhiyun     else if (pWin->drawable.depth == 15)
173*4882a593Smuzhiyun         wc.depth = XP_DEPTH_RGB555;
174*4882a593Smuzhiyun     else if (pWin->drawable.depth == 24)
175*4882a593Smuzhiyun         wc.depth = XP_DEPTH_ARGB8888;
176*4882a593Smuzhiyun     else
177*4882a593Smuzhiyun         wc.depth = XP_DEPTH_NIL;
178*4882a593Smuzhiyun     mask |= XP_DEPTH;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun     if (pShape != NULL) {
181*4882a593Smuzhiyun         wc.shape_nrects = RegionNumRects(pShape);
182*4882a593Smuzhiyun         wc.shape_rects = RegionRects(pShape);
183*4882a593Smuzhiyun         wc.shape_tx = wc.shape_ty = 0;
184*4882a593Smuzhiyun         mask |= XP_SHAPE;
185*4882a593Smuzhiyun     }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun     pFrame->level =
188*4882a593Smuzhiyun         !IsRoot(pWin) ? AppleWMWindowLevelNormal : AppleWMNumWindowLevels;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun     if (XQuartzIsRootless)
191*4882a593Smuzhiyun         wc.window_level = normal_window_levels[pFrame->level];
192*4882a593Smuzhiyun     else if (XQuartzShieldingWindowLevel)
193*4882a593Smuzhiyun         wc.window_level = XQuartzShieldingWindowLevel + 1;
194*4882a593Smuzhiyun     else
195*4882a593Smuzhiyun         wc.window_level = rooted_window_levels[pFrame->level];
196*4882a593Smuzhiyun     mask |= XP_WINDOW_LEVEL;
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun     err = xp_create_window(mask, &wc, (xp_window_id *)&pFrame->wid);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun     if (err != Success) {
201*4882a593Smuzhiyun         return FALSE;
202*4882a593Smuzhiyun     }
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun     dispatch_async(window_hash_serial_q, ^ {
205*4882a593Smuzhiyun                        x_hash_table_insert(window_hash, pFrame->wid, pFrame);
206*4882a593Smuzhiyun                    });
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun     xprSetNativeProperty(pFrame);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun     return TRUE;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun /*
214*4882a593Smuzhiyun  * Destroy a frame.
215*4882a593Smuzhiyun  */
216*4882a593Smuzhiyun static void
xprDestroyFrame(RootlessFrameID wid)217*4882a593Smuzhiyun xprDestroyFrame(RootlessFrameID wid)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun     xp_error err;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun     dispatch_async(window_hash_serial_q, ^ {
222*4882a593Smuzhiyun                        x_hash_table_remove(window_hash, wid);
223*4882a593Smuzhiyun                    });
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun     err = xp_destroy_window(x_cvt_vptr_to_uint(wid));
226*4882a593Smuzhiyun     if (err != Success)
227*4882a593Smuzhiyun         FatalError("Could not destroy window %d (%d).",
228*4882a593Smuzhiyun                    (int)x_cvt_vptr_to_uint(
229*4882a593Smuzhiyun                        wid), (int)err);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun /*
233*4882a593Smuzhiyun  * Move a frame on screen.
234*4882a593Smuzhiyun  */
235*4882a593Smuzhiyun static void
xprMoveFrame(RootlessFrameID wid,ScreenPtr pScreen,int newX,int newY)236*4882a593Smuzhiyun xprMoveFrame(RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun     xp_window_changes wc;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun     wc.x = newX;
241*4882a593Smuzhiyun     wc.y = newY;
242*4882a593Smuzhiyun     //    ErrorF("xprMoveFrame(%d, %p, %d, %d)\n", wid, pScreen, newX, newY);
243*4882a593Smuzhiyun     xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_ORIGIN, &wc);
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun /*
247*4882a593Smuzhiyun  * Resize and move a frame.
248*4882a593Smuzhiyun  */
249*4882a593Smuzhiyun static void
xprResizeFrame(RootlessFrameID wid,ScreenPtr pScreen,int newX,int newY,unsigned int newW,unsigned int newH,unsigned int gravity)250*4882a593Smuzhiyun xprResizeFrame(RootlessFrameID wid, ScreenPtr pScreen,
251*4882a593Smuzhiyun                int newX, int newY, unsigned int newW, unsigned int newH,
252*4882a593Smuzhiyun                unsigned int gravity)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun     xp_window_changes wc;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun     wc.x = newX;
257*4882a593Smuzhiyun     wc.y = newY;
258*4882a593Smuzhiyun     wc.width = newW;
259*4882a593Smuzhiyun     wc.height = newH;
260*4882a593Smuzhiyun     wc.bit_gravity = gravity;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun     /* It's unlikely that being async will save us anything here.
263*4882a593Smuzhiyun        But it can't hurt. */
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun     xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_BOUNDS, &wc);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /*
269*4882a593Smuzhiyun  * Change frame stacking.
270*4882a593Smuzhiyun  */
271*4882a593Smuzhiyun static void
xprRestackFrame(RootlessFrameID wid,RootlessFrameID nextWid)272*4882a593Smuzhiyun xprRestackFrame(RootlessFrameID wid, RootlessFrameID nextWid)
273*4882a593Smuzhiyun {
274*4882a593Smuzhiyun     xp_window_changes wc;
275*4882a593Smuzhiyun     unsigned int mask = XP_STACKING;
276*4882a593Smuzhiyun     __block
277*4882a593Smuzhiyun     RootlessWindowRec * winRec;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun     /* Stack frame below nextWid it if it exists, or raise
280*4882a593Smuzhiyun        frame above everything otherwise. */
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun     if (nextWid == NULL) {
283*4882a593Smuzhiyun         wc.stack_mode = XP_MAPPED_ABOVE;
284*4882a593Smuzhiyun         wc.sibling = 0;
285*4882a593Smuzhiyun     }
286*4882a593Smuzhiyun     else {
287*4882a593Smuzhiyun         wc.stack_mode = XP_MAPPED_BELOW;
288*4882a593Smuzhiyun         wc.sibling = x_cvt_vptr_to_uint(nextWid);
289*4882a593Smuzhiyun     }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun     dispatch_sync(window_hash_serial_q, ^ {
292*4882a593Smuzhiyun                       winRec = x_hash_table_lookup(window_hash, wid, NULL);
293*4882a593Smuzhiyun                   });
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun     if (winRec) {
296*4882a593Smuzhiyun         if (XQuartzIsRootless)
297*4882a593Smuzhiyun             wc.window_level = normal_window_levels[winRec->level];
298*4882a593Smuzhiyun         else if (XQuartzShieldingWindowLevel)
299*4882a593Smuzhiyun             wc.window_level = XQuartzShieldingWindowLevel + 1;
300*4882a593Smuzhiyun         else
301*4882a593Smuzhiyun             wc.window_level = rooted_window_levels[winRec->level];
302*4882a593Smuzhiyun         mask |= XP_WINDOW_LEVEL;
303*4882a593Smuzhiyun     }
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     xprConfigureWindow(x_cvt_vptr_to_uint(wid), mask, &wc);
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun /*
309*4882a593Smuzhiyun  * Change the frame's shape.
310*4882a593Smuzhiyun  */
311*4882a593Smuzhiyun static void
xprReshapeFrame(RootlessFrameID wid,RegionPtr pShape)312*4882a593Smuzhiyun xprReshapeFrame(RootlessFrameID wid, RegionPtr pShape)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun     xp_window_changes wc;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun     if (pShape != NULL) {
317*4882a593Smuzhiyun         wc.shape_nrects = RegionNumRects(pShape);
318*4882a593Smuzhiyun         wc.shape_rects = RegionRects(pShape);
319*4882a593Smuzhiyun     }
320*4882a593Smuzhiyun     else {
321*4882a593Smuzhiyun         wc.shape_nrects = -1;
322*4882a593Smuzhiyun         wc.shape_rects = NULL;
323*4882a593Smuzhiyun     }
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun     wc.shape_tx = wc.shape_ty = 0;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun     xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_SHAPE, &wc);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun /*
331*4882a593Smuzhiyun  * Unmap a frame.
332*4882a593Smuzhiyun  */
333*4882a593Smuzhiyun static void
xprUnmapFrame(RootlessFrameID wid)334*4882a593Smuzhiyun xprUnmapFrame(RootlessFrameID wid)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun     xp_window_changes wc;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun     wc.stack_mode = XP_UNMAPPED;
339*4882a593Smuzhiyun     wc.sibling = 0;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     xprConfigureWindow(x_cvt_vptr_to_uint(wid), XP_STACKING, &wc);
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun /*
345*4882a593Smuzhiyun  * Start drawing to a frame.
346*4882a593Smuzhiyun  *  Prepare for direct access to its backing buffer.
347*4882a593Smuzhiyun  */
348*4882a593Smuzhiyun static void
xprStartDrawing(RootlessFrameID wid,char ** pixelData,int * bytesPerRow)349*4882a593Smuzhiyun xprStartDrawing(RootlessFrameID wid, char **pixelData, int *bytesPerRow)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun     void *data[2];
352*4882a593Smuzhiyun     unsigned int rowbytes[2];
353*4882a593Smuzhiyun     xp_error err;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun #ifdef DEBUG_XP_LOCK_WINDOW
356*4882a593Smuzhiyun     void* callstack[128];
357*4882a593Smuzhiyun     int i, frames = backtrace(callstack, 128);
358*4882a593Smuzhiyun     char** strs = backtrace_symbols(callstack, frames);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun     ErrorF("=== LOCK %d ===\n", (int)x_cvt_vptr_to_uint(wid));
361*4882a593Smuzhiyun     for (i = 0; i < frames; ++i) {
362*4882a593Smuzhiyun         ErrorF("    %s\n", strs[i]);
363*4882a593Smuzhiyun     }
364*4882a593Smuzhiyun     free(strs);
365*4882a593Smuzhiyun #endif
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun     err = xp_lock_window(x_cvt_vptr_to_uint(
368*4882a593Smuzhiyun                              wid), NULL, NULL, data, rowbytes, NULL);
369*4882a593Smuzhiyun     if (err != Success)
370*4882a593Smuzhiyun         FatalError("Could not lock window %d for drawing (%d).",
371*4882a593Smuzhiyun                    (int)x_cvt_vptr_to_uint(
372*4882a593Smuzhiyun                        wid), (int)err);
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun     *pixelData = data[0];
375*4882a593Smuzhiyun     *bytesPerRow = rowbytes[0];
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun /*
379*4882a593Smuzhiyun  * Stop drawing to a frame.
380*4882a593Smuzhiyun  */
381*4882a593Smuzhiyun static void
xprStopDrawing(RootlessFrameID wid,Bool flush)382*4882a593Smuzhiyun xprStopDrawing(RootlessFrameID wid, Bool flush)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun     xp_error err;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun #ifdef DEBUG_XP_LOCK_WINDOW
387*4882a593Smuzhiyun     void* callstack[128];
388*4882a593Smuzhiyun     int i, frames = backtrace(callstack, 128);
389*4882a593Smuzhiyun     char** strs = backtrace_symbols(callstack, frames);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     ErrorF("=== UNLOCK %d ===\n", (int)x_cvt_vptr_to_uint(wid));
392*4882a593Smuzhiyun     for (i = 0; i < frames; ++i) {
393*4882a593Smuzhiyun         ErrorF("    %s\n", strs[i]);
394*4882a593Smuzhiyun     }
395*4882a593Smuzhiyun     free(strs);
396*4882a593Smuzhiyun #endif
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun     err = xp_unlock_window(x_cvt_vptr_to_uint(wid), flush);
399*4882a593Smuzhiyun     /* This should be a FatalError, but we started tripping over it.  Make it a
400*4882a593Smuzhiyun      * FatalError after http://xquartz.macosforge.org/trac/ticket/482 is fixed.
401*4882a593Smuzhiyun      */
402*4882a593Smuzhiyun     if (err != Success)
403*4882a593Smuzhiyun         ErrorF("Could not unlock window %d after drawing (%d).",
404*4882a593Smuzhiyun                (int)x_cvt_vptr_to_uint(
405*4882a593Smuzhiyun                    wid), (int)err);
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun /*
409*4882a593Smuzhiyun  * Flush drawing updates to the screen.
410*4882a593Smuzhiyun  */
411*4882a593Smuzhiyun static void
xprUpdateRegion(RootlessFrameID wid,RegionPtr pDamage)412*4882a593Smuzhiyun xprUpdateRegion(RootlessFrameID wid, RegionPtr pDamage)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun     xp_flush_window(x_cvt_vptr_to_uint(wid));
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun /*
418*4882a593Smuzhiyun  * Mark damaged rectangles as requiring redisplay to screen.
419*4882a593Smuzhiyun  */
420*4882a593Smuzhiyun static void
xprDamageRects(RootlessFrameID wid,int nrects,const BoxRec * rects,int shift_x,int shift_y)421*4882a593Smuzhiyun xprDamageRects(RootlessFrameID wid, int nrects, const BoxRec *rects,
422*4882a593Smuzhiyun                int shift_x, int shift_y)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun     xp_mark_window(x_cvt_vptr_to_uint(wid), nrects, rects, shift_x, shift_y);
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun /*
428*4882a593Smuzhiyun  * Called after the window associated with a frame has been switched
429*4882a593Smuzhiyun  * to a new top-level parent.
430*4882a593Smuzhiyun  */
431*4882a593Smuzhiyun static void
xprSwitchWindow(RootlessWindowPtr pFrame,WindowPtr oldWin)432*4882a593Smuzhiyun xprSwitchWindow(RootlessWindowPtr pFrame, WindowPtr oldWin)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun     DeleteProperty(serverClient, oldWin, xa_native_window_id());
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun     xprSetNativeProperty(pFrame);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun /*
440*4882a593Smuzhiyun  * Called to check if the frame should be reordered when it is restacked.
441*4882a593Smuzhiyun  */
442*4882a593Smuzhiyun static Bool
xprDoReorderWindow(RootlessWindowPtr pFrame)443*4882a593Smuzhiyun xprDoReorderWindow(RootlessWindowPtr pFrame)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun     WindowPtr pWin = pFrame->win;
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun     return AppleWMDoReorderWindow(pWin);
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun /*
451*4882a593Smuzhiyun  * Copy area in frame to another part of frame.
452*4882a593Smuzhiyun  *  Used to accelerate scrolling.
453*4882a593Smuzhiyun  */
454*4882a593Smuzhiyun static void
xprCopyWindow(RootlessFrameID wid,int dstNrects,const BoxRec * dstRects,int dx,int dy)455*4882a593Smuzhiyun xprCopyWindow(RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
456*4882a593Smuzhiyun               int dx, int dy)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun     xp_copy_window(x_cvt_vptr_to_uint(wid), x_cvt_vptr_to_uint(wid),
459*4882a593Smuzhiyun                    dstNrects, dstRects, dx, dy);
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun static RootlessFrameProcsRec xprRootlessProcs = {
463*4882a593Smuzhiyun     xprCreateFrame,
464*4882a593Smuzhiyun     xprDestroyFrame,
465*4882a593Smuzhiyun     xprMoveFrame,
466*4882a593Smuzhiyun     xprResizeFrame,
467*4882a593Smuzhiyun     xprRestackFrame,
468*4882a593Smuzhiyun     xprReshapeFrame,
469*4882a593Smuzhiyun     xprUnmapFrame,
470*4882a593Smuzhiyun     xprStartDrawing,
471*4882a593Smuzhiyun     xprStopDrawing,
472*4882a593Smuzhiyun     xprUpdateRegion,
473*4882a593Smuzhiyun     xprDamageRects,
474*4882a593Smuzhiyun     xprSwitchWindow,
475*4882a593Smuzhiyun     xprDoReorderWindow,
476*4882a593Smuzhiyun     xprHideWindow,
477*4882a593Smuzhiyun     xprUpdateColormap,
478*4882a593Smuzhiyun     xp_copy_bytes,
479*4882a593Smuzhiyun     xprCopyWindow
480*4882a593Smuzhiyun };
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun /*
483*4882a593Smuzhiyun  * Initialize XPR implementation
484*4882a593Smuzhiyun  */
485*4882a593Smuzhiyun Bool
xprInit(ScreenPtr pScreen)486*4882a593Smuzhiyun xprInit(ScreenPtr pScreen)
487*4882a593Smuzhiyun {
488*4882a593Smuzhiyun     RootlessInit(pScreen, &xprRootlessProcs);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun     rootless_CopyBytes_threshold = xp_copy_bytes_threshold;
491*4882a593Smuzhiyun     rootless_CopyWindow_threshold = xp_scroll_area_threshold;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun     assert((window_hash = x_hash_table_new(NULL, NULL, NULL, NULL)));
494*4882a593Smuzhiyun     assert((window_hash_serial_q =
495*4882a593Smuzhiyun                 dispatch_queue_create(BUNDLE_ID_PREFIX ".X11.xpr_window_hash",
496*4882a593Smuzhiyun                                       NULL)));
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun     return TRUE;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun /*
502*4882a593Smuzhiyun  * Given the id of a physical window, try to find the top-level (or root)
503*4882a593Smuzhiyun  * X window that it represents.
504*4882a593Smuzhiyun  */
505*4882a593Smuzhiyun WindowPtr
xprGetXWindow(xp_window_id wid)506*4882a593Smuzhiyun xprGetXWindow(xp_window_id wid)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun     RootlessWindowRec *winRec __block;
509*4882a593Smuzhiyun     dispatch_sync(window_hash_serial_q, ^ {
510*4882a593Smuzhiyun                       winRec =
511*4882a593Smuzhiyun                           x_hash_table_lookup(window_hash,
512*4882a593Smuzhiyun                                               x_cvt_uint_to_vptr(wid), NULL);
513*4882a593Smuzhiyun                   });
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun     return winRec != NULL ? winRec->win : NULL;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun /*
519*4882a593Smuzhiyun  * The windowNumber is an AppKit window number. Returns TRUE if xpr is
520*4882a593Smuzhiyun  * displaying a window with that number.
521*4882a593Smuzhiyun  */
522*4882a593Smuzhiyun Bool
xprIsX11Window(int windowNumber)523*4882a593Smuzhiyun xprIsX11Window(int windowNumber)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun     Bool ret;
526*4882a593Smuzhiyun     xp_window_id wid;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun     if (xp_lookup_native_window(windowNumber, &wid))
529*4882a593Smuzhiyun         ret = xprGetXWindow(wid) != NULL;
530*4882a593Smuzhiyun     else
531*4882a593Smuzhiyun         ret = FALSE;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun     return ret;
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun /*
537*4882a593Smuzhiyun  * xprHideWindows
538*4882a593Smuzhiyun  *  Hide or unhide all top level windows. This is called for application hide/
539*4882a593Smuzhiyun  *  unhide events if the window manager is not Apple-WM aware. Xplugin windows
540*4882a593Smuzhiyun  *  do not hide or unhide themselves.
541*4882a593Smuzhiyun  */
542*4882a593Smuzhiyun void
xprHideWindows(Bool hide)543*4882a593Smuzhiyun xprHideWindows(Bool hide)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun     int screen;
546*4882a593Smuzhiyun     WindowPtr pRoot, pWin;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun     for (screen = 0; screen < screenInfo.numScreens; screen++) {
549*4882a593Smuzhiyun         RootlessFrameID prevWid = NULL;
550*4882a593Smuzhiyun         pRoot = screenInfo.screens[screen]->root;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun         for (pWin = pRoot->firstChild; pWin; pWin = pWin->nextSib) {
553*4882a593Smuzhiyun             RootlessWindowRec *winRec = WINREC(pWin);
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun             if (winRec != NULL) {
556*4882a593Smuzhiyun                 if (hide) {
557*4882a593Smuzhiyun                     xprUnmapFrame(winRec->wid);
558*4882a593Smuzhiyun                 }
559*4882a593Smuzhiyun                 else {
560*4882a593Smuzhiyun                     BoxRec box;
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun                     xprRestackFrame(winRec->wid, prevWid);
563*4882a593Smuzhiyun                     prevWid = winRec->wid;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun                     box.x1 = 0;
566*4882a593Smuzhiyun                     box.y1 = 0;
567*4882a593Smuzhiyun                     box.x2 = winRec->width;
568*4882a593Smuzhiyun                     box.y2 = winRec->height;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun                     xprDamageRects(winRec->wid, 1, &box, 0, 0);
571*4882a593Smuzhiyun                     RootlessQueueRedisplay(screenInfo.screens[screen]);
572*4882a593Smuzhiyun                 }
573*4882a593Smuzhiyun             }
574*4882a593Smuzhiyun         }
575*4882a593Smuzhiyun     }
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun // XXX: identical to x_cvt_vptr_to_uint ?
579*4882a593Smuzhiyun #define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun Bool no_configure_window;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun static inline int
configure_window(xp_window_id id,unsigned int mask,const xp_window_changes * values)584*4882a593Smuzhiyun configure_window(xp_window_id id, unsigned int mask,
585*4882a593Smuzhiyun                  const xp_window_changes *values)
586*4882a593Smuzhiyun {
587*4882a593Smuzhiyun     if (!no_configure_window)
588*4882a593Smuzhiyun         return xp_configure_window(id, mask, values);
589*4882a593Smuzhiyun     else
590*4882a593Smuzhiyun         return XP_Success;
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun static
594*4882a593Smuzhiyun void
xprUpdateColormap(RootlessFrameID wid,ScreenPtr pScreen)595*4882a593Smuzhiyun xprUpdateColormap(RootlessFrameID wid, ScreenPtr pScreen)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun     /* This is how we tell xp that the colormap may have changed. */
598*4882a593Smuzhiyun     xp_window_changes wc;
599*4882a593Smuzhiyun     wc.colormap = xprColormapCallback;
600*4882a593Smuzhiyun     wc.colormap_data = pScreen;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun     configure_window(MAKE_WINDOW_ID(wid), XP_COLORMAP, &wc);
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun static
606*4882a593Smuzhiyun void
xprHideWindow(RootlessFrameID wid)607*4882a593Smuzhiyun xprHideWindow(RootlessFrameID wid)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun     xp_window_changes wc;
610*4882a593Smuzhiyun     wc.stack_mode = XP_UNMAPPED;
611*4882a593Smuzhiyun     wc.sibling = 0;
612*4882a593Smuzhiyun     configure_window(MAKE_WINDOW_ID(wid), XP_STACKING, &wc);
613*4882a593Smuzhiyun }
614