diff --git a/README.md b/README.md index 44770590..398f31d4 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ located in the `deps/` directory. functions - [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in examples - - [Nuklear](https://github.com/vurtun/nuklear) for test and example UI + - [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) for test and example UI - [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk The documentation is generated with [Doxygen](http://doxygen.org/) if CMake can @@ -138,6 +138,11 @@ information on what to include when reporting a bug. - [Cocoa] Bugfix: Failing to retrieve the refresh rate of built-in displays could leak memory - [Cocoa] Bugfix: Objective-C files were compiled as C with CMake 3.19 (#1787) + - [Cocoa] Bugfix: Duplicate video modes were not filtered out (#1830) + - [Cocoa] Bugfix: Menubar was not clickable on macOS 10.15+ until it lost and + regained focus (#1648,#1802) + - [Cocoa] Bugfix: Monitor name query could segfault on macOS 11 (#1809,#1833) + - [Cocoa] Bugfix: The install name of the installed dylib was relative (#1504) - [X11] Bugfix: IME input of CJK was broken for "C" locale (#1587,#1636) - [X11] Bugfix: Xlib errors caused by other parts of the application could be reported as GLFW errors @@ -179,13 +184,16 @@ GLFW exists because people around the world donated their time and lent their skills. - Bobyshev Alexander + - Laurent Aphecetche - Matt Arsenault + - ashishgamedev - David Avedissian - Keith Bauer - John Bartholomew - Coşku Baş - Niklas Behrens - Andrew Belt + - Nevyn Bengtsson - Niklas Bergström - Denis Bernard - Doug Binks @@ -369,6 +377,7 @@ skills. - Waris - Jay Weisskopf - Frank Wille + - Richard A. Wilkes - Tatsuya Yatagawa - Ryogo Yoshimura - Lukas Zanner diff --git a/docs/vulkan.dox b/docs/vulkan.dox index 2585c2bb..68e3d5fe 100644 --- a/docs/vulkan.dox +++ b/docs/vulkan.dox @@ -93,7 +93,7 @@ if (glfwVulkanSupported()) This function returns `GLFW_TRUE` if the Vulkan loader and any minimally functional ICD was found. -If if one or both were not found, calling any other Vulkan related GLFW function +If one or both were not found, calling any other Vulkan related GLFW function will generate a @ref GLFW_API_UNAVAILABLE error. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e18b14aa..a409459b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,7 +63,7 @@ elseif (_GLFW_OSMESA) endif() if (_GLFW_X11 OR _GLFW_WAYLAND) - if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") set(glfw_HEADERS ${glfw_HEADERS} linux_joystick.h) set(glfw_SOURCES ${glfw_SOURCES} linux_joystick.c) else() @@ -73,7 +73,7 @@ if (_GLFW_X11 OR _GLFW_WAYLAND) endif() # Workaround for CMake not knowing about .m files before version 3.16 -if ("${CMAKE_VERSION}" VERSION_LESS "3.16" AND APPLE) +if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE) set_source_files_properties(cocoa_init.m cocoa_joystick.m cocoa_monitor.m cocoa_window.m nsgl_context.m PROPERTIES LANGUAGE C) @@ -87,8 +87,8 @@ set_target_properties(glfw PROPERTIES POSITION_INDEPENDENT_CODE ON FOLDER "GLFW3") -if (${CMAKE_VERSION} VERSION_EQUAL "3.1.0" OR - ${CMAKE_VERSION} VERSION_GREATER "3.1.0") +if (CMAKE_VERSION VERSION_EQUAL "3.1.0" OR + CMAKE_VERSION VERSION_GREATER "3.1.0") set_target_properties(glfw PROPERTIES C_STANDARD 99) else() @@ -111,7 +111,7 @@ target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES}) # Make GCC warn about declarations that VS 2010 and 2012 won't accept for all # source files that VS will build (Clang ignores this because we set -std=c99) -if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") +if (CMAKE_C_COMPILER_ID STREQUAL "GNU") set_source_files_properties(context.c init.c input.c monitor.c vulkan.c window.c win32_init.c win32_joystick.c win32_monitor.c win32_time.c win32_thread.c @@ -121,11 +121,11 @@ if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") endif() # Enable a reasonable set of warnings -if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR - "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR - "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") +if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR + CMAKE_C_COMPILER_ID STREQUAL "Clang" OR + CMAKE_C_COMPILER_ID STREQUAL "AppleClang") - if ("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC") + if (CMAKE_C_SIMULATE_ID STREQUAL "MSVC") # Tell Clang-CL that this is a Clang flag target_compile_options(glfw PRIVATE "/clang:-Wall") else() @@ -168,9 +168,6 @@ if (BUILD_SHARED_LIBS) elseif (APPLE) # Add -fno-common to work around a bug in Apple's GCC target_compile_options(glfw PRIVATE "-fno-common") - - set_target_properties(glfw PROPERTIES - INSTALL_NAME_DIR "${CMAKE_INSTALL_LIBDIR}") endif() if (UNIX) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 579b6e6c..209639e2 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -428,9 +428,6 @@ static GLFWbool initializeTIS(void) { if (_glfw.hints.init.ns.menubar) { - // In case we are unbundled, make us a proper UI application - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - // Menu bar setup must go between sharedApplication and finishLaunching // in order to properly emulate the behavior of NSApplicationMain @@ -449,6 +446,11 @@ static GLFWbool initializeTIS(void) { _glfw.ns.finishedLaunching = GLFW_TRUE; _glfwPlatformPostEmptyEvent(); + + // In case we are unbundled, make us a proper UI application + if (_glfw.hints.init.ns.menubar) + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + [NSApp stop:nil]; } diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index cc45f85e..55638cf0 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -39,8 +39,21 @@ // Get the name of the specified display, or NULL // -static char* getDisplayName(CGDirectDisplayID displayID) +static char* getMonitorName(CGDirectDisplayID displayID, NSScreen* screen) { + // IOKit doesn't work on Apple Silicon anymore + // Luckily, 10.15 introduced -[NSScreen localizedName]. + // Use it if available, and fall back to IOKit otherwise. + if (screen) + { + if ([screen respondsToSelector:@selector(localizedName)]) + { + NSString* name = [screen valueForKey:@"localizedName"]; + if (name) + return _glfw_strdup([name UTF8String]); + } + } + io_iterator_t it; io_service_t service; CFDictionaryRef info; @@ -209,31 +222,6 @@ static void endFadeReservation(CGDisplayFadeReservationToken token) } } -// Finds and caches the NSScreen corresponding to the specified monitor -// -static GLFWbool refreshMonitorScreen(_GLFWmonitor* monitor) -{ - if (monitor->ns.screen) - return GLFW_TRUE; - - for (NSScreen* screen in [NSScreen screens]) - { - NSNumber* displayID = [screen deviceDescription][@"NSScreenNumber"]; - - // HACK: Compare unit numbers instead of display IDs to work around - // display replacement on machines with automatic graphics - // switching - if (monitor->ns.unitNumber == CGDisplayUnitNumber([displayID unsignedIntValue])) - { - monitor->ns.screen = screen; - return GLFW_TRUE; - } - } - - _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to find a screen for monitor"); - return GLFW_FALSE; -} - // Returns the display refresh rate queried from the I/O registry // static double getFallbackRefreshRate(CGDirectDisplayID displayID) @@ -334,27 +322,46 @@ void _glfwPollMonitorsNS(void) if (CGDisplayIsAsleep(displays[i])) continue; + const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]); + NSScreen* screen = nil; + + for (screen in [NSScreen screens]) + { + NSNumber* screenNumber = [screen deviceDescription][@"NSScreenNumber"]; + + // HACK: Compare unit numbers instead of display IDs to work around + // display replacement on machines with automatic graphics + // switching + if (CGDisplayUnitNumber([screenNumber unsignedIntValue]) == unitNumber) + break; + } + // HACK: Compare unit numbers instead of display IDs to work around // display replacement on machines with automatic graphics // switching - const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]); - for (uint32_t j = 0; j < disconnectedCount; j++) + uint32_t j; + for (j = 0; j < disconnectedCount; j++) { if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber) { + disconnected[j]->ns.screen = screen; disconnected[j] = NULL; break; } } + if (j < disconnectedCount) + continue; + const CGSize size = CGDisplayScreenSize(displays[i]); - char* name = getDisplayName(displays[i]); + char* name = getMonitorName(displays[i], screen); if (!name) name = _glfw_strdup("Unknown"); _GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height); monitor->ns.displayID = displays[i]; monitor->ns.unitNumber = unitNumber; + monitor->ns.screen = screen; free(name); @@ -463,8 +470,11 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, { @autoreleasepool { - if (!refreshMonitorScreen(monitor)) - return; + if (!monitor->ns.screen) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Cannot query content scale without screen"); + } const NSRect points = [monitor->ns.screen frame]; const NSRect pixels = [monitor->ns.screen convertRectToBacking:points]; @@ -483,8 +493,11 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, { @autoreleasepool { - if (!refreshMonitorScreen(monitor)) - return; + if (!monitor->ns.screen) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Cannot query workarea without screen"); + } const NSRect frameRect = [monitor->ns.screen visibleFrame]; @@ -527,7 +540,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) } // Skip duplicate modes - if (i < *count) + if (j < *count) continue; (*count)++; diff --git a/src/internal.h b/src/internal.h index 92b9497a..91631c06 100644 --- a/src/internal.h +++ b/src/internal.h @@ -342,9 +342,9 @@ struct _GLFWcontext int robustness; int release; - PFNGLGETSTRINGIPROC GetStringi; + PFNGLGETSTRINGIPROC GetStringi; PFNGLGETINTEGERVPROC GetIntegerv; - PFNGLGETSTRINGPROC GetString; + PFNGLGETSTRINGPROC GetString; _GLFWmakecontextcurrentfun makeCurrent; _GLFWswapbuffersfun swapBuffers; @@ -396,23 +396,23 @@ struct _GLFWwindow _GLFWcontext context; struct { - GLFWwindowposfun pos; - GLFWwindowsizefun size; - GLFWwindowclosefun close; - GLFWwindowrefreshfun refresh; - GLFWwindowfocusfun focus; - GLFWwindowiconifyfun iconify; - GLFWwindowmaximizefun maximize; - GLFWframebuffersizefun fbsize; + GLFWwindowposfun pos; + GLFWwindowsizefun size; + GLFWwindowclosefun close; + GLFWwindowrefreshfun refresh; + GLFWwindowfocusfun focus; + GLFWwindowiconifyfun iconify; + GLFWwindowmaximizefun maximize; + GLFWframebuffersizefun fbsize; GLFWwindowcontentscalefun scale; - GLFWmousebuttonfun mouseButton; - GLFWcursorposfun cursorPos; - GLFWcursorenterfun cursorEnter; - GLFWscrollfun scroll; - GLFWkeyfun key; - GLFWcharfun character; - GLFWcharmodsfun charmods; - GLFWdropfun drop; + GLFWmousebuttonfun mouseButton; + GLFWcursorposfun cursorPos; + GLFWcursorenterfun cursorEnter; + GLFWscrollfun scroll; + GLFWkeyfun key; + GLFWcharfun character; + GLFWcharmodsfun charmods; + GLFWdropfun drop; } callbacks; // This is defined in the window API's platform.h