diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e980c547..8ef9ed79 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,7 +54,7 @@ jobs: timeout-minutes: 4 env: CFLAGS: -Werror - MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_DEPLOYMENT_TARGET: 10.11 CMAKE_OSX_ARCHITECTURES: x86_64;arm64 steps: - uses: actions/checkout@v4 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index c4c74ade..1371aedb 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -33,6 +33,7 @@ video tutorials. - Nicolas Caramelli - David Carlier - Arturo Castro + - Jose Luis Cercós Pita - Chi-kwan Chan - Victor Chernyakin - TheChocolateOre @@ -48,6 +49,7 @@ video tutorials. - Andrew Corrigan - Bailey Cosier - Noel Cower + - James Cowgill - CuriouserThing - Bill Currie - Jason Daly diff --git a/README.md b/README.md index ac952e18..17c38183 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ more information. ## 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 a desktop environment or modern extensions, although some features require a running window or clipboard manager. The OSMesa backend requires Mesa 6.3. @@ -124,6 +124,17 @@ information on what to include when reporting a bug. - Added OpenGL and OpenGL ES user contexts for multiple window contexts via `GLFWusercontext`, `glfwCreateUserContext`, `glfwDestroyUserContext`, `glfwMakeUserContextCurrent`, `glfwGetCurrentUserContext` (#1687,#1870) + - Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond + 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: `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 EGL context creation on Mesa via `EGL_MESA_platform_surfaceless` + - [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to + `GLFW_NATIVE_CONTEXT_API` (#2518) ## Contact diff --git a/docs/build.md b/docs/build.md index ab4b6817..7b0f8bfe 100644 --- a/docs/build.md +++ b/docs/build.md @@ -390,8 +390,8 @@ If you are using the dynamic library version of GLFW, add it to the project dependencies. 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 -found in `/System/Library/Frameworks`. +OpenGL, IOKit and QuartzCore frameworks to the project as dependencies. They +can all be found in `/System/Library/Frameworks`. ### 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: ```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` diff --git a/docs/compat.md b/docs/compat.md index ef64b0cc..5072d5c1 100644 --- a/docs/compat.md +++ b/docs/compat.md @@ -242,24 +242,27 @@ extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect. ## OpenGL on macOS {#compat_osx} -Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then -only forward-compatible, core profile contexts are supported. Support for -OpenGL 4.1 was introduced with OS X 10.9, also limited to forward-compatible, -core profile contexts. There is also still no mechanism for requesting debug -contexts or no-error contexts. Versions of Mac OS X earlier than 10.7 support -at most OpenGL version 2.1. +macOS (as of version 14) still provides OpenGL but it has been deprecated by +Apple. While the API is still available, it is poorly maintained and frequently +develops new issues. On modern systems, OpenGL is implemented on top of Metal +and is not fully thread-safe. -Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and -`GLFW_CONTEXT_VERSION_MINOR` hints will cause @ref glfwCreateWindow to fail if -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. +macOS does not support OpenGL stereo rendering. If the `GLFW_STEREO` hint is +set to true, OpenGL context creation will always fail. -Also, on Mac OS X 10.6 and below, the `GLFW_CONTEXT_VERSION_MAJOR` and -`GLFW_CONTEXT_VERSION_MINOR` hints will fail if given a version above 2.1, -setting the `GLFW_OPENGL_PROFILE` or `GLFW_OPENGL_FORWARD_COMPAT` hints to -a non-default value will cause @ref glfwCreateWindow to fail and the -`GLFW_CONTEXT_DEBUG` hint is ignored. +macOS only supports OpenGL core profile contexts that are forward-compatible, +but the `GLFW_OPENGL_FORWARD_COMPAT` hint is ignored since GLFW 3.4. Even if +this hint is set to false (the default), a forward-compatible context will be +returned if available. + +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} diff --git a/docs/input.md b/docs/input.md index 56983b08..3ef1aebe 100644 --- a/docs/input.md +++ b/docs/input.md @@ -492,6 +492,20 @@ a mouse button callback. glfwSetMouseButtonCallback(window, mouse_button_callback); ``` +@anchor GLFW_UNLIMITED_MOUSE_BUTTONS +To handle all mouse buttons in the callback, instead of only ones with associated +[button tokens](@ref buttons), set the @ref GLFW_UNLIMITED_MOUSE_BUTTONS +input mode. + +```c +glfwSetInputMode(window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE); +``` + +When this input mode is enabled, GLFW doesn't limit the reported mouse buttons +to only those that have an associated button token, for compatibility with +earlier versions of GLFW, which never reported any buttons over +@ref GLFW_MOUSE_BUTTON_LAST, on which users could have relied on. + The callback function receives the [mouse button](@ref buttons), button action and [modifier bits](@ref mods). @@ -503,11 +517,16 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) } ``` +The mouse button is an integer that can be one of the +[mouse button tokens](@ref buttons) or, if the +@ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode is set, any other positive value. + The action is one of `GLFW_PRESS` or `GLFW_RELEASE`. -The last reported state for every [supported mouse button](@ref buttons) is also +The last reported state for every [mouse button token](@ref buttons) is also saved in per-window state arrays that can be polled with @ref -glfwGetMouseButton. +glfwGetMouseButton. This is not effected by the @ref GLFW_UNLIMITED_MOUSE_BUTTONS +input mode. ```c int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT); @@ -540,7 +559,7 @@ had been processed in the meantime, the state will reset to `GLFW_RELEASE`, otherwise it will remain `GLFW_PRESS`. The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any -[supported mouse button](@ref buttons). +[mouse button token](@ref buttons). ### Scroll input {#scrolling} diff --git a/docs/news.md b/docs/news.md index 76e0fce2..16464366 100644 --- a/docs/news.md +++ b/docs/news.md @@ -14,6 +14,15 @@ destroyed using @ref glfwDestroyUserContext, and managed with @ref glfwMakeUserContextCurrent and @ref glfwGetCurrentUserContext. For more information see the [user context](@ref context_user) documentation. +### Unlimited mouse buttons {#unlimited_mouse_buttons} + +GLFW now has an input mode which allows an unlimited number of mouse buttons to +be reported by the mouse buttton callback, rather than just the associated +[mouse button tokens](@ref buttons). This allows using mouse buttons with +values over 8. For compatibility with older versions, the +@ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode needs to be set to make use of +this. + ## Caveats {#caveats} ## Deprecations {#deprecations} @@ -28,6 +37,8 @@ For more information see the [user context](@ref context_user) documentation. ### New constants {#new_constants} +- @ref GLFW_UNLIMITED_MOUSE_BUTTONS + ## Release notes for earlier versions {#news_archive} - [Release notes for 3.4](https://www.glfw.org/docs/3.4/news.html) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index aeacb573..08d9521c 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1149,11 +1149,12 @@ extern "C" { #define GLFW_OPENGL_CORE_PROFILE 0x00032001 #define GLFW_OPENGL_COMPAT_PROFILE 0x00032002 -#define GLFW_CURSOR 0x00033001 -#define GLFW_STICKY_KEYS 0x00033002 -#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 -#define GLFW_LOCK_KEY_MODS 0x00033004 -#define GLFW_RAW_MOUSE_MOTION 0x00033005 +#define GLFW_CURSOR 0x00033001 +#define GLFW_STICKY_KEYS 0x00033002 +#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 +#define GLFW_LOCK_KEY_MODS 0x00033004 +#define GLFW_RAW_MOUSE_MOTION 0x00033005 +#define GLFW_UNLIMITED_MOUSE_BUTTONS 0x00033006 #define GLFW_CURSOR_NORMAL 0x00034001 #define GLFW_CURSOR_HIDDEN 0x00034002 @@ -3194,8 +3195,8 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value); * * [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 - * at full resolution on Retina displays unless the + * @remark @macos The window frame will not be rendered at full resolution on + * Retina displays unless the * [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the * application bundle's `Info.plist`. For more information, see @@ -4688,8 +4689,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); * * This function sets an input mode option for the specified window. The mode * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, - * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or - * @ref GLFW_RAW_MOUSE_MOTION. + * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS + * @ref GLFW_RAW_MOUSE_MOTION, or @ref GLFW_UNLIMITED_MOUSE_BUTTONS. * * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor * modes: @@ -4729,6 +4730,11 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); * attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref * glfwRawMouseMotionSupported to check for support. * + * If the mode is `GLFW_UNLIMITED_MOUSE_BUTTONS`, the value must be either + * `GLFW_TRUE` to disable the mouse button limit when calling the mouse button + * callback, or `GLFW_FALSE` to limit the mouse buttons sent to the callback + * to the mouse button token values up to `GLFW_MOUSE_BUTTON_LAST`. + * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or @@ -4923,8 +4929,11 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key); * returns `GLFW_PRESS` the first time you call it for a mouse button that was * pressed, even if that mouse button has already been released. * + * The @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode does not effect the + * limit on buttons which can be polled with this function. + * * @param[in] window The desired window. - * @param[in] button The desired [mouse button](@ref buttons). + * @param[in] button The desired [mouse button token](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref @@ -5300,10 +5309,15 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmods * is called when a mouse button is pressed or released. * * When a window loses input focus, it will generate synthetic mouse button - * release events for all pressed mouse buttons. You can tell these events - * from user-generated events by the fact that the synthetic ones are generated - * after the focus loss event has been processed, i.e. after the - * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. + * release events for all pressed mouse buttons with associated button tokens. + * You can tell these events from user-generated events by the fact that the + * synthetic ones are generated after the focus loss event has been processed, + * i.e. after the [window focus callback](@ref glfwSetWindowFocusCallback) has + * been called. + * + * The reported `button` value can be higher than `GLFW_MOUSE_BUTTON_LAST` if + * the button does not have an associated [button token](@ref buttons) and the + * @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode is set. * * @param[in] window The window whose callback to set. * @param[in] callback The new callback, or `NULL` to remove the currently set diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1057a6f9..463b898d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -151,10 +151,11 @@ endif() if (GLFW_BUILD_COCOA) target_link_libraries(glfw PRIVATE "-framework Cocoa" "-framework IOKit" - "-framework CoreFoundation") + "-framework CoreFoundation" + "-framework QuartzCore") 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() if (GLFW_BUILD_WAYLAND) diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 75f8ec53..6495e1f3 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -136,7 +137,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode) if (flags & kDisplayModeStretchedFlag) return GLFW_FALSE; -#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 +#if MAC_OS_X_VERSION_MAX_ALLOWED == 101100 CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) && CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0)) @@ -163,7 +164,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode, if (result.refreshRate == 0) 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); if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) { @@ -179,7 +180,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode, result.blueBits = 8; } -#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 +#if MAC_OS_X_VERSION_MAX_ALLOWED == 101100 CFRelease(format); #endif /* MAC_OS_X_VERSION_MAX_ALLOWED */ return result; @@ -627,7 +628,6 @@ void _glfwSetGammaRampCocoa(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(kCGNullDirectDisplay); if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) @@ -636,6 +636,9 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle) return kCGNullDirectDisplay; } + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + return monitor->ns.displayID; } diff --git a/src/cocoa_window.m b/src/cocoa_window.m index a61173e3..24ccce1d 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -28,8 +28,11 @@ #if defined(_GLFW_COCOA) +#import + #include #include +#include // HACK: This enum value is missing from framework headers on OS X 10.11 despite // having been (according to documentation) added in Mac OS X 10.7 @@ -309,7 +312,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)windowDidChangeOcclusionState:(NSNotification* )notification { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 if ([window->ns.object respondsToSelector:@selector(occlusionState)]) { if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible) @@ -317,7 +319,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; else window->ns.occluded = GLFW_TRUE; } -#endif } @end @@ -1949,19 +1950,8 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, { @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 - window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer]; + window->ns.layer = [CAMetalLayer layer]; if (!window->ns.layer) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -2026,9 +2016,6 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, } return err; -#else - return VK_ERROR_EXTENSION_NOT_PRESENT; -#endif } // autoreleasepool } @@ -2059,7 +2046,6 @@ _GLFWusercontext* _glfwCreateUserContextCocoa(_GLFWwindow* window) GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(nil); if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) @@ -2069,12 +2055,14 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle) return nil; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + return window->ns.object; } GLFWAPI id glfwGetCocoaView(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(nil); if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) @@ -2084,6 +2072,9 @@ GLFWAPI id glfwGetCocoaView(GLFWwindow* handle) return nil; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + return window->ns.view; } diff --git a/src/context.c b/src/context.c index 573af60d..b4675267 100644 --- a/src/context.c +++ b/src/context.c @@ -615,11 +615,11 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* previous; - _GLFW_REQUIRE_INIT(); - _glfwPlatformSetTls(&_glfw.usercontextSlot, NULL); previous = _glfwPlatformGetTls(&_glfw.contextSlot); @@ -648,11 +648,11 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void) GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - if (window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, diff --git a/src/egl_context.c b/src/egl_context.c index 3e604438..a82c3271 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -92,7 +92,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, EGLConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; - int i, nativeCount, usableCount, apiBit; + int i, nativeCount, usableCount, apiBit, surfaceTypeBit; GLFWbool wrongApiAvailable = GLFW_FALSE; if (ctxconfig->client == GLFW_OPENGL_ES_API) @@ -105,6 +105,11 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, else apiBit = EGL_OPENGL_BIT; + if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA) + surfaceTypeBit = EGL_PBUFFER_BIT; + else + surfaceTypeBit = EGL_WINDOW_BIT; + if (fbconfig->stereo) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported"); @@ -133,8 +138,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER) continue; - // Only consider window EGLConfigs - if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) + if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & surfaceTypeBit)) continue; #if defined(_GLFW_X11) @@ -420,6 +424,8 @@ GLFWbool _glfwInitEGL(void) _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglDestroyContext"); _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface) _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreateWindowSurface"); + _glfw.egl.CreatePbufferSurface = (PFN_eglCreatePbufferSurface) + _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreatePbufferSurface"); _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent) _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglMakeCurrent"); _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers) @@ -446,6 +452,7 @@ GLFWbool _glfwInitEGL(void) !_glfw.egl.DestroySurface || !_glfw.egl.DestroyContext || !_glfw.egl.CreateWindowSurface || + !_glfw.egl.CreatePbufferSurface || !_glfw.egl.MakeCurrent || !_glfw.egl.SwapBuffers || !_glfw.egl.SwapInterval || @@ -483,6 +490,8 @@ GLFWbool _glfwInitEGL(void) _glfwStringInExtensionString("EGL_ANGLE_platform_angle_vulkan", extensions); _glfw.egl.ANGLE_platform_angle_metal = _glfwStringInExtensionString("EGL_ANGLE_platform_angle_metal", extensions); + _glfw.egl.MESA_platform_surfaceless = + _glfwStringInExtensionString("EGL_MESA_platform_surfaceless", extensions); } if (_glfw.egl.EXT_platform_base) @@ -731,20 +740,36 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); } + if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA) + { + int width, height; + _glfw.platform.getFramebufferSize(window, &width, &height); + + SET_ATTRIB(EGL_WIDTH, width); + SET_ATTRIB(EGL_HEIGHT, height); + } + SET_ATTRIB(EGL_NONE, EGL_NONE); native = _glfw.platform.getEGLNativeWindow(window); - // HACK: ANGLE does not implement eglCreatePlatformWindowSurfaceEXT - // despite reporting EGL_EXT_platform_base - if (_glfw.egl.platform && _glfw.egl.platform != EGL_PLATFORM_ANGLE_ANGLE) + if (!_glfw.egl.platform || _glfw.egl.platform == EGL_PLATFORM_ANGLE_ANGLE) { + // HACK: Also use non-platform function for ANGLE, as it does not + // implement eglCreatePlatformWindowSurfaceEXT despite reporting + // support for EGL_EXT_platform_base window->context.egl.surface = - eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, window->context.egl.config, native, attribs); + eglCreateWindowSurface(_glfw.egl.display, window->context.egl.config, native, attribs); + } + else if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA) + { + // HACK: Use a pbuffer surface as the default framebuffer + window->context.egl.surface = + eglCreatePbufferSurface(_glfw.egl.display, window->context.egl.config, attribs); } else { window->context.egl.surface = - eglCreateWindowSurface(_glfw.egl.display, window->context.egl.config, native, attribs); + eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, window->context.egl.config, native, attribs); } if (window->context.egl.surface == EGL_NO_SURFACE) @@ -992,13 +1017,19 @@ GLFWAPI EGLDisplay glfwGetEGLDisplay(void) GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_EGL_CONTEXT_API) { - _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); - return EGL_NO_CONTEXT; + if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND || + window->context.source != GLFW_NATIVE_CONTEXT_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return EGL_NO_CONTEXT; + } } return window->context.egl.handle; @@ -1006,13 +1037,19 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_EGL_CONTEXT_API) { - _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); - return EGL_NO_SURFACE; + if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND || + window->context.source != GLFW_NATIVE_CONTEXT_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return EGL_NO_CONTEXT; + } } return window->context.egl.surface; diff --git a/src/glx_context.c b/src/glx_context.c index 5ce58874..e70ebfcc 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -734,7 +734,6 @@ _GLFWusercontext* _glfwCreateUserContextGLX(_GLFWwindow* window) GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (_glfw.platform.platformID != GLFW_PLATFORM_X11) @@ -743,6 +742,9 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle) return NULL; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); @@ -754,7 +756,6 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle) GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(None); if (_glfw.platform.platformID != GLFW_PLATFORM_X11) @@ -763,6 +764,9 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle) return None; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); diff --git a/src/input.c b/src/input.c index 3f8ddb30..c619eefc 100644 --- a/src/input.c +++ b/src/input.c @@ -348,20 +348,22 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) { assert(window != NULL); assert(button >= 0); - assert(button <= GLFW_MOUSE_BUTTON_LAST); assert(action == GLFW_PRESS || action == GLFW_RELEASE); assert(mods == (mods & GLFW_MOD_MASK)); - if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) + if (button < 0 || (!window->disableMouseButtonLimit && button > GLFW_MOUSE_BUTTON_LAST)) return; if (!window->lockKeyMods) mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK); - if (action == GLFW_RELEASE && window->stickyMouseButtons) - window->mouseButtons[button] = _GLFW_STICK; - else - window->mouseButtons[button] = (char) action; + if (button <= GLFW_MOUSE_BUTTON_LAST) + { + if (action == GLFW_RELEASE && window->stickyMouseButtons) + window->mouseButtons[button] = _GLFW_STICK; + else + window->mouseButtons[button] = (char) action; + } if (window->callbacks.mouseButton) window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); @@ -559,11 +561,11 @@ void _glfwCenterCursorInContentArea(_GLFWwindow* window) GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) { + _GLFW_REQUIRE_INIT_OR_RETURN(0); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(0); - switch (mode) { case GLFW_CURSOR: @@ -576,6 +578,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) return window->lockKeyMods; case GLFW_RAW_MOUSE_MOTION: return window->rawMouseMotion; + case GLFW_UNLIMITED_MOUSE_BUTTONS: + return window->disableMouseButtonLimit; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); @@ -584,11 +588,11 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - switch (mode) { case GLFW_CURSOR: @@ -683,6 +687,12 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) _glfw.platform.setRawMouseMotion(window, value); return; } + + case GLFW_UNLIMITED_MOUSE_BUTTONS: + { + window->disableMouseButtonLimit = value ? GLFW_TRUE : GLFW_FALSE; + return; + } } _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); @@ -734,11 +744,11 @@ GLFWAPI int glfwGetKeyScancode(int key) GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) { + _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); - if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); @@ -757,11 +767,11 @@ GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) { + _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); - if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button); @@ -780,9 +790,6 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); - if (xpos) *xpos = 0; if (ypos) @@ -790,6 +797,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (xpos) @@ -803,11 +813,11 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX || ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX) { @@ -897,10 +907,10 @@ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape) GLFWAPI void glfwDestroyCursor(GLFWcursor* handle) { - _GLFWcursor* cursor = (_GLFWcursor*) handle; - _GLFW_REQUIRE_INIT(); + _GLFWcursor* cursor = (_GLFWcursor*) handle; + if (cursor == NULL) return; @@ -932,12 +942,12 @@ GLFWAPI void glfwDestroyCursor(GLFWcursor* handle) GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) windowHandle; _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - window->cursor = cursor; _glfw.platform.setCursor(window, cursor); @@ -945,30 +955,33 @@ GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle) GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWkeyfun, window->callbacks.key, cbfun); return cbfun; } GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWcharfun, window->callbacks.character, cbfun); return cbfun; } GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWcharmodsfun, window->callbacks.charmods, cbfun); return cbfun; } @@ -976,10 +989,11 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmods GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle, GLFWmousebuttonfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWmousebuttonfun, window->callbacks.mouseButton, cbfun); return cbfun; } @@ -987,10 +1001,11 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle, GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle, GLFWcursorposfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWcursorposfun, window->callbacks.cursorPos, cbfun); return cbfun; } @@ -998,10 +1013,11 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle, GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle, GLFWcursorenterfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWcursorenterfun, window->callbacks.cursorEnter, cbfun); return cbfun; } @@ -1009,20 +1025,22 @@ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle, GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle, GLFWscrollfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWscrollfun, window->callbacks.scroll, cbfun); return cbfun; } GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWdropfun, window->callbacks.drop, cbfun); return cbfun; } diff --git a/src/internal.h b/src/internal.h index 28df8256..2117c3c3 100644 --- a/src/internal.h +++ b/src/internal.h @@ -48,6 +48,8 @@ #define GLFW_INCLUDE_NONE #include "../include/GLFW/glfw3.h" +#include + #define _GLFW_INSERT_FIRST 0 #define _GLFW_INSERT_LAST 1 @@ -152,8 +154,8 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint); #define EGL_NO_CONTEXT ((EGLContext) 0) #define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0) #define EGL_PBUFFER_BIT 0x0001 -#define EGL_HEIGHT 0x3056 #define EGL_WIDTH 0x3057 +#define EGL_HEIGHT 0x3056 #define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 @@ -185,6 +187,7 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint); #define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450 #define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489 #define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348f +#define EGL_PLATFORM_SURFACELESS_MESA 0x31dd typedef int EGLint; typedef unsigned int EGLBoolean; @@ -209,12 +212,12 @@ typedef EGLContext (APIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLCon typedef EGLBoolean (APIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface); typedef EGLBoolean (APIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext); typedef EGLSurface (APIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*); +typedef EGLSurface (APIENTRY * PFN_eglCreatePbufferSurface)(EGLDisplay,EGLContext,const EGLint*); typedef EGLBoolean (APIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext); typedef EGLBoolean (APIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface); typedef EGLBoolean (APIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint); typedef const char* (APIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint); typedef GLFWglproc (APIENTRY * PFN_eglGetProcAddress)(const char*); -typedef EGLSurface (APIENTRY * PFN_eglCreatePbufferSurface)(EGLDisplay,EGLConfig,const EGLint*); typedef EGLBoolean (APIENTRY * PFN_eglChooseConfig)(EGLDisplay,EGLint const*,EGLConfig*,EGLint,EGLint*); #define eglGetConfigAttrib _glfw.egl.GetConfigAttrib #define eglGetConfigs _glfw.egl.GetConfigs @@ -227,6 +230,7 @@ typedef EGLBoolean (APIENTRY * PFN_eglChooseConfig)(EGLDisplay,EGLint const*,EGL #define eglDestroySurface _glfw.egl.DestroySurface #define eglDestroyContext _glfw.egl.DestroyContext #define eglCreateWindowSurface _glfw.egl.CreateWindowSurface +#define eglCreatePbufferSurface _glfw.egl.CreatePbufferSurface #define eglMakeCurrent _glfw.egl.MakeCurrent #define eglSwapBuffers _glfw.egl.SwapBuffers #define eglSwapInterval _glfw.egl.SwapInterval @@ -285,6 +289,7 @@ typedef enum VkStructureType VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, + VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; @@ -575,6 +580,7 @@ struct _GLFWwindow GLFWbool stickyKeys; GLFWbool stickyMouseButtons; GLFWbool lockKeyMods; + GLFWbool disableMouseButtonLimit; int cursorMode; char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]; char keys[GLFW_KEY_LAST + 1]; @@ -844,6 +850,7 @@ struct _GLFWlibrary GLFWbool ANGLE_platform_angle_d3d; GLFWbool ANGLE_platform_angle_vulkan; GLFWbool ANGLE_platform_angle_metal; + GLFWbool MESA_platform_surfaceless; void* handle; @@ -858,12 +865,12 @@ struct _GLFWlibrary PFN_eglDestroySurface DestroySurface; PFN_eglDestroyContext DestroyContext; PFN_eglCreateWindowSurface CreateWindowSurface; + PFN_eglCreatePbufferSurface CreatePbufferSurface; PFN_eglMakeCurrent MakeCurrent; PFN_eglSwapBuffers SwapBuffers; PFN_eglSwapInterval SwapInterval; PFN_eglQueryString QueryString; PFN_eglGetProcAddress GetProcAddress; - PFN_eglCreatePbufferSurface CreatePbufferSurface; PFN_eglChooseConfig ChooseConfig; PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT; @@ -895,6 +902,7 @@ struct _GLFWlibrary GLFWbool KHR_xlib_surface; GLFWbool KHR_xcb_surface; GLFWbool KHR_wayland_surface; + GLFWbool EXT_headless_surface; } vk; struct { diff --git a/src/monitor.c b/src/monitor.c index 6f802e32..cc95efb6 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -325,9 +325,6 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void) GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; - assert(monitor != NULL); - if (xpos) *xpos = 0; if (ypos) @@ -335,6 +332,9 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos) _GLFW_REQUIRE_INIT(); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + _glfw.platform.getMonitorPos(monitor, xpos, ypos); } @@ -342,9 +342,6 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, int* xpos, int* ypos, int* width, int* height) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; - assert(monitor != NULL); - if (xpos) *xpos = 0; if (ypos) @@ -356,14 +353,14 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, _GLFW_REQUIRE_INIT(); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + _glfw.platform.getMonitorWorkarea(monitor, xpos, ypos, width, height); } GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; - assert(monitor != NULL); - if (widthMM) *widthMM = 0; if (heightMM) @@ -371,6 +368,9 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* _GLFW_REQUIRE_INIT(); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + if (widthMM) *widthMM = monitor->widthMM; if (heightMM) @@ -380,42 +380,46 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle, float* xscale, float* yscale) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; - assert(monitor != NULL); - if (xscale) *xscale = 0.f; if (yscale) *yscale = 0.f; _GLFW_REQUIRE_INIT(); + + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + _glfw.platform.getMonitorContentScale(monitor, xscale, yscale); } GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; assert(monitor != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return monitor->name; } GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer) { + _GLFW_REQUIRE_INIT(); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; assert(monitor != NULL); - _GLFW_REQUIRE_INIT(); monitor->userPointer = pointer; } GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; assert(monitor != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return monitor->userPointer; } @@ -428,14 +432,15 @@ GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun) GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; - assert(monitor != NULL); assert(count != NULL); *count = 0; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + if (!refreshVideoModes(monitor)) return NULL; @@ -445,11 +450,11 @@ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count) GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; assert(monitor != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (!_glfw.platform.getVideoMode(monitor, &monitor->currentMode)) return NULL; @@ -462,12 +467,13 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma) unsigned short* values; GLFWgammaramp ramp; const GLFWgammaramp* original; - assert(handle != NULL); assert(gamma > 0.f); assert(gamma <= FLT_MAX); _GLFW_REQUIRE_INIT(); + assert(handle != NULL); + if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX) { _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma); @@ -505,11 +511,11 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma) GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; assert(monitor != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - _glfwFreeGammaArrays(&monitor->currentRamp); if (!_glfw.platform.getGammaRamp(monitor, &monitor->currentRamp)) return NULL; @@ -519,8 +525,6 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle) GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; - assert(monitor != NULL); assert(ramp != NULL); assert(ramp->size > 0); assert(ramp->red != NULL); @@ -529,6 +533,9 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) _GLFW_REQUIRE_INIT(); + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + if (ramp->size <= 0) { _glfwInputError(GLFW_INVALID_VALUE, diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 6493291e..74fbbcd9 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -30,6 +30,7 @@ #include #include +#include static void makeContextCurrentNSGL(_GLFWwindow* window) { @@ -182,16 +183,16 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, 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 - // 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 - // 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 - // 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 #define ADD_ATTRIB(a) \ @@ -217,14 +218,11 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching); } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 if (ctxconfig->major >= 4) { SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core); } - else -#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ - if (ctxconfig->major >= 3) + else if (ctxconfig->major >= 3) { SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); } @@ -406,7 +404,6 @@ _GLFWusercontext* _glfwCreateUserContextNSGL(_GLFWwindow* window) GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(nil); if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) @@ -416,6 +413,9 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) return nil; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); diff --git a/src/null_platform.h b/src/null_platform.h index f2604525..691139d3 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -157,6 +157,17 @@ #define GLFW_NULL_SC_MENU 120 #define GLFW_NULL_SC_LAST GLFW_NULL_SC_MENU +typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT; + +typedef struct VkHeadlessSurfaceCreateInfoEXT +{ + VkStructureType sType; + const void* pNext; + VkHeadlessSurfaceCreateFlagsEXT flags; +} VkHeadlessSurfaceCreateInfoEXT; + +typedef VkResult (APIENTRY *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance,const VkHeadlessSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*); + // Null-specific per-window data // typedef struct _GLFWwindowNull diff --git a/src/null_window.c b/src/null_window.c index d87513ce..822eb182 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -28,6 +28,7 @@ #include "internal.h" #include +#include static void applySizeLimits(_GLFWwindow* window, int* width, int* height) { @@ -552,12 +553,15 @@ const char* _glfwGetClipboardStringNull(void) EGLenum _glfwGetEGLPlatformNull(EGLint** attribs) { - return 0; + if (_glfw.egl.EXT_platform_base && _glfw.egl.MESA_platform_surfaceless) + return EGL_PLATFORM_SURFACELESS_MESA; + else + return 0; } EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void) { - return 0; + return EGL_DEFAULT_DISPLAY; } EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window) @@ -699,13 +703,18 @@ int _glfwGetKeyScancodeNull(int key) void _glfwGetRequiredInstanceExtensionsNull(char** extensions) { + if (!_glfw.vk.KHR_surface || !_glfw.vk.EXT_headless_surface) + return; + + extensions[0] = "VK_KHR_surface"; + extensions[1] = "VK_EXT_headless_surface"; } GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily) { - return GLFW_FALSE; + return GLFW_TRUE; } VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, @@ -713,8 +722,29 @@ VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface) { - // This seems like the most appropriate error to return here - return VK_ERROR_EXTENSION_NOT_PRESENT; + PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT = + (PFN_vkCreateHeadlessSurfaceEXT) + vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT"); + if (!vkCreateHeadlessSurfaceEXT) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Null: Vulkan instance missing VK_EXT_headless_surface extension"); + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + + VkHeadlessSurfaceCreateInfoEXT sci; + memset(&sci, 0, sizeof(sci)); + sci.sType = VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT; + + const VkResult err = vkCreateHeadlessSurfaceEXT(instance, &sci, allocator, surface); + if (err) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Null: Failed to create Vulkan surface: %s", + _glfwGetVulkanResultString(err)); + } + + return err; } _GLFWusercontext* _glfwCreateUserContextNull(_GLFWwindow* window) diff --git a/src/osmesa_context.c b/src/osmesa_context.c index ea0b00f6..fcd978c5 100644 --- a/src/osmesa_context.c +++ b/src/osmesa_context.c @@ -361,11 +361,12 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width, { void* mesaBuffer; GLint mesaWidth, mesaHeight, mesaFormat; - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_OSMESA_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); @@ -400,11 +401,12 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle, { void* mesaBuffer; GLint mesaWidth, mesaHeight, mesaBytes; - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_OSMESA_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); @@ -434,9 +436,11 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle, GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_OSMESA_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); diff --git a/src/vulkan.c b/src/vulkan.c index 274d21ca..9c87fcfe 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -142,6 +142,8 @@ GLFWbool _glfwInitVulkan(int mode) _glfw.vk.KHR_xcb_surface = GLFW_TRUE; else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0) _glfw.vk.KHR_wayland_surface = GLFW_TRUE; + else if (strcmp(ep[i].extensionName, "VK_EXT_headless_surface") == 0) + _glfw.vk.EXT_headless_surface = GLFW_TRUE; } _glfw_free(ep); @@ -272,11 +274,11 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily) { + _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); + assert(instance != VK_NULL_HANDLE); assert(device != VK_NULL_HANDLE); - _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); - if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) return GLFW_FALSE; @@ -297,15 +299,16 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(instance != VK_NULL_HANDLE); - assert(window != NULL); assert(surface != NULL); *surface = VK_NULL_HANDLE; _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + assert(instance != VK_NULL_HANDLE); + if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) return VK_ERROR_INITIALIZATION_FAILED; diff --git a/src/wgl_context.c b/src/wgl_context.c index 1dd9bd23..de2ca0a5 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -836,7 +836,6 @@ _GLFWusercontext* _glfwCreateUserContextWGL(_GLFWwindow* window) GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) @@ -846,6 +845,9 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) return NULL; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (window->context.source != GLFW_NATIVE_CONTEXT_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 1be43e66..87e5c206 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -33,6 +33,7 @@ #include #include #include +#include // Callback for EnumDisplayMonitors in createMonitor @@ -539,7 +540,6 @@ void _glfwSetGammaRampWin32(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) @@ -548,12 +548,14 @@ GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle) return NULL; } + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + return monitor->win32.publicAdapterName; } GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) @@ -562,6 +564,9 @@ GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle) return NULL; } + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + return monitor->win32.publicDisplayName; } diff --git a/src/win32_window.c b/src/win32_window.c index a48bd084..3a01ed1f 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -2598,7 +2599,6 @@ _GLFWusercontext* _glfwCreateUserContextWin32(_GLFWwindow* window) GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) @@ -2608,6 +2608,9 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle) return NULL; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + return window->win32.handle; } diff --git a/src/window.c b/src/window.c index 8b5d9f34..e03121a4 100644 --- a/src/window.c +++ b/src/window.c @@ -467,10 +467,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value) GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; - _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; + // Allow closing of NULL (to match the behavior of free) if (window == NULL) return; @@ -501,40 +501,43 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(0); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(0); return window->shouldClose; } GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); window->shouldClose = value; } GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - return window->title; } GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); assert(title != NULL); _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + char* prev = window->title; window->title = _glfw_strdup(title); @@ -546,14 +549,15 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle, int count, const GLFWimage* images) { int i; - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); assert(count >= 0); assert(count == 0 || images != NULL); _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (count < 0) { _glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon"); @@ -577,25 +581,26 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle, GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); - if (xpos) *xpos = 0; if (ypos) *ypos = 0; _GLFW_REQUIRE_INIT(); + + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + _glfw.platform.getWindowPos(window, xpos, ypos); } GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - if (window->monitor) return; @@ -604,27 +609,29 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); - if (width) *width = 0; if (height) *height = 0; _GLFW_REQUIRE_INIT(); + + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + _glfw.platform.getWindowSize(window, width, height); } GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); assert(width >= 0); assert(height >= 0); _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + window->videoMode.width = width; window->videoMode.height = height; @@ -635,11 +642,11 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, int minwidth, int minheight, int maxwidth, int maxheight) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE) { if (minwidth < 0 || minheight < 0) @@ -678,13 +685,14 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle, GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); assert(numer != 0); assert(denom != 0); _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE) { if (numer <= 0 || denom <= 0) @@ -707,15 +715,16 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); - if (width) *width = 0; if (height) *height = 0; _GLFW_REQUIRE_INIT(); + + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + _glfw.platform.getFramebufferSize(window, width, height); } @@ -723,9 +732,6 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle, int* left, int* top, int* right, int* bottom) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); - if (left) *left = 0; if (top) @@ -736,43 +742,50 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle, *bottom = 0; _GLFW_REQUIRE_INIT(); + + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + _glfw.platform.getWindowFrameSize(window, left, top, right, bottom); } GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle, float* xscale, float* yscale) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); - if (xscale) *xscale = 0.f; if (yscale) *yscale = 0.f; _GLFW_REQUIRE_INIT(); + + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + _glfw.platform.getWindowContentScale(window, xscale, yscale); } GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(0.f); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(0.f); return _glfw.platform.getWindowOpacity(window); } GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity) { - _GLFWwindow* window = (_GLFWwindow*) handle; - assert(window != NULL); assert(opacity == opacity); assert(opacity >= 0.f); assert(opacity <= 1.f); _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + if (opacity != opacity || opacity < 0.f || opacity > 1.f) { _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity); @@ -784,29 +797,31 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity) GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); _glfw.platform.iconifyWindow(window); } GLFWAPI void glfwRestoreWindow(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); _glfw.platform.restoreWindow(window); } GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - if (window->monitor) return; @@ -815,11 +830,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle) GLFWAPI void glfwShowWindow(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - if (window->monitor) return; @@ -831,21 +846,21 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle) GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - _glfw.platform.requestWindowAttention(window); } GLFWAPI void glfwHideWindow(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - if (window->monitor) return; @@ -854,21 +869,21 @@ GLFWAPI void glfwHideWindow(GLFWwindow* handle) GLFWAPI void glfwFocusWindow(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - _glfw.platform.focusWindow(window); } GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) { + _GLFW_REQUIRE_INIT_OR_RETURN(0); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(0); - switch (attrib) { case GLFW_FOCUSED: @@ -927,11 +942,11 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); - value = value ? GLFW_TRUE : GLFW_FALSE; switch (attrib) @@ -973,10 +988,11 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return (GLFWmonitor*) window->monitor; } @@ -986,14 +1002,15 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh, int width, int height, int refreshRate) { - _GLFWwindow* window = (_GLFWwindow*) wh; - _GLFWmonitor* monitor = (_GLFWmonitor*) mh; - assert(window != NULL); assert(width >= 0); assert(height >= 0); _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) wh; + _GLFWmonitor* monitor = (_GLFWmonitor*) mh; + assert(window != NULL); + if (width <= 0 || height <= 0) { _glfwInputError(GLFW_INVALID_VALUE, @@ -1021,29 +1038,32 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh, GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) { + _GLFW_REQUIRE_INIT(); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT(); window->userPointer = pointer; } GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return window->userPointer; } GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle, GLFWwindowposfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWwindowposfun, window->callbacks.pos, cbfun); return cbfun; } @@ -1051,10 +1071,11 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle, GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, GLFWwindowsizefun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWwindowsizefun, window->callbacks.size, cbfun); return cbfun; } @@ -1062,10 +1083,11 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, GLFWwindowclosefun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWwindowclosefun, window->callbacks.close, cbfun); return cbfun; } @@ -1073,10 +1095,11 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle, GLFWwindowrefreshfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWwindowrefreshfun, window->callbacks.refresh, cbfun); return cbfun; } @@ -1084,10 +1107,11 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle, GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, GLFWwindowfocusfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWwindowfocusfun, window->callbacks.focus, cbfun); return cbfun; } @@ -1095,10 +1119,11 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, GLFWwindowiconifyfun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWwindowiconifyfun, window->callbacks.iconify, cbfun); return cbfun; } @@ -1106,10 +1131,11 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle, GLFWwindowmaximizefun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWwindowmaximizefun, window->callbacks.maximize, cbfun); return cbfun; } @@ -1117,10 +1143,11 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle, GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle, GLFWframebuffersizefun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWframebuffersizefun, window->callbacks.fbsize, cbfun); return cbfun; } @@ -1128,10 +1155,11 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle, GLFWwindowcontentscalefun cbfun) { + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFWwindow* window = (_GLFWwindow*) handle; assert(window != NULL); - _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP(GLFWwindowcontentscalefun, window->callbacks.scale, cbfun); return cbfun; } diff --git a/src/wl_init.c b/src/wl_init.c index c6edca82..9e4b5846 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -137,6 +137,13 @@ static void registryHandleGlobal(void* userData, wl_registry_bind(registry, name, &wl_seat_interface, _glfw_min(4, version)); _glfwAddSeatListenerWayland(_glfw.wl.seat); + + if (wl_seat_get_version(_glfw.wl.seat) >= + WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) + { + _glfw.wl.keyRepeatTimerfd = + timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + } } } else if (strcmp(interface, "wl_data_device_manager") == 0) @@ -854,12 +861,6 @@ int _glfwInitWayland(void) } } - if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) - { - _glfw.wl.keyRepeatTimerfd = - timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); - } - if (!_glfw.wl.wmBase) { _glfwInputError(GLFW_PLATFORM_ERROR, diff --git a/src/wl_monitor.c b/src/wl_monitor.c index dca8ebbd..1ec5f5af 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "wayland-client-protocol.h" @@ -258,7 +259,6 @@ void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND) @@ -267,6 +267,9 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle) return NULL; } + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + return monitor->wl.output; } diff --git a/src/wl_platform.h b/src/wl_platform.h index 25199d6f..c43b9125 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -28,8 +28,6 @@ #include #include -#include - typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; typedef struct VkWaylandSurfaceCreateInfoKHR diff --git a/src/wl_window.c b/src/wl_window.c index 3548be20..cc06943b 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1974,41 +1974,41 @@ static void dataDeviceHandleEnter(void* userData, _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) + break; + } + + 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) { - _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 (_glfw.wl.offers[i].text_uri_list) { _glfw.wl.dragOffer = offer; _glfw.wl.dragFocus = window; _glfw.wl.dragSerial = serial; - } - _glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1]; - _glfw.wl.offerCount--; - break; + wl_data_offer_accept(offer, serial, "text/uri-list"); + } } } - 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"); - else + if (!_glfw.wl.dragOffer) { wl_data_offer_accept(offer, serial, NULL); wl_data_offer_destroy(offer); } + + _glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1]; + _glfw.wl.offerCount--; } static void dataDeviceHandleLeave(void* userData, @@ -2042,15 +2042,17 @@ static void dataDeviceHandleDrop(void* userData, int count; char** paths = _glfwParseUriList(string, &count); if (paths) + { _glfwInputDrop(_glfw.wl.dragFocus, count, (const char**) paths); - for (int i = 0; i < count; i++) - _glfw_free(paths[i]); + for (int i = 0; i < count; i++) + _glfw_free(paths[i]); - _glfw_free(paths); + _glfw_free(paths); + } + + _glfw_free(string); } - - _glfw_free(string); } static void dataDeviceHandleSelection(void* userData, @@ -2183,6 +2185,12 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window) if (window == _glfw.wl.keyboardFocus) _glfw.wl.keyboardFocus = NULL; + if (window->wl.fractionalScale) + wp_fractional_scale_v1_destroy(window->wl.fractionalScale); + + if (window->wl.scalingViewport) + wp_viewport_destroy(window->wl.scalingViewport); + if (window->wl.activationToken) xdg_activation_token_v1_destroy(window->wl.activationToken); @@ -3304,7 +3312,6 @@ GLFWAPI struct wl_display* glfwGetWaylandDisplay(void) GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND) @@ -3314,6 +3321,9 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle) return NULL; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + return window->wl.surface; } diff --git a/src/x11_monitor.c b/src/x11_monitor.c index cab81127..3af82752 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -33,6 +33,7 @@ #include #include #include +#include // Check whether the display mode should be included in enumeration @@ -611,7 +612,6 @@ void _glfwSetGammaRampX11(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(None); if (_glfw.platform.platformID != GLFW_PLATFORM_X11) @@ -620,12 +620,14 @@ GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle) return None; } + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + return monitor->x11.crtc; } GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle) { - _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(None); if (_glfw.platform.platformID != GLFW_PLATFORM_X11) @@ -634,6 +636,9 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle) return None; } + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + return monitor->x11.output; } diff --git a/src/x11_window.c b/src/x11_window.c index 0d0d5bc8..dc2db13f 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -3320,7 +3320,6 @@ GLFWAPI Display* glfwGetX11Display(void) GLFWAPI Window glfwGetX11Window(GLFWwindow* handle) { - _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(None); if (_glfw.platform.platformID != GLFW_PLATFORM_X11) @@ -3329,11 +3328,16 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle) return None; } + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + return window->x11.handle; } GLFWAPI void glfwSetX11SelectionString(const char* string) { + assert(string != NULL); + _GLFW_REQUIRE_INIT(); if (_glfw.platform.platformID != GLFW_PLATFORM_X11) diff --git a/tests/events.c b/tests/events.c index fdc3c199..ab3b99a7 100644 --- a/tests/events.c +++ b/tests/events.c @@ -630,6 +630,7 @@ int main(int argc, char** argv) glfwTerminate(); exit(EXIT_FAILURE); } + glfwSetInputMode(slots[i].window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE); glfwSetWindowUserPointer(slots[i].window, slots + i); diff --git a/tests/window.c b/tests/window.c index c81bf024..ffea5dbf 100644 --- a/tests/window.c +++ b/tests/window.c @@ -78,6 +78,7 @@ int main(int argc, char** argv) glfwTerminate(); exit(EXIT_FAILURE); } + glfwSetInputMode(window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE); glfwMakeContextCurrent(window); gladLoadGL(glfwGetProcAddress);