From dbe810e4036fa6640fbe5d509e1a551c8a77f371 Mon Sep 17 00:00:00 2001 From: Grzesiek11 Date: Fri, 24 Nov 2023 18:04:13 +0100 Subject: [PATCH 01/21] Documentation: only named keys generate synthetic key releases The current wording states that all keys have synthetic key release events generated after focus is lost, but keys that aren't named don't have any state held, so no such events are generated for them. The new wording clarifies that only named keys have the events generated for them. --- CONTRIBUTORS.md | 1 + include/GLFW/glfw3.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 18db7c02..9e0fb922 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -269,6 +269,7 @@ video tutorials. - Jonas Ådahl - Lasse Öörni - Leonard König + - Grzesiek11 - All the unmentioned and anonymous contributors in the GLFW community, for bug reports, patches, feedback, testing and encouragement diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 58b395cd..f8b0ae00 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -5058,9 +5058,9 @@ GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); * [character callback](@ref glfwSetCharCallback) instead. * * When a window loses input focus, it will generate synthetic key release - * events for all pressed keys. 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 + * events for all pressed named keys. 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 scancode of a key is specific to that platform or sometimes even to that From 659d161446ad6e3f3e67cdc1baabcf61abd70aef Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Fri, 24 Nov 2023 17:06:18 +0000 Subject: [PATCH 02/21] Reorder credit --- CONTRIBUTORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9e0fb922..1b9a277a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -78,6 +78,7 @@ video tutorials. - Kovid Goyal - Kevin Grandemange - Eloi Marín Gratacós + - Grzesiek11 - Stefan Gustavson - Andrew Gutekanst - Stephen Gutekanst @@ -269,7 +270,6 @@ video tutorials. - Jonas Ådahl - Lasse Öörni - Leonard König - - Grzesiek11 - All the unmentioned and anonymous contributors in the GLFW community, for bug reports, patches, feedback, testing and encouragement From 23ea072c4157f2a7760d26f4d6e375833646bd88 Mon Sep 17 00:00:00 2001 From: Doug Binks Date: Mon, 27 Nov 2023 16:56:58 +0000 Subject: [PATCH 03/21] Reorder changelog entry --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eb19011b..d0a40c34 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,6 @@ information on what to include when reporting a bug. - Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization - Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization - Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092) - - [Win32] Fix pkg-config for dynamic library on Windows (#2386, #2420) - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access to the window menu - [Win32] Added a version info resource to the GLFW DLL @@ -231,6 +230,7 @@ information on what to include when reporting a bug. - [Win32] Bugfix: The OSMesa library was not unloaded on termination - [Win32] Bugfix: Right shift emitted `GLFW_KEY_UNKNOWN` when using a CJK IME (#2050) - [Win32] Bugfix: `glfwWaitEventsTimeout` did not return for some sent messages (#2408) + - [Win32] Bugfix: Fix pkg-config for dynamic library on Windows (#2386, #2420) - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Moved main menu creation to GLFW initialization time (#1649) From 9fdc425931888ea70bc095e53cc006fca8ccb703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Nov 2023 02:43:48 +0100 Subject: [PATCH 04/21] Wayland: Use Wayland to wait for libdecor to init Much of libdecor is initialized only after certain events have been received from the compositor and some parts of libdecor 0.1 are unsafe to use until this delayed initialization has completed. Since libdecor does not provide an API to query if or be notified when this has happened, GLFW processed events until its newly created libdecor frame had created its XDG shell objects. This commit switches to using a generic Wayland sync point created just after libdecor (and presumably its plugin) has set up its delayed initialization, instead of relying on the more specific implementation detail mentioned above. It also makes this wait mandatory before the first libdecor frame is created instead of a pre-condition for certain libdecor frame calls, hopefully removing even more dependence on implementation details. --- src/wl_init.c | 32 +++++++++++++++++++++++++++++--- src/wl_platform.h | 2 ++ src/wl_window.c | 10 ++++------ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index 66d77dca..0ec65900 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "wayland-client-protocol.h" #include "wayland-xdg-shell-client-protocol.h" @@ -216,6 +217,22 @@ static const struct libdecor_interface libdecorInterface = libdecorHandleError }; +static void libdecorReadyCallback(void* userData, + struct wl_callback* callback, + uint32_t time) +{ + _glfw.wl.libdecor.ready = GLFW_TRUE; + + assert(_glfw.wl.libdecor.callback == callback); + wl_callback_destroy(_glfw.wl.libdecor.callback); + _glfw.wl.libdecor.callback = NULL; +} + +static const struct wl_callback_listener libdecorReadyListener = +{ + libdecorReadyCallback +}; + // Create key code translation tables // static void createKeyTables(void) @@ -775,10 +792,17 @@ int _glfwInitWayland(void) if (_glfw.wl.libdecor.handle) { _glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface); - - // Allow libdecor to receive its globals before proceeding if (_glfw.wl.libdecor.context) - libdecor_dispatch(_glfw.wl.libdecor.context, 1); + { + // Perform an initial dispatch and flush to get the init started + libdecor_dispatch(_glfw.wl.libdecor.context, 0); + + // Create sync point to "know" when libdecor is ready for use + _glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display); + wl_callback_add_listener(_glfw.wl.libdecor.callback, + &libdecorReadyListener, + NULL); + } } #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION @@ -822,6 +846,8 @@ void _glfwTerminateWayland(void) _glfwTerminateEGL(); _glfwTerminateOSMesa(); + if (_glfw.wl.libdecor.callback) + wl_callback_destroy(_glfw.wl.libdecor.callback); if (_glfw.wl.libdecor.context) libdecor_unref(_glfw.wl.libdecor.context); diff --git a/src/wl_platform.h b/src/wl_platform.h index e9dd0b4a..d00e28fe 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -550,6 +550,8 @@ typedef struct _GLFWlibraryWayland struct { void* handle; struct libdecor* context; + struct wl_callback* callback; + GLFWbool ready; PFN_libdecor_new libdecor_new_; PFN_libdecor_unref libdecor_unref_; PFN_libdecor_get_fd libdecor_get_fd_; diff --git a/src/wl_window.c b/src/wl_window.c index fc4a671a..c7dd62b0 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -735,6 +735,10 @@ static const struct libdecor_frame_interface libdecorFrameInterface = static GLFWbool createLibdecorFrame(_GLFWwindow* window) { + // Allow libdecor to finish initialization of itself and its plugin + while (!_glfw.wl.libdecor.ready) + _glfwWaitEventsWayland(); + window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context, window->wl.surface, &libdecorFrameInterface, @@ -776,12 +780,6 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window) if (window->monitor) { - // HACK: Allow libdecor to finish initialization of itself and its - // plugin so it will create the xdg_toplevel for the frame - // This needs to exist when setting the frame to fullscreen - while (!libdecor_frame_get_xdg_toplevel(window->wl.libdecor.frame)) - _glfwWaitEventsWayland(); - libdecor_frame_set_fullscreen(window->wl.libdecor.frame, window->monitor->wl.output); setIdleInhibitor(window, GLFW_TRUE); From 23e40548b15db9a53a755d152d1fd2072c39610e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 29 Nov 2023 16:25:29 +0100 Subject: [PATCH 05/21] Wayland: Fix protocol error on undecorated window When setting the visibility of a libdecor frame on a compositor that supports XDG decorations, libdecor 0.1 will update the geometry of the XDG surface. GLFW attempted to set the visibility before having told libdecor what size the content area is. This caused a Wayland protocol error when libdecor attempted to set the window size to 0x0. This commit adds setting the content area size for the libdecor frame directly after creation, allowing libdecor to know what it's doing. --- README.md | 1 + src/wl_window.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index d0a40c34..52081c1c 100644 --- a/README.md +++ b/README.md @@ -387,6 +387,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450) - [Wayland] Bugfix: Joysticks connected after `glfwInit` were not detected (#2198) - [Wayland] Bugfix: Fallback decorations emitted `GLFW_CURSOR_UNAVAILABLE` errors + - [Wayland] Bugfix: Showing an undecorated window would cause a protocol error - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043) diff --git a/src/wl_window.c b/src/wl_window.c index c7dd62b0..8292dcd6 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -750,6 +750,11 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window) return GLFW_FALSE; } + struct libdecor_state* frameState = + libdecor_state_new(window->wl.width, window->wl.height); + libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL); + libdecor_state_free(frameState); + if (strlen(window->wl.appId)) libdecor_frame_set_app_id(window->wl.libdecor.frame, window->wl.appId); From d097e35743ee49d38811a89ea29c7f2525dc8d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Nov 2023 16:47:35 +0100 Subject: [PATCH 06/21] Wayland: Fix heuristics for what counts as events The Wayland implementation of glfwWaitEvents* keeps waiting until it sees evidence that a significant event has been processed. However, this included updating an animated cursor (not a significant event) but did not include previously buffered Wayland events or libdecor events (definitely significant events). This commit corrects these cases. --- src/wl_window.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 8292dcd6..7c509896 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1118,7 +1118,10 @@ static void handleEvents(double* timeout) while (!event) { while (wl_display_prepare_read(_glfw.wl.display) != 0) - wl_display_dispatch_pending(_glfw.wl.display); + { + if (wl_display_dispatch_pending(_glfw.wl.display) > 0) + return; + } // If an error other than EAGAIN happens, we have likely been disconnected // from the Wayland session; try to handle that the best we can. @@ -1176,14 +1179,14 @@ static void handleEvents(double* timeout) uint64_t repeats; if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8) - { incrementCursorImage(_glfw.wl.pointerFocus); - event = GLFW_TRUE; - } } if (fds[3].revents & POLLIN) - libdecor_dispatch(_glfw.wl.libdecor.context, 0); + { + if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0) + event = GLFW_TRUE; + } } } From fb94e4268b222448a55b151f3c115f57f1e6540f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 1 Dec 2023 12:38:57 +0100 Subject: [PATCH 07/21] Remove changelog entry This bug was introduced since the last release and should not be listed. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 52081c1c..d0a40c34 100644 --- a/README.md +++ b/README.md @@ -387,7 +387,6 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450) - [Wayland] Bugfix: Joysticks connected after `glfwInit` were not detected (#2198) - [Wayland] Bugfix: Fallback decorations emitted `GLFW_CURSOR_UNAVAILABLE` errors - - [Wayland] Bugfix: Showing an undecorated window would cause a protocol error - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043) From 8c5471d6cdc6d87935e494b8c379f659e998bcf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 1 Dec 2023 13:22:11 +0100 Subject: [PATCH 08/21] Fix return value on error for glfwGetKeyScancode The documentation says it should be -1, not zero. --- README.md | 1 + src/input.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d0a40c34..797ffd17 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,7 @@ information on what to include when reporting a bug. - Bugfix: `glfwMakeContextCurrent` would access TLS slot before initialization - Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization - Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092) + - Bugfix: `glfwGetKeyScancode` returned `0` on error when initialized instead of `-1` - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access to the window menu - [Win32] Added a version info resource to the GLFW DLL diff --git a/src/input.c b/src/input.c index 36128e10..8c1bb7ef 100644 --- a/src/input.c +++ b/src/input.c @@ -721,7 +721,7 @@ GLFWAPI int glfwGetKeyScancode(int key) if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); - return GLFW_RELEASE; + return -1; } return _glfw.platform.getKeyScancode(key); From fa0ea5c41f53119c68748a0e8570ef120b7fa703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 3 Dec 2023 16:06:31 +0100 Subject: [PATCH 09/21] Fix potential violation of invariant The shared function for reading back context attributes, _glfwRefreshContextAttribs, did not check whether the newly created context had been successfully made current. This violated the invariant that the context TLS slot always points to a valid window and that its context is current whenever _glfw.platform.getProcAddress is called. Related to #2327 --- src/context.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/context.c b/src/context.c index 33b399c9..f8610e1e 100644 --- a/src/context.c +++ b/src/context.c @@ -363,6 +363,8 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window, previous = _glfwPlatformGetTls(&_glfw.contextSlot); glfwMakeContextCurrent((GLFWwindow*) window); + if (_glfwPlatformGetTls(&_glfw.contextSlot) != window) + return GLFW_FALSE; window->context.GetIntegerv = (PFNGLGETINTEGERVPROC) window->context.getProcAddress("glGetIntegerv"); From 93d70cb6a8c9571b5b493936596633a1a8538cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 3 Dec 2023 17:07:25 +0100 Subject: [PATCH 10/21] Add assertions for context function invariants Related to #2327 --- src/egl_context.c | 1 + src/glx_context.c | 1 + src/nsgl_context.m | 9 ++++----- src/wgl_context.c | 1 + 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/egl_context.c b/src/egl_context.c index 64dcdd6f..4f76d351 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -311,6 +311,7 @@ static int extensionSupportedEGL(const char* extension) static GLFWglproc getProcAddressEGL(const char* procname) { _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); + assert(window != NULL); if (window->context.egl.client) { diff --git a/src/glx_context.c b/src/glx_context.c index 4406dfd3..f3f4b3ec 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -192,6 +192,7 @@ static void swapBuffersGLX(_GLFWwindow* window) static void swapIntervalGLX(int interval) { _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); + assert(window != NULL); if (_glfw.glx.EXT_swap_control) { diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 878f32ed..de89e421 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -83,11 +83,10 @@ static void swapIntervalNSGL(int interval) @autoreleasepool { _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); - if (window) - { - [window->context.nsgl.object setValues:&interval - forParameter:NSOpenGLContextParameterSwapInterval]; - } + assert(window != NULL); + + [window->context.nsgl.object setValues:&interval + forParameter:NSOpenGLContextParameterSwapInterval]; } // autoreleasepool } diff --git a/src/wgl_context.c b/src/wgl_context.c index cfe24b27..08c499ff 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -332,6 +332,7 @@ static void swapBuffersWGL(_GLFWwindow* window) static void swapIntervalWGL(int interval) { _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); + assert(window != NULL); window->context.wgl.interval = interval; From 1b2605dbcd674608ba3ef57ff40880c2bf899029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 3 Dec 2023 17:23:37 +0100 Subject: [PATCH 11/21] Fix missing new constant in release notes --- docs/news.dox | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/news.dox b/docs/news.dox index e16267b2..28c500d9 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -277,6 +277,7 @@ then GLFW will fail to initialize. - @ref GLFW_POSITION_X - @ref GLFW_POSITION_Y - @ref GLFW_ANY_POSITION + - @ref GLFW_WAYLAND_APP_ID - @ref GLFW_WAYLAND_LIBDECOR - @ref GLFW_WAYLAND_PREFER_LIBDECOR - @ref GLFW_WAYLAND_DISABLE_LIBDECOR From 3f31519de81b943d17231b3d59108923d0d2e302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 3 Dec 2023 17:40:42 +0100 Subject: [PATCH 12/21] Clarify documentation for glfwMakeContextCurrent --- include/GLFW/glfw3.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index f8b0ae00..0b05aa7f 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -5959,12 +5959,15 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void); * thread. * * This function makes the OpenGL or OpenGL ES context of the specified window - * current on the calling thread. A context must only be made current on - * a single thread at a time and each thread can have only a single current - * context at a time. + * current on the calling thread. It can also detach the current context from + * the calling thread without making a new one current by passing in `NULL`. * - * When moving a context between threads, you must make it non-current on the - * old thread before making it current on the new one. + * A context must only be made current on a single thread at a time and each + * thread can have only a single current context at a time. Making a context + * current detaches any previously current context on the calling thread. + * + * When moving a context between threads, you must detach it (make it + * non-current) on the old thread before making it current on the new one. * * By default, making a context non-current implicitly forces a pipeline flush. * On machines that support `GL_KHR_context_flush_control`, you can control @@ -5979,6 +5982,10 @@ GLFWAPI uint64_t glfwGetTimerFrequency(void); * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * + * @remarks If the previously current context was created via a different + * context creation API than the one passed to this function, GLFW will still + * detach the previous one from its API before making the new one current. + * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. * From b1517e5b3ee6f060f2e7ebd47c9de0c10e6ad411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 4 Dec 2023 18:48:24 +0100 Subject: [PATCH 13/21] Fix glfwGetKeyName not checking key token is valid --- src/input.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/input.c b/src/input.c index 8c1bb7ef..8ab141fb 100644 --- a/src/input.c +++ b/src/input.c @@ -701,6 +701,12 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode) if (key != GLFW_KEY_UNKNOWN) { + if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) + { + _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); + return NULL; + } + if (key != GLFW_KEY_KP_EQUAL && (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) && (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2)) From 557a633b2d926431090367e9536cd5ba661a276d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 5 Dec 2023 15:53:42 +0100 Subject: [PATCH 14/21] Fix list of possible errors for glfwGetKeyName --- include/GLFW/glfw3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 0b05aa7f..8116784d 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -4718,8 +4718,8 @@ GLFWAPI int glfwRawMouseMotionSupported(void); * @param[in] scancode The scancode of the key to query. * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * * @remark The contents of the returned string may change when a keyboard * layout change event is received. From 9959dc69cadd1f7790060846ffbc44e7da56fc56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 4 Dec 2023 20:06:10 +0100 Subject: [PATCH 15/21] Improve documentation relating to key tokens Shifted the documentation away from the term 'named keys' as something different than keys that glfwGetKeyName will return a name for. The already existing term 'key token' should now be used to refer to the GLFW_KEY_* constants. The associated term 'named mouse button' was also replaced with 'supported mouse button'. The parts explaining which key tokens will return a valid scancode from glfwGetKeyScancode have hopefully been clarified. This issue was reported in #2055. The GLFW_KEY_UNKNOWN constant has been moved out of the list of key tokens to simplify and hopefully clarify the related documentation. Various other keyboard key related edits were made, hopefully resulting in improvements. Related to #2055 --- docs/input.dox | 30 ++++++++++++++++++------------ include/GLFW/glfw3.h | 35 ++++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/docs/input.dox b/docs/input.dox index d3904f46..f57520bb 100644 --- a/docs/input.dox +++ b/docs/input.dox @@ -95,7 +95,7 @@ new size before everything returns back out of the @ref glfwSetWindowSize call. GLFW divides keyboard input into two categories; key events and character events. Key events relate to actual physical keyboard keys, whereas character -events relate to the Unicode code points generated by pressing some of them. +events relate to the text that is generated by pressing some of them. Keys and characters do not map 1:1. A single key press may produce several characters, and a single character may require several keys to produce. This @@ -127,6 +127,10 @@ The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. Events with `GLFW_PRESS` and `GLFW_RELEASE` actions are emitted for every key press. Most keys will also emit events with `GLFW_REPEAT` actions while a key is held down. +Note that many keyboards have a limit on how many keys being simultaneous held +down that they can detect. This limit is called +[key rollover](https://en.wikipedia.org/wiki/Key_rollover). + Key events with `GLFW_REPEAT` actions are intended for text input. They are emitted at the rate set in the user's keyboard settings. At most one key is repeated even if several keys are held down. `GLFW_REPEAT` actions should not @@ -142,16 +146,16 @@ keys. The scancode is unique for every key, regardless of whether it has a key token. Scancodes are platform-specific but consistent over time, so keys will have different scancodes depending on the platform but they are safe to save to disk. -You can query the scancode for any [named key](@ref keys) on the current -platform with @ref glfwGetKeyScancode. +You can query the scancode for any [key token](@ref keys) supported on the +current platform with @ref glfwGetKeyScancode. @code const int scancode = glfwGetKeyScancode(GLFW_KEY_X); set_key_mapping(scancode, swap_weapons); @endcode -The last reported state for every [named key](@ref keys) is also saved in -per-window state arrays that can be polled with @ref glfwGetKey. +The last reported state for every physical key with a [key token](@ref keys) is +also saved in per-window state arrays that can be polled with @ref glfwGetKey. @code int state = glfwGetKey(window, GLFW_KEY_E); @@ -164,7 +168,8 @@ if (state == GLFW_PRESS) The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`. This function only returns cached key event state. It does not poll the -system for the current physical state of the key. +system for the current state of the physical key. It also does not provide any +key repeat information. @anchor GLFW_STICKY_KEYS Whenever you poll state, you risk missing the state change you are looking for. @@ -195,15 +200,15 @@ Lock was on when the event occurred and the @ref GLFW_MOD_NUM_LOCK bit set if Num Lock was on. The `GLFW_KEY_LAST` constant holds the highest value of any -[named key](@ref keys). +[key token](@ref keys). @subsection input_char Text input GLFW supports text input in the form of a stream of [Unicode code points](https://en.wikipedia.org/wiki/Unicode), as produced by the -operating system text input system. Unlike key input, text input obeys keyboard -layouts and modifier keys and supports composing characters using +operating system text input system. Unlike key input, text input is affected by +keyboard layouts and modifier keys and supports composing characters using [dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can encode the code points into UTF-8 or any other encoding you prefer. @@ -502,8 +507,9 @@ void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) The action is one of `GLFW_PRESS` or `GLFW_RELEASE`. -Mouse button states for [named buttons](@ref buttons) are also saved in -per-window state arrays that can be polled with @ref glfwGetMouseButton. +The last reported state for every [supported mouse button](@ref buttons) is also +saved in per-window state arrays that can be polled with @ref +glfwGetMouseButton. @code int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT); @@ -536,7 +542,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 -[named button](@ref buttons). +[supported mouse button](@ref buttons). @subsection scrolling Scroll input diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 8116784d..eb98dafd 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -361,10 +361,15 @@ extern "C" { #define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN) #define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP) #define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN) + +/*! @ingroup input + */ +#define GLFW_KEY_UNKNOWN -1 + /*! @} */ -/*! @defgroup keys Keyboard keys - * @brief Keyboard key IDs. +/*! @defgroup keys Keyboard key tokens + * @brief Keyboard key tokens. * * See [key input](@ref input_key) for how these are used. * @@ -387,9 +392,6 @@ extern "C" { * @{ */ -/* The unknown key */ -#define GLFW_KEY_UNKNOWN -1 - /* Printable keys */ #define GLFW_KEY_SPACE 32 #define GLFW_KEY_APOSTROPHE 39 /* ' */ @@ -4741,15 +4743,18 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode); * * This function returns the platform-specific scancode of the specified key. * - * If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this - * method will return `-1`. + * If the specified [key token](@ref keys) corresponds to a physical key not + * supported on the current platform then this method will return `-1`. + * Calling this function with anything other than a key token will return `-1` + * and generate a @ref GLFW_INVALID_ENUM error. * - * @param[in] key Any [named key](@ref keys). - * @return The platform-specific scancode for the key, or `-1` if an - * [error](@ref error_handling) occurred. + * @param[in] key Any [key token](@ref keys). + * @return The platform-specific scancode for the key, or `-1` if the key is + * not supported on the current platform or an [error](@ref error_handling) + * occurred. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. * * @thread_safety This function may be called from any thread. * @@ -5058,9 +5063,9 @@ GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); * [character callback](@ref glfwSetCharCallback) instead. * * When a window loses input focus, it will generate synthetic key release - * events for all pressed named keys. 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 + * events for all pressed keys with associated key 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 scancode of a key is specific to that platform or sometimes even to that From 52405a9d599412545efd3bc3ace8342ae571ccd0 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 7 Mar 2023 23:03:06 -0800 Subject: [PATCH 16/21] Win32: Fix invalid hat bit mask being accepted It is reportedly possible to get opposing directions of an XInput DPad bit mask set simultaneously with some controllers. This commit ensures that those values are not passed on to other parts of GLFW. This commit is based on the PR #2291 by @ PeterJohnson but with the following changes: - moved XInput-specific special case to XInput implementation - attempt to preserve data by only masking out the invalid axis - admin (credit, changelog, commit message) Closes #2291 --- CONTRIBUTORS.md | 1 + README.md | 1 + src/win32_joystick.c | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1b9a277a..afd91a01 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -102,6 +102,7 @@ video tutorials. - JannikGM - Erik S. V. Jansson - jjYBdx4IL + - Peter Johnson - Toni Jovanoski - Arseny Kapoulkine - Cem Karan diff --git a/README.md b/README.md index 797ffd17..7045e75c 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,7 @@ information on what to include when reporting a bug. - [Win32] Bugfix: Right shift emitted `GLFW_KEY_UNKNOWN` when using a CJK IME (#2050) - [Win32] Bugfix: `glfwWaitEventsTimeout` did not return for some sent messages (#2408) - [Win32] Bugfix: Fix pkg-config for dynamic library on Windows (#2386, #2420) + - [Win32] Bugfix: XInput could reportedly provide invalid DPad bit masks (#2291) - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Moved main menu creation to GLFW initialization time (#1649) diff --git a/src/win32_joystick.c b/src/win32_joystick.c index 4e83577a..eae44edf 100644 --- a/src/win32_joystick.c +++ b/src/win32_joystick.c @@ -736,6 +736,13 @@ GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode) if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) dpad |= GLFW_HAT_LEFT; + // Treat invalid combinations as neither being pressed + // while preserving what data can be preserved + if ((dpad & GLFW_HAT_RIGHT) && (dpad & GLFW_HAT_LEFT)) + dpad &= ~(GLFW_HAT_RIGHT | GLFW_HAT_LEFT); + if ((dpad & GLFW_HAT_UP) && (dpad & GLFW_HAT_DOWN)) + dpad &= ~(GLFW_HAT_UP | GLFW_HAT_DOWN); + _glfwInputJoystickHat(js, 0, dpad); } From 0ede5f58c6f7c167499c0c78ce445828f44c15ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 5 Dec 2023 22:14:53 +0100 Subject: [PATCH 17/21] Simplify joystick hat value assertions --- src/input.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/input.c b/src/input.c index 8ab141fb..8b7ef29c 100644 --- a/src/input.c +++ b/src/input.c @@ -462,10 +462,11 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) assert(hat >= 0); assert(hat < js->hatCount); - // Valid hat values only use the least significant nibble and have at most two bits - // set, which can be considered adjacent plus an arbitrary rotation within the nibble + // Valid hat values only use the least significant nibble assert((value & 0xf0) == 0); - assert((value & ((value << 2) | (value >> 2))) == 0); + // Valid hat values do not have both bits of an axis set + assert((value & GLFW_HAT_LEFT) == 0 || (value & GLFW_HAT_RIGHT) == 0); + assert((value & GLFW_HAT_UP) == 0 || (value & GLFW_HAT_DOWN) == 0); base = js->buttonCount + hat * 4; From 5e4496cb420df4d93b4a31805b9fef443433f73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 5 Dec 2023 20:59:42 +0100 Subject: [PATCH 18/21] Cocoa: Fix compilation error on OS X 10.8 The occlusion state parts of NSWindow are OS X 10.9+ only but we still (technically) support building for only 10.8. Fixes #2161 --- README.md | 2 ++ src/cocoa_window.m | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7045e75c..fc8f89ce 100644 --- a/README.md +++ b/README.md @@ -273,6 +273,8 @@ information on what to include when reporting a bug. application (#2110) - [Cocoa] Bugfix: The Vulkan loader was not loaded from the `Frameworks` bundle subdirectory (#2113,#2120) + - [Cocoa] Bugfix: Compilation failed on OS X 10.8 due to unconditional use of 10.9+ + symbols (#2161) - [X11] Bugfix: The CMake files did not check for the XInput headers (#1480) - [X11] Bugfix: Key names were not updated when the keyboard layout changed (#1462,#1528) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 6f8aa978..c030c2d5 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -311,10 +311,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)windowDidChangeOcclusionState:(NSNotification* )notification { - if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible) - window->ns.occluded = GLFW_FALSE; - else - window->ns.occluded = GLFW_TRUE; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 + if ([window->ns.object respondsToSelector:@selector(occlusionState)]) + { + if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible) + window->ns.occluded = GLFW_FALSE; + else + window->ns.occluded = GLFW_TRUE; + } +#endif } @end From ddd92a4fa8dea2729ad2ea09172a8cfd541e53e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 6 Dec 2023 17:02:24 +0100 Subject: [PATCH 19/21] Update changelog and add credit Related to #2327 --- CONTRIBUTORS.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index afd91a01..741bce3a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -213,6 +213,7 @@ video tutorials. - Matt Sealey - Steve Sexton - Arkady Shapkin + - Mingjie Shen - Ali Sherief - Yoshiki Shibukawa - Dmitri Shuralyov diff --git a/README.md b/README.md index fc8f89ce..d7810cd5 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ information on what to include when reporting a bug. - Bugfix: `glfwSetGammaRamp` could emit `GLFW_INVALID_VALUE` before initialization - Bugfix: `glfwGetJoystickUserPointer` returned `NULL` during disconnection (#2092) - Bugfix: `glfwGetKeyScancode` returned `0` on error when initialized instead of `-1` + - Bugfix: Failure to make a newly created context current could cause segfault (#2327) - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access to the window menu - [Win32] Added a version info resource to the GLFW DLL From 68edc66aa4e0bcd2772e60711331629e9e369916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 7 Dec 2023 16:01:47 +0100 Subject: [PATCH 20/21] Add credit Fixes #2397 --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 741bce3a..40569702 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -66,6 +66,7 @@ video tutorials. - Nikita Fediuchin - Felipe Ferreira - Michael Fogleman + - forworldm - Jason Francis - Gerald Franz - Mário Freitas From 46cebb5081820418f2a20f3e90b07f9b1bd44b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 7 Dec 2023 16:51:13 +0100 Subject: [PATCH 21/21] EGL: Only use EGL_EXT_present_opaque on Wayland The EGL_EXT_present_opaque extension is primarily a workaround meant for Wayland, even if the language in it doesn't mention this. GLFW previously always enabled this extension where supported. This caused issues on X11 when running the Nvidia binary blob. This commit ensures the extension is only enabled on Wayland. Fixes #2365 --- CONTRIBUTORS.md | 1 + src/egl_context.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 40569702..a78fd5ce 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -252,6 +252,7 @@ video tutorials. - Jari Vetoniemi - Ricardo Vieira - Nicholas Vitovitch + - Vladimír Vondruš - Simon Voordouw - Corentin Wallez - Torsten Walluhn diff --git a/src/egl_context.c b/src/egl_context.c index 4f76d351..a18590b9 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -704,8 +704,11 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, if (!fbconfig->doublebuffer) SET_ATTRIB(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); - if (_glfw.egl.EXT_present_opaque) - SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); + if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) + { + if (_glfw.egl.EXT_present_opaque) + SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); + } SET_ATTRIB(EGL_NONE, EGL_NONE);