Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xquartz / xpr / xprScreen.c
CommitLineData
a09e091a
JB
1/*
2 * Xplugin rootless implementation screen functions
3 *
4 * Copyright (c) 2002-2012 Apple Computer, Inc. All Rights Reserved.
5 * Copyright (c) 2004 Torrey T. Lyons. All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
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.
24 *
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.
28 */
29
30#include "sanitizedCarbon.h"
31
32#ifdef HAVE_DIX_CONFIG_H
33#include <dix-config.h>
34#endif
35
36#include "quartzCommon.h"
37#include "inputstr.h"
38#include "quartz.h"
39#include "quartzRandR.h"
40#include "xpr.h"
41#include "xprEvent.h"
42#include "pseudoramiX.h"
43#include "darwinEvents.h"
44#include "rootless.h"
45#include "dri.h"
46#include "globals.h"
47#include <Xplugin.h>
48#include "applewmExt.h"
49#include "micmap.h"
50
51#include "rootlessCommon.h"
52
53#ifdef DAMAGE
54#include "damage.h"
55#endif
56
57/* 10.4's deferred update makes X slower.. have to live with the tearing
58 * for now.. */
59#define XP_NO_DEFERRED_UPDATES 8
60
61// Name of GLX bundle for native OpenGL
62static const char *xprOpenGLBundle = "glxCGL.bundle";
63
64/*
65 * eventHandler
66 * Callback handler for Xplugin events.
67 */
68static void
69eventHandler(unsigned int type, const void *arg,
70 unsigned int arg_size, void *data)
71{
72
73 switch (type) {
74 case XP_EVENT_DISPLAY_CHANGED:
75 DEBUG_LOG("XP_EVENT_DISPLAY_CHANGED\n");
76 DarwinSendDDXEvent(kXquartzDisplayChanged, 0);
77 break;
78
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;
82
83 DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: id=%d, state=%d\n",
84 ws_arg->id,
85 ws_arg->state);
86 DarwinSendDDXEvent(kXquartzWindowState, 2,
87 ws_arg->id, ws_arg->state);
88 }
89 else {
90 DEBUG_LOG("XP_EVENT_WINDOW_STATE_CHANGED: ignored\n");
91 }
92 break;
93
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);
99 }
100 break;
101
102 case XP_EVENT_SURFACE_DESTROYED:
103 DEBUG_LOG("XP_EVENT_SURFACE_DESTROYED\n");
104
105 case XP_EVENT_SURFACE_CHANGED:
106 DEBUG_LOG("XP_EVENT_SURFACE_CHANGED\n");
107 if (arg_size == sizeof(xp_surface_id)) {
108 int kind;
109
110 if (type == XP_EVENT_SURFACE_DESTROYED)
111 kind = AppleDRISurfaceNotifyDestroyed;
112 else
113 kind = AppleDRISurfaceNotifyChanged;
114
115 DRISurfaceNotify(*(xp_surface_id *)arg, kind);
116 }
117 break;
118
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);
125 }
126 break;
127
128#endif
129 default:
130 ErrorF("Unknown XP_EVENT type (%d) in xprScreen:eventHandler\n", type);
131 }
132}
133
134/*
135 * displayAtIndex
136 * Return the display ID for a particular display index.
137 */
138static CGDirectDisplayID
139displayAtIndex(int index)
140{
141 CGError err;
142 CGDisplayCount cnt;
143 CGDirectDisplayID dpy[index + 1];
144
145 err = CGGetActiveDisplayList(index + 1, dpy, &cnt);
146 if (err == kCGErrorSuccess && cnt == index + 1)
147 return dpy[index];
148 else
149 return kCGNullDirectDisplay;
150}
151
152/*
153 * displayScreenBounds
154 * Return the bounds of a particular display.
155 */
156static CGRect
157displayScreenBounds(CGDirectDisplayID id)
158{
159 CGRect frame;
160
161 frame = CGDisplayBounds(id);
162
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);
166
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;
172 }
173
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);
177
178 return frame;
179}
180
181/*
182 * xprAddPseudoramiXScreens
183 * Add a single virtual screen encompassing all the physical screens
184 * with PseudoramiX.
185 */
186static void
187xprAddPseudoramiXScreens(int *x, int *y, int *width, int *height,
188 ScreenPtr pScreen)
189{
190 CGDisplayCount i, displayCount;
191 CGDirectDisplayID *displayList = NULL;
192 CGRect unionRect = CGRectNull, frame;
193
194 // Find all the CoreGraphics displays
195 CGGetActiveDisplayList(0, NULL, &displayCount);
196 DEBUG_LOG("displayCount: %d\n", (int)displayCount);
197
198 if (!displayCount) {
199 ErrorF(
200 "CoreGraphics has reported no connected displays. Creating a stub 800x600 display.\n");
201 *x = *y = 0;
202 *width = 800;
203 *height = 600;
204 PseudoramiXAddScreen(*x, *y, *width, *height);
205 QuartzCopyDisplayIDs(pScreen, 0, NULL);
206 return;
207 }
208
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.
212 */
213 if (CGDisplayIsCaptured(kCGDirectMainDisplay))
214 displayCount = 1;
215
216 displayList = malloc(displayCount * sizeof(CGDirectDisplayID));
217 if (!displayList)
218 FatalError("Unable to allocate memory for list of displays.\n");
219 CGGetActiveDisplayList(displayCount, displayList, &displayCount);
220 QuartzCopyDisplayIDs(pScreen, displayCount, displayList);
221
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);
227 }
228
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;
234
235 DEBUG_LOG(" screen union origin: (%d,%d) size: (%d,%d).\n",
236 *x, *y, *width, *height);
237
238 /* Tell PseudoramiX about the real screens. */
239 for (i = 0; i < displayCount; i++) {
240 CGDirectDisplayID dpy = displayList[i];
241
242 frame = displayScreenBounds(dpy);
243 frame.origin.x -= unionRect.origin.x;
244 frame.origin.y -= unionRect.origin.y;
245
246 DEBUG_LOG(" placed at X11 coordinate (%d,%d).\n",
247 (int)frame.origin.x, (int)frame.origin.y);
248
249 PseudoramiXAddScreen(frame.origin.x, frame.origin.y,
250 frame.size.width, frame.size.height);
251 }
252
253 free(displayList);
254}
255
256/*
257 * xprDisplayInit
258 * Find number of CoreGraphics displays and initialize Xplugin.
259 */
260static void
261xprDisplayInit(void)
262{
263 CGDisplayCount displayCount;
264
265 TRACE();
266
267 CGGetActiveDisplayList(0, NULL, &displayCount);
268
269 /* With PseudoramiX, the X server only sees one screen; only PseudoramiX
270 itself knows about all of the screens. */
271
272 if (noPseudoramiXExtension)
273 darwinScreensFound = displayCount;
274 else
275 darwinScreensFound = 1;
276
277 if (xp_init(XP_BACKGROUND_EVENTS | XP_NO_DEFERRED_UPDATES) != Success)
278 FatalError("Could not initialize the Xplugin library.");
279
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
285#endif
286 | XP_EVENT_SURFACE_CHANGED
287 | XP_EVENT_SURFACE_DESTROYED,
288 eventHandler, NULL);
289
290 AppleDRIExtensionInit();
291 xprAppleWMInit();
292
293 XQuartzIsRootless = XQuartzRootlessDefault;
294 if (!XQuartzIsRootless)
295 RootlessHideAllWindows();
296}
297
298/*
299 * xprAddScreen
300 * Init the framebuffer and record pixmap parameters for the screen.
301 */
302static Bool
303xprAddScreen(int index, ScreenPtr pScreen)
304{
305 DarwinFramebufferPtr dfb = SCREEN_PRIV(pScreen);
306 int depth = darwinDesiredDepth;
307
308 DEBUG_LOG("index=%d depth=%d\n", index, depth);
309
310 if (depth == -1) {
311#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
312 depth = CGDisplaySamplesPerPixel(kCGDirectMainDisplay) *
313 CGDisplayBitsPerSample(kCGDirectMainDisplay);
314#else
315 CGDisplayModeRef modeRef;
316 CFStringRef encStrRef;
317
318 modeRef = CGDisplayCopyDisplayMode(kCGDirectMainDisplay);
319 if (!modeRef)
320 goto have_depth;
321
322 encStrRef = CGDisplayModeCopyPixelEncoding(modeRef);
323 CFRelease(modeRef);
324 if (!encStrRef)
325 goto have_depth;
326
327 if (CFStringCompare(encStrRef, CFSTR(IO32BitDirectPixels),
328 kCFCompareCaseInsensitive) ==
329 kCFCompareEqualTo) {
330 depth = 24;
331 }
332 else if (CFStringCompare(encStrRef, CFSTR(IO16BitDirectPixels),
333 kCFCompareCaseInsensitive) ==
334 kCFCompareEqualTo) {
335 depth = 15;
336 }
337 else if (CFStringCompare(encStrRef, CFSTR(IO8BitIndexedPixels),
338 kCFCompareCaseInsensitive) ==
339 kCFCompareEqualTo) {
340 depth = 8;
341 }
342
343 CFRelease(encStrRef);
344#endif
345 }
346
347#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
348have_depth:
349#endif
350 switch (depth) {
351 case 8: // pseudo-working
352 dfb->visuals = PseudoColorMask;
353 dfb->preferredCVC = PseudoColor;
354 dfb->depth = 8;
355 dfb->bitsPerRGB = 8;
356 dfb->bitsPerPixel = 8;
357 dfb->redMask = 0;
358 dfb->greenMask = 0;
359 dfb->blueMask = 0;
360 break;
361
362#if 0
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.
366 case 15:
367 dfb->visuals = TrueColorMask; //LARGE_VISUALS;
368 dfb->preferredCVC = TrueColor;
369 dfb->depth = 15;
370 dfb->bitsPerRGB = 5;
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);
375 break;
376#endif
377
378 // case 24:
379 default:
380 if (depth != 24)
381 ErrorF(
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;
386 dfb->depth = 24;
387 dfb->bitsPerRGB = 8;
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);
392 break;
393 }
394
395 if (noPseudoramiXExtension) {
396 CGDirectDisplayID dpy;
397 CGRect frame;
398
399 ErrorF("Warning: noPseudoramiXExtension!\n");
400
401 dpy = displayAtIndex(index);
402 QuartzCopyDisplayIDs(pScreen, 1, &dpy);
403
404 frame = displayScreenBounds(dpy);
405
406 dfb->x = frame.origin.x;
407 dfb->y = frame.origin.y;
408 dfb->width = frame.size.width;
409 dfb->height = frame.size.height;
410 }
411 else {
412 xprAddPseudoramiXScreens(&dfb->x, &dfb->y, &dfb->width, &dfb->height,
413 pScreen);
414 }
415
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. */
419 dfb->pitch = 0;
420 dfb->framebuffer = NULL;
421
422 DRIScreenInit(pScreen);
423
424 return TRUE;
425}
426
427/*
428 * xprSetupScreen
429 * Setup the screen for rootless access.
430 */
431static Bool
432xprSetupScreen(int index, ScreenPtr pScreen)
433{
434#ifdef DAMAGE
435 // The Damage extension needs to wrap underneath the
436 // generic rootless layer, so do it now.
437 if (!DamageSetup(pScreen))
438 return FALSE;
439#endif
440
441 // Initialize generic rootless code
442 if (!xprInit(pScreen))
443 return FALSE;
444
445 return DRIFinishScreenInit(pScreen);
446}
447
448/*
449 * xprUpdateScreen
450 * Update screen after configuation change.
451 */
452static void
453xprUpdateScreen(ScreenPtr pScreen)
454{
455 rootlessGlobalOffsetX = darwinMainScreenX;
456 rootlessGlobalOffsetY = darwinMainScreenY;
457
458 AppleWMSetScreenOrigin(pScreen->root);
459
460 RootlessRepositionWindows(pScreen);
461 RootlessUpdateScreenPixmap(pScreen);
462}
463
464/*
465 * xprInitInput
466 * Finalize xpr specific setup.
467 */
468static void
469xprInitInput(int argc, char **argv)
470{
471 int i;
472
473 rootlessGlobalOffsetX = darwinMainScreenX;
474 rootlessGlobalOffsetY = darwinMainScreenY;
475
476 for (i = 0; i < screenInfo.numScreens; i++)
477 AppleWMSetScreenOrigin(screenInfo.screens[i]->root);
478}
479
480/*
481 * Quartz display mode function list.
482 */
483static QuartzModeProcsRec xprModeProcs = {
484 xprDisplayInit,
485 xprAddScreen,
486 xprSetupScreen,
487 xprInitInput,
488 QuartzInitCursor,
489 QuartzSuspendXCursor,
490 QuartzResumeXCursor,
491 xprAddPseudoramiXScreens,
492 xprUpdateScreen,
493 xprIsX11Window,
494 xprHideWindows,
495 RootlessFrameForWindow,
496 TopLevelParent,
497 DRICreateSurface,
498 DRIDestroySurface
499};
500
501/*
502 * QuartzModeBundleInit
503 * Initialize the display mode bundle after loading.
504 */
505Bool
506QuartzModeBundleInit(void)
507{
508 quartzProcs = &xprModeProcs;
509 quartzOpenGLBundle = xprOpenGLBundle;
510 return TRUE;
511}