Compare commits

...

9 Commits

10 changed files with 100 additions and 78 deletions

View File

@ -54,7 +54,7 @@ jobs:
timeout-minutes: 4 timeout-minutes: 4
env: env:
CFLAGS: -Werror CFLAGS: -Werror
MACOSX_DEPLOYMENT_TARGET: 10.8 MACOSX_DEPLOYMENT_TARGET: 10.11
CMAKE_OSX_ARCHITECTURES: x86_64;arm64 CMAKE_OSX_ARCHITECTURES: x86_64;arm64
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@ -79,7 +79,7 @@ more information.
## System requirements ## System requirements
GLFW supports Windows XP and later and macOS 10.8 and later. Linux and other GLFW supports Windows XP and later and macOS 10.11 and later. Linux and other
Unix-like systems running the X Window System are supported even without Unix-like systems running the X Window System are supported even without
a desktop environment or modern extensions, although some features require a desktop environment or modern extensions, although some features require
a running window or clipboard manager. The OSMesa backend requires Mesa 6.3. a running window or clipboard manager. The OSMesa backend requires Mesa 6.3.
@ -123,8 +123,11 @@ information on what to include when reporting a bug.
- Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond - Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond
the limit of the mouse button tokens to be reported (#2423) the limit of the mouse button tokens to be reported (#2423)
- [Cocoa] Added `QuartzCore` framework as link-time dependency
- [Cocoa] Removed support for OS X 10.10 Yosemite and earlier (#2506)
- [Wayland] Bugfix: The fractional scaling related objects were not destroyed - [Wayland] Bugfix: The fractional scaling related objects were not destroyed
- [Wayland] Bugfix: `glfwInit` would segfault on compositor with no seat (#2517) - [Wayland] Bugfix: `glfwInit` would segfault on compositor with no seat (#2517)
- [Wayland] Bugfix: A drag entering a non-GLFW surface could cause a segfault
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface` - [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` - [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
- [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to - [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to

View File

@ -390,8 +390,8 @@ If you are using the dynamic library version of GLFW, add it to the project
dependencies. dependencies.
If you are using the static library version of GLFW, add it and the Cocoa, If you are using the static library version of GLFW, add it and the Cocoa,
OpenGL and IOKit frameworks to the project as dependencies. They can all be OpenGL, IOKit and QuartzCore frameworks to the project as dependencies. They
found in `/System/Library/Frameworks`. can all be found in `/System/Library/Frameworks`.
### With command-line or makefile on macOS {#build_link_osx} ### With command-line or makefile on macOS {#build_link_osx}
@ -405,7 +405,7 @@ command-line yourself using the `-l` and `-framework` switches.
If you are using the dynamic GLFW library, which is named `libglfw.3.dylib`, do: If you are using the dynamic GLFW library, which is named `libglfw.3.dylib`, do:
```sh ```sh
cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit cc -o myprog myprog.c -lglfw -framework Cocoa -framework OpenGL -framework IOKit -framework QuartzCore
``` ```
If you are using the static library, named `libglfw3.a`, substitute `-lglfw3` If you are using the static library, named `libglfw3.a`, substitute `-lglfw3`

View File

@ -242,24 +242,27 @@ extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
## OpenGL on macOS {#compat_osx} ## OpenGL on macOS {#compat_osx}
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then macOS (as of version 14) still provides OpenGL but it has been deprecated by
only forward-compatible, core profile contexts are supported. Support for Apple. While the API is still available, it is poorly maintained and frequently
OpenGL 4.1 was introduced with OS X 10.9, also limited to forward-compatible, develops new issues. On modern systems, OpenGL is implemented on top of Metal
core profile contexts. There is also still no mechanism for requesting debug and is not fully thread-safe.
contexts or no-error contexts. Versions of Mac OS X earlier than 10.7 support
at most OpenGL version 2.1.
Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and macOS does not support OpenGL stereo rendering. If the `GLFW_STEREO` hint is
`GLFW_CONTEXT_VERSION_MINOR` hints will cause @ref glfwCreateWindow to fail if set to true, OpenGL context creation will always fail.
given version 3.0 or 3.1. The `GLFW_OPENGL_PROFILE` hint must be set to
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts. The
`GLFW_CONTEXT_DEBUG` and `GLFW_CONTEXT_NO_ERROR` hints are ignored.
Also, on Mac OS X 10.6 and below, the `GLFW_CONTEXT_VERSION_MAJOR` and macOS only supports OpenGL core profile contexts that are forward-compatible,
`GLFW_CONTEXT_VERSION_MINOR` hints will fail if given a version above 2.1, but the `GLFW_OPENGL_FORWARD_COMPAT` hint is ignored since GLFW 3.4. Even if
setting the `GLFW_OPENGL_PROFILE` or `GLFW_OPENGL_FORWARD_COMPAT` hints to this hint is set to false (the default), a forward-compatible context will be
a non-default value will cause @ref glfwCreateWindow to fail and the returned if available.
`GLFW_CONTEXT_DEBUG` hint is ignored.
macOS does not support OpenGL debug contexts, no-error contexts or robustness.
The `GLFW_CONTEXT_DEBUG`, `GLFW_CONTEXT_NO_ERROR` and `GLFW_CONTEXT_ROBUSTNESS`
hints will be ignored and a context without these features will be returned.
macOS does not flush OpenGL contexts when they are made non-current. The
`GLFW_CONTEXT_RELEASE_BEHAVIOR` hint is ignored and the release behavior will
always be the equivalent of `GLFW_RELEASE_BEHAVIOR_NONE`. If you need a context
to be flushed, call `glFlush` before making it non-current.
## Vulkan loader and API {#compat_vulkan} ## Vulkan loader and API {#compat_vulkan}

View File

@ -3183,8 +3183,8 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* *
* [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/ * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/
* *
* @remark @macos On OS X 10.10 and later the window frame will not be rendered * @remark @macos The window frame will not be rendered at full resolution on
* at full resolution on Retina displays unless the * Retina displays unless the
* [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) * [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint)
* hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the
* application bundle's `Info.plist`. For more information, see * application bundle's `Info.plist`. For more information, see

View File

@ -151,10 +151,11 @@ endif()
if (GLFW_BUILD_COCOA) if (GLFW_BUILD_COCOA)
target_link_libraries(glfw PRIVATE "-framework Cocoa" target_link_libraries(glfw PRIVATE "-framework Cocoa"
"-framework IOKit" "-framework IOKit"
"-framework CoreFoundation") "-framework CoreFoundation"
"-framework QuartzCore")
set(glfw_PKG_DEPS "") set(glfw_PKG_DEPS "")
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation") set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework QuartzCore")
endif() endif()
if (GLFW_BUILD_WAYLAND) if (GLFW_BUILD_WAYLAND)

View File

@ -137,7 +137,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
if (flags & kDisplayModeStretchedFlag) if (flags & kDisplayModeStretchedFlag)
return GLFW_FALSE; return GLFW_FALSE;
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 #if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) && if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0)) CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
@ -164,7 +164,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
if (result.refreshRate == 0) if (result.refreshRate == 0)
result.refreshRate = (int) round(fallbackRefreshRate); result.refreshRate = (int) round(fallbackRefreshRate);
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 #if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
{ {
@ -180,7 +180,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
result.blueBits = 8; result.blueBits = 8;
} }
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 #if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFRelease(format); CFRelease(format);
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */ #endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
return result; return result;

View File

@ -28,6 +28,8 @@
#if defined(_GLFW_COCOA) #if defined(_GLFW_COCOA)
#import <QuartzCore/CAMetalLayer.h>
#include <float.h> #include <float.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
@ -310,7 +312,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidChangeOcclusionState:(NSNotification* )notification - (void)windowDidChangeOcclusionState:(NSNotification* )notification
{ {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
if ([window->ns.object respondsToSelector:@selector(occlusionState)]) if ([window->ns.object respondsToSelector:@selector(occlusionState)])
{ {
if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible) if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
@ -318,7 +319,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
else else
window->ns.occluded = GLFW_TRUE; window->ns.occluded = GLFW_TRUE;
} }
#endif
} }
@end @end
@ -560,6 +560,36 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
[super updateTrackingAreas]; [super updateTrackingAreas];
} }
- (BOOL)performKeyEquivalent:(NSEvent *)nsevent
{
// At the moment the only reason we define this method
// is Ctrl-tab key event never reaching any view at all.
// After -performKeyEquivalent: returns NO on all responders,
// we receve Ctrl-tab in our QNSWindow's -sendEvent:,
// but somehow it never reaches QNSView's -keyDown:.
// Apparently, it's treated in a special (and undocumented)
// way by Cocoa. 'Illegal' but really nice, clear and safe solution
// would be to define _wantsKeyDownForEvent, but it's a
// private/undocumented API.
if ([[self window] firstResponder] == self)
{
const NSUInteger modifierFlags = [nsevent modifierFlags];
NSString *chs = [nsevent charactersIgnoringModifiers];
if (modifierFlags & NSEventModifierFlagControl)
{
if ([chs characterAtIndex:0] == NSTabCharacter)
{
if (![[NSApp mainMenu] performKeyEquivalent:nsevent])
{
[self keyDown:nsevent];
}
return YES;
}
}
}
return NO;
}
- (void)keyDown:(NSEvent *)event - (void)keyDown:(NSEvent *)event
{ {
const int key = translateKey([event keyCode]); const int key = translateKey([event keyCode]);
@ -1950,19 +1980,8 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
{ {
@autoreleasepool { @autoreleasepool {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
// HACK: Dynamically load Core Animation to avoid adding an extra
// dependency for the majority who don't use MoltenVK
NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
if (!bundle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to find QuartzCore.framework");
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// NOTE: Create the layer here as makeBackingLayer should not return nil // NOTE: Create the layer here as makeBackingLayer should not return nil
window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer]; window->ns.layer = [CAMetalLayer layer];
if (!window->ns.layer) if (!window->ns.layer)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -2027,9 +2046,6 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
} }
return err; return err;
#else
return VK_ERROR_EXTENSION_NOT_PRESENT;
#endif
} // autoreleasepool } // autoreleasepool
} }

View File

@ -183,16 +183,16 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
// Context robustness modes (GL_KHR_robustness) are not yet supported by // Context robustness modes (GL_KHR_robustness) are not supported by
// macOS but are not a hard constraint, so ignore and continue // macOS but are not a hard constraint, so ignore and continue
// Context release behaviors (GL_KHR_context_flush_control) are not yet // Context release behaviors (GL_KHR_context_flush_control) are not
// supported by macOS but are not a hard constraint, so ignore and continue // supported by macOS but are not a hard constraint, so ignore and continue
// Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not // Debug contexts (GL_KHR_debug) are not supported by macOS but are not
// a hard constraint, so ignore and continue // a hard constraint, so ignore and continue
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but // No-error contexts (GL_KHR_no_error) are not supported by macOS but
// are not a hard constraint, so ignore and continue // are not a hard constraint, so ignore and continue
#define ADD_ATTRIB(a) \ #define ADD_ATTRIB(a) \
@ -218,14 +218,11 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching); ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching);
} }
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
if (ctxconfig->major >= 4) if (ctxconfig->major >= 4)
{ {
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core); SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
} }
else else if (ctxconfig->major >= 3)
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
if (ctxconfig->major >= 3)
{ {
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
} }

