More work to clean up compiler warnings.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 #include "SDL_config.h"
23 #if SDL_VIDEO_DRIVER_COCOA
25 #include "SDL_cocoavideo.h"
27 /* we need this for ShowMenuBar() and HideMenuBar(). */
28 #include <Carbon/Carbon.h>
30 static inline void Cocoa_ToggleMenuBar(const BOOL show)
32 /* !!! FIXME: keep an eye on this.
33 * ShowMenuBar/HideMenuBar is officially unavailable for 64-bit binaries.
34 * It happens to work, as of 10.7, but we're going to see if
35 * we can just simply do without it on newer OSes...
37 #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
46 /* !!! FIXME: clean out the pre-10.6 code when it makes sense to do so. */
47 #define FORCE_OLD_API 0 || (MAC_OS_X_VERSION_MAX_ALLOWED < 1060)
50 #undef MAC_OS_X_VERSION_MIN_REQUIRED
51 #define MAC_OS_X_VERSION_MIN_REQUIRED 1050
54 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
56 Add methods to get at private members of NSScreen.
57 Since there is a bug in Apple's screen switching code
58 that does not update this variable when switching
59 to fullscreen, we'll set it manually (but only for the
62 @interface NSScreen (NSScreenAccess)
63 - (void) setFrame:(NSRect)frame;
66 @implementation NSScreen (NSScreenAccess)
67 - (void) setFrame:(NSRect)frame;
75 IS_SNOW_LEOPARD_OR_LATER(_THIS)
80 return ((((SDL_VideoData *) _this->driverdata))->osversion >= 0x1060);
85 CG_SetError(const char *prefix, CGDisplayErr result)
91 error = "kCGErrorFailure";
93 case kCGErrorIllegalArgument:
94 error = "kCGErrorIllegalArgument";
96 case kCGErrorInvalidConnection:
97 error = "kCGErrorInvalidConnection";
99 case kCGErrorInvalidContext:
100 error = "kCGErrorInvalidContext";
102 case kCGErrorCannotComplete:
103 error = "kCGErrorCannotComplete";
105 case kCGErrorNameTooLong:
106 error = "kCGErrorNameTooLong";
108 case kCGErrorNotImplemented:
109 error = "kCGErrorNotImplemented";
111 case kCGErrorRangeCheck:
112 error = "kCGErrorRangeCheck";
114 case kCGErrorTypeCheck:
115 error = "kCGErrorTypeCheck";
117 case kCGErrorNoCurrentPoint:
118 error = "kCGErrorNoCurrentPoint";
120 case kCGErrorInvalidOperation:
121 error = "kCGErrorInvalidOperation";
123 case kCGErrorNoneAvailable:
124 error = "kCGErrorNoneAvailable";
127 error = "Unknown Error";
130 SDL_SetError("%s: %s", prefix, error);
134 GetDisplayMode(_THIS, const void *moderef, SDL_DisplayMode *mode)
136 SDL_DisplayModeData *data;
140 long refreshRate = 0;
142 data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
146 data->moderef = moderef;
148 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
149 if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
150 CGDisplayModeRef vidmode = (CGDisplayModeRef) moderef;
151 CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode);
152 width = (long) CGDisplayModeGetWidth(vidmode);
153 height = (long) CGDisplayModeGetHeight(vidmode);
154 refreshRate = (long) CGDisplayModeGetRefreshRate(vidmode);
156 if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
157 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
159 } else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
160 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
163 bpp = 0; /* ignore 8-bit and such for now. */
170 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
171 if (!IS_SNOW_LEOPARD_OR_LATER(_this)) {
173 CFDictionaryRef vidmode = (CFDictionaryRef) moderef;
174 number = CFDictionaryGetValue(vidmode, kCGDisplayWidth);
175 CFNumberGetValue(number, kCFNumberLongType, &width);
176 number = CFDictionaryGetValue(vidmode, kCGDisplayHeight);
177 CFNumberGetValue(number, kCFNumberLongType, &height);
178 number = CFDictionaryGetValue(vidmode, kCGDisplayBitsPerPixel);
179 CFNumberGetValue(number, kCFNumberLongType, &bpp);
180 number = CFDictionaryGetValue(vidmode, kCGDisplayRefreshRate);
181 CFNumberGetValue(number, kCFNumberLongType, &refreshRate);
185 mode->format = SDL_PIXELFORMAT_UNKNOWN;
188 mode->format = SDL_PIXELFORMAT_ARGB1555;
191 mode->format = SDL_PIXELFORMAT_ARGB8888;
193 case 8: /* We don't support palettized modes now */
194 default: /* Totally unrecognizable bit depth. */
199 mode->refresh_rate = refreshRate;
200 mode->driverdata = data;
205 Cocoa_ReleaseDisplayMode(_THIS, const void *moderef)
207 /* We don't own moderef unless we use the 10.6+ APIs. */
208 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
209 if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
210 CGDisplayModeRelease((CGDisplayModeRef) moderef); /* NULL is ok */
216 Cocoa_ReleaseDisplayModeList(_THIS, CFArrayRef modelist)
218 /* We don't own modelis unless we use the 10.6+ APIs. */
219 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
220 if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
221 CFRelease(modelist); /* NULL is ok */
227 Cocoa_InitModes(_THIS)
230 CGDirectDisplayID *displays;
231 CGDisplayCount numDisplays;
234 result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
235 if (result != kCGErrorSuccess) {
236 CG_SetError("CGGetOnlineDisplayList()", result);
239 displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays);
240 result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
241 if (result != kCGErrorSuccess) {
242 CG_SetError("CGGetOnlineDisplayList()", result);
243 SDL_stack_free(displays);
247 /* Pick up the primary display in the first pass, then get the rest */
248 for (pass = 0; pass < 2; ++pass) {
249 for (i = 0; i < numDisplays; ++i) {
250 SDL_VideoDisplay display;
251 SDL_DisplayData *displaydata;
252 SDL_DisplayMode mode;
253 const void *moderef = NULL;
256 if (!CGDisplayIsMain(displays[i])) {
260 if (CGDisplayIsMain(displays[i])) {
265 if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay) {
269 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
270 if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
271 moderef = CGDisplayCopyDisplayMode(displays[i]);
275 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
276 if (!IS_SNOW_LEOPARD_OR_LATER(_this)) {
277 moderef = CGDisplayCurrentMode(displays[i]);
285 displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
287 Cocoa_ReleaseDisplayMode(_this, moderef);
290 displaydata->display = displays[i];
293 if (!GetDisplayMode (_this, moderef, &mode)) {
294 Cocoa_ReleaseDisplayMode(_this, moderef);
295 SDL_free(displaydata);
299 display.desktop_mode = mode;
300 display.current_mode = mode;
301 display.driverdata = displaydata;
302 SDL_AddVideoDisplay(&display);
305 SDL_stack_free(displays);
309 Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
311 SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
314 cgrect = CGDisplayBounds(displaydata->display);
315 rect->x = (int)cgrect.origin.x;
316 rect->y = (int)cgrect.origin.y;
317 rect->w = (int)cgrect.size.width;
318 rect->h = (int)cgrect.size.height;
323 Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
325 SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
326 CFArrayRef modes = NULL;
328 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
329 if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
330 modes = CGDisplayCopyAllDisplayModes(data->display, NULL);
334 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
335 if (!IS_SNOW_LEOPARD_OR_LATER(_this)) {
336 modes = CGDisplayAvailableModes(data->display);
341 const CFIndex count = CFArrayGetCount(modes);
344 for (i = 0; i < count; i++) {
345 const void *moderef = CFArrayGetValueAtIndex(modes, i);
346 SDL_DisplayMode mode;
347 if (GetDisplayMode(_this, moderef, &mode)) {
348 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
349 if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
350 CGDisplayModeRetain((CGDisplayModeRef) moderef);
353 SDL_AddDisplayMode(display, &mode);
357 Cocoa_ReleaseDisplayModeList(_this, modes);
362 Cocoa_SwitchMode(_THIS, CGDirectDisplayID display, const void *mode)
364 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
365 if (IS_SNOW_LEOPARD_OR_LATER(_this)) {
366 return CGDisplaySetDisplayMode(display, (CGDisplayModeRef) mode, NULL);
370 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
371 if (!IS_SNOW_LEOPARD_OR_LATER(_this)) {
372 return CGDisplaySwitchToMode(display, (CFDictionaryRef) mode);
376 return kCGErrorFailure;
380 Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
382 SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
383 SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
384 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
387 /* Fade to black to hide resolution-switching flicker */
388 if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
389 CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
392 if (data == display->desktop_mode.driverdata) {
393 /* Restoring desktop mode */
394 Cocoa_SwitchMode(_this, displaydata->display, data->moderef);
396 if (CGDisplayIsMain(displaydata->display)) {
397 CGReleaseAllDisplays();
399 CGDisplayRelease(displaydata->display);
402 if (CGDisplayIsMain(displaydata->display)) {
403 Cocoa_ToggleMenuBar(YES);
406 /* Put up the blanking window (a window above all other windows) */
407 if (CGDisplayIsMain(displaydata->display)) {
408 /* If we don't capture all displays, Cocoa tries to rearrange windows... *sigh* */
409 result = CGCaptureAllDisplays();
411 result = CGDisplayCapture(displaydata->display);
413 if (result != kCGErrorSuccess) {
414 CG_SetError("CGDisplayCapture()", result);
418 /* Do the physical switch */
419 result = Cocoa_SwitchMode(_this, displaydata->display, data->moderef);
420 if (result != kCGErrorSuccess) {
421 CG_SetError("CGDisplaySwitchToMode()", result);
425 /* Hide the menu bar so it doesn't intercept events */
426 if (CGDisplayIsMain(displaydata->display)) {
427 Cocoa_ToggleMenuBar(NO);
431 /* Fade in again (asynchronously) */
432 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
433 CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
434 CGReleaseDisplayFadeReservation(fade_token);
439 /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
441 CGDisplayRelease(displaydata->display);
443 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
444 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
445 CGReleaseDisplayFadeReservation(fade_token);
451 Cocoa_QuitModes(_THIS)
455 for (i = 0; i < _this->num_displays; ++i) {
456 SDL_VideoDisplay *display = &_this->displays[i];
457 SDL_DisplayModeData *mode;
459 if (display->current_mode.driverdata != display->desktop_mode.driverdata) {
460 Cocoa_SetDisplayMode(_this, display, &display->desktop_mode);
463 mode = (SDL_DisplayModeData *) display->desktop_mode.driverdata;
464 Cocoa_ReleaseDisplayMode(_this, mode->moderef);
466 for (j = 0; j < display->num_display_modes; j++) {
467 mode = (SDL_DisplayModeData*) display->display_modes[j].driverdata;
468 Cocoa_ReleaseDisplayMode(_this, mode->moderef);
472 Cocoa_ToggleMenuBar(YES);
475 #endif /* SDL_VIDEO_DRIVER_COCOA */
477 /* vi: set ts=4 sw=4 expandtab: */