21 #include "../../SDL_internal.h"
24 #if SDL_VIDEO_DRIVER_COCOA
29 #include <IOKit/graphics/IOGraphicsLib.h>
32 #include <CoreVideo/CVBase.h>
33 #include <CoreVideo/CVDisplayLink.h>
36 #include <Carbon/Carbon.h>
39 #include <AvailabilityMacros.h>
43 Cocoa_ToggleMenuBar(
const BOOL show)
50 #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
60 CG_SetError(
const char *prefix, CGDisplayErr
result)
66 error =
"kCGErrorFailure";
68 case kCGErrorIllegalArgument:
69 error =
"kCGErrorIllegalArgument";
71 case kCGErrorInvalidConnection:
72 error =
"kCGErrorInvalidConnection";
74 case kCGErrorInvalidContext:
75 error =
"kCGErrorInvalidContext";
77 case kCGErrorCannotComplete:
78 error =
"kCGErrorCannotComplete";
80 case kCGErrorNotImplemented:
81 error =
"kCGErrorNotImplemented";
83 case kCGErrorRangeCheck:
84 error =
"kCGErrorRangeCheck";
86 case kCGErrorTypeCheck:
87 error =
"kCGErrorTypeCheck";
89 case kCGErrorInvalidOperation:
90 error =
"kCGErrorInvalidOperation";
92 case kCGErrorNoneAvailable:
93 error =
"kCGErrorNoneAvailable";
96 error =
"Unknown Error";
116 data->moderef = vidmode;
118 fmt = CGDisplayModeCopyPixelEncoding(vidmode);
119 width = (int) CGDisplayModeGetWidth(vidmode);
120 height = (int) CGDisplayModeGetHeight(vidmode);
121 refreshRate = (int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
123 if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
124 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
126 }
else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
127 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
129 }
else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
130 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
139 if (refreshRate == 0 && link !=
NULL) {
140 CVTime
time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
141 if ((
time.flags & kCVTimeIsIndefinite) == 0 &&
time.timeValue != 0) {
142 refreshRate = (int) ((
time.timeScale / (
double)
time.timeValue) + 0.5);
164 mode->refresh_rate = refreshRate;
170 Cocoa_GetDisplayName(CGDirectDisplayID displayID)
172 CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), kIODisplayOnlyPreferredName);
173 NSDictionary *localizedNames = [(NSDictionary *)deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
174 const char* displayName =
NULL;
176 if ([localizedNames
count] > 0) {
177 displayName =
SDL_strdup([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
179 CFRelease(deviceInfo);
188 CGDirectDisplayID *displays;
189 CGDisplayCount numDisplays;
193 result = CGGetOnlineDisplayList(0,
NULL, &numDisplays);
194 if (
result != kCGErrorSuccess) {
195 CG_SetError(
"CGGetOnlineDisplayList()",
result);
199 result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
200 if (
result != kCGErrorSuccess) {
201 CG_SetError(
"CGGetOnlineDisplayList()",
result);
207 for (pass = 0; pass < 2; ++pass) {
208 for (
i = 0;
i < numDisplays; ++
i) {
212 CGDisplayModeRef moderef =
NULL;
213 CVDisplayLinkRef link =
NULL;
216 if (!CGDisplayIsMain(displays[
i])) {
220 if (CGDisplayIsMain(displays[
i])) {
225 if (CGDisplayMirrorsDisplay(displays[
i]) != kCGNullDirectDisplay) {
229 moderef = CGDisplayCopyDisplayMode(displays[
i]);
237 CGDisplayModeRelease(moderef);
240 displaydata->
display = displays[i];
242 CVDisplayLinkCreateWithCGDisplay(displays[
i], &link);
246 display.
name = (
char *)Cocoa_GetDisplayName(displays[
i]);
247 if (!GetDisplayMode(
_this, moderef, link, &
mode)) {
248 CVDisplayLinkRelease(link);
249 CGDisplayModeRelease(moderef);
255 CVDisplayLinkRelease(link);
273 cgrect = CGDisplayBounds(displaydata->
display);
274 rect->
x = (int)cgrect.origin.x;
275 rect->
y = (
int)cgrect.origin.y;
276 rect->
w = (int)cgrect.size.width;
277 rect->
h = (
int)cgrect.size.height;
285 const CGDirectDisplayID cgdisplay = displaydata->
display;
286 NSArray *screens = [NSScreen screens];
290 for (NSScreen *
i in screens) {
291 const CGDirectDisplayID thisDisplay = (CGDirectDisplayID) [[[
i deviceDescription] objectForKey:
@"NSScreenNumber"] unsignedIntValue];
292 if (thisDisplay == cgdisplay) {
303 const NSRect
frame = [screen visibleFrame];
315 const float MM_IN_INCH = 25.4f;
319 CGSize displaySize = CGDisplayScreenSize(
data->display);
320 int pixelWidth = (int) CGDisplayPixelsWide(
data->display);
321 int pixelHeight = (int) CGDisplayPixelsHigh(
data->display);
324 *ddpi =
SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH);
327 *hdpi = pixelWidth * MM_IN_INCH / displaySize.width;
330 *vdpi = pixelHeight * MM_IN_INCH / displaySize.height;
340 CVDisplayLinkRef link =
NULL;
341 CGDisplayModeRef desktopmoderef;
345 CVDisplayLinkCreateWithCGDisplay(
data->display, &link);
347 desktopmoderef = CGDisplayCopyDisplayMode(
data->display);
355 if (desktopmoderef && GetDisplayMode(
_this, desktopmoderef, link, &desktopmode)) {
357 CGDisplayModeRelease(desktopmoderef);
361 CGDisplayModeRelease(desktopmoderef);
364 modes = CGDisplayCopyAllDisplayModes(
data->display,
NULL);
368 const CFIndex
count = CFArrayGetCount(modes);
371 CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes,
i);
374 if (GetDisplayMode(
_this, moderef, link, &
mode)) {
376 CGDisplayModeRetain(moderef);
386 CVDisplayLinkRelease(link);
394 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
398 if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
399 CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0,
TRUE);
406 if (CGDisplayIsMain(displaydata->
display)) {
407 CGReleaseAllDisplays();
409 CGDisplayRelease(displaydata->
display);
412 if (CGDisplayIsMain(displaydata->
display)) {
413 Cocoa_ToggleMenuBar(YES);
417 if (CGDisplayIsMain(displaydata->
display)) {
419 result = CGCaptureAllDisplays();
423 if (
result != kCGErrorSuccess) {
424 CG_SetError(
"CGDisplayCapture()",
result);
430 if (
result != kCGErrorSuccess) {
431 CG_SetError(
"CGDisplaySwitchToMode()",
result);
436 if (CGDisplayIsMain(displaydata->
display)) {
437 Cocoa_ToggleMenuBar(NO);
442 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
443 CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0,
FALSE);
444 CGReleaseDisplayFadeReservation(fade_token);
451 CGDisplayRelease(displaydata->
display);
453 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
454 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0,
FALSE);
455 CGReleaseDisplayFadeReservation(fade_token);
470 Cocoa_SetDisplayMode(_this, display, &display->desktop_mode);
474 CGDisplayModeRelease(
mode->moderef);
478 CGDisplayModeRelease(
mode->moderef);
482 Cocoa_ToggleMenuBar(YES);