From 43095307da327e82f136c5fe17d4fdecb3f78cb6 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Mon, 10 Mar 2014 16:50:20 +0100 Subject: [PATCH] Cleanup of CGDisplayIOServicePort replacement. --- README.md | 1 + src/cocoa_monitor.m | 146 ++++++++++++++++++-------------------------- 2 files changed, 59 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index ef57db63..64d5a114 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,7 @@ skills. - Marcus Geelnard - Stefan Gustavson - Sylvain Hellegouarch + - Matthew Henry - heromyth - Paul Holden - Toni Jovanoski diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index a2f9a7f1..ab401ca1 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -36,110 +36,74 @@ #include -// 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. +// Returns the name of the specified display // -static io_service_t IOServicePortFromCGDisplayID(CGDirectDisplayID displayID) +static char* getDisplayName(CGDirectDisplayID displayID) { 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"); - - // 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) + if (IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iter) != 0) + return NULL; + + while ((service = IOIteratorNext(iter)) != 0) + { + CFIndex size, vendorID, productID; + CFDictionaryRef info, names; + CFStringRef name; + + info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName); + + CFNumberGetValue(CFDictionaryGetValue(info, CFSTR(kDisplayVendorID)), + kCFNumberCFIndexType, &vendorID); + CFNumberGetValue(CFDictionaryGetValue(info, CFSTR(kDisplayProductID)), + kCFNumberCFIndexType, &productID); + + if (vendorNumber != vendorID || modelNumber != productID) { CFRelease(info); continue; } - - if (CGDisplayVendorNumber(displayID) != vendorID || - CGDisplayModelNumber(displayID) != productID) + + names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName)); + 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); continue; } - - // we're a match - servicePort = serv; + + size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), + kCFStringEncodingUTF8); + result = calloc(size + 1, sizeof(char)); + CFStringGetCString(name, result, size, kCFStringEncodingUTF8); + CFRelease(info); - break; } - + 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 // static GLboolean modeIsGood(CGDisplayModeRef mode) @@ -332,10 +296,16 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) { int j; const CGSize size = CGDisplayScreenSize(displays[i]); + char* name = getDisplayName(displays[i]); - monitors[found] = _glfwAllocMonitor(getDisplayName(displays[i]), - size.width, size.height); + if (!name) + { + _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]; for (j = 0; j < [screens count]; j++)