From e0a6772e5e4c672179fc69a90bcda3369792ed1f Mon Sep 17 00:00:00 2001 From: "Jared P. Jones" Date: Sun, 10 May 2015 03:11:14 -0500 Subject: [PATCH 1/2] Fixed Deprecated CGDisplayIOServicePort *A function has manually been created that deals with grabbing the approriate service_io port. *This function adds support for collision detection against the VendorID, ProductID, and the SerialNumber. The serial number check is required incase a user has two types of identical monitors. *Supports OS X 10.4 (Tiger) and Newer (Untested, based on API Docs) I would like to give special thanks to mhernr18 for providing the initial code. Recloses #165 --- include/GLFW/glfw3native.h | 11 +++++ src/cocoa_monitor.m | 86 ++++++++++++++++++++++++++++++++++++-- src/nsgl_context.m | 5 +++ 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/include/GLFW/glfw3native.h b/include/GLFW/glfw3native.h index b3ce7482d..f37c92d0e 100644 --- a/include/GLFW/glfw3native.h +++ b/include/GLFW/glfw3native.h @@ -56,6 +56,7 @@ extern "C" { * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` * * `GLFW_EXPOSE_NATIVE_NSGL` + * * `GLFW_EXPOSE_NATIVE_CGL` * * `GLFW_EXPOSE_NATIVE_GLX` * * `GLFW_EXPOSE_NATIVE_EGL` * @@ -94,6 +95,8 @@ extern "C" { /* WGL is declared by windows.h */ #elif defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ +#elif defined(GLFW_EXPOSE_NATIVE_CGL) + #include #elif defined(GLFW_EXPOSE_NATIVE_GLX) #include #elif defined(GLFW_EXPOSE_NATIVE_EGL) @@ -221,6 +224,14 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window); */ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window); #endif + +#if defined(GLFW_EXPOSE_NATIVE_CGL) + /*! @brief Returns the `CGLContextObj` of the specified window. + * @return The `CGLContextObj` of the specified window. + * @ingroup native + */ + GLFWAPI CGLContextObj glfwGetCGLContext(GLFWwindow* window); +#endif #if defined(GLFW_EXPOSE_NATIVE_X11) /*! @brief Returns the `Display` used by GLFW. diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index a99aa33f4..d05d287b8 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -38,6 +38,76 @@ #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, serialNumber; + CFNumberRef vendorIDRef, productIDRef, serialNumberRef; + Boolean success; + + info = IODisplayCreateInfoDictionary(serv, + kIODisplayOnlyPreferredName); + + vendorIDRef = CFDictionaryGetValue(info, + CFSTR(kDisplayVendorID)); + productIDRef = CFDictionaryGetValue(info, + CFSTR(kDisplayProductID)); + serialNumberRef = CFDictionaryGetValue(info, + CFSTR(kDisplaySerialNumber)); + + success = CFNumberGetValue(vendorIDRef, kCFNumberCFIndexType, + &vendorID); + success &= CFNumberGetValue(productIDRef, kCFNumberCFIndexType, + &productID); + success &= CFNumberGetValue(serialNumberRef, kCFNumberCFIndexType, + &serialNumber); + + if (!success) + { + CFRelease(info); + continue; + } + + // If the vendor and product id along with the serial don't match + // then we are not looking at the correct monitor. + // NOTE: The serial number is important in cases where two monitors + // are the exact same. + if (CGDisplayVendorNumber(displayID) != vendorID || + CGDisplayModelNumber(displayID) != productID || + CGDisplaySerialNumber(displayID) != serialNumber) + { + CFRelease(info); + continue; + } + + // The VendorID, Product ID, and the Serial Number all Match Up! + // Therefore we have found the appropriate display io_service + servicePort = serv; + CFRelease(info); + break; + } + + IOObjectRelease(iter); + return servicePort; +} + // Get the name of the specified display // static char* getDisplayName(CGDirectDisplayID displayID) @@ -47,10 +117,18 @@ 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); + // Supports OS X 10.4 Tiger and Newer + io_service_t serv = IOServicePortFromCGDisplayID(displayID); + if (serv == 0) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: IOServicePortFromCGDisplayID Returned an Invalid Port. (Port: 0)"); + return strdup("Unknown"); + } + + info = IODisplayCreateInfoDictionary(serv, kIODisplayOnlyPreferredName); + IOObjectRelease(serv); + names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName)); if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"), diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 28758060f..b614874a7 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -306,3 +306,8 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) return window->nsgl.context; } +GLFWAPI CGLContextObj glfwGetCGLContext(GLFWwindow* handle) +{ + NSOpenGLContext* ctx = glfwGetNSGLContext(handle); + return [ctx CGLContextObj]; +} \ No newline at end of file From 8e3c423ed423a65f15e87b1d38507138dbb663a5 Mon Sep 17 00:00:00 2001 From: Moritz Pflanzer Date: Tue, 12 May 2015 17:13:00 +0100 Subject: [PATCH 2/2] Fixed problem with no existing serial number for built-in display --- src/cocoa_monitor.m | 71 +++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index d05d287b8..1832a81a1 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -55,55 +55,58 @@ static io_service_t IOServicePortFromCGDisplayID(CGDirectDisplayID displayID) if (err) return 0; - while ((serv = IOIteratorNext(iter)) != 0) + while((serv = IOIteratorNext(iter)) != 0) { - CFDictionaryRef info; - CFIndex vendorID, productID, serialNumber; - CFNumberRef vendorIDRef, productIDRef, serialNumberRef; + CFDictionaryRef displayInfo; + + CFNumberRef vendorIDRef; + CFNumberRef productIDRef; + CFNumberRef serialNumberRef; + + NSNumber *vendorID; + NSNumber *productID; + NSNumber *serialNumber; + Boolean success; - - info = IODisplayCreateInfoDictionary(serv, - kIODisplayOnlyPreferredName); - - vendorIDRef = CFDictionaryGetValue(info, - CFSTR(kDisplayVendorID)); - productIDRef = CFDictionaryGetValue(info, - CFSTR(kDisplayProductID)); - serialNumberRef = CFDictionaryGetValue(info, - CFSTR(kDisplaySerialNumber)); - - success = CFNumberGetValue(vendorIDRef, kCFNumberCFIndexType, - &vendorID); - success &= CFNumberGetValue(productIDRef, kCFNumberCFIndexType, - &productID); - success &= CFNumberGetValue(serialNumberRef, kCFNumberCFIndexType, - &serialNumber); - - if (!success) + + displayInfo = IODisplayCreateInfoDictionary(serv, kIODisplayOnlyPreferredName); + + success = CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplayVendorID), (const void**)&vendorIDRef); + success &= CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplayProductID), (const void**)&productIDRef); + + if(!success) { - CFRelease(info); + CFRelease(displayInfo); continue; } - + + vendorID = (__bridge NSNumber*)vendorIDRef; + productID = (__bridge NSNumber*)productIDRef; + + // If a serial number is found use it + // Otherwise serial number will be nil (= 0) which will match with the output of 'CGDisplaySerialNumber' + if(CFDictionaryGetValueIfPresent(displayInfo, CFSTR(kDisplaySerialNumber), (const void**)&serialNumberRef)) + { + serialNumber = (__bridge NSNumber*)serialNumberRef; + } + // If the vendor and product id along with the serial don't match // then we are not looking at the correct monitor. // NOTE: The serial number is important in cases where two monitors // are the exact same. - if (CGDisplayVendorNumber(displayID) != vendorID || - CGDisplayModelNumber(displayID) != productID || - CGDisplaySerialNumber(displayID) != serialNumber) + if(CGDisplayVendorNumber(displayID) != vendorID.unsignedIntValue || + CGDisplayModelNumber(displayID) != productID.unsignedIntValue || + CGDisplaySerialNumber(displayID) != serialNumber.unsignedIntValue) { - CFRelease(info); + CFRelease(displayInfo); continue; } - - // The VendorID, Product ID, and the Serial Number all Match Up! - // Therefore we have found the appropriate display io_service + servicePort = serv; - CFRelease(info); + CFRelease(displayInfo); break; } - + IOObjectRelease(iter); return servicePort; }