Replace CGDisplayIOServicePort with a workaround

This could be cleaned up and refined a bit by comparing more display
attributes when available, but it gets the job done.

Closes #192.
This commit is contained in:
Matthew Henry 2013-12-14 01:03:39 +10:00 committed by Camilla Berglund
parent d2cc815009
commit bebae14223

View File

@ -36,6 +36,68 @@
#include <CoreVideo/CVDisplayLink.h> #include <CoreVideo/CVDisplayLink.h>
// Returns the io_service_t corresponding to a CG display ID, or 0 on failure.
// The io_service_t should be released with IOObjectRelease when not needed.
//
static io_service_t IOServicePortFromCGDisplayID(CGDirectDisplayID displayID)
{
io_iterator_t iter;
io_service_t serv, servicePort = 0;
CFMutableDictionaryRef matching = IOServiceMatching("IODisplayConnect");
// releases matching for us
kern_return_t err = IOServiceGetMatchingServices(kIOMasterPortDefault,
matching,
&iter);
if (err)
{
return 0;
}
while ((serv = IOIteratorNext(iter)) != 0)
{
CFDictionaryRef info;
CFIndex vendorID, productID;
CFNumberRef vendorIDRef, productIDRef;
Boolean success;
info = IODisplayCreateInfoDictionary(serv,
kIODisplayOnlyPreferredName);
vendorIDRef = CFDictionaryGetValue(info,
CFSTR(kDisplayVendorID));
productIDRef = CFDictionaryGetValue(info,
CFSTR(kDisplayProductID));
success = CFNumberGetValue(vendorIDRef, kCFNumberCFIndexType,
&vendorID);
success &= CFNumberGetValue(productIDRef, kCFNumberCFIndexType,
&productID);
if (!success)
{
CFRelease(info);
continue;
}
if (CGDisplayVendorNumber(displayID) != vendorID ||
CGDisplayModelNumber(displayID) != productID)
{
CFRelease(info);
continue;
}
// we're a match
servicePort = serv;
CFRelease(info);
break;
}
IOObjectRelease(iter);
return servicePort;
}
// Get the name of the specified display // Get the name of the specified display
// //
static const char* getDisplayName(CGDirectDisplayID displayID) static const char* getDisplayName(CGDirectDisplayID displayID)
@ -44,31 +106,40 @@ static const char* getDisplayName(CGDirectDisplayID displayID)
CFDictionaryRef info, names; CFDictionaryRef info, names;
CFStringRef value; CFStringRef value;
CFIndex size; CFIndex size;
info = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), io_service_t serv = IOServicePortFromCGDisplayID(displayID);
kIODisplayOnlyPreferredName); if (!serv)
{
return strdup("Unknown");
}
info = IODisplayCreateInfoDictionary(serv,
kIODisplayOnlyPreferredName);
IOObjectRelease(serv);
names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName)); names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"), if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
(const void**) &value)) (const void**) &value))
{ {
// This may happen if a desktop Mac is running headless // This may happen if a desktop Mac is running headless
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to retrieve display name"); _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to retrieve display name");
CFRelease(info); CFRelease(info);
return strdup("Unknown"); return strdup("Unknown");
} }
size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value),
kCFStringEncodingUTF8); kCFStringEncodingUTF8);
name = calloc(size + 1, sizeof(char)); name = calloc(size + 1, sizeof(char));
CFStringGetCString(value, name, size, kCFStringEncodingUTF8); CFStringGetCString(value, name, size, kCFStringEncodingUTF8);
CFRelease(info); CFRelease(info);
return name; return name;
} }
// Check whether the display mode should be included in enumeration // Check whether the display mode should be included in enumeration
// //
static GLboolean modeIsGood(CGDisplayModeRef mode) static GLboolean modeIsGood(CGDisplayModeRef mode)