Cleanup of CGDisplayIOServicePort replacement.

This commit is contained in:
Camilla Berglund 2014-03-10 16:50:20 +01:00
parent bebae14223
commit 43095307da
2 changed files with 59 additions and 88 deletions

View File

@ -123,6 +123,7 @@ skills.
- Marcus Geelnard - Marcus Geelnard
- Stefan Gustavson - Stefan Gustavson
- Sylvain Hellegouarch - Sylvain Hellegouarch
- Matthew Henry
- heromyth - heromyth
- Paul Holden - Paul Holden
- Toni Jovanoski - Toni Jovanoski

View File

@ -36,110 +36,74 @@
#include <CoreVideo/CVDisplayLink.h> #include <CoreVideo/CVDisplayLink.h>
// Returns the io_service_t corresponding to a CG display ID, or 0 on failure. // Returns the name of the specified display
// The io_service_t should be released with IOObjectRelease when not needed.
// //
static io_service_t IOServicePortFromCGDisplayID(CGDirectDisplayID displayID) static char* getDisplayName(CGDirectDisplayID displayID)
{ {
io_iterator_t iter; io_iterator_t iter;
io_service_t serv, servicePort = 0; io_service_t service;
char* result = NULL;
const uint32_t modelNumber = CGDisplayModelNumber(displayID);
const uint32_t vendorNumber = CGDisplayVendorNumber(displayID);
if (modelNumber == kDisplayProductIDGeneric || modelNumber == 0xffffffff ||
vendorNumber == kDisplayVendorIDUnknown || vendorNumber == 0xffffffff)
{
return NULL;
}
CFMutableDictionaryRef matching = IOServiceMatching("IODisplayConnect"); CFMutableDictionaryRef matching = IOServiceMatching("IODisplayConnect");
// releases matching for us if (IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iter) != 0)
kern_return_t err = IOServiceGetMatchingServices(kIOMasterPortDefault, return NULL;
matching,
&iter); while ((service = IOIteratorNext(iter)) != 0)
if (err)
{ {
return 0; CFIndex size, vendorID, productID;
} CFDictionaryRef info, names;
CFStringRef name;
while ((serv = IOIteratorNext(iter)) != 0) info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
{
CFDictionaryRef info;
CFIndex vendorID, productID;
CFNumberRef vendorIDRef, productIDRef;
Boolean success;
info = IODisplayCreateInfoDictionary(serv, CFNumberGetValue(CFDictionaryGetValue(info, CFSTR(kDisplayVendorID)),
kIODisplayOnlyPreferredName); kCFNumberCFIndexType, &vendorID);
CFNumberGetValue(CFDictionaryGetValue(info, CFSTR(kDisplayProductID)),
kCFNumberCFIndexType, &productID);
vendorIDRef = CFDictionaryGetValue(info, if (vendorNumber != vendorID || modelNumber != productID)
CFSTR(kDisplayVendorID));
productIDRef = CFDictionaryGetValue(info,
CFSTR(kDisplayProductID));
success = CFNumberGetValue(vendorIDRef, kCFNumberCFIndexType,
&vendorID);
success &= CFNumberGetValue(productIDRef, kCFNumberCFIndexType,
&productID);
if (!success)
{ {
CFRelease(info); CFRelease(info);
continue; continue;
} }
if (CGDisplayVendorNumber(displayID) != vendorID || names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
CGDisplayModelNumber(displayID) != productID) if (!names)
{
// This may happen if a desktop Mac is running headless
CFRelease(info);
continue;
}
if (!CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
(const void**) &name))
{ {
CFRelease(info); CFRelease(info);
continue; continue;
} }
// we're a match size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name),
servicePort = serv; kCFStringEncodingUTF8);
result = calloc(size + 1, sizeof(char));
CFStringGetCString(name, result, size, kCFStringEncodingUTF8);
CFRelease(info); CFRelease(info);
break;
} }
IOObjectRelease(iter); IOObjectRelease(iter);
return servicePort; return result;
} }
// Get the name of the specified display
//
static const char* getDisplayName(CGDirectDisplayID displayID)
{
char* name;
CFDictionaryRef info, names;
CFStringRef value;
CFIndex size;
io_service_t serv = IOServicePortFromCGDisplayID(displayID);
if (!serv)
{
return strdup("Unknown");
}
info = IODisplayCreateInfoDictionary(serv,
kIODisplayOnlyPreferredName);
IOObjectRelease(serv);
names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
(const void**) &value))
{
// This may happen if a desktop Mac is running headless
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to retrieve display name");
CFRelease(info);
return strdup("Unknown");
}
size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value),
kCFStringEncodingUTF8);
name = calloc(size + 1, sizeof(char));
CFStringGetCString(value, name, size, kCFStringEncodingUTF8);
CFRelease(info);
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)
@ -332,10 +296,16 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{ {
int j; int j;
const CGSize size = CGDisplayScreenSize(displays[i]); const CGSize size = CGDisplayScreenSize(displays[i]);
char* name = getDisplayName(displays[i]);
monitors[found] = _glfwAllocMonitor(getDisplayName(displays[i]), if (!name)
size.width, size.height); {
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to retrieve display name");
name = strdup("Unknown");
}
monitors[found] = _glfwAllocMonitor(name, size.width, size.height);
monitors[found]->ns.displayID = displays[i]; monitors[found]->ns.displayID = displays[i];
for (j = 0; j < [screens count]; j++) for (j = 0; j < [screens count]; j++)