diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 0d6cb8fd..d0298a7a 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -36,6 +36,68 @@ #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. +// +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 // static char* getDisplayName(CGDirectDisplayID displayID) @@ -45,10 +107,17 @@ static char* getDisplayName(CGDirectDisplayID displayID) CFStringRef value; CFIndex size; - // NOTE: This uses a deprecated function because Apple has - // (as of January 2015) not provided any alternative - info = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID), - kIODisplayOnlyPreferredName); + 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"),