2 * Xplugin rootless implementation screen functions
4 * Copyright (c) 2002-2012 Apple Computer, Inc. All Rights Reserved.
5 * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
25 * Except as contained in this notice, the name(s) of the above copyright
26 * holders shall not be used in advertising or otherwise to promote the sale,
27 * use or other dealings in this Software without prior written authorization.
30 #include "sanitizedCarbon.h"
32 #ifdef HAVE_DIX_CONFIG_H
33 #include <dix-config.h>
36 #include "quartzCommon.h"
39 #include "quartzRandR.h"
42 #include "pseudoramiX.h"
43 #include "darwinEvents.h"
48 #include "applewmExt.h"
51 #include "rootlessCommon.h"
57 /* 10.4's deferred update makes X slower.. have to live with the tearing
59 #define XP_NO_DEFERRED_UPDATES 8
61 // Name of GLX bundle for native OpenGL
62 static const char *xprOpenGLBundle
= "glxCGL.bundle";
66 * Callback handler for Xplugin events.
69 eventHandler(unsigned int type
, const void *arg
,
70 unsigned int arg_size
, void *data
)
74 case XP_EVENT_DISPLAY_CHANGED
:
75 DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n");
76 DarwinSendDDXEvent(kXquartzDisplayChanged
, 0);
79 case XP_EVENT_WINDOW_STATE_CHANGED
:
80 if (arg_size
>= sizeof(xp_window_state_event
)) {
81 const xp_window_state_event
*ws_arg
= arg
;
83 DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: id=%d, state=%d\n",
86 DarwinSendDDXEvent(kXquartzWindowState
, 2,
87 ws_arg
->id
, ws_arg
->state
);
90 DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: ignored\n");
94 case XP_EVENT_WINDOW_MOVED
:
95 DEBUG_LOG("XP_EVENT_WINDOW_MOVED\n");
96 if (arg_size
== sizeof(xp_window_id
)) {
97 xp_window_id id
= *(xp_window_id
*)arg
;
98 DarwinSendDDXEvent(kXquartzWindowMoved
, 1, id
);
102 case XP_EVENT_SURFACE_DESTROYED
:
103 DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n");
105 case XP_EVENT_SURFACE_CHANGED
:
106 DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n");
107 if (arg_size
== sizeof(xp_surface_id
)) {
110 if (type
== XP_EVENT_SURFACE_DESTROYED
)
111 kind
= AppleDRISurfaceNotifyDestroyed
;
113 kind
= AppleDRISurfaceNotifyChanged
;
115 DRISurfaceNotify(*(xp_surface_id
*)arg
, kind
);
119 #ifdef XP_EVENT_SPACE_CHANGED
120 case XP_EVENT_SPACE_CHANGED
:
121 DEBUG_LOG("XP_EVENT_SPACE_CHANGED\n");
122 if (arg_size
== sizeof(uint32_t)) {
123 uint32_t space_id
= *(uint32_t *)arg
;
124 DarwinSendDDXEvent(kXquartzSpaceChanged
, 1, space_id
);
130 ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n", type
);
136 * Return the display ID for a particular display index.
138 static CGDirectDisplayID
139 displayAtIndex(int index
)
143 CGDirectDisplayID dpy
[index
+ 1];
145 err
= CGGetActiveDisplayList(index
+ 1, dpy
, &cnt
);
146 if (err
== kCGErrorSuccess
&& cnt
== index
+ 1)
149 return kCGNullDirectDisplay
;
153 * displayScreenBounds
154 * Return the bounds of a particular display.
157 displayScreenBounds(CGDirectDisplayID id
)
161 frame
= CGDisplayBounds(id
);
163 DEBUG_LOG(" %dx%d @ (%d,%d).\n",
164 (int)frame
.size
.width
, (int)frame
.size
.height
,
165 (int)frame
.origin
.x
, (int)frame
.origin
.y
);
167 /* Remove menubar to help standard X11 window managers. */
168 if (XQuartzIsRootless
&&
169 frame
.origin
.x
== 0 && frame
.origin
.y
== 0) {
170 frame
.origin
.y
+= aquaMenuBarHeight
;
171 frame
.size
.height
-= aquaMenuBarHeight
;
174 DEBUG_LOG(" %dx%d @ (%d,%d).\n",
175 (int)frame
.size
.width
, (int)frame
.size
.height
,
176 (int)frame
.origin
.x
, (int)frame
.origin
.y
);
182 * xprAddPseudoramiXScreens
183 * Add a single virtual screen encompassing all the physical screens
187 xprAddPseudoramiXScreens(int *x
, int *y
, int *width
, int *height
,
190 CGDisplayCount i
, displayCount
;
191 CGDirectDisplayID
*displayList
= NULL
;
192 CGRect unionRect
= CGRectNull
, frame
;
194 // Find all the CoreGraphics displays
195 CGGetActiveDisplayList(0, NULL
, &displayCount
);
196 DEBUG_LOG("displayCount: %d\n", (int)displayCount
);
200 "CoreGraphics has reported no connected displays. Creating a stub 800x600 display.\n");
204 PseudoramiXAddScreen(*x
, *y
, *width
, *height
);
205 QuartzCopyDisplayIDs(pScreen
, 0, NULL
);
209 /* If the displays are captured, we are in a RandR game mode
210 * on the primary display, so we only want to include the first
211 * display. The others are covered by the shield window.
213 if (CGDisplayIsCaptured(kCGDirectMainDisplay
))
216 displayList
= malloc(displayCount
* sizeof(CGDirectDisplayID
));
218 FatalError("Unable to allocate memory for list of displays.\n");
219 CGGetActiveDisplayList(displayCount
, displayList
, &displayCount
);
220 QuartzCopyDisplayIDs(pScreen
, displayCount
, displayList
);
222 /* Get the union of all screens */
223 for (i
= 0; i
< displayCount
; i
++) {
224 CGDirectDisplayID dpy
= displayList
[i
];
225 frame
= displayScreenBounds(dpy
);
226 unionRect
= CGRectUnion(unionRect
, frame
);
229 /* Use unionRect as the screen size for the X server. */
230 *x
= unionRect
.origin
.x
;
231 *y
= unionRect
.origin
.y
;
232 *width
= unionRect
.size
.width
;
233 *height
= unionRect
.size
.height
;
235 DEBUG_LOG(" screen union origin: (%d,%d) size: (%d,%d).\n",
236 *x
, *y
, *width
, *height
);
238 /* Tell PseudoramiX about the real screens. */
239 for (i
= 0; i
< displayCount
; i
++) {
240 CGDirectDisplayID dpy
= displayList
[i
];
242 frame
= displayScreenBounds(dpy
);
243 frame
.origin
.x
-= unionRect
.origin
.x
;
244 frame
.origin
.y
-= unionRect
.origin
.y
;
246 DEBUG_LOG(" placed at X11 coordinate (%d,%d).\n",
247 (int)frame
.origin
.x
, (int)frame
.origin
.y
);
249 PseudoramiXAddScreen(frame
.origin
.x
, frame
.origin
.y
,
250 frame
.size
.width
, frame
.size
.height
);
258 * Find number of CoreGraphics displays and initialize Xplugin.
263 CGDisplayCount displayCount
;
267 CGGetActiveDisplayList(0, NULL
, &displayCount
);
269 /* With PseudoramiX, the X server only sees one screen; only PseudoramiX
270 itself knows about all of the screens. */
272 if (noPseudoramiXExtension
)
273 darwinScreensFound
= displayCount
;
275 darwinScreensFound
= 1;
277 if (xp_init(XP_BACKGROUND_EVENTS
| XP_NO_DEFERRED_UPDATES
) != Success
)
278 FatalError("Could not initialize the Xplugin library.");
280 xp_select_events(XP_EVENT_DISPLAY_CHANGED
281 | XP_EVENT_WINDOW_STATE_CHANGED
282 | XP_EVENT_WINDOW_MOVED
283 #ifdef XP_EVENT_SPACE_CHANGED
284 | XP_EVENT_SPACE_CHANGED
286 | XP_EVENT_SURFACE_CHANGED
287 | XP_EVENT_SURFACE_DESTROYED
,
290 AppleDRIExtensionInit();
293 XQuartzIsRootless
= XQuartzRootlessDefault
;
294 if (!XQuartzIsRootless
)
295 RootlessHideAllWindows();
300 * Init the framebuffer and record pixmap parameters for the screen.
303 xprAddScreen(int index
, ScreenPtr pScreen
)
305 DarwinFramebufferPtr dfb
= SCREEN_PRIV(pScreen
);
306 int depth
= darwinDesiredDepth
;
308 DEBUG_LOG("index=%d depth=%d\n", index
, depth
);
311 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
312 depth
= CGDisplaySamplesPerPixel(kCGDirectMainDisplay
) *
313 CGDisplayBitsPerSample(kCGDirectMainDisplay
);
315 CGDisplayModeRef modeRef
;
316 CFStringRef encStrRef
;
318 modeRef
= CGDisplayCopyDisplayMode(kCGDirectMainDisplay
);
322 encStrRef
= CGDisplayModeCopyPixelEncoding(modeRef
);
327 if (CFStringCompare(encStrRef
, CFSTR(IO32BitDirectPixels
),
328 kCFCompareCaseInsensitive
) ==
332 else if (CFStringCompare(encStrRef
, CFSTR(IO16BitDirectPixels
),
333 kCFCompareCaseInsensitive
) ==
337 else if (CFStringCompare(encStrRef
, CFSTR(IO8BitIndexedPixels
),
338 kCFCompareCaseInsensitive
) ==
343 CFRelease(encStrRef
);
347 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
351 case 8: // pseudo-working
352 dfb
->visuals
= PseudoColorMask
;
353 dfb
->preferredCVC
= PseudoColor
;
356 dfb
->bitsPerPixel
= 8;
363 // Removed because Mountain Lion removed support for
364 // 15bit backing stores. We can possibly re-add
365 // this once libXplugin is updated to work around it.
367 dfb
->visuals
= TrueColorMask
; //LARGE_VISUALS;
368 dfb
->preferredCVC
= TrueColor
;
371 dfb
->bitsPerPixel
= 16;
372 dfb
->redMask
= RM_ARGB(0, 5, 5, 5);
373 dfb
->greenMask
= GM_ARGB(0, 5, 5, 5);
374 dfb
->blueMask
= BM_ARGB(0, 5, 5, 5);
382 "Unsupported color depth requested. Defaulting to 24bit. (depth=%d darwinDesiredDepth=%d)\n",
383 depth
, darwinDesiredDepth
);
384 dfb
->visuals
= TrueColorMask
; //LARGE_VISUALS;
385 dfb
->preferredCVC
= TrueColor
;
388 dfb
->bitsPerPixel
= 32;
389 dfb
->redMask
= RM_ARGB(0, 8, 8, 8);
390 dfb
->greenMask
= GM_ARGB(0, 8, 8, 8);
391 dfb
->blueMask
= BM_ARGB(0, 8, 8, 8);
395 if (noPseudoramiXExtension
) {
396 CGDirectDisplayID dpy
;
399 ErrorF("Warning: noPseudoramiXExtension!\n");
401 dpy
= displayAtIndex(index
);
402 QuartzCopyDisplayIDs(pScreen
, 1, &dpy
);
404 frame
= displayScreenBounds(dpy
);
406 dfb
->x
= frame
.origin
.x
;
407 dfb
->y
= frame
.origin
.y
;
408 dfb
->width
= frame
.size
.width
;
409 dfb
->height
= frame
.size
.height
;
412 xprAddPseudoramiXScreens(&dfb
->x
, &dfb
->y
, &dfb
->width
, &dfb
->height
,
416 /* Passing zero width (pitch) makes miCreateScreenResources set the
417 screen pixmap to the framebuffer pointer, i.e. NULL. The generic
418 rootless code takes care of making this work. */
420 dfb
->framebuffer
= NULL
;
422 DRIScreenInit(pScreen
);
429 * Setup the screen for rootless access.
432 xprSetupScreen(int index
, ScreenPtr pScreen
)
435 // The Damage extension needs to wrap underneath the
436 // generic rootless layer, so do it now.
437 if (!DamageSetup(pScreen
))
441 // Initialize generic rootless code
442 if (!xprInit(pScreen
))
445 return DRIFinishScreenInit(pScreen
);
450 * Update screen after configuation change.
453 xprUpdateScreen(ScreenPtr pScreen
)
455 rootlessGlobalOffsetX
= darwinMainScreenX
;
456 rootlessGlobalOffsetY
= darwinMainScreenY
;
458 AppleWMSetScreenOrigin(pScreen
->root
);
460 RootlessRepositionWindows(pScreen
);
461 RootlessUpdateScreenPixmap(pScreen
);
466 * Finalize xpr specific setup.
469 xprInitInput(int argc
, char **argv
)
473 rootlessGlobalOffsetX
= darwinMainScreenX
;
474 rootlessGlobalOffsetY
= darwinMainScreenY
;
476 for (i
= 0; i
< screenInfo
.numScreens
; i
++)
477 AppleWMSetScreenOrigin(screenInfo
.screens
[i
]->root
);
481 * Quartz display mode function list.
483 static QuartzModeProcsRec xprModeProcs
= {
489 QuartzSuspendXCursor
,
491 xprAddPseudoramiXScreens
,
495 RootlessFrameForWindow
,
502 * QuartzModeBundleInit
503 * Initialize the display mode bundle after loading.
506 QuartzModeBundleInit(void)
508 quartzProcs
= &xprModeProcs
;
509 quartzOpenGLBundle
= xprOpenGLBundle
;