diff --git a/readme.html b/readme.html index 5762b023..5f3af632 100644 --- a/readme.html +++ b/readme.html @@ -312,7 +312,7 @@ version of GLFW.

  • [Cocoa] Added support for joysticks
  • [Cocoa] Postponed menu creation to first window creation
  • [Cocoa] Replaced NSDate time source with mach_absolute_time
  • -
  • [Cocoa] Replaced deprecated CoreGraphics calls in video mode enumeration
  • +
  • [Cocoa] Replaced deprecated CoreGraphics calls in video mode enumeration and setting
  • [Cocoa] Bugfix: glfwOpenWindow did not properly enforce the forward-compatible and context profile hints
  • [Cocoa] Bugfix: The loop condition for saving video modes used the wrong index variable
  • [Cocoa] Bugfix: The OpenGL framework was not retrieved, making glfwGetProcAddress crash
  • diff --git a/src/cocoa_fullscreen.m b/src/cocoa_fullscreen.m index cc5df538..d3a715ba 100644 --- a/src/cocoa_fullscreen.m +++ b/src/cocoa_fullscreen.m @@ -29,6 +29,9 @@ #include "internal.h" +#include +#include + //======================================================================== // Check whether the display mode should be included in enumeration @@ -91,6 +94,100 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode) } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Change the current video mode +//======================================================================== + +GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate) +{ + CGDisplayModeRef bestMode = NULL; + CFArrayRef modes; + CFIndex count, i; + unsigned int leastSizeDiff = UINT_MAX; + double leastRateDiff = DBL_MAX; + + modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); + count = CFArrayGetCount(modes); + + for (i = 0; i < count; i++) + { + CGDisplayModeRef mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); + if (!modeIsGood(mode)) + continue; + + int modeBPP; + + // Identify display mode pixel encoding + { + CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); + + if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) + modeBPP = 16; + else + modeBPP = 32; + + CFRelease(format); + } + + int modeWidth = (int) CGDisplayModeGetWidth(mode); + int modeHeight = (int) CGDisplayModeGetHeight(mode); + + unsigned int sizeDiff = (abs(modeBPP - *bpp) << 25) | + ((modeWidth - *width) * (modeWidth - *width) + + (modeHeight - *height) * (modeHeight - *height)); + + double rateDiff; + + if (*refreshRate > 0) + rateDiff = fabs(CGDisplayModeGetRefreshRate(mode) - *refreshRate); + else + { + // If no refresh rate was specified, then they're all the same + rateDiff = 0; + } + + if ((sizeDiff < leastSizeDiff) || + (sizeDiff == leastSizeDiff && (rateDiff < leastRateDiff))) + { + bestMode = mode; + + leastSizeDiff = sizeDiff; + leastRateDiff = rateDiff; + } + } + + if (!bestMode) + { + CFRelease(modes); + return GL_FALSE; + } + + CGDisplayCapture(CGMainDisplayID()); + CGDisplaySetDisplayMode(CGMainDisplayID(), bestMode, NULL); + + CFRelease(modes); + return GL_TRUE; +} + + +//======================================================================== +// Restore the previously saved (original) video mode +//======================================================================== + +void _glfwRestoreVideoMode(void) +{ + CGDisplaySetDisplayMode(CGMainDisplayID(), + _glfwLibrary.NS.desktopMode, + NULL); + + CGDisplayRelease(CGMainDisplayID()); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 5a753707..a06c13a0 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -109,5 +109,8 @@ void _glfwInitTimer(void); void _glfwInitJoysticks(void); void _glfwTerminateJoysticks(void); +// Fullscreen +GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate); +void _glfwRestoreVideoMode(void); #endif // _platform_h_ diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 94a11118..c1d710c0 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -850,28 +850,6 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, // Don't use accumulation buffer support; it's not accelerated // Aux buffers probably aren't accelerated either - CFDictionaryRef fullscreenMode = NULL; - if (wndconfig->mode == GLFW_FULLSCREEN) - { - // I think it's safe to pass 0 to the refresh rate for this function - // rather than conditionalizing the code to call the version which - // doesn't specify refresh... - fullscreenMode = - CGDisplayBestModeForParametersAndRefreshRateWithProperty( - CGMainDisplayID(), - colorBits + fbconfig->alphaBits, - window->width, window->height, - wndconfig->refreshRate, - // Controversial, see macosx_fullscreen.m for discussion - kCGDisplayModeIsSafeForHardware, - NULL); - - window->width = - [[(id)fullscreenMode objectForKey:(id)kCGDisplayWidth] intValue]; - window->height = - [[(id)fullscreenMode objectForKey:(id)kCGDisplayHeight] intValue]; - } - if (!createWindow(window, wndconfig)) return GL_FALSE; @@ -883,8 +861,15 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, if (wndconfig->mode == GLFW_FULLSCREEN) { - CGCaptureAllDisplays(); - CGDisplaySwitchToMode(CGMainDisplayID(), fullscreenMode); + int bpp = colorBits + fbconfig->alphaBits; + + if (!_glfwSetVideoMode(&window->width, + &window->height, + &bpp, + &window->refreshRate)) + { + return GL_FALSE; + } [[window->NS.window contentView] enterFullScreenMode:[NSScreen mainScreen] withOptions:nil]; @@ -914,9 +899,7 @@ void _glfwPlatformCloseWindow(_GLFWwindow* window) { [[window->NS.window contentView] exitFullScreenModeWithOptions:nil]; - CGDisplaySwitchToMode(CGMainDisplayID(), - (CFDictionaryRef) _glfwLibrary.NS.desktopMode); - CGReleaseAllDisplays(); + _glfwRestoreVideoMode(); } [window->NSGL.pixelFormat release];