|
|
|
@ -36,109 +36,73 @@ |
|
|
|
|
#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. |
|
|
|
|
// 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; |
|
|
|
|
|
|
|
|
|
CFMutableDictionaryRef matching = IOServiceMatching("IODisplayConnect"); |
|
|
|
|
|
|
|
|
|
// releases matching for us |
|
|
|
|
kern_return_t err = IOServiceGetMatchingServices(kIOMasterPortDefault, |
|
|
|
|
matching, |
|
|
|
|
&iter); |
|
|
|
|
if (err) |
|
|
|
|
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 0; |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
while ((serv = IOIteratorNext(iter)) != 0) |
|
|
|
|
|
|
|
|
|
CFMutableDictionaryRef matching = IOServiceMatching("IODisplayConnect"); |
|
|
|
|
|
|
|
|
|
if (IOServiceGetMatchingServices(kIOMasterPortDefault, matching, &iter) != 0) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
while ((service = 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) |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// we're a match |
|
|
|
|
servicePort = serv; |
|
|
|
|
CFRelease(info); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IOObjectRelease(iter); |
|
|
|
|
return servicePort; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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"); |
|
|
|
|
if (!CFDictionaryGetValueIfPresent(names, CFSTR("en_US"), |
|
|
|
|
(const void**) &name)) |
|
|
|
|
{ |
|
|
|
|
CFRelease(info); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), |
|
|
|
|
kCFStringEncodingUTF8); |
|
|
|
|
result = calloc(size + 1, sizeof(char)); |
|
|
|
|
CFStringGetCString(name, result, size, kCFStringEncodingUTF8); |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IOObjectRelease(iter); |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Check whether the display mode should be included in enumeration |
|
|
|
|
// |
|
|
|
@ -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++) |
|
|
|
|