Cocoa: Monitor name cleanup

Only retrieve the display info dictionary once.  Remove non-standard
function name.
This commit is contained in:
Camilla Berglund 2016-11-15 20:39:39 +01:00
parent 94b8486d4b
commit d19a21bd01
2 changed files with 60 additions and 82 deletions

View File

@ -116,6 +116,8 @@ information on what to include when reporting a bug.
- [Cocoa] Added support for Vulkan window surface creation via MoltenVK (#870) - [Cocoa] Added support for Vulkan window surface creation via MoltenVK (#870)
- [Cocoa] Bugfix: Disabling window aspect ratio would assert (#852) - [Cocoa] Bugfix: Disabling window aspect ratio would assert (#852)
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883) - [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
- [Cocoa] Bugfix: Removed use of deprecated `CGDisplayIOServicePort` function
(#165,#192,#508,#511)
- [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871) - [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871)

View File

@ -36,108 +36,82 @@
#include <ApplicationServices/ApplicationServices.h> #include <ApplicationServices/ApplicationServices.h>
// Returns the io_service_t corresponding to a CG display ID, or 0 on failure. // Get the name of the specified display, or NULL
// 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) static char* getDisplayName(CGDirectDisplayID displayID)
{ {
char* name; io_iterator_t it;
CFDictionaryRef info, names; io_service_t service;
CFStringRef value; CFDictionaryRef info;
CFIndex size;
io_service_t serv = IOServicePortFromCGDisplayID(displayID); if (IOServiceGetMatchingServices(kIOMasterPortDefault,
if (!serv) IOServiceMatching("IODisplayConnect"),
&it) != 0)
{ {
return strdup("Unknown"); _glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to get display service port iterator");
return 0;
} }
info = IODisplayCreateInfoDictionary(serv, while ((service = IOIteratorNext(it)) != 0)
kIODisplayOnlyPreferredName); {
info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
IOObjectRelease(serv); CFNumberRef vendorIDRef =
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
CFNumberRef productIDRef =
CFDictionaryGetValue(info, CFSTR(kDisplayProductID));
if (!vendorIDRef || !productIDRef)
{
CFRelease(info);
continue;
}
names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName)); unsigned int vendorID, productID;
CFNumberGetValue(vendorIDRef, kCFNumberIntType, &vendorID);
CFNumberGetValue(productIDRef, kCFNumberIntType, &productID);
if (CGDisplayVendorNumber(displayID) == vendorID &&
CGDisplayModelNumber(displayID) == productID)
{
// Info dictionary is used and freed below
break;
}
CFRelease(info);
}
IOObjectRelease(it);
if (!service)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to find service port for display");
return NULL;
}
CFDictionaryRef names =
CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
CFStringRef nameRef;
if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"), if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
(const void**) &value)) (const void**) &nameRef))
{ {
// This may happen if a desktop Mac is running headless // This may happen if a desktop Mac is running headless
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to retrieve display name"); "Cocoa: Failed to retrieve display name");
CFRelease(info); CFRelease(info);
return strdup("Unknown"); return NULL;
} }
size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), const CFIndex size =
CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef),
kCFStringEncodingUTF8); kCFStringEncodingUTF8);
name = calloc(size + 1, 1); char* name = calloc(size + 1, 1);
CFStringGetCString(value, name, size, kCFStringEncodingUTF8); CFStringGetCString(nameRef, name, size, kCFStringEncodingUTF8);
CFRelease(info); CFRelease(info);
return name; return name;
} }
@ -332,6 +306,8 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
const CGSize size = CGDisplayScreenSize(displays[i]); const CGSize size = CGDisplayScreenSize(displays[i]);
char* name = getDisplayName(displays[i]); char* name = getDisplayName(displays[i]);
if (!name)
name = strdup("Unknown");
monitor = _glfwAllocMonitor(name, size.width, size.height); monitor = _glfwAllocMonitor(name, size.width, size.height);
monitor->ns.displayID = displays[i]; monitor->ns.displayID = displays[i];