View File

@ -1974,41 +1974,41 @@ static void dataDeviceHandleEnter(void* userData,
_glfw.wl.dragFocus = NULL; _glfw.wl.dragFocus = NULL;
} }
for (unsigned int i = 0; i < _glfw.wl.offerCount; i++) unsigned int i;
for (i = 0; i < _glfw.wl.offerCount; i++)
{ {
if (_glfw.wl.offers[i].offer == offer) if (_glfw.wl.offers[i].offer == offer)
{ break;
_GLFWwindow* window = NULL;
if (surface)
{
if (wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag)
window = wl_surface_get_user_data(surface);
} }
if (surface == window->wl.surface && _glfw.wl.offers[i].text_uri_list) if (i == _glfw.wl.offerCount)
return;
if (surface && wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag)
{
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (window->wl.surface == surface)
{
if (_glfw.wl.offers[i].text_uri_list)
{ {
_glfw.wl.dragOffer = offer; _glfw.wl.dragOffer = offer;
_glfw.wl.dragFocus = window; _glfw.wl.dragFocus = window;
_glfw.wl.dragSerial = serial; _glfw.wl.dragSerial = serial;
}
_glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];
_glfw.wl.offerCount--;
break;
}
}
if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
return;
if (_glfw.wl.dragOffer)
wl_data_offer_accept(offer, serial, "text/uri-list"); wl_data_offer_accept(offer, serial, "text/uri-list");
else }
}
}
if (!_glfw.wl.dragOffer)
{ {
wl_data_offer_accept(offer, serial, NULL); wl_data_offer_accept(offer, serial, NULL);
wl_data_offer_destroy(offer); wl_data_offer_destroy(offer);
} }
_glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];
_glfw.wl.offerCount--;
} }
static void dataDeviceHandleLeave(void* userData, static void dataDeviceHandleLeave(void* userData,
@ -2042,6 +2042,7 @@ static void dataDeviceHandleDrop(void* userData,
int count; int count;
char** paths = _glfwParseUriList(string, &count); char** paths = _glfwParseUriList(string, &count);
if (paths) if (paths)
{
_glfwInputDrop(_glfw.wl.dragFocus, count, (const char**) paths); _glfwInputDrop(_glfw.wl.dragFocus, count, (const char**) paths);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
@ -2051,6 +2052,7 @@ static void dataDeviceHandleDrop(void* userData,
} }
_glfw_free(string); _glfw_free(string);
}
} }
static void dataDeviceHandleSelection(void* userData, static void dataDeviceHandleSelection(void* userData,